contrib/sasc-ng/sasc-ng
contrib/sasc-ng/objs/version.cpp
contrib/sasc-ng/sc/config.h
+contrib/sasc-ng/sc/PLUGINS/src/sc-src
syntax: regexp
^testing/test[^.]*$
DEFINES += -DRELEASE_VERSION=\"$(VERSION)\"
INCLUDES += -Idvbloopback/module -I/lib/modules/$(shell uname -r)/build/include
LBDIR = dvbloopback/src
-SCDIR = ./sc/PLUGINS/src/$(SCVER)
-SCSYSLIBS := $(foreach ob,$(shell ls -A -I ".*" $(SCDIR)/systems), -lsc-$(ob))
+SCDIR = sc/PLUGINS/src/$(SCVER)
SC_FLAGS = -O2 -fPIC -Wall -Woverloaded-virtual
ifdef AUXSERVER_OPTS
$(CC) -fPIC -g -O2 -Wall -I. -nostdlib -shared -o $@ $< -ldl -lc
clean:
- @$(MAKE) -C $(SCDIR) SASC=1 clean
+ @-rm -rf $(SCDIR)/*
@-rm -f ./sc/PLUGINS/lib/*.so*
@-rm -f ./sc/config.h
@-rm -f $(OBJS)
module_clean:
cd dvbloopback/module && $(MAKE) clean
-sc-plugin:
+sc-plugin-link:
+ @bash ./makelinks.sh . $(SCDIR)
+ @mkdir -p $(SCDIR)/systems-pre $(SCDIR)/po
+
+sc-plugin: sc-plugin-link
@-rm -f sc/config.h
@ln -s include/vdr/config.h sc/config.h
@if [ ! -d sc/PLUGINS/lib ]; then mkdir sc/PLUGINS/lib; fi
objs/%.o: dvblb_plugins/%.c $(INC_DEPS) $(INC_DEPS_LB) link-FFdecsa
$(CXX) $(CXXFLAGS) -o $@ -c $(DEFINES) -I$(LBDIR) $(INCLUDES) $<
-objs/%.o: sc/%.cpp
+objs/%.o: sc/%.cpp sc-plugin-link
$(CXX) $(CXXFLAGS) -o $@ -c $(DEFINES) $(INCLUDES_SC) $(INCLUDES) $<
objs/si_%.o: sc/libsi/%.c
--- /dev/null
+#!/bin/bash
+
+SRC="$1"
+DEST="$2"
+PAR="../.."
+SLEN=`echo -n "$SRC" | wc -c`
+SLEN=`expr $SLEN + 2`
+
+
+mkdir -p "$DEST"
+
+(cd "$PAR"; find "$SRC" -name contrib -prune -o -name .hg -prune -o -type f -regex ".*\(Makefile.*\|\.\(h\|c\|mk\|po\|pl\)\)") |
+ while read i; do
+ base=`echo -n "$i" | cut -c $SLEN-999`
+ dir=`dirname "$base"`
+ mkdir -p "$DEST/$dir"
+ COR=`echo -n "$DEST/$dir" | sed -e 'sX/\.XX' | sed -e 'sX[^/]*X..Xg'`
+ ln -sf "$PAR/$COR/$SRC/$base" "$DEST/$base"
+ done
+++ /dev/null
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-\f
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-\f
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-\f
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-\f
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-\f
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
+++ /dev/null
-VDR Plugin 'sc' Revision History
---------------------------------
-
-09.02.2008: Version 0.9.0
-- NOTE: the versioning scheme has been changed. All releases (regardless if even
- or odd minor) are considered stable. Unstable development is in HG only.
-- Updated keys are now written back to the SoftCAM.Key file. If the keyfile is
- modified externaly it will be re-read. Introduce new cache files ecm.cache &
- tps.cache. ca.cache is obsolete now.
-- All config files are expected to be located in the "sc" subdir of the plugin
- config directory now. Removed commandline option -c.
-- A bunch of changes to the Nagra2 code, including 0501 maprom, 0101 map 29, 97W
- hack, fixed HW_SECURITY and map timings.
-- Fixed Viaccess TPS AU.
-- Added dedicated housekeeping thread.
-- Display (important) user messages on the OSD (if enabled in setup).
-- Various updates to testing code.
-- Fixed Makefile default target.
-- Fixed gcc 4.x warnings.
-- Added patch for DVB multiproto driver.
-- Updated finnish and french translations.
-
-------------------------------------------------------------
-
-18.01.2008: Version 0.8.7
-- Several changes to the Nagra2 code including HW reg mapper, map cycle counts,
- 0501 AU, 0101 auxed map57, tableless map3e and new build system.
-- Increased smartcard info buffer size.
-- Fixed memcpy in Seca ECM/EMM processing.
-- Fixed ExtAU to trigger on wrong key. Don't trigger on EMM keys.
-- Fixed RotateBytes to be robust against bad input.
-- Updated Makefile for HG.
-- Updated italian, russian, finnish translations.
-- The 0.8.x branch is now frozen, only bugfixes will be applied.
-
-21.12.2007: Version 0.8.6
-- Added Nagra2 0501 dyn. AU execution fix.
-- Added Nagra2 4101 map58 AU (though already outdated). Using unified ECC code
- for map57 & map58.
-- Added instruction cycle counter to Nagra ST7/19 cpu emulation.
-- Added support for recent Nagra2 0101/0901 ECM (including map4e/22/3e cycle
- calculation, timer/CRC hardware simulation, DES map, EEPROM updates, dynamic
- ECM code, auxserver V2 call).
-- Added Nagra2 config option to drop EMM-S packets.
-- Added Nagra1 UK reg05 fix (i.e. moved it from N2 to N1).
-- Added TPS AU fix.
-- Added SVDR commands to inject keys and to configure logging to file.
-- Removed some gcc'isims (case ranges, named variadic macros, variable length
- arrays).
-- Updated finnish translations.
-
-10.11.2007: Version 0.8.5
-- Added new Nagra2 0501 AU sheme.
-- Added Nagra2 NA 'temporarily' fixes.
-- For simplicity the high provider id is used always now, when loading an EEP
- file in Nagra2 emu. e.g. for provider 0901 you have to rename the file to
- EEP09_102.bin.
-- Added an option to start AutoUpdate even if no audio/video pids are set (e.g.
- EPG scan). Has to be enabled from the plugin setup menu.
-- Fixed cardclient camd35 EMM request length check.
-- Fixed smartcard Viaccess ATR check and transcription errors in smartcard NDS
- camcrypt. Thanks to dr.aus.
-- Fixed saving ScCaps to config if all cards are disabled.
-- Fixed sasc-ng compile (FFdecsa dir).
-- Obmit error messages about (optional) config files (e.g. *.KID).
-- Added some glue for gcc 2.95 compile.
-- Added Hungarian translations.
-
-30.09.2007: Version 0.8.4
-- Added Nagra2 4101 Bx support.
-- Added smartcard NDS Videoguard2 code (untested). Needs NDS seed and boxid in
- smartcard.conf (later only for newer card revisions). This is based on code
- from sasc-ng changeset r155.
-- Fixed Nagra cpu emu SetPc and ReadHandler call.
-- Fixed crash on TPS ECM when no TPS encryption is used and no TPS AU keys are
- available (null pointer dereference).
-- Updated russian and finnish translations.
-
-15.09.2007: Version 0.8.3
-- Added Nagra2 3101 MECM (same as 0501).
-- Added Nagra2 0901 new 0x40 MECM and rev248 morph (from sasc-ng).
-- Changed TPS AU instruction limit for st20 emulation. Fixed callback pointer
- search and decryption in case super encryption is disabled temporarily.
-- Added a setup option to limit the size of the logfile.
-- Fixed Makefile for Debian compile.
-- Some fixes for sasc-ng compile/operation.
-- Now autogenerating i18n.c file with po2i18n.pl from po files on VDR < 1.5.7.
- Note that after changes to the *.c files the po files have to be recreated, so
- you should have gettext package installed.
-- Fixed plugin .mo filename for VDR 1.5.7.
-- Updated finnish translations.
-
-02.09.2007: Version 0.8.2
-- Reworked Nagra2 EMM nano handling, key updates and map core (the latter is
- partly based on Emunation 2.0.0 code).
-- Added Nagra2 0101 register 0x05,0x16 fix (not well tested).
-- Added Nagra2 0511,1101 MECM (same as 0501).
-- Added compatibility option for sasc-ng.
-- Added commandline option -c to select a config subdirectory.
-- Fixed FFdecsa to prevent CW change while key in use. Based on racepatch from
- DVBN.
-- Fixed cardclient camd35 packet ID compare (short vs. int).
-- Fixed Nagra2 skipping expiry date in ECM.
-- Added support for VDR 1.5.7+ gettext sheme (most po-files need to be revised
- by translators).
-
-06.07.2007: Version 0.8.1
-- Added Nagra2 7101 3DES support.
-- Added a setup option to force transfermode with digital audio. Another common
- used patched for the vdr-core is made unnecessary by this option.
-- Fixed camd33 EMM packet processing.
-- Fixed recording device allocation (1.4.x). You have to update the VDR core
- patch. Thanks to dingo35.
-- Fixed compiling with VDR 1.5.0.
-
-22.06.2007: Version 0.8.0
-- Added Nagra2 0501 MECM support.
-- Added support for Nagra smartcards. Code is not well tested. Volunteers
- welcome. Timing is tricky, so you have to get cardreader clock AND -C
- parameter right.
-- Added debug description to CI adapter ringbuffers.
-- Added a note to README that the plugin have to be put first on VDR
- commandline. Loading certain plugins (e.g. softdevice) in front of SC leads to
- mismatched device numbering in VDR which causes some strange effects.
-- Added sanity check for device numbering.
-- Fixed Nagra2 nano processing.
-- Fixed Seca EMM signature check.
-- Never ending story: fixed cardclient reconnecting on read timeout again.
-- Fixed cardclient camd35 sending Nagra provider in ECM request.
-- Added russian translations (core only).
-
-------------------------------------------------------------
-
-13.05.2007: Version 0.7.5
-- Fixed memcpy race in OpenTV decompress.
-- Fixed endless loop with evil EMM data in Nagra2 0101 B1 code.
-- Fixed access to disabled DVB cards (1.4.x).
-- Fixed budget card problem in VDR core patch (1.4.x).
-
-06.05.2007: Version 0.7.4
-- Added compatibility for VDR 1.4.6 (VDR core has to be patched). Note that this
- is experimental code.
-- Added support for new TPS AU sheme.
-- Added some Map handling to DN/BEV B1 processing code.
-- Added version information to hello message in cardclient radegast.
-- Added logic to Makefile to copy max. number of CAIDs from VDR.
-- Extended ConstCW key to handle cable/terrestrial sources.
-- Fixed race in camslot reset code.
-- Fixed zero-cw-index handling for CI update messages.
-- Fixed handling of same SID on different transponders in lru-caid-cache.
-- Fixed menu processing on ECM cache flush abort.
-
-06.04.2007: Version 0.7.3
-- This is a beta release. As the code seems pretty stable, we would like to
- encourage everybody to try this release. Nevertheless it should be used under
- controlled conditions only.
-- Further improved camslot reset behaviour. Toggling concurrent flag takes
- effect at runtime now too.
-- Removed obsolete D+ AU code.
-- Fixed unexpect side effect of cardclient reconnecting on read timeout.
-- Fixed CAID allocation (CheckIgnore).
-
-31.03.2007: Version 0.7.2
-- Now creating the devices nodes after loading setup.conf. Should solve problems
- with SourceCaps patch and remove the "nextCardIndex to big" error. But this
- requires some ugly hacking which may not work with every gcc/vdr version.
-- Added DarkAvengers FFdecsa optimizations for mmx, sse and sse2 modes.
-- Added SVDR command to display all message classes.
-- Added new D+ AU. You need an additional NN 52 RSA key (and optional NN 53
- verify key).
-- Added autodetection of pid where TPS broadcasts AU data. You still have to
- switch to transponder 10873 for AU.
-- Changed the plugin shutdown sequence to fix the hang-on-exit problem. It seems
- to be fixed now, although the reason for the problem is still unknown.
-- Fixed Nagra2 0101 map 4d input.
-- Fixed logging Nagra cpu emu messages to general.unknown.
-- Fixed reseting module options to default.
-- Fixed a mismatched Lock/Unlock in smartcard code (in error path).
-- Fixed off-by-one error in CI adapter read.
-- Fixed camslot reset logic.
-- Fixed some 'valgrind' problems and properly unload all sub-libraries on plugin
- exit too.
-- Updated README documentation, removed README.0.7.x.
-- Updated finnish translations.
-
-09.03.2007: Version 0.7.1
-- Reduced the number of used camslots to 1 per device. Multiply camslots cause
- all kinds of problems. Reworked CAID allocation algorithm. This should make
- operation much more reliable.
-- Improved operation with hardware CAM.
-- Introducing a completely new message logging system. All messages classes can
- be enabled/disabled at runtime (via setup menu and SVDR) and can be written to
- console, file and/or syslog (configurable from setup menu).
-- Added Nagra2 provider 0101 Map57 call.
-- Added TPS AU code. Note that you have to add 8 TPS master keys to your
- keyfile. Update seems to work only on transponder 10873, e.g. switch to
- Equidia.
-- Fixed FF concurrent streams if sc.ConcurrentFF is set to a value >1.
-- Fixed CI adapter TPDU length decoding.
-- Fixed processing stale ECM packets after a channel switch.
-- Fixed long standing bug in Nagra1 RSA key update (which was a problem in a
- key base class, introduced in 0.5.10).
-- Fixed paged long indirect and paged long indirect indexed adressing modes in
- Nagra cpu emu (HILOS macro).
-- Fixed cardclient reconnecting on read timeout.
-- Fixed clobbering the name of the sc shared library in the shared objects
- table.
-- Fixed compiling if openssl lacks IDEA support.
-
-17.02.2007: Version 0.7.0
-- Forked development branch.
-- This is an alpha release. Using it in a production enviroment is not
- recommended. You are strongly advised to read the file README.0.7.x.
-- Requires VDR version 1.5.0 or newer and openssl package 0.9.7 or newer.
-- Now operates without any patches to the VDR core.
-- Integrated FFdecsa functionality.
-- Using a openssl package without IDEA & AES support is deprecated. Included
- support code will be removed in the future.
-- Added commandline option to force budget mode on a DVB device.
-- Added setup menu item to flush ECM cache (from ca.cache).
-- Added support for Nagra2 3DES encrypted key updates. Tweaked EMM caid and RSA
- key selection for D+ AU.
-- Added fix for Nagra2 BEV B1 updates.
-- Added pre-crypted camkey challenges for Irdeto ACS 384. This is a last resort
- convenience mode and usage is strongly deprecated! Don't relay on this!
-- Added NewCS client identification in cardclient newcamd.
-- Fixed include path order.
-- Added swedish translations.
-
-------------------------------------------------------------
-
-06.04.2007: Version 0.6.2
-- Backported from 0.7.2:
- * Mismatched Lock/Unlock in smartcard code.
- * Autodetection of pid with TPS AU data.
- * Finnish translations.
-- Backported from 0.7.1:
- * Nagra2 provider 0101 Map57 call.
- * Nagra1 RSA key update.
- * Paged adressing modes in Nagra cpu emu.
- * TPS AU.
- * Cardclient reconnecting on read timeout.
- * Processing stale ECM packets after a channel switch.
- * Clobbering shared library name in shared objects table.
- * Compiling if openssl lacks IDEA support.
-
-17.02.2007: Version 0.6.1
-- Backported from 0.7.0:
- * Nagra2 3DES encrypted key updates (D+ AU).
- * Nagra2 BEV B1 updates.
- * Pre-crypted camkey challenges for Irdeto ACS 384.
- * NewCS client identification in cardclient newcamd.
- * Include path order.
- * Swedish translations.
-
-13.01.2007: Version 0.6.0
-- Stable release. Minimum supported VDR version is 1.4.0. Note that the stable
- branch doesn't support and probably will not support VDR 1.5.x series. This is
- left to the upcomming unstable branch.
-- Added support for new TPS algo. You need a current tps.bin (mostly changing
- daily) file in plugins/viaccess/.
-- Fixed CW swap for Nagra2 providers 0501/1101/1102.
-- Fixed BEV inadvertently using Nagra1 ECM decoding only.
-- Fixed Nagra1 ROM10 updates (broken by ROM3 changes in 0.5.12).
-- Fixed compiling issue with missing "asm/unaligned.h".
-- Added Makefile option for static build (sasc-ng).
-
-------------------------------------------------------------
-
-15.12.2006: Version 0.5.12
-- Major restructure of Nagra code. Added basic ST19 features to Nagra cpu
- emulation (Nano B1 processing). Added provider 0101/0901 map 3b. Fixed long
- standing bug in ROM3 key update.
-- Updated Viaccess AU to new parsing code. Fixed signature check in shared
- updates (introduced in 0.5.11).
-- Changed the order in which ECM pids/systems are tried to a more consistent way
- regarding the system priority.
-- Fixed cardclient newcamd using wrong SA for Seca provider.
-- Fixed ignoring CAIDs when used together with a hardware CAM.
-- Fixed writing garbage to setup.conf if CAID ignore list is empty.
-- Fixed AutoUpdate switch. Turning it off had no effect. ExternalAU honors the
- AutoUpdate switch now too.
-- Added russian translations.
-
-04.10.2006: Version 0.5.11
-- Added Nagra2 MECM handling, support for AUX server (version 0.9.3 or newer
- only) and DN EMM hacks.
-- Added smartcard Cryptoworks camcrypt. You must have a valid IPK or UCPK in
- your smartcard.conf to make it actually work. If you have a PIN for your card
- in smartcard.conf, parental rating can be disabled even if the PIN cannot be
- read from the card. See example smartcard.conf for format.
-- Added additional checks to Viaccess AU code to prevent segfault on bad input
- data (e.g. short EMM).
-- Added V4 server capability check in cardclient radegast. EMM processing would
- be possible, if the server would send UA/SA to the client.
-- Added cardclient gbox. GBOX must be running on the local machine and you have
- to make sure that there is no /var/tmp/pmt.tmp file. Based on morfsta's
- version but rewritten nearly from scratch.
-- Added a configurable list of CAIDs which are ignore by the plugin. See plugin
- setup menu.
-- Fixed triggering external AU too often.
-- Fixed stupid Viacess key length error.
-- Fixed parsing CA descriptors for all SIDs if a handler has attached several.
- Thanks to Aroureos for testing.
-
-21.07.2006: Version 0.5.10
-- Added external key updates via shell script. See README for details.
-- Now checking for duplicate serial ports in smartcard config.
-- Fixed supersede for Viaccess TPS keys.
-- Fixed re-adding DEFAULT_PORT on config-file reload.
-- Fixed design bug in key comparison.
-
-05.06.2006: Version 0.5.9
-- Smartcard code now supports setting the cardreader clock (see commandline
- switch -C/--clock), custom baudrates (if your UART supports that), PTS
- specific mode and PTS 1-stopbit mode. Note: due to the new clock parameter,
- the format of DEFAULT_PORT has changed!
-- Added a filter for unused chid's in Irdeto ECM stream.
-- Fixed cardclient camd33 checking for unsuccessfull ECM answer (causing 5s
- delay). Thanks to Aroureos for all the testing.
-- Fixed cardclient camd35 parsing provider information in EMM request.
-- Fixed a side effect in main cam loop.
-- Various fixes to Makefile (unsupported cp options, sublibrary naming scheme,
- honour DVBDIR in Makefile.system, libcrypto linkage).
-- Fixed libvdr-sc overloading a global VDR symbol (translations).
-- Fixed compiling with VDR < 1.3.47.
-- Corrected information about min. required VDR version (currently 1.3.31).
-
-26.05.2006: Version 0.5.8
-- Completely new build system. Now using shared libraries for individual
- encryption systems, which are loaded at runtime. Copy all wanted libsc-* to
- your VDR plugin lib directory. Encryption systems might be provided in binary
- form only. See README for details.
-- Added Cryptoworks emulation. See example keyfile for key format.
-- Added Nagra2 EMM nano E0 (DN) handling.
-- Don't try failed ECMs too often (by caching them).
-- Fixed Nagra2 PW inverse CW.
-- Fixed handling of channels which share the same PIDs.
-- Fixed ConstCW key handling (broken in 0.5.7).
-- Fixed Cardclient ECM caching.
-- Fixed Newcamd EMM Viaccess provider ID matching.
-- Fixed Viaccess EMM assembling.
-- Fixed dvb-cwidx patch for undefined LINUX_VERSION_CODE. There seems to be
- compatibility problems with certain kernel/driver version (e.g. kernel driver
- vs HG): gcc complains mutex_lock() is called with incompatible pointer type.
- Therefore the old dvb-cwidx patch has been re-added as dvb-cwidx-old in case
- someone has problems with the new version.
-- Fixed odd compiler error for a struct member with the same name as the struct
- itself (probably some ancient gcc version).
-- Added frensh translations.
-
-06.05.2006: Version 0.5.7
-- Disable keyfile stuff if no system uses keys, prevent loader error messages
- about unknown sections, prevent ca.cache trashing, fixed key saving.
-- If smartcard PTS request fails, reset card again and continue without PTS.
-- Now reading entitlements from Conax smartcard.
-- Added a workaround for providers which seem to broadcast fake ECM.
-- Added warning about channels which share the same PID.
-- Fixed Nagra2 crash with EMM-S keys.
-- Fixed compile problem when disabling certain modules.
-- Updated dvb-cwidx patch for kernel >= 2.6.16.
-- Changed Makefile to take APIVERSION into account.
-- Added polish translations.
-
-30.03.2006: Version 0.5.6
-- Added Nagra2 ECM DES decryption code.
-- Nagra signature check is now skipped, if your keyfile lacks verify keys. Don't
- put fake verify keys in there!
-- Now reading entitlements from Cryptoworks smartcard.
-- Smartcard engine now supports ISO7816 PTS protocol i.e. baudrate changes.
-- Improved OSD display of smartcard information/entitlements.
-- Fixed exit condition in Nagra2 ECM/EMM nano parse loop.
-- Prevent frequent relaunch of the logger thread.
-- Fixed CW-index allocation for idle ECM handler.
-- Fixed missing initialisation in ECM handler.
-- Fixed ECM handler selection in special cases where a recording starts and
- used-FF-streams == allowed-FF-streams but one of the stream is used for live
- viewing. Involves changes to vdr-sc patch too.
-- Fixed concurrent check in vdr-sc patch. A bad comparison broke the check if
- the first CAID in channel entry was 0x100.
-- Fixed cardclient radegast to handle NULL-cw.
-- Added dutch translations and updated finnish translations.
-- NOTE: you have to upgrade the VDR core with the supplied vdr-sc patch. Older
- versions will refuse to work.
-
-16.02.2006: Version 0.5.5
-- Complete restructure of Nagra code (e.g. separating Nagra1 & Nagra2). Added
- signature check, verify keys are mandatory now.
- As a consequence Nagra2 key format has changed (as announced). See example
- keyfile. A quick upgrade guide:
- N xxxx 10 -> N xxxx 01
- N xxxx 02 -> N xxxx NN 02
- N xxxx N2 -> N xxxx NN 12
- verify keys -> N xxxx V
- -> N xxxx NN 03
-- Restructured AutoUpdate code. EMM data is now passed to all systems which can
- handle it, concurrent recordings doesn't cause multiple processing of the same
- date and it's possible to log on all available CAIDs concurrently (though this
- may cause high CPU load). See plugin setup menu. Option LoggerActive has been
- renamed to AutoUpdate. Option LoggerTimeout has been removed. Check your
- config.
-- Added some statistics about EMM packet load.
-- Now using non-RSA (i.e. plain) camkey challenge for Irdeto smartcards if the
- word PLAIN is given in smartcard.conf instead of a certificate. See example
- smartcard.conf. For ACS 0383/0384 cards the challenge type is autodetected. If
- anybody knows a generic way to detect the challenge type, please let us know.
-- Fixed several crypto classes to be reentrant (fixing possible race in
- multi-threaded ECM/EMM handling).
-- Fixed access to (possibly) deleted filter class in section filter handling.
-- Fixed complaining about erroneous entries in smartcard.conf if compiled
- without SC_IRDETO.
-- Fixed endless loop in SimpleList handling.
-- Fixed vdr-1.3.38-sc patch (one hunk was lost).
-
-08.01.2006: Version 0.5.4
-- Added a plugin SVDR interface. The only command is RELOAD for now (triggers a
- reload of the configuration files).
-- Added support for multiple TPS keys (key is selected based on Viaccess hash).
-- Added premiliary support for Nagra2 AU. See example keyfile for format of
- needed keys. Key format is subject to change in next releases.
-- Complete rewrite of the Seca2 provider specific code.
-- Added generic RSA & IDEA crypto classes.
-- Added better checking of CW decryption status in smartcard Cryptoworks.
-- General code review (eliminated duplicate code, replaced VDR base classes by
- own shorter ones, beautified code).
-- Now generating smartcard Irdeto info string for OSD card menu.
-- If the DVB driver doesn't support the CA_SET_PID ioctl call (i.e. unpatched
- driver), auto adjust the FF concurrent limit to 1.
-- Fixed checking card status in smartcard Irdeto camkey exchange.
-- Fixed detaching a PID from a handler if VDR has removed this PID from the
- channels.conf entry meanwhile.
-- Fixed ECM table handling in ca.cache.
-- Fixed Nagra2 CW order for D+.
-- Fixed a gcc4.1 compiling issue.
-- Added additional debug output in cardclient camd35 to snoop for AU problems.
- You may comment DEBUG_EXTRA to disable verbose log.
-- Updated FFdecsa patch to 0.1.3 (fixing a race condition).
-- Note: this release was forced by the release of VDR 1.3.38 and not all of the
- changes above are tested as well as they should be.
-
-09.12.2005: Version 0.5.3
-- Added Nagra2 EMM support and EMM caching to cardclient newcamd.
-- Added Cryptoworks EMM support and EMM caching to cardclient camd35.
-- You may now add multiple CAID fields to cardclient.conf. A valid line would be
- e.g. camd35:192.168.0.1:20248:1/1702/FF00,0604,0d0c/FF00:hero:itsme
-- Added support for systems which broadcast ECM on tables other than 0x80/0x81.
-- Added support for Nagra2 BEV & dual IDEA opkeys (00/10).
-- Now reading CAID from Cryptoworks smartcard.
-- Added sanity check to nano sorting to prevent memory trashing.
-- Added new CAID nano to cardclient Radegast ECM request.
-- Fixed Cryptoworks shared EMM parsing. Added additional checks to reduced EMM
- load too.
-- Fixed smartcard Irdeto camkey challenge for Premiere S01 and other non-Z
- cards. As these cards don't support the RSA challenge, you don't need a
- certificate for them.
-- Fixed matching Irdeto certificates which are given with ACS version only.
-- Fixed misleading error messages in smartcard.conf parser.
-- Fixed ECM-EMM caid mismatch and segfault due to leftover debug statements in
- cardclient camd35.
-- Fixed (i.e. removed) global cardclient EMM cache as it corrupts EMM merging
- for systems which broadcast shared updates on different tables.
-- Fixed cardclient newcamd segfault on bad config data.
-
-12.11.2005: Version 0.5.2
-- Introducing a new config file for smartcard specific data e.g. RSA certificate
- or box keys. The file is called smartcard.conf. See the example file.
-- Added support for full camkey challenge in smartcard Irdeto. You need a RSA
- certificate matching your card (either Irdeto default or card specific one) in
- smartcard.conf or your card won't work!
-- Added an abstract layer to parse and assemble EMM messages. This touches
- several systems e.g. Viaccess, Cryptoworks & NDS. A bug here may break them
- all.
-- Added Cryptoworks & Viaccess EMM handling to newcamd cardclient (via new
- assemble code).
-- Added some more MAP math calls to Nagra emulation to fix Rom10 AU.
-- Several fixes to NDS EMM parsing/assembling.
-- Fixed ConstCW key lookup (was broken due to Nagra1/2 key handling changes).
-- Fixed cardclient camd3 to include SID in ECM request.
-- Fixed cardclient newcamd to handle NULL-cw which are send by newcs.
-- Removed logger option 'non-recording on' from the config. In 0.5.x it is
- without function anyways.
-- Added a message to hint the user about unusual values in ScCaps. Changed the
- default values to something more reasonable too.
-- Updated FFdecsa patch to 0.1.2 (fixing a segfault).
-
-13.10.2005: Version 0.5.1
-- Added smartcard Cryptoworks EMM handling. There is a setup option to disable
- the parental rating on the card too (experimental). Thanks to scotty for the
- sample code.
-- Added smartcard Viaccess EMM handling (experimental).
-- Added FFdecsa-0.1.1 patch.
-- Don't count a live stream on a FF card when deciding about allowed
- concurrency. A live stream doesn't use bandwidth on the bus.
-- Apply min. ECM processing time to Nagra2 too.
-- Fixed segfault for Seca1.
-- Fixed Irdeto key updates. Somehow/sometime the code was broken.
-- Fixed cardclient newcamd NDS EMM (still experimental).
-- Now considering the key size when superseding keys.
-- Forgot to mention that you need additional table files for Seca 6a (s2_sse.bin
- 5120; s2_sse_006a.bin 336; s2_cw_006a.bin 512 (Numbers are the filesize)).
-- Updated finnish translations.
-
-15.09.2005: Version 0.5.0
-- Forked development branch.
-- Added concurrent recording feature i.e. record/view multiple encrypted
- channels on a single DVB card. This also works on a full-featured DVB card!
- To make this feature work you NEED:
- on a BUDGET card:
- * SoftCSA version 0.1.0 or greater
- on a FULL-FEATURED card:
- * a DVB driver patched with dvb-cwidx.diff
- * a specialy patched firmware. The "normal" patched firmware doesn't work!
- See further details in the README.
-- vdr-sc patch has been updated. This plugin version ONLY works with this patch!
- Older plugin versions doesn't work with this patch, although they may compile
- fine!
-- Dropped compatibility for older VDR versions. Requires VDR version 1.3.29 or
- newer.
-- Changed card & provider handling in cardclient camd35 (experimental).
-- Added NDS support to newcamd cardclient (experimental).
-- Added limited Seca 6a support.
-- Fixed mismatching Nagra1 & Nagra2 keys.
-
-------------------------------------------------------------
-
-17.12.2005: Version 0.4.12
-- Backported from 0.5.3:
- * Fixed cardclient newcamd segfault on bad config data.
- * Fixed ECM-EMM caid mismatch and segfault in cardclient camd35.
- * Added new CAID nano to cardclient Radegast ECM request.
-- Backported from 0.5.2:
- * Fixed ConstCW key lookup.
- * Fixed cardclient camd3 to include SID in ECM request.
- * Fixed cardclient newcamd to handle NULL-cw.
- * Changed plugin default conf values to something more reasonable.
-- This is the final release for the 0.4.x branch. The 0.5.x branch is already
- pretty stable. Please consider upgrading.
-
-31.10.2005: Version 0.4.11
-- Backported from 0.5.1:
- * Fixed segfault for Seca1.
- * Fixed Irdeto key updates.
- * Now considering the key size when superseding keys.
- * Updated finnish translations.
-
-24.09.2005: Version 0.4.10
-- Apply min. ECM processing time to Nagra2 too.
-- Backported from 0.5.0:
- * Fixed mismatching Nagra1 & Nagra2 keys.
- * Limited Seca 6a support.
-
-10.09.2005: Version 0.4.9
-- Fixed cardclient camd35 to include provider ID in ECM request.
-- Fixed Nagra2 padding 2nd RSA and CW swap for NA.
-- Fixed compiling issue in Nagra code on older VDR versions.
-- Fixed compiling issue in IDEA code if a recent openssl but without IDEA is
- installed.
-
-04.09.2005: Version 0.4.8
-- Added Nagra2 code. See example keyfile for key format.
-- Fixed coredump in ECM delay feature.
-- Fixed buffer overflow in cardclient camd35.
-- Fixed setting serial IO speed for smartcard access.
-- Now truncating all key printouts in the debug log.
-
-18.08.2005: Version 0.4.7
-- Fixed compatibility issue with camd 3.7x.
-- Fixed switching to FTA while card is replaying.
-- Changed decoding, so that if the decoding fails consecutively, further
- processing is delayed until the next parity change.
-- Fixed ECM card response parsing in smartcard Conax.
-- Added some generic ECM/EMM parsing.
-- Updated finnish translations.
-
-20.06.2005: Version 0.4.6
-- Added EMM support for smartcard Conax.
-- Added EMM support to Newcamd client.
-- Fixed EMM card command in smartcard Seca.
-- Fixed Camd Cmd05/Cmd06 offsets.
-- Now really fixed canceling netwatcher thread.
-
-25.05.2005: Version 0.4.5
-- Fixed Nagra key update issues.
-- Added support for the new Camd Cmd05/Cmd06. Thanks to Dukat for the example.
-- Added support for broadcasts without ECM data (only if system delivers
- constant CW). Based on Ragnos patch.
-- Fixed ca.cache handling if ECM PID changed since entry was created.
-- Fixed Radegast client to work with shared Seca cards.
-- Fixed netwatcher cancel timeout.
-- Now using unaligned.h in cDes to prevent unaligned memory accesses on
- architectures which doesn't support them (e.g. Alpha).
-
-07.02.2005: Version 0.4.4
-- Now caching CA descriptor data to speed up intial sync for systems which
- depend on this data (e.g. Seca).
-- Fixed Nagra EMM code to handle additional nanos in front of cpu updates.
-- Fixed Seca RSA for short decrypt results.
-- Fixed Viaccess EMM assemble buffer size.
-
-21.01.2005: Version 0.4.3
-- Added Seca2 nano 5109 handling. You need special RSA keys for this. See
- example keyfile.
-- Increased wait timeout for ECM extra data.
-- Fixed Seca permtables. Thanks to millemila.
-- Fixed Seca SHA1 signature. Thanks to BB.
-- Fixed return length position in Newcamd cardclient. Thanks to cart.
-
-10.01.2005: Version 0.4.2
-- Added workarounds for changes in vdr 1.3.18.
-- Fixed comparision of BIGNUM keys (Nagra, but not only Nagra).
-- Fixed cCondWait calls for vdr before 1.3.13.
-
-23.12.2004: Version 0.4.1
-- Added constant-CW system, CONSTCW=1 to activate. See example keyfile for CW
- key format.
-- Added support for Viaccess TPS crypt v2. You need a suitable TPS key for your
- provider. See example keyfile.
-- Added support for v5.25 protocol in Newcamd cardclient (with fallback to old
- protocol).
-- Added support for Nagra RSA key updates (high system id only). You need a
- proper eeprom file for this to work.
-- Now delaying first access to smartcards until the cards are initialised.
-- Fixed Seca code which though it has a correct decode while it hasn't.
-- Fixed several minor issues in Nagra code.
-- Fixed CA descriptor parsing for sc-viaccess and cardclients.
-- Fixed cardd client to send network message of at least 96 bytes.
-- Fixed inline asm macros to be used only on x86 CPUs.
-- Replaced non-reentrant libc functions with their reentrant counter part.
-- Replaced usleep() calls with proper cCondWait calls (vdr 1.3.x only).
-
-26.10.2004: Version 0.4.0
-- Versions bump, now in stable branch.
-- Added Viaccess smartcard code, SC_VIACCESS=1 to activate. ECM only for now.
-- Added ragnos Sc-Seca-PPV patch.
-- Added zens FullX-2 patch.
-- Added permtable for Seca provider 0x65.
-- Added cardclient config option to trigger immediate connect to cardserver on
- startup.
-- Extended smartcard code to support indirect convention, zero-byte writes and
- 256-byte reads.
-- Fixed Nagra plaintext AU.
-- Fixed camd33 reconnecting and discard keep-alive packets.
-- Removed unnecessary bind() in udp networking (allows camd35 server on same
- machine).
-- Fixed disconnect timeout not working if no dial script is given.
-- Updated finnish translations.
-
-------------------------------------------------------------
-
-26.09.2004: Version 0.3.17
-- Joined "dukat" & "freezer" cardclients to new "camd33" client.
-- Added cardclient "camd35", supporting camd 3.5 udp protocol.
-- Added caid & mask to cardclient config. Added carddata (hexbase, hexser) to
- Aroureos cardclient config. See example cardclient.conf.
-- Fixed Viaccess logger (wrong section filter mask).
-- Fixed dialup networking not hanging up in case of connect error.
-
-14.09.2004: Version 0.3.16
-- Now supporting all Nagra keysets (pk0-2,typ0-1). Keyformat has changed. See
- example keyfile.
-- Fixed some long standing bugs in Nagra ECM handling. Verify keys (V) are
- mandatory now, 80 keynumber is obsolete. Note: you need both keysets for a
- provider, e.g. for Polsat 7001 & 7101.
-- Added support for Seca provider 0x65 (appropriate hash/mt files needed).
-- Added finnish translations.
-- Fixed key length mismatch on EMM update for 8/16 byte keys.
-- Fixed sc-cryptoworks ATR parsing for cards with bios3mod.
-- Fixed stupid typo bug in sc-Irdeto which prevented EMM updates at all
- (introduced in .13), fixed potentional buffer overflows.
-- Fixed Seca to really loop through all available keys (with same key nr).
-- Several compatibility fixes for 64-bit systems.
-
-07.08.2004: Version 0.3.15
-- Unified Seca, Viaccess & Nagra DES implementation.
-- Added CAID parsing to dukat cardclient.
-- Added support for 16-byte Seca keys.
-- Added Seca2 0064 51 nano processing.
-- Attempt to fix cardclient EMM update problem (appearently AES related).
-- Fixed Nagra CPU emu (random generator).
-
-23.07.2004: Version 0.3.14
-- Fixed Seca2 nano processing (Thanks to Sandali for new permutation values).
-- Fixed missing CAT parsing in Viaccess logger.
-- Fixed logger debug output (cardNum vs. CardNum()).
-- Fixed error-case memory leak in Nagra file mapper.
-
-01.07.2004: Version 0.3.13
-- Added Viaccess2 algo. Note that you need 16-byte keys for Viaccess2.
-- Added extended Seca2 nano handling.
-- Added provider based addressing and Irdeto2 support in common cardclient.
-- Added local caching of ECM/EMM messages to reduce cardserver load.
-- Major code restructure to unify system & logger code.
-- Fixed reconnecting to server in newcamd client.
-- Some changes for gcc 3.4.x compatibility.
-
-06.06.2004: Version 0.3.12
-- Added new Seca2 nano handling. Thanks to Nightshad.
-- Added some glue for VDR 1.3.7+ compatibility.
-- Major code rewrite in cardclient. Use CARDCLIENT=1 to activate. Configuration
- of cardclients has changed completely. See README.
-- New network code supporting on demand dialup networking.
-- Added Radegast and Newcamd client.
-- Added minimum processing time to Nagra ECM code (emulates card processing time
- in case timing depends on this). Configurable from the setup menu (0=disabled).
-- Fixed Nagra EMM tester code for DISH and ROM10/11 OTP size.
-- Fixed some possible table overflows in Seca code.
-- Fixed processing of short blocks in Conax code.
-- Fixed FTA switch in case VDR shortly interrupts a recording (e.g. when
- changing PIDs).
-
-07.04.2004: Version 0.3.11a
-- Fixed Seca2 segfault on mask table access.
-- Now flushing ECM filter buffers on error.
-
-02.04.2004: Version 0.3.11
-- Added Seca2 support. Openssl and mask/hash table files needed. See README.
- Seca1 compatiblility not yet tested. Thanks to Nightshad.
-- Added fix for Nagra ROM11 and plain key updates.
-- Using multiple threads to read from PID filters. Prevents that high-latency
- systems (like smartcards) block out other systems.
-- Remember the system name in ca.cache and use this system first later on.
- Prevents delays for low-priority systems if ECM is cached.
-- Fixed smartcard Seca PBM checking for cards which doesn't support the needed
- card command.
-- Fixed network timeout and flushing read buffer in cardserver client.
-- Fixed transponder handling for VDR 1.3.x (frequency vs. transponder).
-
-22.02.2004: Version 0.3.10
-- Added cardserver client (Streamboard client). EMM transfers are disabled at
- the moment. Contributed by S.Laurel.
-- Added support for Conax smartcards. Thanks to Nightshad.
-- Added provider based addressing for EMM updates in Irdeto smartcard.
-- Added commandline option to support card reader with reverse reset line (-R).
-- Added make option to add a smartcard default port (DEFAULT_PORT).
-- Reworked plugin setup menu. Added separate status page. Added smartcard
- information page (press OK on the smartcard interface line).
-- Added code to allow system specific setup options.
-- Fixed off by one error and more mixed up arguments in Seca1 decryption.
-- Fixed typos in Viaccess logger debug statements.
-
-05.02.2004: Version 0.3.9
-- Fixed memory initialisation in Nagra cardemu.
-- Fixed filedescriptor leak in Nagra ROM mapping code.
-- Fixed MECM XOR table if there are less than 64 bytes. Thanks to Vlinders.
-- Fixed off by one error in (unused) smartcard Irdeto camcrypt code.
-- Fixed mixed up function arguments in Seca1 decryption.
-- Fixed Viaccess logger for ViaSat and TPS shared updates. Note that the format
- of the Viaccess.KID file has changed (SA added). Thanks to Nightshad.
-- Changed default make options. Irdeto, Seca & Viaccess systems aren't compiled
- by default anymore. Use IRDETO=1 SECA=1 VIACCESS=1 for old behaviour.
-
-18.01.2004: Version 0.3.8
-- Several improvements to the Nagra code (Cardemu, MECM). Completely new
- layout, no more libnagra. Now you need some Eeprom files and the location for
- the ROM files has changed. See README file.
- Thanks to Nightshad, BB and their friends.
-- Fixed Irdeto smartcard EMM command creation for PW. Also don't overrun the
- card with ECM requests in case of not subscribed/expired channel.
-- Reworked Seca, Viaccess and Irdeto crypto code. No more libmgcam.
-- Added commandline option to detect smartcards in readers with reverse CD.
-- Added a SC patch for vdr 1.3.1 and some glue to the plugin. See README for
- notes about 1.3.1 support.
-
-13.12.2003: Version 0.3.7
-- Several Nagra auto-update fixes. Thanks to Nightshad.
-- Fixed Irdeto smartcard EMM path. Thanks to Scotty.
-- Fixed wrong behaviour in case of transfer mode.
-- Added support to load Nagra ROM extentions (needs ROM?ext.bin files).
-- Now checking PBM and date in Seca smartcard. Fixed card status for EMM
- updates. Thanks to Nightshad.
-- Added a VDR patch to prevent SC activation during EPG scans.
- Contributed by Andy.
-- Changed CICAM handling. SC activation is now more channel base.
- Note: you have to update your config! See README file.
-
-8.11.2003: Version 0.3.6
-- Added support for Irdeto smartcards (e.g. Premiere). Thanks to Scotty.
-- Added smartcard insert/remove detection, card auto-initialisation and support
- for multiple card interfaces.
-- Enhanced smartcard ISO functions (e.g. 0x60 handling, ATR parsing).
-- Fixed smartcard Cryptoworks (V3 ATR, serial timeout).
-- Fixed Nagra ROM10 emu (Cabo 4801).
-- Fixed saving ECM values to ca.cache.
-- Fixed removing of cached ECM entries so that only really failed entries are
- removed.
-
-24.10.2003: Version 0.3.5
-- Fixed Nagra cardemulator (MUL bug, OTP area, etc). Thanks to BB & Nightshad.
-- Added handling for ROM specific Nagra keys. See examples/Softcam.Key.
-- Fixed display of used Nagra key in the OSD.
-
-18.10.2003: Version 0.3.4
-- Added EMM logger in sc-Seca to auto-update card data. Works for Seca2 cards
- too. Thanks to Nightshad.
-- Added cardemulator to execute ROM code for improved Nagra key updates. Thanks
- to BB & Nightshad. Probably there are still some issues with providers which
- require seperate keys for EMM processing. This will be addressed in the next
- release.
-- Now removing old, failed ECM entries from the cache.
-- Fixed possible race condition in Nagra rom locking.
-- Fixed memory leaks in Nagra & Conax code (BIGNUM handling).
-
-18.07.2003: Version 0.3.3
-- Allow new keys to supersede/invalidate older keys (only for systems with
- unique key identifiers; for now all beside Irdeto & @SHL). This should fix
- Viaccess key updates.
-- Made Viaccess loop through all available keys while decrypting.
-
-05.07.2003: Version 0.3.2
-- Added some information about @SHL to the README.
-- Cleaned up @SHL code. Now supporting multiple keys in keyfile, no need to
- uncomment unused keys.
-- New code for hex dumping of incoming data (see common.h for activation).
-- Excluding a range of potentional "fake" ECM pids for Viaccess system. Does
- this affects any valid channel?
-
-24.06.2003: Version 0.3.1unstable
-- Completely new section filter handling.
-- Restructure of the logger code (will allow EMM processing for smartcards).
-- Reworked Viaccess logger. Thanks to BB & Nightshad.
-- Added @SHL (SkyCrypyt) support. Thanks to Nightshad and his friends.
-- Fixed writing duplicate ecm entries into cache file.
-- Fixed SoftCSA activation (was broken in 0.3.0, 0.2.x is fine).
-- Fixed saving Viaccess keys with odd digit count.
-- Fixed leaving a locked mutex in CAM setup.
-- Fixed crash in smartcard setup if no serial device was given.
-- Added examples files to show file formats.
-- Added system specific Makefile's (*.mk).
-- Added french translations.
-
-25.05.2003: Version 0.3.0unstable
-- Forked 0.3.x unstable branch.
-- Major restructure of CA system code.
-- Added Viaccess logger. Requires Viaccess.KID. Thanks to BB for providing
- the sample code.
-- Generalized smartcard code. Use new plugin commandline option -s to set
- serial port. Use setup menu to select card type.
-- Now supporting Seca smartcards. Another big thanks to Nightshad.
-- Reworked Cryptoworks smartcard code. Please report working status.
-
-------------------------------------------------------------
-
-29.05.2003: Version 0.2.2
-- Added patch for vdr 1.1.32/33.
-- Added french translations. Thanks to Piout.
-
-14.05.2003: Version 0.2.1
-- Adapted to the changes in (and now also requires) VDR 1.1.31.
-
-05.05.2003: Version 0.2.0
-- Some code cleanup.
-- Fixed Nagra key saving.
-- Added Greek translations. Thanks to Aroureos.
-- Stable release version. A new development branch will fork soon.
-
-27.04.2003: Version 0.2.0rc1
-- Added patch for vdr 1.1.29
-
-24.04.2003: Version 0.1.13
-- Rescanning CaDescr from time to time in case that we initialy got some
- descriptors but are unable to find a valid key with them.
-- Some more Cryptoworks fixes.
-- Fixed BN bug in Nagra RSA code.
-- Newbie protection: actively checking required VDR version and some patch
- versions.
-- Adapted to the changes in (and now also requires) VDR 1.1.28. Timeshifting of
- encrypted channels works. You must use a patched LL firmware for this feature,
- the -icam firmware won't allow timeshift.
-
-14.04.2003: Version 0.1.12
-- Changed debug messages to avoid confusion between loaded keys and loaded
- cards *sigh*.
-- Now using VDR internal functions to get the ECM pids. This requires VDR 1.1.27
- to work. Note also, that there is a new sc patch for VDR 1.1.27.
-- Make the ECM cache take care of the fact that the SID may not be unique (now
- matching for source & transponder too).
-- Cleanup of Nagra code (now in libnagra). Got rid of the miracle stuff, now
- using libcrypto (openssl) here too. Big thanks to Nightshad.
-- Added (untested) Nagra BEV/DISH support.
-
-21.03.2003: Version 0.1.11
-- Fixed segmentation fault on plugin exit (stupid: static initialization of
- list members is a no-no).
-- Increased timeout for reading PAT.
-- Some fixes to the Cryptoworks code. Hope this works better. No testing here.
-
-03.03.2003: Version 0.1.10
-- Improved "stop logger" with transfer mode. Disabled this feature for budget
- cards. They don't crash with logger enabled.
-- Fixed stopping sc processing if a transfer mode ends.
-- SoftCSA now available as separate archive.
-
-19.03.2003: Version 0.1.9
-- Fixed Nagra MECM handling.
-- Logger is stopped when a transfer mode is detected, too.
-- Experimental SoftCSA support. See README for setup instructions. Thanks to
- emumensch for the initial version.
-
-31.01.2003: Version 0.1.8
-- Fixed Conax decoding and key handling.
-- Fixed Nagra key strings which havn't been NULL terminated.
-- Fixed loading SoftCam.Key with Nagra/Conax keys if one or both have been
- disabled at compile time.
-- Fixed long standing bug in FastKey().
-- Added Nagra logger. No need for a Nagra.KID, the keys should still be in
- SoftCam.Key if you are able to watch Nagra channels. Thanks to Nightshad.
-
-15.01.2003: Version 0.1.7
-- Switched to Conax code from mgcam_20030114 (much shorter). You must have
- installed libcrypto (part of openssl). This fixes the Conax linking problem in
- 0.1.6 too.
-- Nagra & Conax keys are now loaded from SoftCam.Key too. See README for format.
-
-14.01.2003: Version 0.1.6
-- Fixed Viacess code for NTV and TPS crypt (mgcam_20021123).
-- Extended setup option for logger. Logger can be stopped during recordings as
- soon as a valid key is found. Is this more stable?
-- Fixed a compile error in Nagra code (miracl.h).
-- Switched Cryptoworks support to libcwemu. Serial line detection is now in the
- main Makefile, see ISO_TTY. CRYTOWORKS=1 to enable.
-- Added Conax support, based on lincardemu0.1.9n and some adaptions to mgcam
- found on the net. Thanks to all the guys for their work. CONAX=1 to enable.
-- Fixed PMK update in Irdeto logger.
-- Updated card data is also written to ca.cache now. The ca.cache format has
- changed for this. The old format is converted automatically.
-- Changed detection of fake channel id's.
-- Improved filter settings and paket reading.
-
-16.11.2002: Version 0.1.5
-- Adapted to the changes in vdr 1.1.15. Now requires vdr >=1.1.15 and HEAD
- driver.
-- Added Cryptoworks support together with original cards and a cardreader with
- Phoenix ISO interface at the serial line. Add CRYPTOWORKS=1 to enable. (see
- libmgcam/cryptoworks.c for serial line selection).
-- Remove xor/firmware hacks (not needed anymore).
-
-28.10.2002: Version 0.1.4
-- Adapted to the changes up to vdr 1.1.14 and the new HEAD DVB driver.
-- Added option to setup menu to reload config files.
-- Added code to detect fake channel id's on primafila.
-- Minor logger fixes.
-
-28.09.2002: Version 0.1.3
-- Now compiles with vdr 1.1.9+.
-- Cleaned up Viaccess code.
-- Added Seca logger.
-- Fixed switching back to a FTA channel after recording.
-
-09.09.2002: Version 0.1.2
-- Load cardinfos/cacache even if no keyfile found.
-- Fixed rescanning of PAT/PMT if temporarily no enc. system found.
-- Fixed timeout handling while reading from dvb device.
-- Removed usleep() loops from logger code.
-
-29.08.2002: Version 0.1.1
-- Added missing code to save the xor & firmware hack setup.
-
-22.08.2002: Version 0.1.0
-- Initial release.
+++ /dev/null
-#
-# Softcam plugin to VDR
-#
-# This code is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This code is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-# Or, point your browser to http://www.gnu.org/copyleft/gpl.html
-
-# The official name of this plugin.
-# This name will be used in the '-P...' option of VDR to load the plugin.
-# By default the main source file also carries this name.
-#
-PLUGIN = sc
-
-### The version number of this plugin
-
-DISTFILE = .distvers
-HGARCHIVE = .hg_archival.txt
-RELEASE := $(shell grep 'define SC_RELEASE' version.h | awk '{ print $$3 }' | sed -e 's/[";]//g')
-SUBREL := $(shell if test -d .hg; then \
- echo -n "HG-"; (hg identify 2>/dev/null || echo -n "Unknown") | sed -e 's/ .*//'; \
- elif test -r $(HGARCHIVE); then \
- echo -n "AR-"; grep "^node" $(HGARCHIVE) | awk '{ printf "%.12s",$$2 }'; \
- elif test -r $(DISTFILE); then \
- cat $(DISTFILE); \
- else \
- echo -n "Unknown"; \
- fi)
-VERSION := $(RELEASE)-$(SUBREL)
-SCAPIVERS := $(shell sed -ne '/define SCAPIVERS/ s/^.[a-zA-Z ]*\([0-9]*\).*$$/\1/p' $(PLUGIN).c)
-
-### The directory environment:
-
-VDRDIR = ../../..
-LIBDIR = ../../lib
-SYSDIR = ./systems
-PREDIR = ./systems-pre
-TMPDIR = /tmp
-
-### The C++ compiler and options:
-
-CXX ?= g++
-CXXFLAGS ?= -O2 -g -fPIC -Wall -Woverloaded-virtual
-
-### Includes and Defines
-
-INCLUDES = -I$(VDRDIR)/include
-DEFINES = -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
-SHAREDDEFINES = -DAPIVERSNUM=$(APIVERSNUM) -D_GNU_SOURCE
-LIBS = -lcrypto
-SHAREDLIBS =
-
-### Allow user defined options to overwrite defaults:
-
--include $(VDRDIR)/Make.config
--include Make.config
-
-### The version number of VDR (taken from VDR's "config.h"):
-
-VDRVERSION := $(shell sed -ne '/define VDRVERSION/ s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/include/vdr/config.h)
-APIVERSION := $(shell sed -ne '/define APIVERSION/ s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/include/vdr/config.h)
-ifeq ($(strip $(APIVERSION)),)
- APIVERSION = $(VDRVERSION)
-endif
-VDRVERSNUM := $(shell sed -ne '/define VDRVERSNUM/ s/^.[a-zA-Z ]*\([0-9]*\) .*$$/\1/p' $(VDRDIR)/include/vdr/config.h)
-APIVERSNUM := $(shell sed -ne '/define APIVERSNUM/ s/^.[a-zA-Z ]*\([0-9]*\) .*$$/\1/p' $(VDRDIR)/include/vdr/config.h)
-ifeq ($(strip $(APIVERSNUM)),)
- APIVERSNUM = $(VDRVERSNUM)
-endif
-
-### The object files (add further files here):
-
-OBJS = $(PLUGIN).o data.o filter.o system.o misc.o cam.o version.o \
- smartcard.o network.o crypto.o system-common.o parse.o log.o
-
-### Internationalization (I18N):
-
-PODIR = po
-I18Npot = $(PODIR)/$(PLUGIN).pot
-ifeq ($(strip $(APIVERSION)),1.5.7)
- I18Nmo = $(PLUGIN).mo
-else
- I18Nmo = vdr-$(PLUGIN).mo
-endif
-I18Nmsgs = $(addprefix $(LOCALEDIR)/,$(addsuffix /LC_MESSAGES/$(I18Nmo),$(notdir $(foreach file, $(wildcard $(PODIR)/*.po), $(basename $(file))))))
-LOCALEDIR = $(VDRDIR)/locale
-HASLOCALE = $(shell grep -l 'I18N_DEFAULT_LOCALE' $(VDRDIR)/include/vdr/i18n.h)
-
-ifeq ($(strip $(HASLOCALE)),)
- OBJS += i18n.o
-endif
-
-#
-# generic stuff
-#
-
-# smartcard default port
-ifdef DEFAULT_PORT
- TEST := $(shell echo '$(DEFAULT_PORT)' | sed -ne '/".*",.*,.*,.*/p')
- ifneq ($(strip $(TEST)),)
- DEFINES += -DDEFAULT_PORT='$(DEFAULT_PORT)'
- else
- $(error DEFAULT_PORT has bad format)
- endif
-endif
-
-# max number of CAIDs per slot
-MAXCAID := $(shell sed -ne '/define MAXCASYSTEMIDS/ s/^.[a-zA-Z ]*\([0-9]*\).*$$/\1/p' $(VDRDIR)/ci.c)
-ifneq ($(strip $(MAXCAID)),)
- DEFINES += -DVDR_MAXCAID=$(MAXCAID)
-endif
-
-# FFdeCSA
-CPUOPT ?= pentium
-PARALLEL ?= PARALLEL_32_INT
-CSAFLAGS ?= -Wall -fPIC -g -O3 -mmmx -fomit-frame-pointer -fexpensive-optimizations -funroll-loops
-FFDECSADIR = FFdecsa
-FFDECSA = $(FFDECSADIR)/FFdecsa.o
-
-# SASC
-ifdef SASC
-DEFINES += -DSASC
-FFDECSA =
-endif
-
-# export for system makefiles
-export SCAPIVERS
-export APIVERSION
-export INCLUDES
-export SHAREDDEFINES
-export SHAREDLIBS
-export CXX
-export CXXFLAGS
-
-### Targets:
-
-ifdef STATIC
-BUILDTARGETS = $(LIBDIR)/libvdr-$(PLUGIN).a systems
-SHAREDDEFINES += -DSTATICBUILD
-else
-BUILDTARGETS = $(LIBDIR)/libvdr-$(PLUGIN).so.$(APIVERSION) systems systems-pre
-endif
-
-ifneq ($(strip $(HASLOCALE)),)
-BUILDTARGETS += i18n
-endif
-
-all: $(BUILDTARGETS)
-.PHONY: i18n systems systems-pre clean clean-core clean-systems clean-pre dist srcdist
-
-# Dependencies:
-
-MAKEDEP = g++ -MM -MG
-DEPFILE = .dependencies
-DEPFILES = $(subst i18n.c,,$(subst version.c,,$(OBJS:%.o=%.c)))
-$(DEPFILE): $(DEPFILES) $(wildcard *.h)
- @$(MAKEDEP) $(DEFINES) $(SHAREDDEFINES) $(INCLUDES) $(DEPFILES) > $@
-
--include $(DEPFILE)
-
-# Rules
-
-%.o: %.c
- $(CXX) $(CXXFLAGS) -c $(DEFINES) $(SHAREDDEFINES) $(INCLUDES) $<
-
-libvdr-$(PLUGIN).so: $(OBJS) $(FFDECSA)
- $(CXX) $(CXXFLAGS) -shared $(OBJS) $(FFDECSA) $(LIBS) $(SHAREDLIBS) -o $@
-
-$(LIBDIR)/libvdr-$(PLUGIN).so.$(APIVERSION): libvdr-$(PLUGIN).so
- @cp -p $< $@
-
-$(LIBDIR)/libvdr-$(PLUGIN).a: $(OBJS)
- $(AR) r $@ $(OBJS)
-
-$(FFDECSA): $(FFDECSADIR)/*.c $(FFDECSADIR)/*.h
- @$(MAKE) COMPILER="$(CXX)" FLAGS="$(CSAFLAGS) -march=$(CPUOPT) -DPARALLEL_MODE=$(PARALLEL)" -C $(FFDECSADIR) all
-
-$(I18Npot): $(shell grep -rl '\(tr\|trNOOP\)(\".*\")' *.c $(SYSDIR))
- xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --msgid-bugs-address='<noone@nowhere.org>' -o $@ $^
-
-%.po: $(I18Npot)
- msgmerge -U --no-wrap --no-location --backup=none -q $@ $<
- @touch $@
-
-%.mo: %.po
- msgfmt -c -o $@ $<
-
-$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/$(I18Nmo): $(PODIR)/%.mo
- @mkdir -p $(dir $@)
- cp $< $@
-
-i18n: $(I18Nmsgs)
-
-i18n.c: $(PODIR)/*.po i18n-template.c po2i18n.pl
- perl ./po2i18n.pl <i18n-template.c >i18n.c
-
-version.c: FORCE
- @echo >$@.new "/* generated file, do not edit */"; \
- echo >>$@.new 'const char *ScVersion =' '"'$(VERSION)'";'; \
- diff $@.new $@ >$@.diff 2>&1; \
- if test -s $@.diff; then mv -f $@.new $@; fi; \
- rm -f $@.new $@.diff;
-
-systems:
- @for i in `ls -A -I ".*" $(SYSDIR)`; do $(MAKE) -f ../../Makefile.system -C "$(SYSDIR)/$$i" all || exit 1; done
-
-systems-pre:
- @for i in `ls -A -I ".*" $(PREDIR) | grep -- '-$(SCAPIVERS).so.$(APIVERSION)$$'`; do cp -p "$(PREDIR)/$$i" "$(LIBDIR)"; done
-
-clean-systems:
- @for i in `ls -A -I ".*" $(SYSDIR)`; do $(MAKE) -f ../../Makefile.system -C "$(SYSDIR)/$$i" clean; done
-
-clean-core:
- @$(MAKE) -C testing clean
- @if test -d $(FFDECSADIR); then $(MAKE) -C $(FFDECSADIR) clean; fi
- @-rm -f $(LIBDIR)/libsc-*-$(SCAPIVERS).so.$(APIVERSION)
- @-rm -f $(LIBDIR)/libvdr-$(PLUGIN).a $(LIBDIR)/libsc-*.a
- @-rm -f $(OBJS) $(DEPFILE) version.c i18n.c *.so *.tar.gz core* *~
- @-rm -f $(PODIR)/*.mo
-
-clean-pre:
- @-find "$(PREDIR)" -type f -not -name ".empty" -not -iname "*-$(SCAPIVERS).so.*" | xargs rm -f
-
-clean: clean-core clean-systems
-
-dist: ARCHIVE := $(PLUGIN)-$(RELEASE)
-dist: clean-core
- @for i in `ls -A -I ".*" $(SYSDIR)`; do $(MAKE) -f ../../Makefile.system -C "$(SYSDIR)/$$i" dist; done
- @-rm -rf $(TMPDIR)/$(ARCHIVE)
- @mkdir $(TMPDIR)/$(ARCHIVE)
- @cp -a * $(TMPDIR)/$(ARCHIVE)
- @echo -n "release" >$(TMPDIR)/$(ARCHIVE)/$(DISTFILE)
- @path="$(TMPDIR)/$(ARCHIVE)/$(notdir $(SYSDIR))";\
- for i in `ls -A -I ".*" $$path`; do if [ -f "$$path/$$i/nonpublic.mk" ]; then rm -rf "$$path/$$i"; fi; if [ -f "$$path/$$i/nonpublic.sh" ]; then (cd $$path/$$i ; source ./nonpublic.sh ; rm ./nonpublic.sh); fi; done
- @strip --strip-unneeded --preserve-dates $(TMPDIR)/$(ARCHIVE)/$(notdir $(PREDIR))/*
- @tar czf vdr-$(ARCHIVE).tar.gz -C $(TMPDIR) $(ARCHIVE)
- @-rm -rf $(TMPDIR)/$(ARCHIVE)
- @echo Distribution package created as vdr-$(ARCHIVE).tar.gz
-
-copy: ARCHIVE := $(PLUGIN)-$(VERSION)
-copy: clean clean-pre
- @-rm -rf $(TMPDIR)/$(ARCHIVE)
- @mkdir $(TMPDIR)/$(ARCHIVE)
- @cp -a .hgtags .hgignore * $(TMPDIR)/$(ARCHIVE)
- @echo -n $(SUBREL) | sed -e 's/HG-/CP-/' >$(TMPDIR)/$(ARCHIVE)/$(DISTFILE)
- @tar czf vdr-$(ARCHIVE).tar.gz -C $(TMPDIR) $(ARCHIVE)
- @-rm -rf $(TMPDIR)/$(ARCHIVE)
- @echo Full copy package created as vdr-$(ARCHIVE).tar.gz
-
-FORCE:
+++ /dev/null
-#
-# Softcam plugin to VDR
-#
-# This code is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This code is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-# Or, point your browser to http://www.gnu.org/copyleft/gpl.html
-
-### The directory environment:
-
-LIBDIR = ../../../../lib
-PREDIR = ../../systems-pre
-
-### Includes and Defines
-
-SINCLUDES = -I../..
-SINCLUDES += $(shell echo "$(INCLUDES)" | sed -e 's+-I *+-I+g' | sed -e 's+-I\([^/]\)+-I../../\1+g')
-
--include *.mk
-
-# Dependencies:
-
-MAKEDEP = g++ -MM -MG
-DEPFILE = .dependencies
-$(DEPFILE): $(OBJS:%.o=%.c) $(wildcard *.h)
- @$(MAKEDEP) $(DEFINES) $(SHAREDDEFINES) $(SINCLUDES) $(OBJS:%.o=%.c) > $@
-
--include $(DEPFILE)
-
-### Targets:
-
-LIBSC = libsc-$(TARGET).so
-LIBSCVER = libsc-$(TARGET)-$(SCAPIVERS).so.$(APIVERSION)
-LIBSCAR = libsc-$(TARGET).a
-
-ifdef STATIC
-BUILDTARGETS = $(LIBDIR)/$(LIBSCAR)
-else
-BUILDTARGETS = $(LIBDIR)/$(LIBSCVER) $(PREDIR)/$(LIBSCVER)
-endif
-
-define clean
-@-rm -f $(OBJS) $(CLEAN_RM) $(DEPFILE) $(LIBSC) core* *~
-endef
-
-define clean-pre
-@find "$(PREDIR)" -type f -iname "libsc-$(TARGET)-*.so.*" -not -iname "libsc-$(TARGET)-$(SCAPIVERS).so.*" | xargs rm -f
-@-rm -f $(PREDIR)/$(LIBSCVER)
-endef
-
-all: $(BUILDTARGETS)
-.PHONY: clean dist
-
-%.o: %.c
- $(CXX) $(CXXFLAGS) -c $(DEFINES) $(SHAREDDEFINES) $(SINCLUDES) $<
-
-$(LIBSC): $(OBJS)
- $(CXX) $(CXXFLAGS) -shared $(OBJS) $(LIBS) $(SHAREDLIBS) -o $@
- $(clean-pre)
-
-$(LIBDIR)/$(LIBSCVER): $(LIBSC)
- @cp -p $< $@
-
-$(LIBDIR)/$(LIBSCAR): $(OBJS)
- $(AR) r $@ $(OBJS)
-
-ifdef NONPUBLIC
-$(PREDIR)/$(LIBSCVER): $(LIBSC)
- $(clean-pre)
- @cp -p $< $@
-
-dist: $(PREDIR)/$(LIBSCVER)
- $(clean)
-else
-$(PREDIR)/$(LIBSCVER):
-
-dist:
- $(clean-pre)
- $(clean)
-endif
-
-clean:
- $(clean-pre)
- $(clean)
+++ /dev/null
-This is a "plugin" for the Video Disk Recorder (VDR).
-
-See the file COPYING for license information.
-
-Description: SoftCAM for Irdeto, Seca, Viaccess, Nagra, Conax & Cryptoworks
-
------------------------------------------------------------------------
-
-
-
-What is it ?
-------------
-
-First: Most certainly it's not legal to use this software in most countries of
-the world. But probably you already know this...
-
-SC means softcam, which means a software CAM emulation.
-
-The plugin captures the DVB devices in an early startup stage of VDR startup
-(before VDR itself has got access to them) and makes VDR believe that there is
-another CAM connected to the device. This CAM is emulated from the plugin by
-providing a cut-down EN50221 interface for communication with the VDR core. From
-VDR views there is no difference between a real hardware CAM and the emulated
-CAM.
-
-The plugin decrypts the scrambling codewords from the incomming ECM stream. The
-actual descrambling of the video stream is either done by the ECD chip on
-full-featured DVB cards or with the included FFdecsa implementation on budget
-cards.
-
-This piece of software is originaly based on (and still contains code from)
-mgcam (a standalone CAM emulation). Many thanks to the (anonymous) author for
-his really fine piece of software :-)
-
-
-
-Requirements
-------------
-
-* DVB driver from dvb-kernel 2.6 or 2.4 branch with applied patches
-* a patched firmware version 2620 or newer
-* VDR 1.5.0 or newer (VDR 1.4.6+ in compatibility mode, see 1.4.x setup section)
-* Openssl package version 0.9.7 or newer
-
-
-
-How to setup ?
---------------
-
-First you should start with a recent dvb-kernel driver (cvs recomended). Copy
-the patched firmware in place and apply at least the dvb-cwidx patch. Make sure
-that you use a patched firmware if you intend to use the plugin together with a
-full-featured DVB card. You definitely need a patched firmware in this case, but
-only recent versions support concurrent recording! Recompile the driver, unload
-the modules, install the new ones and reload the DVB driver. If you suffer from
-ARM crashes, add "hw_sections=0" while loading the dvb-ttpci module.
-
-Contrary to older plugin versions you MUST NOT apply any patches to the VDR core
-(neither vdr-sc nor ffdecsa/softcsa).
-
-You must have installed the openssl development files. For most distributions
-this means to install openssl-devel package. You should use a openssl package
-with AES and IDEA enabled, as support for openssl without these will be removed
-in the near future.
-
-Now follow the VDR instruction to compile plugins (make plugins). Beside the
-core plugin (libvdr-sc.so), the make process (if successfull) creates an
-additional shared library object for every supported system (libsc-*.so). You
-can enable/disable individual systems by adding or removing the shared library
-from your VDR plugin lib directory.
-
-Starting with version 0.5.8 all make compile time options (e.g. IRDETO=1) except
-DEFAULT_PORT have been removed!
-
-Note that in combination with other plugins which create devices (e.g.
-softdevice) it's essential that this plugin is loaded before any of these
-plugins, i.e. as a rule of thumb put this plugins first on the VDR commandline.
-The plugin will fail on startup if the plugin load order results in mismatched
-device numbering inside VDR.
-
-Note that some budget card drivers provide a CA device too. This might make VDR
-and the plugin detect the card as a full-featured card, thus disabling FFdecsa.
-You should use commandline option -B to force detection as a budget card in such
-a case. This commandline option takes a device number as argument and may appear
-multiple times (compare VDR commandline option -D).
-
-By default the plugin logs his messages to console only. For testing purpose
-it's a good idea to start VDR in foreground so you can see any error messages.
-Other available log targets are file and syslog. You can enable/disable any of
-the log targets in the plugin setup menu. For the file target you have to set a
-destination filename too. If you set a filesize limit (in KByte) and the logfile
-grows bigger than the limit, the current logfile is renamed to logfile.old and a
-new logfile is started. If the filesize limit is zero, the logfile never is
-rotated.
-
-
-
-How to setup for VDR 1.4.x ?
-----------------------------
-
-Additional to the points mentioned above, you have to patch the VDR core with
-the supplied patch (vdr-1.4.x-sc7.diff). Recompile VDR and use the new binary.
-Patches from older SC releases are not going to work.
-
-Even with VDR 1.4.x you don't have to use a softcsa/ffdecsa patch.
-
-Activating/deactivating DVB cards in the plugin setup menu needs a VDR restart
-to take effect.
-
-
-
-Pre-compiled libraries
-----------------------
-
-
-There is the possibility that encryption systems are provided in binary, pre-
-compiled only form. During make process, all pre-compiled libraries are copied
-to your VDR plugin lib directory.
-
-Please be aware, that pre-compiled libraries are more or less bound to the hard-
-& software configuration they have been build on. Currently the build system is
-Intel 32bit, gcc 3.2.2, glibc 2.2.5. If your system differs too much, it may be
-impossible to use the pre-compiled libraries.
-
-Obviously, pre-compiled libraries cannot be exchanged between different SC
-and/or VDR API versions. Be aware that if you patch your VDR core and this patch
-involves changes to header files (*.h) this might change the VDR API even if the
-API version number hasn't changed. This may lead to silent malfunction/failure
-of pre-compiled libraries. In particular you should stay away from thread.h and
-tools.h as classes from there are used at many, many places.
-
-The naming scheme for the libraries is libsc-<MODULE>-<SCAPI>.so.<APIVERSION>,
-e.g. libsc-cardclient-2.so.1.3.47
-
-
-
-CAID and VDR CICAM setup
-------------------------
-
-The activation of the SC is controlled by your CICAM setup. As general setup
-(which is not SC specific) you should leave the CA values (in channels.conf)
-set to zero and let VDR's channel scanner (autopid) fill in the correct values.
-Don't touch the CA values afterwards.
-In the plugin setup menu, you now have to specify for which DVB cards the SC
-should be activated. The first two cards can be setup from the menu. If you
-need more, you can edit the setup.conf file manualy and add up to 10 cards.
-
-A real hardware CAM normaly knows which CAIDs it supports. With SC the situation
-is a bit different. There is support for a wide range of encryption system and
-cardclients. This results in a huge number of supported CAIDs, but for most of
-them it's uncertain if SC will actualy be able to decrypt a channel for them. On
-the other hand VDR limits the number of supported CAIDs to 16 for a CAM slot (64
-CAIDs in VDR 1.5.3 or later), so SC is able to announce a small number of CAIDs
-only. This is not as bad as it sounds, as VDR will try a CAM if ANY of the
-channel CAIDs matches the CAIDs announced by the CAM.
-On startup and at regular intervals the plugin scans the channels list and
-builds a chain of CAIDs. The CAIDs are assigned to the simulated CAM.
-
-To reduce the number of CAIDs SC has to deal with, you should obey some rules:
--Remove all libsc-* files for encryption system which you don't intend to use
- (e.g. SHL seems pretty useless nowadays).
--When using a cardclient, be as precise as possible with the CAID/MASK values in
- the cardclient.conf file. Using wide open 0000/0000 is deprecated.
--Add CAIDs which you cannot use due to lack of keys to the SC.CaIgnore setting.
-
-
-
-
-Concurrent Recordings
----------------------
-
-There is an entries in the plugin setup menu to control concurrent usage of a
-full-featured DVB card. You should enable concurrent usage only if you are using
-the special patched firmware AND a patched DVB driver. Note that toggling the
-flag will take effect the next time the plugin is idle on that specific DVB card
-only (i.e. no channel is being decrypted).
-
-There is no possibility to limit the number of concurrent streams. VDR itself
-has no limit in concurrent streams (neither FTA nor encrypted) and as the VDR
-core control all aspects of operation, there is no way to enforce a limit
-(beside disabling concurrent encrypted streams at all).
-
-
-
-Additional files
-----------------
-
-All config files are expected to be located in the subdirectory "sc" of VDRs
-plugin config directory. The user executing VDR should have write permissions
-for this directory, as the plugin will create cache files there.
-
-The keyfile must be named "SoftCam.Key". Any updated keys are saved back to this
-file. At this the structure of the file (e.g. comments) is preserved as far as
-possible. Updated key are inserted near to the old one (there is a setup option
-to selected if the old key is commented out or deleted), while new keys are
-inserted close to the top of the file.
-
-For Irdeto, Seca and Viaccess AU you need valid subscription card data, which
-have to be located in the files "Ird-Beta.KID", "Seca.KID" or "Viaccess.KID".
-See the files in the "examples" subdirectory for file formats.
-
-Note, that for this @SHL implementation the key must be in Z 00 00 <key> format
-(the V 000000 00 <key> format doesn't work).
-
-For Seca2 support you need binary files which contain the hash & mask tables.
-The file format is the same as for Yankse. The files must be located in the
-"seca" subdirectory. The name sheme is s2_TTTT_XXXX.bin where TTTT is
-one of "hash","mt" and XXXX is the provider ID (e.g. s2_hash_0064.bin,
-s2_mt_0070.bin). The hash file must be 1536 bytes long. The mt file is normaly
-16384 bytes long, but this may differ for your provider. For advanced Seca2
-providers you may need additional table files. At the moment these are
-s2_sse.bin, s2_sse_XXXX.bin and s2_cw_XXXX.bin.
-
-For Nagra1 AU you need appropriate binary Rom and Eeprom files. The files have
-to be named "ROMX.bin", "ROMXext.bin" or "eepX_Z.bin", where X is the ROM number
-(decimal) and Z is the upper part of the provider ID (hexadecimal). The Eeprom
-files may be updated from the EMM data, take care that the permissions are set
-right. The plugin searches for these files in the "nagra" subdirectory.
-
-For Nagra2 AU some providers need binary Rom and Eeprom files. The files have to
-be named "ROMxxx.bin" and "EEPyy_xxx.bin", where xxx is the ROM version (e.g.
-102) and yy is the upper part of the provider ID (e.g. 09 for BEV). The files
-must contain the joined contents of all Rom/Eeprom pages. The plugin searches
-for these files in the "nagra" subdirectory.
-
-
-
-External key updates
---------------------
-
-If key updates are available from external sources (e.g. website) only, they may
-be feed from a shell script. To enable this, you have to specify the script name
-with commandline option "-E". The script will be called at a regular interval
-(currently 15 minutes) or whenever a needed key is not available (but not more
-often than every 2 minutes). The script has to output the keys to it's stdout in
-the same format as for the key file. The script may output several keys in one
-call (each key on a seperate line). You can find an example script in the
-"examples" subdirectory.
-
-
-
-Smartcard support
------------------
-
-For most encrpytion systems this plugin supports original subscription
-smartcards on a Phoenix/Smartmouse ISO interface connected to a serial port.
-
-To enable smartcard support you have to copy one or more of the smartcard
-systems to the VDR plugin lib directory. To actually activate the smartcard
-interface, you should use the commandline option "-s" to specify one or more
-serial devices to which the Phoenix interface are connected e.g. use "-s
-/dev/ttyS0 -s /dev/ttyS1" to use two intefaces at COM1/COM2. If you want to add
-a default smartcard interface at compile time use the make option DEFAULT_PORT,
-e.g. DEFAULT_PORT='"/dev/ttyS0","phoenix",0,0,0'. Note the quotes and double quotes. The
-three numeric values are identical to the -I and -R options (set to 1 to enable)
-and -C option (set to 0 for default clock) below.
-
-Appearently there are "broken" card readers which swap the meaning of the CD
-line (used for card detection). For these readers use the option "-I". This
-enables inverse CD detection for the next interface e.g. "-I -s /dev/ttyS0 -s
-/dev/ttyS1" will use inverse CD on COM1 and normal CD on COM2 while "-I -s
-/dev/ttyS0 -I -s /dev/ttyS1" will use inverse CD on both.
-Some other card readers have a reversed logic with the reset line (card won't
-reset with default settings). You can use the option "-R" for these readers.
-In some cases it's mandatory to know the exact clock frequency at which your
-cardreader runs (e.g. for baudrate calculations). With the option "-C" you can
-give a clock frequency (in Hz) which will be used instead of the default
-(3571200 Hz) for the next interface e.g. "-C 3579545 -s /dev/ttyS1".
-
-Some smartcards need additional information to establish communication with the
-card (e.g. certificate or box key for camcrypt). These information must be
-available in the "smartcard.conf" file (see example file for format) or you card
-won't work correctly.
-
-If you insert a card into a interface the card is autodetected (your interface
-should use the CD line to signal card presence or it won't work) and
-initialised (this may take some seconds to complete). You can use the setup
-menu to see which cards are currently inserted and detected. You can remove a
-smartcard at any time without prior action, but of course this will disrupt
-decryption if you are tuned to a channel which requires the card.
-
-Note that a normal Phoenix interface may not be sufficient for communication
-with some smartcards. This is due to timing issues. The Smargo SmartReader+
-interface has a special "SmartReader+" mode, where the interface itself
-handles communication with the smartcard (i.e. independent of host serial
-configuration). The "SmartReader+" mode is supported via the option "-m",
-e.g. "-m smartreader -s /dev/ttyUSB0". For compile time configuration use e.g.
-make DEFAULT_PORT='"/dev/ttyUSB0","smartreader",0,0,0'.
-
-In "SmartReader+" mode the cardreader clock frequency is automatically
-configured according to ISO 7816-3. It is still possible to override the
-clock frequency via the option "-C" for overclocking, however don't do this
-unless you know exactly what you're doing - you may possibly fry your
-smartcard!
-
-
-Cardserver client
------------------
-
-The cardclient is a client for several cardservers. Supported cardservers are :
-radegast, newcamd, camd33 (tcp), camd35 (udp), cardd, buffy and aroureos.
-
-You can configure as many clients for different servers as you want. The client
-configuration is read from the file "cardclient.conf". Every line in the file
-defines a client-server connection. The line starts with the client name and is
-followed by additional arguments which depend on the client type. See the file
-"examples/cardclient.conf.example" for format and arguments.
-
-The connections are tried in the order they are defined in the conf file until
-a valid decryption is obtained. After that, the decryption sticks to that
-particular connection until next channel switch.
-
-The network code supports dialup on demand. To use this you have to provide an
-external script to connect/disconnect your dialup link. Use commandline option
--d to set the script name and enable the feature, e.g. "-d dialup.sh". See the
-example script "examples/dialup.sh.example". The network is brought up as soon
-as an server connection is requested. All server connections are disconnected if
-they are idle too long (normaly after 120 seconds). The network is brought down
-after the last connection has terminated and an additional network timeout has
-expired. The network timeout is configurable with the commandline option -t and
-defaults to 60 seconds, e.g. "-t 120".
-
-The current cardclient implementation is loosely based on the Streamboard
-client (contributed by S.Laurel from the Streamboard), which was included in
-earlier releases.
-
-
-
-Summary of commandline options
-------------------------------
-
--B N --budget=N forces DVB device N to budget mode (using FFdecsa)
--I --inverse-cd use inverse CD detection for the next serial device
--R --inverse-rst use inverse RESET for the next serial device
--C FREQ --clock=FREQ use FREQ as clock for the card reader on the next
- serial device (rather than 3.5712 MHz
--s DEV --serial=DEV activate Phoenix ISO interface on serial device DEV
- (default: none)
--d CMD --dialup=CMD call CMD to start/stop dialup-network
- (default: none)
--t SECS --timeout=SECS shutdown timeout for dialup-network
- (default: 60 secs)
-
-
-
-SVDR interface
---------------
-
-The plugin implements a SVDR interface. Supported commands are:
- RELOAD
- Reload all configuration files (only if the softcam isn't active at the
- moment).
- Return codes: 550 - Softcam active, can't reload files.
- 901 - Reloading files not entirely successfull. Most of the
- time this will leave you with an unusable softcam.
- 900 - Reload successfull.
-
- KEY string
- Parse the given string and add the key to the key database (as if it was
- received from EMM stream).
- Return codes: 501 - Syntax error.
- 900 - Key added.
- 901 - Invalid key format or key already known.
-
- LOG <on|off> module.option[,module.option][,...]
- Enables or disables all given message classes.
- Return codes: 501 - Syntax error or unknown message class.
- 900 - Options set and saved.
-
- LOGCFG
- Display all available message classes and report their status. This can be
- usefull if you want to provide an external GUI or whatever to handle the
- message classes.
- Return codes: 901 - No message classes available.
- 900 - Message class status (multi line reply).
-
- LOGFILE <on|off> [filename]
- Enables or disables logging to file and optionaly sets the filename.",
- Return codes: 501 - Syntax error.
- 900 - Logfile option set and saved.
+++ /dev/null
-
- po2i18n - Converter for po files
-
-
-Written by: Udo Richter <udo_richter@gmx.de>
-Project's homepage: http://www.udo-richter.de/vdr/scripts.html#po2i18n
- http://www.udo-richter.de/vdr/scripts.en.html#po2i18n
-
-
-
-About
---------------------------------------------------------------------------
-po2i18n is a perl script that generates an i18n.c file compatible to the i18n
-system of VDR 1.2.0 - VDR 1.5.6, based on the .po files of VDR 1.5.7. This
-allows plugins to transit to the translation system of VDR 1.5.7 while
-maintaining compatibility to earlier versions. The script can be used manually
-or automatically as part of the Makefile.
-
-
-Use
---------------------------------------------------------------------------
-po2i18n.pl is a filter and can be used manually like this:
-
- ./po2i18n.pl < i18n-template.c > i18n.c
-
-The filter reads all relevant ./po/*.po files and writes the i18n strings
-into the template file. Strings will be added between the following two lines:
-
- // START I18N
- // END I18N
-
-See also the sample i18n.h and i18n-template.c file. Note that the phrases data
-structure is encapsulated in #if VDRVERSNUM < 10507, so the i18n strings won't
-be in the plugin file after 1.5.7. The call to RegisterI18n() of your plugin
-should also be encapsulated like this.
-
-po2i18n can also generate the i18n.c file on the fly while compiling. The
-changes to the Makefile are demonstrated by the included Makefile.diff sample.
-With these changes, the i18n.c file will be generated on VDR up to 1.5.6, and
-the whole gettext conversion is skipped. From 1.5.7 on, the i18n-template.c
-file will be simply copied as a dummy, and the new locale system will run.
-
-As a drawback, the automatic .dependencies for i18n.c won't work.
-
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <dlfcn.h>
-
-#include <linux/dvb/ca.h>
-#include <vdr/channels.h>
-#include <vdr/ci.h>
-#include <vdr/dvbdevice.h>
-#ifndef SASC
-#if APIVERSNUM >= 10500
-#include <vdr/dvbci.h>
-#endif
-#include <vdr/thread.h>
-
-#include "FFdecsa/FFdecsa.h"
-#endif //SASC
-
-#include "cam.h"
-#include "scsetup.h"
-#include "filter.h"
-#include "system.h"
-#include "data.h"
-#include "misc.h"
-#include "log-core.h"
-
-#define IDLE_SLEEP 0 // idleTime when sleeping
-#define IDLE_GETCA 200 // idleTime when waiting for ca descriptors
-#define IDLE_GETCA_SLOW 20000 // idleTime if no enc. system
-#define IDLE_NO_SYNC 800 // idleTime when not in sync
-#define IDLE_SYNC 2000 // idleTime when in sync
-
-#define CW_REPEAT_TIME 2000 // rewrite CW after X ms
-#define LOG_COUNT 3 // stop logging after X complete ECM cycles
-#define CHAIN_HOLD 120000 // min. time to hold a logger chain
-#define ECM_DATA_TIME 6000 // time to wait for ECM data updates
-#define ECM_UPD_TIME 120000 // delay between ECM data updates
-#define MAX_ECM_IDLE 300000 // delay before an idle handler can be removed
-#define MAX_ECM_HOLD 15000 // delay before an idle handler stops processing
-#define CAID_TIME 300000 // time between caid scans
-
-#define ECMCACHE_FILE "ecm.cache"
-
-#define L_HEX 2
-#define L_HEX_ECM LCLASS(L_HEX,2)
-#define L_HEX_EMM LCLASS(L_HEX,4)
-#define L_HEX_CAT LCLASS(L_HEX,8)
-#define L_HEX_PMT LCLASS(L_HEX,16)
-#define L_HEX_HOOK LCLASS(L_HEX,32)
-#define L_HEX_ALL LALL(L_HEX_HOOK)
-
-static const struct LogModule lm_hex = {
- (LMOD_ENABLE|L_HEX_ALL)&LOPT_MASK,
- (LMOD_ENABLE)&LOPT_MASK,
- "hexdata",
- { "ecm","emm","cat","pmt","hook" }
- };
-ADD_MODULE(L_HEX,lm_hex)
-
-static const char *typeNames[] = { "typ0","typ1","VIDEO","typ3","AUDIO","typ5","DOLBY","typ6+" };
-#define TYPENAME(type) (typeNames[(type)<=7?(type):7])
-
-// -- cLogStats ---------------------------------------------------------------
-
-#define COUNTS 20
-#define SAMPLE (30*1000)
-#define AVR1 (60*1000)
-#define AVR2 (4*60*1000)
-#define AVR3 (10*60*1000)
-#define REPORT (60*1000)
-
-class cLogStats : public cThread {
-private:
- cTimeMs sTime, repTime;
- int sCount, sIdx, sCounts[COUNTS][2];
-protected:
- virtual void Action(void);
-public:
- cLogStats(void);
- ~cLogStats();
- void Count(void);
- };
-
-static cMutex logstatsMutex;
-static cLogStats *logstats=0;
-
-void LogStatsUp(void)
-{
- logstatsMutex.Lock();
- if(LOG(L_CORE_AUSTATS) && !logstats) logstats=new cLogStats;
- logstatsMutex.Unlock();
-}
-
-void LogStatsDown(void)
-{
- logstatsMutex.Lock();
- if(logstats) { delete logstats; logstats=0; }
- logstatsMutex.Unlock();
-}
-
-cLogStats::cLogStats(void)
-{
- sCount=sIdx=0;
- for(int i=0; i<COUNTS; i++) { sCounts[i][0]=0; sCounts[i][1]=SAMPLE; }
- SetDescription("logger stats");
- Start();
-}
-
-cLogStats::~cLogStats()
-{
- Cancel(2);
-}
-
-void cLogStats::Count(void)
-{
- sCount++;
-}
-
-void cLogStats::Action(void)
-{
- while(Running()) {
- cCondWait::SleepMs(50);
- if(sTime.Elapsed()>SAMPLE) {
- sCounts[sIdx][0]=sCount; sCount=0;
- sCounts[sIdx][1]=sTime.Elapsed(); sTime.Set();
- if(++sIdx >= COUNTS) sIdx=0;
- }
- if(repTime.Elapsed()>REPORT) {
- repTime.Set();
- if(sCounts[(sIdx+COUNTS-1)%COUNTS][0]>0) {
- LBSTART(L_CORE_AUSTATS);
- LBPUT("EMM packet load average (%d/%d/%dmin)",AVR1/60000,AVR2/60000,AVR3/60000);
- int s=0, t=0;
- for(int i=1; i<=COUNTS; i++) {
- s+=sCounts[(sIdx+COUNTS-i)%COUNTS][0];
- t+=sCounts[(sIdx+COUNTS-i)%COUNTS][1];
- if(i==(AVR1/SAMPLE) || i==(AVR2/SAMPLE) || i==(AVR3/SAMPLE))
- LBPUT(" %4d",(int)((float)s/(float)t*1000.0));
- }
- LBPUT(" pks/s");
- LBEND();
- }
- }
- }
-}
-
-// -- cHookManager -------------------------------------------------------------
-
-class cHookManager : public cAction {
- int cardNum;
- cSimpleList<cLogHook> hooks;
- //
- cPidFilter *AddFilter(int Pid, int Section, int Mask, int Mode, int IdleTime, bool Crc);
- void ClearHooks(void);
- void DelHook(cLogHook *hook);
-protected:
- virtual void Process(cPidFilter *filter, unsigned char *data, int len);
-public:
- cHookManager(int CardNum);
- virtual ~cHookManager();
- void AddHook(cLogHook *hook);
- bool TriggerHook(int id);
- void Down(void);
- };
-
-cHookManager::cHookManager(int CardNum)
-:cAction("hookmanager",CardNum)
-{
- cardNum=CardNum;
- Priority(10);
-}
-
-cHookManager::~cHookManager()
-{
- Down();
-}
-
-void cHookManager::Down(void)
-{
- Lock();
- while(cLogHook *hook=hooks.First()) DelHook(hook);
- DelAllFilter();
- Unlock();
-}
-
-bool cHookManager::TriggerHook(int id)
-{
- Lock();
- for(cLogHook *hook=hooks.First(); hook; hook=hooks.Next(hook))
- if(hook->id==id) {
- hook->delay.Set(CHAIN_HOLD);
- Unlock();
- return true;
- }
- Unlock();
- return false;
-}
-
-void cHookManager::AddHook(cLogHook *hook)
-{
- Lock();
- PRINTF(L_CORE_HOOK,"%d: starting hook '%s' (%04x)",cardNum,hook->name,hook->id);
- hook->delay.Set(CHAIN_HOLD);
- hook->cardNum=cardNum;
- hooks.Add(hook);
- for(cPid *pid=hook->pids.First(); pid; pid=hook->pids.Next(pid)) {
- cPidFilter *filter=AddFilter(pid->pid,pid->sct,pid->mask,pid->mode,CHAIN_HOLD/8,false);
- if(filter) {
- filter->userData=(void *)hook;
- pid->filter=filter;
- }
- }
- Unlock();
-}
-
-void cHookManager::DelHook(cLogHook *hook)
-{
- PRINTF(L_CORE_HOOK,"%d: stopping hook '%s' (%04x)",cardNum,hook->name,hook->id);
- for(cPid *pid=hook->pids.First(); pid; pid=hook->pids.Next(pid)) {
- cPidFilter *filter=pid->filter;
- if(filter) {
- DelFilter(filter);
- pid->filter=0;
- }
- }
- hooks.Del(hook);
-}
-
-cPidFilter *cHookManager::AddFilter(int Pid, int Section, int Mask, int Mode, int IdleTime, bool Crc)
-{
- cPidFilter *filter=NewFilter(IdleTime);
- if(filter) {
- filter->SetBuffSize(32768);
- filter->Start(Pid,Section,Mask,Mode,Crc);
- PRINTF(L_CORE_HOOK,"%d: added filter pid=0x%.4x sct=0x%.2x/0x%.2x/0x%.2x idle=%d crc=%d",cardNum,Pid,Section,Mask,Mode,IdleTime,Crc);
- }
- else PRINTF(L_GEN_ERROR,"no free slot or filter failed to open for hookmanager %d",cardNum);
- return filter;
-}
-
-void cHookManager::Process(cPidFilter *filter, unsigned char *data, int len)
-{
- if(data && len>0) {
- HEXDUMP(L_HEX_HOOK,data,len,"HOOK pid 0x%04x",filter->Pid());
- if(SCT_LEN(data)==len) {
- cLogHook *hook=(cLogHook *)(filter->userData);
- if(hook) {
- hook->Process(filter->Pid(),data);
- if(hook->bailOut || hook->delay.TimedOut()) DelHook(hook);
- }
- }
- else PRINTF(L_CORE_HOOK,"%d: incomplete section %d != %d",cardNum,len,SCT_LEN(data));
- }
- else {
- cLogHook *hook=(cLogHook *)(filter->userData);
- if(hook && (hook->bailOut || hook->delay.TimedOut())) DelHook(hook);
- }
-}
-
-// -- cLogChain ----------------------------------------------------------------
-
-class cLogChain : public cSimpleItem {
-public:
- int cardNum, caid;
- bool softCSA, active, delayed;
- cTimeMs delay;
- cPids pids;
- cSimpleList<cSystem> systems;
- //
- cLogChain(int CardNum, bool soft);
- void Process(int pid, unsigned char *data);
- bool Parse(const unsigned char *cat);
- };
-
-cLogChain::cLogChain(int CardNum, bool soft)
-{
- cardNum=CardNum; softCSA=soft; active=delayed=false;
-}
-
-void cLogChain::Process(int pid, unsigned char *data)
-{
- if(active) {
- for(cSystem *sys=systems.First(); sys; sys=systems.Next(sys))
- sys->ProcessEMM(pid,caid,data);
- }
-}
-
-bool cLogChain::Parse(const unsigned char *cat)
-{
- if(cat[0]==0x09) {
- caid=WORD(cat,2,0xFFFF);
- LBSTARTF(L_CORE_AU);
- LBPUT("%d: chain caid %04x",cardNum,caid);
- cSystem *sys;
- if(systems.Count()>0) {
- LBPUT(" ++");
- for(sys=systems.First(); sys; sys=systems.Next(sys))
- sys->ParseCAT(&pids,cat);
- }
- else {
- LBPUT(" ->");
- int Pri=0;
- while((sys=cSystems::FindBySysId(caid,!softCSA,Pri))) {
- Pri=sys->Pri();
- if(sys->HasLogger()) {
- sys->CardNum(cardNum);
- sys->ParseCAT(&pids,cat);
- systems.Add(sys);
- LBPUT(" %s(%d)",sys->Name(),sys->Pri());
- }
- else
- delete sys;
- }
- }
- if(systems.Count()==0) LBPUT(" none available");
- for(cPid *pid=pids.First(); pid; pid=pids.Next(pid))
- LBPUT(" [%04x-%02x/%02x/%02x]",pid->pid,pid->sct,pid->mask,pid->mode);
- LBEND();
- if(systems.Count()>0 && pids.Count()>0)
- return true;
- }
- return false;
-}
-
-// -- cLogger ------------------------------------------------------------------
-
-class cLogger : public cAction {
-private:
- int cardNum;
- bool softCSA, up;
- cSimpleList<cLogChain> chains;
- cSimpleList<cEcmInfo> active;
- //
- cPidFilter *catfilt;
- int catVers;
- //
- enum ePreMode { pmNone, pmStart, pmWait, pmActive, pmStop };
- ePreMode prescan;
- cTimeMs pretime;
- //
- cPidFilter *AddFilter(int Pid, int Section, int Mask, int Mode, int IdleTime, bool Crc);
- void SetChains(void);
- void ClearChains(void);
- void StartChain(cLogChain *chain);
- void StopChain(cLogChain *chain, bool force);
-protected:
- virtual void Process(cPidFilter *filter, unsigned char *data, int len);
-public:
- cLogger(int CardNum, bool soft);
- virtual ~cLogger();
- void EcmStatus(const cEcmInfo *ecm, bool on);
- void Up(void);
- void Down(void);
- void PreScan(void);
- };
-
-cLogger::cLogger(int CardNum, bool soft)
-:cAction("logger",CardNum)
-{
- cardNum=CardNum; softCSA=soft;
- catfilt=0; up=false; prescan=pmNone;
- Priority(10);
-}
-
-cLogger::~cLogger()
-{
- Down();
-}
-
-void cLogger::Up(void)
-{
- Lock();
- if(!up) {
- PRINTF(L_CORE_AUEXTRA,"%d: UP",cardNum);
- catVers=-1;
- catfilt=AddFilter(1,0x01,0xFF,0,0,true);
- up=true;
- }
- Unlock();
-}
-
-void cLogger::Down(void)
-{
- Lock();
- if(up) {
- PRINTF(L_CORE_AUEXTRA,"%d: DOWN",cardNum);
- ClearChains();
- DelAllFilter();
- catfilt=0; up=false; prescan=pmNone;
- }
- Unlock();
-}
-
-void cLogger::PreScan(void)
-{
- Lock();
- prescan=pmStart; Up();
- Unlock();
-}
-
-void cLogger::EcmStatus(const cEcmInfo *ecm, bool on)
-{
- Lock();
- PRINTF(L_CORE_AUEXTRA,"%d: ecm prgid=%d caid=%04x prov=%.4x %s",cardNum,ecm->prgId,ecm->caId,ecm->provId,on ? "active":"inactive");
- cEcmInfo *e;
- if(on) {
- e=new cEcmInfo(ecm);
- active.Add(e);
- if(!up) Up();
- }
- else {
- for(e=active.First(); e; e=active.Next(e))
- if(e->Compare(ecm)) {
- active.Del(e);
- break;
- }
- }
- if(prescan>=pmWait) prescan=pmStop;
- SetChains();
- prescan=pmNone;
- Unlock();
-}
-
-void cLogger::SetChains(void)
-{
- for(cLogChain *chain=chains.First(); chain; chain=chains.Next(chain)) {
- bool act=false;
- if(ScSetup.AutoUpdate>1 || prescan==pmActive) act=true;
- else if(ScSetup.AutoUpdate==1) {
- for(cEcmInfo *e=active.First(); e; e=active.Next(e))
- if((e->emmCaId && chain->caid==e->emmCaId) || chain->caid==e->caId) {
- act=true; break;
- }
- }
- if(act) StartChain(chain);
- else StopChain(chain,prescan==pmStop);
- }
-}
-
-void cLogger::ClearChains(void)
-{
- for(cLogChain *chain=chains.First(); chain; chain=chains.Next(chain))
- StopChain(chain,true);
- chains.Clear();
-}
-
-void cLogger::StartChain(cLogChain *chain)
-{
- if(chain->delayed)
- PRINTF(L_CORE_AUEXTRA,"%d: restarting delayed chain %04x",cardNum,chain->caid);
- chain->delayed=false;
- if(!chain->active) {
- PRINTF(L_CORE_AU,"%d: starting chain %04x",cardNum,chain->caid);
- chain->active=true;
- for(cPid *pid=chain->pids.First(); pid; pid=chain->pids.Next(pid)) {
- cPidFilter *filter=AddFilter(pid->pid,pid->sct,pid->mask,pid->mode,CHAIN_HOLD/8,false);
- if(filter) {
- filter->userData=(void *)chain;
- pid->filter=filter;
- }
- }
- }
-}
-
-void cLogger::StopChain(cLogChain *chain, bool force)
-{
- if(chain->active) {
- if(force || (chain->delayed && chain->delay.TimedOut())) {
- PRINTF(L_CORE_AU,"%d: stopping chain %04x",cardNum,chain->caid);
- chain->active=false;
- for(cPid *pid=chain->pids.First(); pid; pid=chain->pids.Next(pid)) {
- cPidFilter *filter=pid->filter;
- if(filter) {
- DelFilter(filter);
- pid->filter=0;
- }
- }
- }
- else if(!chain->delayed) {
- PRINTF(L_CORE_AUEXTRA,"%d: delaying chain %04x",cardNum,chain->caid);
- chain->delayed=true;
- chain->delay.Set(CHAIN_HOLD);
- }
- }
-}
-
-cPidFilter *cLogger::AddFilter(int Pid, int Section, int Mask, int Mode, int IdleTime, bool Crc)
-{
- cPidFilter *filter=NewFilter(IdleTime);
- if(filter) {
- if(Pid>1) filter->SetBuffSize(32768);
- filter->Start(Pid,Section,Mask,Mode,Crc);
- PRINTF(L_CORE_AUEXTRA,"%d: added filter pid=0x%.4x sct=0x%.2x/0x%.2x/0x%.2x idle=%d crc=%d",cardNum,Pid,Section,Mask,Mode,IdleTime,Crc);
- }
- else PRINTF(L_GEN_ERROR,"no free slot or filter failed to open for logger %d",cardNum);
- return filter;
-}
-
-void cLogger::Process(cPidFilter *filter, unsigned char *data, int len)
-{
- if(data && len>0) {
- if(filter==catfilt) {
- int vers=(data[5]&0x3E)>>1;
- if(data[0]==0x01 && vers!=catVers) {
- PRINTF(L_CORE_AUEXTRA,"%d: got CAT version %02x",cardNum,vers);
- catVers=vers;
- HEXDUMP(L_HEX_CAT,data,len,"CAT vers %02x",catVers);
- ClearChains();
- for(int i=8; i<len-4; i+=data[i+1]+2) {
- if(data[i]==0x09) {
- int caid=WORD(data,i+2,0xFFFF);
- cLogChain *chain;
- for(chain=chains.First(); chain; chain=chains.Next(chain))
- if(chain->caid==caid) break;
- if(chain)
- chain->Parse(&data[i]);
- else {
- chain=new cLogChain(cardNum,softCSA);
- if(chain->Parse(&data[i]))
- chains.Add(chain);
- else
- delete chain;
- }
- }
- }
- SetChains();
- if(prescan==pmStart) { prescan=pmWait; pretime.Set(2000); }
- }
- if(prescan==pmWait && pretime.TimedOut()) { prescan=pmActive; SetChains(); }
- }
- else {
- HEXDUMP(L_HEX_EMM,data,len,"EMM pid 0x%04x",filter->Pid());
- if(logstats) logstats->Count();
- if(SCT_LEN(data)==len) {
- cLogChain *chain=(cLogChain *)(filter->userData);
- if(chain) {
- chain->Process(filter->Pid(),data);
- if(chain->delayed) StopChain(chain,false);
- }
- }
- else PRINTF(L_CORE_AU,"%d: incomplete section %d != %d",cardNum,len,SCT_LEN(data));
- }
- }
- else {
- cLogChain *chain=(cLogChain *)(filter->userData);
- if(chain && chain->delayed) StopChain(chain,false);
- }
-}
-
-// -- cEcmData -----------------------------------------------------------------
-
-class cEcmData : public cEcmInfo {
-public:
- cEcmData(void):cEcmInfo() {}
- cEcmData(cEcmInfo *e):cEcmInfo(e) {}
- virtual cString ToString(bool hide);
- bool Parse(const char *buf);
- };
-
-bool cEcmData::Parse(const char *buf)
-{
- char Name[64];
- int nu=0, num;
- Name[0]=0;
- if(sscanf(buf,"%d:%x:%x:%63[^:]:%x/%x:%x:%x/%x:%d%n",&prgId,&source,&transponder,Name,&caId,&emmCaId,&provId,&ecm_pid,&ecm_table,&nu,&num)>=9) {
- SetName(Name);
- const char *line=buf+num;
- if(nu>0 && *line++==':') {
- unsigned char *dat=AUTOMEM(nu);
- if(GetHex(line,dat,nu,true)==nu) AddData(dat,nu);
- }
- return true;
- }
- return false;
-}
-
-cString cEcmData::ToString(bool hide)
-{
- char *str;
- if(data) {
- str=AUTOARRAY(char,dataLen*2+2);
- sprintf(str,":%d:%s",dataLen,HexStr(str,data,dataLen));
- }
- else {
- str=AUTOARRAY(char,4);
- strcpy(str,":0");
- }
- return cString::sprintf("%d:%x:%x:%s:%x/%x:%x:%x/%x%s",
- prgId,source,transponder,name,
- caId,emmCaId,provId,ecm_pid,ecm_table,
- str);
-}
-
-// -- cEcmCache ----------------------------------------------------------------
-
-cEcmCache ecmcache;
-
-cEcmCache::cEcmCache(void)
-:cStructListPlain<cEcmData>("ecm cache",ECMCACHE_FILE,SL_READWRITE|SL_MISSINGOK)
-{}
-
-void cEcmCache::New(cEcmInfo *e)
-{
- ListLock(true);
- cEcmData *dat;
- if(!(dat=Exists(e))) {
- dat=new cEcmData(e);
- Add(dat);
- Modified();
- PRINTF(L_CORE_ECM,"cache add prgId=%d source=%x transponder=%x ecm=%x/%x",e->prgId,e->source,e->transponder,e->ecm_pid,e->ecm_table);
- }
- else {
- if(strcasecmp(e->name,dat->name)) {
- dat->SetName(e->name);
- Modified();
- }
- if(dat->Update(e))
- Modified();
- }
- ListUnlock();
- e->SetCached();
-}
-
-cEcmData *cEcmCache::Exists(cEcmInfo *e)
-{
- cEcmData *dat;
- for(dat=First(); dat; dat=Next(dat))
- if(dat->Compare(e)) break;
- return dat;
-}
-
-int cEcmCache::GetCached(cSimpleList<cEcmInfo> *list, int sid, int Source, int Transponder)
-{
- int n=0;
- list->Clear();
- ListLock(false);
- for(cEcmData *dat=First(); dat; dat=Next(dat)) {
- if(dat->prgId==sid && dat->source==Source && dat->transponder==Transponder) {
- cEcmInfo *e=new cEcmInfo(dat);
- if(e) {
- PRINTF(L_CORE_ECM,"from cache: system %s (%04x) id %04x with ecm %x/%x",e->name,e->caId,e->provId,e->ecm_pid,e->ecm_table);
- e->SetCached();
- list->Add(e);
- n++;
- }
- }
- }
- ListUnlock();
- return n;
-}
-
-void cEcmCache::Delete(cEcmInfo *e)
-{
- ListLock(false);
- cEcmData *dat=Exists(e);
- ListUnlock();
- if(dat) {
- DelItem(dat);
- PRINTF(L_CORE_ECM,"invalidated cached prgId=%d source=%x transponder=%x ecm=%x/%x",dat->prgId,dat->source,dat->transponder,dat->ecm_pid,dat->ecm_table);
- }
-}
-
-void cEcmCache::Flush(void)
-{
- ListLock(true);
- Clear();
- Modified();
- PRINTF(L_CORE_ECM,"cache flushed");
- ListUnlock();
-}
-
-bool cEcmCache::ParseLinePlain(const char *line)
-{
- cEcmData *dat=new cEcmData;
- if(dat && dat->Parse(line) && !Exists(dat)) { Add(dat); return true; }
- delete dat;
- return false;
-}
-
-// -- cEcmSys ------------------------------------------------------------------
-
-class cEcmPri : public cSimpleItem {
-public:
- cEcmInfo *ecm;
- int pri, sysIdent;
- };
-
-// -- cEcmHandler --------------------------------------------------------------
-
-class cEcmHandler : public cSimpleItem, public cAction {
-private:
- int cardNum, cwIndex;
- cCam *cam;
- char *id;
- cTimeMs idleTime;
- //
- cMutex dataMutex;
- int sid;
- cSimpleList<cPrgPid> pids;
- //
- cSystem *sys;
- cPidFilter *filter;
- int filterCwIndex, filterSource, filterTransponder, filterSid;
- unsigned char lastCw[16];
- bool sync, noKey, trigger;
- int triggerMode;
- int mode, count;
- cTimeMs lastsync, startecm, resendTime;
- unsigned int cryptPeriod;
- unsigned char parity;
- cMsgCache failed;
- //
- cSimpleList<cEcmInfo> ecmList;
- cSimpleList<cEcmPri> ecmPriList;
- cEcmInfo *ecm;
- cEcmPri *ecmPri;
- cTimeMs ecmUpdTime;
- //
- int dolog;
- //
- void DeleteSys(void);
- void NoSync(bool clearParity);
- cEcmInfo *NewEcm(void);
- cEcmInfo *JumpEcm(void);
- void StopEcm(void);
- bool UpdateEcm(void);
- void EcmOk(void);
- void EcmFail(void);
- void ParseCAInfo(int sys, int source=0);
- void AddEcmPri(cEcmInfo *n);
-protected:
- virtual void Process(cPidFilter *filter, unsigned char *data, int len);
-public:
- cEcmHandler(cCam *Cam, int CardNum, int cwindex);
- virtual ~cEcmHandler();
- void Stop(void);
- void SetPrg(cPrg *prg);
- void ShiftCwIndex(int cwindex);
- char *CurrentKeyStr(void) const;
- bool IsRemoveable(void);
- bool IsIdle(void);
- int Sid(void) const { return sid; }
- int CwIndex(void) const { return cwIndex; }
- const char *Id(void) const { return id; }
- };
-
-cEcmHandler::cEcmHandler(cCam *Cam, int CardNum, int cwindex)
-:cAction("ecmhandler",CardNum)
-,failed(32,0)
-{
- cam=Cam;
- cardNum=CardNum;
- cwIndex=cwindex;
- sys=0; filter=0; ecm=0; ecmPri=0; mode=-1; sid=-1;
- trigger=false; triggerMode=-1;
- filterSource=filterTransponder=0; filterCwIndex=-1; filterSid=-1;
- asprintf(&id,"%d.%d",cardNum,cwindex);
-}
-
-cEcmHandler::~cEcmHandler()
-{
- Lock();
- StopEcm();
- DelAllFilter(); // delete filters before sys for multi-threading reasons
- DeleteSys();
- Unlock();
- free(id);
-}
-
-bool cEcmHandler::IsIdle(void)
-{
- dataMutex.Lock();
- int n=pids.Count();
- dataMutex.Unlock();
- return n==0;
-}
-
-bool cEcmHandler::IsRemoveable(void)
-{
- return IsIdle() && idleTime.Elapsed()>MAX_ECM_IDLE;
-}
-
-void cEcmHandler::Stop(void)
-{
- dataMutex.Lock();
- if(!IsIdle() || sid!=-1) {
- PRINTF(L_CORE_ECM,"%s: stop",id);
- sid=-1;
- idleTime.Set();
- pids.Clear();
- trigger=true;
- }
- dataMutex.Unlock();
- if(filter) filter->Wakeup();
-}
-
-void cEcmHandler::ShiftCwIndex(int cwindex)
-{
- if(cwIndex!=cwindex) {
- PRINTF(L_CORE_PIDS,"%s: shifting cwIndex from %d to %d",id,cwIndex,cwindex);
- free(id);
- asprintf(&id,"%d.%d",cardNum,cwindex);
- dataMutex.Lock();
- trigger=true;
- cwIndex=cwindex;
- for(cPrgPid *pid=pids.First(); pid; pid=pids.Next(pid))
- cam->SetCWIndex(pid->Pid(),cwIndex);
- dataMutex.Unlock();
- if(filter) filter->Wakeup();
- }
-}
-
-void cEcmHandler::SetPrg(cPrg *prg)
-{
- dataMutex.Lock();
- bool wasIdle=IsIdle();
- if(prg->Prg()!=sid) {
- PRINTF(L_CORE_ECM,"%s: setting new SID %d",id,prg->Prg());
- sid=prg->Prg();
- idleTime.Set();
- pids.Clear();
- trigger=true;
- }
- LBSTART(L_CORE_PIDS);
- LBPUT("%s: pids on entry",id);
- for(cPrgPid *pid=pids.First(); pid; pid=pids.Next(pid))
- LBPUT(" %s=%04x",TYPENAME(pid->Type()),pid->Pid());
- LBEND();
-
- for(cPrgPid *pid=pids.First(); pid;) {
- cPrgPid *npid;
- for(npid=prg->pids.First(); npid; npid=prg->pids.Next(npid)) {
- if(pid->Pid()==npid->Pid()) {
- npid->Proc(true);
- break;
- }
- }
- if(!npid) {
- npid=pids.Next(pid);
- pids.Del(pid);
- pid=npid;
- }
- else pid=pids.Next(pid);
- }
- LBSTART(L_CORE_PIDS);
- LBPUT("%s: pids after delete",id);
- for(cPrgPid *pid=pids.First(); pid; pid=pids.Next(pid))
- LBPUT(" %s=%04x",TYPENAME(pid->Type()),pid->Pid());
- LBEND();
- for(cPrgPid *npid=prg->pids.First(); npid; npid=prg->pids.Next(npid)) {
- if(!npid->Proc()) {
- cPrgPid *pid=new cPrgPid(npid->Type(),npid->Pid());
- pids.Add(pid);
- cam->SetCWIndex(pid->Pid(),cwIndex);
- }
- }
- LBSTART(L_CORE_PIDS);
- LBPUT("%s: pids after add",id);
- for(cPrgPid *pid=pids.First(); pid; pid=pids.Next(pid))
- LBPUT(" %s=%04x",TYPENAME(pid->Type()),pid->Pid());
- LBEND();
- if(!IsIdle()) {
- trigger=true;
- triggerMode=0;
- if(wasIdle) PRINTF(L_CORE_ECM,"%s: is no longer idle",id);
- }
- else {
- if(!wasIdle) idleTime.Set();
- PRINTF(L_CORE_ECM,"%s: is idle%s",id,wasIdle?"":" now");
- }
-
- if(!filter) {
- filter=NewFilter(IDLE_SLEEP);
- if(!filter) PRINTF(L_GEN_ERROR,"failed to open ECM filter in handler %s",id);
- }
- dataMutex.Unlock();
- if(filter) filter->Wakeup();
-}
-
-void cEcmHandler::Process(cPidFilter *filter, unsigned char *data, int len)
-{
- dataMutex.Lock();
- if(trigger) {
- PRINTF(L_CORE_ECM,"%s: triggered SID %d/%d idx %d/%d mode %d/%d %s",
- id,filterSid,sid,filterCwIndex,cwIndex,mode,triggerMode,(mode==3 && sync)?"sync":"-");
- trigger=false;
- if(filterSid!=sid) {
- filterSid=sid;
- filterSource=cam->Source();
- filterTransponder=cam->Transponder();
- filterCwIndex=cwIndex;
- noKey=true; mode=0;
- }
- else {
- if(filterCwIndex!=cwIndex) {
- filterCwIndex=cwIndex;
- if(mode==3 && sync)
- cam->WriteCW(filterCwIndex,lastCw,true);
- }
- if(mode<triggerMode) mode=triggerMode;
- }
- triggerMode=-1;
- }
- dataMutex.Unlock();
-
- switch(mode) {
- case -1:
- filter->SetIdleTime(IDLE_SLEEP);
- break;
-
- case 0:
- StopEcm();
- if(IsIdle()) { mode=-1; break; }
-
- dolog=LOG_COUNT;
- NewEcm();
- filter->SetIdleTime(IDLE_GETCA);
- startecm.Set();
- mode=1;
- break;
-
- case 1:
- if(!ecm && !JumpEcm()) {
- if(startecm.Elapsed()>IDLE_GETCA_SLOW) {
- if(IsIdle()) { mode=0; break; }
- PRINTF(L_CORE_ECM,"%s: no encryption system found",id);
- filter->SetIdleTime(IDLE_GETCA_SLOW/4);
- startecm.Set();
- }
- break;
- }
- mode=4;
- // fall through
-
- case 4:
- case 5:
- NoSync(mode==4);
- failed.Clear();
- filter->SetIdleTime(IDLE_NO_SYNC/2);
- lastsync.Set();
- cryptPeriod=20*1000;
- mode=2;
- // fall through
-
- case 2:
- if(sys->NeedsData()) {
- if(!UpdateEcm()) {
- if(lastsync.Elapsed()<ECM_DATA_TIME) break;
- PRINTF(L_CORE_ECM,"%s: no ecm extra data update (waited %d ms)",id,(int)lastsync.Elapsed());
- }
- if(lastsync.Elapsed()>IDLE_NO_SYNC/4 && dolog)
- PRINTF(L_CORE_ECM,"%s: ecm extra data update took %d ms",id,(int)lastsync.Elapsed());
- }
- filter->SetIdleTime(IDLE_NO_SYNC);
- mode=3;
- // fall through
-
- case 3:
- {
- bool resend=false, cwok=false;
- if(resendTime.TimedOut()) {
- resend=sync; resendTime.Set(8*24*60*60*1000);
- }
-
- if(startecm.Elapsed()<3*60*1000) cam->DumpAV7110();
-
- if(data && len>0) {
- HEXDUMP(L_HEX_ECM,data,len,"ECM sys 0x%04x id 0x%02x pid 0x%04x",ecm->caId,ecm->provId,filter->Pid());
- if(SCT_LEN(data)==len) {
- LDUMP(L_CORE_ECMPROC,data,16,"%s: ECM",id);
- int n;
- if(!(n=sys->CheckECM(ecm,data,sync))) {
- if(resend || parity!=(data[0]&1)) {
- int ecmid;
- cTimeMs procTime;
- cwok=(ecmid=failed.Get(data,len,0))>=0 && sys->ProcessECM(ecm,data);
- n=(ecmid>0)?failed.Cache(ecmid,cwok,0):99;
- sys->CheckECMResult(ecm,data,cwok);
- if(cwok) {
- parity=data[0]&1;
- }
- else {
- if(procTime.Elapsed()>6000) {
- PRINTF(L_CORE_ECM,"%s: filter flush (elapsed %d)",id,(int)procTime.Elapsed());
- filter->Flush();
- }
- if(n>=2) { count++; if(n==2) count++; }
- parity=0xFF;
- if(sync && lastsync.Elapsed()>cryptPeriod*2) {
- PRINTF(L_CORE_ECM,"%s: lost sync (period %d, elapsed %d)",id,cryptPeriod,(int)lastsync.Elapsed());
- NoSync(true);
- }
- }
- PRINTF(L_CORE_ECMPROC,"%s: (%s) cwok=%d ecmid=%d n=%d sync=%d parity=%d count=%d ELA=%d",
- id,sys->Name(),cwok,ecmid,n,sync,parity,count,(int)procTime.Elapsed());
- }
- }
- else {
- PRINTF(L_CORE_ECMPROC,"%s: check result %d\n",id,n);
- switch(n) {
- case 1: NoSync(true); break;
- case 2: count++; break;
- case 3: break;
- }
- }
- }
- else {
- PRINTF(L_CORE_ECM,"%s: incomplete section %d != %d",id,len,SCT_LEN(data));
- count++;
- }
- }
- else if(sys->Constant()) {
- if(sys->ProcessECM(ecm,NULL)) {
- cwok=true;
- if(sync) filter->SetIdleTime(IDLE_SYNC*10);
- }
- else count++;
- }
- else count++;
-
- if(cwok) {
- dolog=LOG_COUNT; sys->DoLog(true);
- cam->WriteCW(filterCwIndex,sys->CW(),resend || !sync);
- memcpy(lastCw,sys->CW(),sizeof(lastCw));
- noKey=false; count=0;
- UpdateEcm(); EcmOk();
- if(!sync) {
- sync=true;
- filter->SetIdleTime(IDLE_SYNC);
- PRINTF(L_CORE_ECM,"%s: correct key found",id);
- if(!cam->IsSoftCSA())
- resendTime.Set(CW_REPEAT_TIME);
- }
- else if(!resend)
- cryptPeriod=max(5000,min(60000,(int)lastsync.Elapsed()));
- lastsync.Set();
- }
-
- if(!sync && !trigger) {
- if(count>=sys->MaxEcmTry()) {
- EcmFail(); JumpEcm();
- mode=4;
- if(!ecm) {
- JumpEcm();
- if(!ecm) { // this should not happen!
- PRINTF(L_GEN_DEBUG,"internal: handler %s, empty ecm list in sync loop",id);
- mode=0; break;
- }
- // if we looped through all systems, we wait until the next parity
- // change before we try again.
- if(dolog!=LOG_COUNT && data) { parity=data[0]&1; mode=5; }
- if(dolog && !--dolog) {
- sys->DoLog(false);
- PRINTF(L_CORE_ECM,"%s: stopping message log until valid key is found",id);
- }
- }
- break;
- }
- }
-
- if(IsIdle() && idleTime.Elapsed()>MAX_ECM_HOLD) {
- PRINTF(L_CORE_ECM,"%s: hold timeout expired",id);
- mode=0;
- }
-
- break;
- }
- }
-}
-
-void cEcmHandler::NoSync(bool clearParity)
-{
- if(clearParity) parity=0xFF;
- count=0; sync=false;
-}
-
-void cEcmHandler::DeleteSys(void)
-{
- delete sys; sys=0;
-}
-
-char *cEcmHandler::CurrentKeyStr(void) const
-{
- if(noKey || !sys) return 0;
- return strdup(sys->CurrentKeyStr());
-}
-
-cEcmInfo *cEcmHandler::NewEcm(void)
-{
- ecmcache.GetCached(&ecmList,filterSid,filterSource,filterTransponder);
- ecmPriList.Clear();
- for(cEcmInfo *n=ecmList.First(); n; n=ecmList.Next(n)) AddEcmPri(n);
- ecm=0; ecmPri=0;
- return JumpEcm();
-}
-
-void cEcmHandler::AddEcmPri(cEcmInfo *n)
-{
- int ident, pri=0;
- while((ident=cSystems::FindIdentBySysId(n->caId,!cam->IsSoftCSA(),pri))>0) {
- cEcmPri *ep=new cEcmPri;
- if(ep) {
- ep->ecm=n;
- ep->pri=pri;
- ep->sysIdent=ident;
- if(n->Cached() && (!ScSetup.LocalPriority || pri!=-15)) ep->pri+=20;
-
- // keep ecmPriList sorted
- cEcmPri *eppp, *epp=ecmPriList.First();
- if(!epp || epp->pri<ep->pri)
- ecmPriList.Ins(ep);
- else {
- do {
- eppp=ecmPriList.Next(epp);
- if(!eppp || eppp->pri<ep->pri) {
- ecmPriList.Add(ep,epp);
- break;
- }
- } while((epp=eppp));
- }
- }
- }
-}
-
-void cEcmHandler::StopEcm(void)
-{
- filter->Stop(); filter->Flush();
- if(ecm) cam->LogEcmStatus(ecm,false);
- DeleteSys();
-}
-
-bool cEcmHandler::UpdateEcm(void)
-{
- if(!ecm->Data() || ecmUpdTime.TimedOut()) {
- bool log=dolog;
- dolog=(sys && sys->NeedsData() && ecm->Data()==0);
- if(dolog) PRINTF(L_CORE_ECM,"%s: try to update ecm extra data",id);
- ParseCAInfo(ecm->caId, ecm->source);
- ecmUpdTime.Set(ECM_UPD_TIME);
- dolog=log;
- if(!ecm->Data()) return false;
- }
- return true;
-}
-
-cEcmInfo *cEcmHandler::JumpEcm(void)
-{
- noKey=true;
- if(!ecmPri) {
- ParseCAInfo(0xFFFF); // all systems
- ecmPri=ecmPriList.First();
- }
- else ecmPri=ecmPriList.Next(ecmPri);
- if(ecmPri) {
- if(ecmPri->ecm!=ecm) {
- StopEcm(); ecmUpdTime.Set();
- ecm=ecmPri->ecm;
- filter->Start(ecm->ecm_pid,ecm->ecm_table,0xfe,0,false);
- cam->LogEcmStatus(ecm,true);
- }
- else {
- DeleteSys();
- filter->Flush();
- }
- sys=cSystems::FindBySysIdent(ecmPri->sysIdent);
- if(!sys) {
- if(dolog) PRINTF(L_GEN_DEBUG,"internal: handler %s, no system found for ident %04x (caid %04x pri %d)",id,ecmPri->sysIdent,ecmPri->ecm->caId,ecmPri->pri);
- return JumpEcm();
- }
- sys->DoLog(dolog!=0); sys->CardNum(cardNum);
- failed.SetMaxFail(sys->MaxEcmTry());
-
- if(dolog) PRINTF(L_CORE_ECM,"%s: try system %s (%04x) id %04x with ecm %x%s (pri=%d)",
- id,sys->Name(),ecm->caId,ecm->provId,ecm->ecm_pid,ecm->Cached()?" (cached)":"",sys->Pri());
- }
- else {
- StopEcm();
- ecm=0;
- }
- return ecm;
-}
-
-void cEcmHandler::EcmOk(void)
-{
- ecm->SetName(sys->Name());
- ecm->Fail(false);
- ecmcache.New(ecm);
- cEcmInfo *e=ecmList.First();
- while(e) {
- if(e->Cached() && e->Failed()) ecmcache.Delete(e);
- e=ecmList.Next(e);
- }
-}
-
-void cEcmHandler::EcmFail(void)
-{
- ecm->Fail(true);
-}
-
-void cEcmHandler::ParseCAInfo(int SysId, int Source)
-{
- unsigned char buff[2048];
- caid_t casys[MAXCAIDS+1];
- if(SysId==0xFFFF) {
- if(!cam->GetPrgCaids(filterSource,filterTransponder,filterSid,casys)) {
- PRINTF(L_CORE_ECM,"%s: no CAIDs for SID %d",id,sid);
- return;
- }
- }
- else {
- casys[0]=SysId;
- casys[1]=0;
- }
- bool streamFlag;
- int len=GetCaDescriptors(filterSource,filterTransponder,filterSid,casys,sizeof(buff),buff,streamFlag);
- if(len>0) {
- if(dolog) PRINTF(L_CORE_ECM,"%s: got CaDescriptors for SID %d (len=%d)",id,sid,len);
- HEXDUMP(L_HEX_PMT,buff,len,"PMT");
- for(int index=0; index<len; index+=buff[index+1]+2) {
- if(buff[index]==0x09) {
- if(dolog) LDUMP(L_CORE_ECM,&buff[index+2],buff[index+1],"%s: descriptor",id);
- int sysId=WORD(buff,index+2,0xFFFF);
- int sysPri=0;
- cSystem *sys;
- while((sys=cSystems::FindBySysId(sysId,!cam->IsSoftCSA(),sysPri))) {
- sysPri=sys->Pri();
- cSimpleList<cEcmInfo> ecms;
- sys->ParseCADescriptor(&ecms,sysId,Source,&buff[index+2],buff[index+1]);
- delete sys;
- if(ecms.Count()) {
- cEcmInfo *n;
- while((n=ecms.First())) {
- ecms.Del(n,false);
- LBSTARTF(L_CORE_ECM);
- if(dolog) LBPUT("%s: found %04x (%s) id %04x with ecm %x ",id,n->caId,n->name,n->provId,n->ecm_pid);
- cEcmInfo *e=ecmList.First();
- while(e) {
- if(e->ecm_pid==n->ecm_pid) {
- if(e->caId==n->caId && e->provId==n->provId) {
- if(n->Data()) {
- if(e->Update(n) && dolog) LBPUT("(updated) ");
- }
- if(dolog) LBPUT("(already present)");
- delete n; n=0;
- break;
- }
- else {
- e->Fail(true);
- if(dolog) LBPUT("(dup) ");
- }
- }
- e=ecmList.Next(e);
- }
- if(n) {
- if(dolog) LBPUT("(new)");
- n->SetSource(sid,filterSource,filterTransponder);
- ecmList.Add(n);
- AddEcmPri(n);
- }
- LBEND();
- }
- break;
- }
- }
- if(sysPri==0 && dolog) PRINTF(L_CORE_ECM,"%s: no module available for system %04x",id,sysId);
- }
- }
- }
- else if(len<0)
- PRINTF(L_CORE_ECM,"%s: CA parse buffer overflow",id);
- if(SysId==0xFFFF) {
- for(cEcmPri *ep=ecmPriList.First(); ep; ep=ecmPriList.Next(ep))
- PRINTF(L_CORE_ECMPROC,"%s: ecmPriList pri=%d ident=%04x caid=%04x pid=%04x",id,ep->pri,ep->sysIdent,ep->ecm->caId,ep->ecm->ecm_pid);
- PRINTF(L_CORE_ECMPROC,"%s: ecmPri list end",id);
- }
-}
-
-// -- cCam ---------------------------------------------------------------
-
-cCam::cCam(cScDvbDevice *dev, int CardNum)
-{
- device=dev; cardNum=CardNum;
- source=transponder=-1; liveVpid=liveApid=0; logger=0; hookman=0;
- memset(lastCW,0,sizeof(lastCW));
- memset(indexMap,0,sizeof(indexMap));
-}
-
-cCam::~cCam()
-{
- handlerList.Clear();
- delete hookman;
- delete logger;
-}
-
-bool cCam::IsSoftCSA(void)
-{
- return device->SoftCSA();
-}
-
-void cCam::Tune(const cChannel *channel)
-{
- cMutexLock lock(this);
- if(source!=channel->Source() || transponder!=channel->Transponder()) {
- source=channel->Source(); transponder=channel->Transponder();
- PRINTF(L_CORE_PIDS,"%d: now tuned to source %x transponder %x",cardNum,source,transponder);
- Stop();
- }
- else PRINTF(L_CORE_PIDS,"%d: tune to same source/transponder",cardNum);
-}
-
-void cCam::PostTune(void)
-{
- if(ScSetup.PrestartAU) {
- LogStartup();
- if(logger) logger->PreScan();
- }
-}
-
-void cCam::SetPid(int type, int pid, bool on)
-{
- cMutexLock lock(this);
- int oldA=liveApid, oldV=liveVpid;
- if(type==1) liveVpid=on ? pid:0;
- else if(type==0) liveApid=on ? pid:0;
- else if(liveVpid==pid && on) liveVpid=0;
- else if(liveApid==pid && on) liveApid=0;
- if(oldA!=liveApid || oldV!=liveVpid)
- PRINTF(L_CORE_PIDS,"%d: livepids video=%04x audio=%04x",cardNum,liveVpid,liveApid);
-}
-
-void cCam::Stop(void)
-{
- cMutexLock lock(this);
- for(cEcmHandler *handler=handlerList.First(); handler; handler=handlerList.Next(handler))
- handler->Stop();
- if(logger) logger->Down();
- if(hookman) hookman->Down();
-}
-
-void cCam::AddPrg(cPrg *prg)
-{
- cMutexLock lock(this);
- bool islive=false;
- for(cPrgPid *pid=prg->pids.First(); pid; pid=prg->pids.Next(pid))
- if(pid->Pid()==liveVpid || pid->Pid()==liveApid) {
- islive=true;
- break;
- }
- bool needZero=!IsSoftCSA() && (islive || !ScSetup.ConcurrentFF);
- bool noshift=IsSoftCSA() || (prg->IsUpdate() && prg->pids.Count()==0);
- PRINTF(L_CORE_PIDS,"%d: %s SID %d (zero=%d noshift=%d)",cardNum,prg->IsUpdate()?"update":"add",prg->Prg(),needZero,noshift);
- if(prg->pids.Count()>0) {
- LBSTART(L_CORE_PIDS);
- LBPUT("%d: pids",cardNum);
- for(cPrgPid *pid=prg->pids.First(); pid; pid=prg->pids.Next(pid))
- LBPUT(" %s=%04x",TYPENAME(pid->Type()),pid->Pid());
- LBEND();
- }
- cEcmHandler *handler=GetHandler(prg->Prg(),needZero,noshift);
- if(handler) {
- PRINTF(L_CORE_PIDS,"%d: found handler for SID %d (%s idle=%d idx=%d)",cardNum,prg->Prg(),handler->Id(),handler->IsIdle(),handler->CwIndex());
- handler->SetPrg(prg);
- }
-}
-
-bool cCam::HasPrg(int prg)
-{
- cMutexLock lock(this);
- for(cEcmHandler *handler=handlerList.First(); handler; handler=handlerList.Next(handler))
- if(!handler->IsIdle() && handler->Sid()==prg)
- return true;
- return false;
-}
-
-char *cCam::CurrentKeyStr(int num)
-{
- cMutexLock lock(this);
- cEcmHandler *handler;
- for(handler=handlerList.First(); handler; handler=handlerList.Next(handler))
- if(--num<0) return handler->CurrentKeyStr();
- return 0;
-}
-
-bool cCam::Active(bool log)
-{
- cMutexLock lock(this);
- for(cEcmHandler *handler=handlerList.First(); handler; handler=handlerList.Next(handler))
- if(!handler->IsIdle()) {
- if(log) PRINTF(L_GEN_INFO,"handler %s on card %d is not idle",handler->Id(),cardNum);
- return true;
- }
- return false;
-}
-
-void cCam::HouseKeeping(void)
-{
- cMutexLock lock(this);
- for(cEcmHandler *handler=handlerList.First(); handler;) {
- cEcmHandler *next=handlerList.Next(handler);
- if(handler->IsRemoveable()) RemHandler(handler);
- handler=next;
- }
- if(handlerList.Count()<1 && !ScSetup.PrestartAU) {
- delete hookman; hookman=0;
- delete logger; logger=0;
- }
-}
-
-bool cCam::GetPrgCaids(int source, int transponder, int prg, caid_t *c)
-{
- return device->GetPrgCaids(source,transponder,prg,c);
-}
-
-void cCam::LogStartup(void)
-{
- cMutexLock lock(this);
- if(!logger && ScSetup.AutoUpdate) {
- logger=new cLogger(cardNum,IsSoftCSA());
- LogStatsUp();
- }
-}
-
-void cCam::LogEcmStatus(const cEcmInfo *ecm, bool on)
-{
- cMutexLock lock(this);
- if(on) LogStartup();
- if(logger) logger->EcmStatus(ecm,on);
-}
-
-void cCam::AddHook(cLogHook *hook)
-{
- cMutexLock lock(this);
- if(!hookman) hookman=new cHookManager(cardNum);
- if(hookman) hookman->AddHook(hook);
-}
-
-bool cCam::TriggerHook(int id)
-{
- return hookman && hookman->TriggerHook(id);
-}
-
-void cCam::SetCWIndex(int pid, int index)
-{
- if(index<MAX_CW_IDX) {
- ca_pid_t ca_pid;
- ca_pid.pid=pid;
- ca_pid.index=index;
- PRINTF(L_CORE_PIDS,"%d: descrambling pid %04x on index %x",cardNum,pid,index);
- if(!device->SetCaPid(&ca_pid))
- if(index>0) {
- PRINTF(L_GEN_ERROR,"CA_SET_PID failed (%s). Expect a black screen/bad recording. Do you use the patched DVB driver?",strerror(errno));
- PRINTF(L_GEN_WARN,"Adjusting 'Concurrent FF streams' to NO");
- ScSetup.ConcurrentFF=0;
- ScSetup.Store(true);
- }
- }
-}
-
-void cCam::WriteCW(int index, unsigned char *cw, bool force)
-{
- if(index<MAX_CW_IDX) {
- for(int i=0; i<16; i+=4) cw[i+3]=cw[i]+cw[i+1]+cw[i+2];
- ca_descr_t ca_descr;
- ca_descr.index=index;
- unsigned char *last=lastCW[index];
- if(force || memcmp(&cw[0],&last[0],8)) {
- memcpy(&last[0],&cw[0],8);
- ca_descr.parity=0;
- memcpy(ca_descr.cw,&cw[0],8);
- if(!device->SetCaDescr(&ca_descr,force))
- PRINTF(L_GEN_ERROR,"CA_SET_DESCR failed (%s). Expect a black screen.",strerror(errno));
- }
-
- if(force || memcmp(&cw[8],&last[8],8)) {
- memcpy(&last[8],&cw[8],8);
- ca_descr.parity=1;
- memcpy(ca_descr.cw,&cw[8],8);
- if(!device->SetCaDescr(&ca_descr,force))
- PRINTF(L_GEN_ERROR,"CA_SET_DESCR failed (%s). Expect a black screen.",strerror(errno));
- }
- }
-}
-
-void cCam::DumpAV7110(void)
-{
- device->DumpAV7110();
-}
-
-int cCam::GetFreeIndex(void)
-{
- for(int idx=0; idx<MAX_CW_IDX; idx++)
- if(!indexMap[idx]) return idx;
- return -1;
-}
-
-cEcmHandler *cCam::GetHandler(int sid, bool needZero, bool noshift)
-{
- cEcmHandler *zerohandler=0, *sidhandler=0, *idlehandler=0;
- for(cEcmHandler *handler=handlerList.First(); handler; handler=handlerList.Next(handler)) {
- if(handler->Sid()==sid)
- sidhandler=handler;
- if(handler->CwIndex()==0)
- zerohandler=handler;
- if(handler->IsIdle() && (!idlehandler || (!(needZero ^ (idlehandler->CwIndex()!=0)) && (needZero ^ (handler->CwIndex()!=0))) ))
- idlehandler=handler;
- }
- LBSTART(L_CORE_PIDS);
- LBPUT("%d: SID=%d zero=%d |",cardNum,sid,needZero);
- if(sidhandler) LBPUT(" sid=%d/%d/%d",sidhandler->CwIndex(),sidhandler->Sid(),sidhandler->IsIdle());
- else LBPUT(" sid=-/-/-");
- if(zerohandler) LBPUT(" zero=%d/%d/%d",zerohandler->CwIndex(),zerohandler->Sid(),zerohandler->IsIdle());
- else LBPUT(" zero=-/-/-");
- if(idlehandler) LBPUT(" idle=%d/%d/%d",idlehandler->CwIndex(),idlehandler->Sid(),idlehandler->IsIdle());
- else LBPUT(" idle=-/-/-");
- LBEND();
-
- if(sidhandler) {
- if(needZero && sidhandler->CwIndex()!=0 && !noshift) {
- if(!sidhandler->IsIdle())
- PRINTF(L_CORE_ECM,"%d: shifting cwindex on non-idle handler.",cardNum);
- if(zerohandler) {
- if(!zerohandler->IsIdle())
- PRINTF(L_CORE_ECM,"%d: shifting non-idle zero handler. This shouldn't happen!",cardNum);
- zerohandler->ShiftCwIndex(sidhandler->CwIndex());
- sidhandler->ShiftCwIndex(0);
- }
- else if(indexMap[0]==0) {
- indexMap[0]=1;
- indexMap[sidhandler->CwIndex()]=0;
- sidhandler->ShiftCwIndex(0);
- }
- else PRINTF(L_CORE_ECM,"%d: zero index not free.",cardNum);
- }
-
- if(!needZero && sidhandler->CwIndex()==0 && !noshift) {
- if(!sidhandler->IsIdle())
- PRINTF(L_CORE_ECM,"%d: shifting cwindex on non-idle handler.",cardNum);
- int idx=GetFreeIndex();
- if(idx>=0) {
- indexMap[idx]=1;
- sidhandler->ShiftCwIndex(idx);
- indexMap[0]=0;
- }
- else PRINTF(L_CORE_ECM,"%d: no free cwindex. Can't free zero index.",cardNum);
- }
-
- return sidhandler;
- }
-
- if(needZero && zerohandler) {
- if(!zerohandler->IsIdle())
- PRINTF(L_CORE_ECM,"%d: changing SID on non-idle zero handler. This shouldn't happen!",cardNum);
- return zerohandler;
- }
-
- if(idlehandler) {
- if(needZero && idlehandler->CwIndex()!=0 && !noshift) {
- if(indexMap[0]==0) {
- indexMap[0]=1;
- indexMap[idlehandler->CwIndex()]=0;
- idlehandler->ShiftCwIndex(0);
- }
- else PRINTF(L_CORE_ECM,"%d: zero index not free. (2)",cardNum);
- }
- if(!needZero && idlehandler->CwIndex()==0 && !noshift) {
- int idx=GetFreeIndex();
- if(idx>=0) {
- indexMap[idx]=1;
- idlehandler->ShiftCwIndex(idx);
- indexMap[0]=0;
- }
- else PRINTF(L_CORE_ECM,"%d: no free cwindex. Can't free zero index. (2)",cardNum);
- }
- if((needZero ^ (idlehandler->CwIndex()==0)))
- PRINTF(L_CORE_ECM,"%d: idlehandler index doesn't match needZero",cardNum);
- return idlehandler;
- }
-
- int idx=GetFreeIndex();
- if(!needZero && idx==0) {
- indexMap[0]=1;
- idx=GetFreeIndex();
- indexMap[0]=0;
- if(idx<0) {
- idx=0;
- PRINTF(L_CORE_ECM,"%d: can't respect !needZero for new handler",cardNum);
- }
- }
- if(idx<0) {
- PRINTF(L_CORE_ECM,"%d: no free cwindex",cardNum);
- return 0;
- }
- indexMap[idx]=1;
- idlehandler=new cEcmHandler(this,cardNum,idx);
- handlerList.Add(idlehandler);
- return idlehandler;
-}
-
-void cCam::RemHandler(cEcmHandler *handler)
-{
- int idx=handler->CwIndex();
- PRINTF(L_CORE_PIDS,"%d: removing %s on cw index %d",cardNum,handler->Id(),idx);
- handlerList.Del(handler);
- indexMap[idx]=0;
-}
-
-#ifndef SASC
-
-// --- cChannelCaids -----------------------------------------------------------
-
-#if APIVERSNUM >= 10500
-
-class cChannelCaids : public cSimpleItem {
-private:
- int prg, source, transponder;
- int numcaids;
- caid_t caids[MAX_CI_SLOT_CAIDS+1];
-public:
- cChannelCaids(cChannel *channel);
- bool IsChannel(cChannel *channel);
- void Sort(void);
- void Del(caid_t caid);
- bool HasCaid(caid_t caid);
- bool Same(cChannelCaids *ch);
- void HistAdd(unsigned short *hist);
- void Dump(int n);
- const caid_t *Caids(void) { caids[numcaids]=0; return caids; }
- int NumCaids(void) { return numcaids; }
- };
-
-cChannelCaids::cChannelCaids(cChannel *channel)
-{
- prg=channel->Sid(); source=channel->Source(); transponder=channel->Transponder();
- numcaids=0;
- for(const caid_t *ids=channel->Caids(); *ids; ids++)
- if(numcaids<MAX_CI_SLOT_CAIDS) caids[numcaids++]=*ids;
- Sort();
-}
-
-bool cChannelCaids::IsChannel(cChannel *channel)
-{
- return prg==channel->Sid() && source==channel->Source() && transponder==channel->Transponder();
-}
-
-void cChannelCaids::Sort(void)
-{
- caid_t tmp[MAX_CI_SLOT_CAIDS];
- int c=0xFFFF;
- for(int i=0; i<numcaids; i++) {
- int d=0;
- for(int j=0; j<numcaids; j++) if(caids[j]>d && caids[j]<c) d=caids[j];
- tmp[i]=d; c=d;
- }
- memcpy(caids,tmp,sizeof(caids));
-}
-
-void cChannelCaids::Del(caid_t caid)
-{
- for(int i=0; i<numcaids; i++)
- if(caids[i]==caid) {
- numcaids--; caids[i]=caids[numcaids];
- if(numcaids>0) Sort();
- caids[numcaids]=0;
- break;
- }
-}
-
-bool cChannelCaids::HasCaid(caid_t caid)
-{
- for(int i=0; i<numcaids; i++) if(caids[i]==caid) return true;
- return false;
-}
-
-bool cChannelCaids::Same(cChannelCaids *ch)
-{
- if(numcaids!=ch->numcaids) return false;
- return memcmp(caids,ch->caids,numcaids*sizeof(caid_t))==0;
-}
-
-void cChannelCaids::HistAdd(unsigned short *hist)
-{
- for(int i=numcaids-1; i>=0; i--) hist[caids[i]]++;
-}
-
-void cChannelCaids::Dump(int n)
-{
- LBSTART(L_CORE_CAIDS);
- LBPUT("%d: channel %d/%x/%x",n,prg,source,transponder);
- for(const caid_t *ids=Caids(); *ids; ids++) LBPUT(" %04x",*ids);
- LBEND();
-}
-
-// --- cChannelList ------------------------------------------------------------
-
-class cChannelList : public cSimpleList<cChannelCaids> {
-private:
- int n;
-public:
- cChannelList(int N);
- void Unique(void);
- void CheckIgnore(void);
- int Histo(void);
- void Purge(int caid);
- };
-
-cChannelList::cChannelList(int N)
-{
- n=N;
-}
-
-void cChannelList::CheckIgnore(void)
-{
- for(cChannelCaids *ch=First(); ch; ch=Next(ch)) {
- const caid_t *ids=ch->Caids();
- while(*ids) {
- int pri=0;
- if(!cSystems::FindIdentBySysId(*ids,false,pri)) {
- for(cChannelCaids *ch2=Next(ch); ch2; ch2=Next(ch2)) ch2->Del(*ids);
- ch->Del(*ids);
- }
- else ids++;
- }
- }
- PRINTF(L_CORE_CAIDS,"%d: after check",n);
- for(cChannelCaids *ch=First(); ch; ch=Next(ch)) ch->Dump(n);
-}
-
-void cChannelList::Unique(void)
-{
- for(cChannelCaids *ch1=First(); ch1; ch1=Next(ch1)) {
- for(cChannelCaids *ch2=Next(ch1); ch2;) {
- if(ch1->Same(ch2) || ch2->NumCaids()<1) {
- cChannelCaids *t=Next(ch2);
- Del(ch2);
- ch2=t;
- }
- else ch2=Next(ch2);
- }
- }
- if(Count()==1 && First() && First()->NumCaids()<1) Del(First());
- PRINTF(L_CORE_CAIDS,"%d: after unique",n);
- for(cChannelCaids *ch=First(); ch; ch=Next(ch)) ch->Dump(n);
-}
-
-int cChannelList::Histo(void)
-{
- int h=-1;
- unsigned short *hist=MALLOC(unsigned short,0x10000);
- if(hist) {
- memset(hist,0,sizeof(unsigned short)*0x10000);
- for(cChannelCaids *ch=First(); ch; ch=Next(ch)) ch->HistAdd(hist);
- int c=0;
- for(int i=0; i<0x10000; i++)
- if(hist[i]>c) { h=i; c=hist[i]; }
- free(hist);
- }
- else PRINTF(L_GEN_ERROR,"malloc failed in cChannelList::Histo");
- return h;
-}
-
-void cChannelList::Purge(int caid)
-{
- for(cChannelCaids *ch=First(); ch;) {
- if(ch->NumCaids()<=0 || ch->HasCaid(caid)) {
- cChannelCaids *t=Next(ch);
- Del(ch);
- ch=t;
- }
- else ch=Next(ch);
- }
- if(Count()>0) {
- PRINTF(L_CORE_CAIDS,"%d: still left",n);
- for(cChannelCaids *ch=First(); ch; ch=Next(ch)) ch->Dump(n);
- }
-}
-
-// -- cScCiAdapter -------------------------------------------------------------
-
-struct TPDU {
- unsigned char slot;
- unsigned char tcid;
- unsigned char tag;
- unsigned char len;
- unsigned char data[1];
- };
-
-class cScCamSlot;
-
-class cScCiAdapter : public cCiAdapter {
-private:
- cDevice *device;
- cCam *cam;
- cMutex ciMutex;
- int cardIndex;
- cRingBufferLinear *rb;
- cScCamSlot *slots[MAX_CI_SLOTS];
- //
- cTimeMs caidTimer;
- int version[MAX_CI_SLOTS];
- caid_t caids[MAX_CI_SLOTS][MAX_CI_SLOT_CAIDS+1];
- int tcid;
- //
- cTimeMs readTimer, writeTimer;
- //
- void BuildCaids(bool force);
-protected:
- virtual int Read(unsigned char *Buffer, int MaxLength);
- virtual void Write(const unsigned char *Buffer, int Length);
- virtual bool Reset(int Slot);
- virtual eModuleStatus ModuleStatus(int Slot);
- virtual bool Assign(cDevice *Device, bool Query=false);
-public:
- cScCiAdapter(cDevice *Device, int CardIndex, cCam *Cam);
- ~cScCiAdapter();
- void CamStop(void);
- void CamAddPrg(cPrg *prg);
- bool CamSoftCSA(void);
- int GetCaids(int slot, unsigned short *Caids, int max);
- };
-
-// -- cScCamSlot ---------------------------------------------------------------
-
-#define SLOT_CAID_CHECK 10000
-#define SLOT_RESET_TIME 600
-
-class cScCamSlot : public cCamSlot, public cRingBufferLinear {
-private:
- cScCiAdapter *ciadapter;
- unsigned short caids[MAX_CI_SLOT_CAIDS+1];
- int slot, cardIndex, version;
- cTimeMs checkTimer;
- bool reset, doReply;
- cTimeMs resetTimer;
- eModuleStatus lastStatus;
- //
- int GetLength(const unsigned char * &data);
- void CaInfo(unsigned char *b, int tcid, int cid);
- bool Check(void);
-public:
- cScCamSlot(cScCiAdapter *ca, int CardIndex, int Slot);
- void Process(const unsigned char *data, int len);
- eModuleStatus Status(void);
- bool Reset(bool log=true);
- };
-
-cScCamSlot::cScCamSlot(cScCiAdapter *ca, int CardIndex, int Slot)
-:cCamSlot(ca)
-,cRingBufferLinear(KILOBYTE(2),5+1,false,"SC-CI slot answer")
-,checkTimer(-SLOT_CAID_CHECK-1000)
-{
- ciadapter=ca; cardIndex=CardIndex; slot=Slot;
- version=0; caids[0]=0; doReply=false; lastStatus=msReset;
- Reset(false);
-}
-
-eModuleStatus cScCamSlot::Status(void)
-{
- eModuleStatus status;
- if(reset) {
- status=msReset;
- if(resetTimer.TimedOut()) reset=false;
- }
- else if(caids[0]) status=msReady;
- else {
- status=msPresent; //msNone;
- Check();
- }
- if(status!=lastStatus) {
- static const char *stext[] = { "none","reset","present","ready" };
- PRINTF(L_CORE_CI,"%d.%d: status '%s'",cardIndex,slot,stext[status]);
- lastStatus=status;
- }
- return status;
-}
-
-bool cScCamSlot::Reset(bool log)
-{
- reset=true; resetTimer.Set(SLOT_RESET_TIME);
- Clear();
- if(log) PRINTF(L_CORE_CI,"%d.%d: reset",cardIndex,slot);
- return true;
-}
-
-bool cScCamSlot::Check(void)
-{
- bool res=false;
- bool dr=ciadapter->CamSoftCSA() || ScSetup.ConcurrentFF>0;
- if(dr!=doReply && !IsDecrypting()) {
- PRINTF(L_CORE_CI,"%d.%d: doReply changed, reset triggered",cardIndex,slot);
- Reset(false);
- doReply=dr;
- }
- if(checkTimer.TimedOut()) {
- if(version!=ciadapter->GetCaids(slot,0,0)) {
- version=ciadapter->GetCaids(slot,caids,MAX_CI_SLOT_CAIDS);
- PRINTF(L_CORE_CI,"%d.%d: now using CAIDs version %d",cardIndex,slot,version);
- res=true;
- }
- checkTimer.Set(SLOT_CAID_CHECK);
- }
- return res;
-}
-
-int cScCamSlot::GetLength(const unsigned char * &data)
-{
- int len=*data++;
- if(len&0x80) {
- int i;
- for(i=len&~0x80, len=0; i>0; i--) len=(len<<8) + *data++;
- }
- return len;
-}
-
-void cScCamSlot::CaInfo(unsigned char *b, int tcid, int cid)
-{
- b[0]=0xa0; b[2]=tcid;
- b[3]=0x90;
- b[4]=0x02; b[5]=cid<<8; b[6]=cid&0xff;
- b[7]=0x9f; b[8]=0x80; b[9]=0x31; // AOT_CA_INFO
- int l=0;
- for(int i=0; caids[i]; i++) {
- b[l+11]=caids[i]>>8;
- b[l+12]=caids[i]&0xff;
- l+=2;
- }
- b[10]=l; b[1]=l+9; b[-1]=l+11; Put(b-1,l+12);
- PRINTF(L_CORE_CI,"%d.%d sending CA info",cardIndex,slot);
-}
-
-void cScCamSlot::Process(const unsigned char *data, int len)
-{
- const unsigned char *save=data;
- data+=3;
- int dlen=GetLength(data);
- if(dlen>len-(data-save)) {
- PRINTF(L_CORE_CI,"%d.%d TDPU length exceeds data length",cardIndex,slot);
- dlen=len-(data-save);
- }
- int tcid=data[0];
-
- unsigned char a[128], *b=&a[1];
- if(Check()) CaInfo(b,tcid,0x01);
-
- if(dlen<8 || data[1]!=0x90) return;
- int cid=(data[3]<<8)+data[4];
- int tag=(data[5]<<16)+(data[6]<<8)+data[7];
- data+=8;
- dlen=GetLength(data);
- if(dlen>len-(data-save)) {
- PRINTF(L_CORE_CI,"%d.%d tag length exceeds data length",cardIndex,slot);
- dlen=len-(data-save);
- }
- switch(tag) {
- case 0x9f8030: // AOT_CA_INFO_ENQ
- CaInfo(b,tcid,cid);
- break;
-
- case 0x9f8032: // AOT_CA_PMT
- if(dlen>=6) {
- int ca_lm=data[0];
- int ci_cmd=-1;
- cPrg *prg=new cPrg((data[1]<<8)+data[2],ca_lm==5);
- int ilen=(data[4]<<8)+data[5];
- LBSTARTF(L_CORE_CI);
- LBPUT("%d.%d CA_PMT decoding len=%x lm=%x prg=%d len=%x",cardIndex,slot,dlen,ca_lm,(data[1]<<8)+data[2],ilen);
- data+=6; dlen-=6;
- LBPUT("/%x",dlen);
- if(ilen>0 && dlen>=ilen) {
- ci_cmd=data[0];
- LBPUT(" ci_cmd(G)=%02x",ci_cmd);
- }
- data+=ilen; dlen-=ilen;
- while(dlen>=5) {
- cPrgPid *pid=new cPrgPid(data[0],(data[1]<<8)+data[2]);
- prg->pids.Add(pid);
- ilen=(data[3]<<8)+data[4];
- LBPUT(" pid=%d,%x len=%x",data[0],(data[1]<<8)+data[2],ilen);
- data+=5; dlen-=5;
- LBPUT("/%x",dlen);
- if(ilen>0 && dlen>=ilen) {
- ci_cmd=data[0];
- LBPUT(" ci_cmd(S)=%x",ci_cmd);
- }
- data+=ilen; dlen-=ilen;
- }
- LBEND();
- PRINTF(L_CORE_CI,"%d.%d got CA pmt ciCmd=%d caLm=%d",cardIndex,slot,ci_cmd,ca_lm);
- if(doReply && (ci_cmd==0x03 || (ci_cmd==0x01 && ca_lm==0x03))) {
- b[0]=0xa0; b[2]=tcid;
- b[3]=0x90;
- b[4]=0x02; b[5]=cid<<8; b[6]=cid&0xff;
- b[7]=0x9f; b[8]=0x80; b[9]=0x33; // AOT_CA_PMT_REPLY
- b[11]=prg->Prg()<<8;
- b[12]=prg->Prg()&0xff;
- b[13]=0x00;
- b[14]=0x81; // CA_ENABLE
- b[10]=4; b[1]=4+9; a[0]=4+11; Put(a,4+12);
- PRINTF(L_CORE_CI,"%d.%d answer to query",cardIndex,slot);
- }
- if(prg->Prg()!=0) {
- if(ci_cmd==0x04) {
- PRINTF(L_CORE_CI,"%d.%d stop decrypt",cardIndex,slot);
- ciadapter->CamStop();
- }
- if(ci_cmd==0x01 || (ci_cmd==-1 && (ca_lm==0x04 || ca_lm==0x05))) {
- PRINTF(L_CORE_CI,"%d.%d set CAM decrypt (prg %d)",cardIndex,slot,prg->Prg());
- ciadapter->CamAddPrg(prg);
- }
- }
- delete prg;
- }
- break;
- }
-}
-
-// -- cScCiAdapter -------------------------------------------------------------
-
-cScCiAdapter::cScCiAdapter(cDevice *Device, int CardIndex, cCam *Cam)
-{
- device=Device; cardIndex=CardIndex; cam=Cam;
- tcid=0;
- memset(version,0,sizeof(version));
- memset(slots,0,sizeof(slots));
- SetDescription("SC-CI adapter on device %d",cardIndex);
- rb=new cRingBufferLinear(KILOBYTE(5),6+1,false,"SC-CI adapter read");
- if(rb) {
- rb->SetTimeouts(0,CAM_READ_TIMEOUT);
-/*
- bool spare=true;
- for(int i=0; i<MAX_CI_SLOTS; i++) {
- if(GetCaids(i,0,0)<=0) {
- if(!spare) break;
- spare=false;
- }
- slots[i]=new cScCamSlot(this,cardIndex,i);
- }
-*/
- BuildCaids(true);
- slots[0]=new cScCamSlot(this,cardIndex,0);
- Start();
- }
- else PRINTF(L_GEN_ERROR,"failed to create ringbuffer for SC-CI adapter %d.",cardIndex);
-}
-
-cScCiAdapter::~cScCiAdapter()
-{
- Cancel(3);
- ciMutex.Lock();
- delete rb; rb=0;
- ciMutex.Unlock();
-}
-
-void cScCiAdapter::CamStop(void)
-{
- if(cam) cam->Stop();
-}
-
-void cScCiAdapter::CamAddPrg(cPrg *prg)
-{
- if(cam) cam->AddPrg(prg);
-}
-
-bool cScCiAdapter::CamSoftCSA(void)
-{
- return cam && cam->IsSoftCSA();
-}
-
-int cScCiAdapter::GetCaids(int slot, unsigned short *Caids, int max)
-{
- BuildCaids(false);
- cMutexLock lock(&ciMutex);
- if(Caids) {
- int i;
- for(i=0; i<MAX_CI_SLOT_CAIDS && i<max && caids[i]; i++) Caids[i]=caids[slot][i];
- Caids[i]=0;
- }
- return version[slot];
-}
-
-void cScCiAdapter::BuildCaids(bool force)
-{
- if(caidTimer.TimedOut() || force) {
- PRINTF(L_CORE_CAIDS,"%d: building caid lists",cardIndex);
- cChannelList list(cardIndex);
- Channels.Lock(false);
- for(cChannel *channel=Channels.First(); channel; channel=Channels.Next(channel)) {
- if(!channel->GroupSep() && channel->Ca()>=CA_ENCRYPTED_MIN && device->ProvidesTransponder(channel)) {
- cChannelCaids *ch=new cChannelCaids(channel);
- if(ch) list.Add(ch);
- }
- }
- Channels.Unlock();
- list.Unique();
- list.CheckIgnore();
- list.Unique();
-
- int n=0, h;
- caid_t c[MAX_CI_SLOT_CAIDS+1];
- memset(c,0,sizeof(c));
- do {
- if((h=list.Histo())<0) break;
- c[n++]=h;
- LBSTART(L_CORE_CAIDS);
- LBPUT("%d: added %04x caids now",cardIndex,h); for(int i=0; i<n; i++) LBPUT(" %04x",c[i]);
- LBEND();
- list.Purge(h);
- } while(n<MAX_CI_SLOT_CAIDS && list.Count()>0);
- c[n]=0;
- if(n==0) PRINTF(L_CORE_CI,"no active CAIDs");
- else if(list.Count()>0) PRINTF(L_GEN_ERROR,"too many CAIDs. You should ignore some CAIDs.");
-
- ciMutex.Lock();
- if((version[0]==0 && c[0]!=0) || memcmp(caids[0],c,sizeof(caids[0]))) {
- memcpy(caids[0],c,sizeof(caids[0]));
- version[0]++;
- if(version[0]>0) {
- LBSTART(L_CORE_CI);
- LBPUT("card %d, slot %d (v=%2d) caids:",cardIndex,0,version[0]);
- for(int i=0; caids[0][i]; i++) LBPUT(" %04x",caids[0][i]);
- LBEND();
- }
- }
- ciMutex.Unlock();
-
- caidTimer.Set(CAID_TIME);
- }
-}
-
-int cScCiAdapter::Read(unsigned char *Buffer, int MaxLength)
-{
- cMutexLock lock(&ciMutex);
- if(cam && rb && Buffer && MaxLength>0) {
- int c;
- unsigned char *data=rb->Get(c);
- if(data) {
- int s=data[0];
- if(c>=s+1) {
- c=s>MaxLength ? MaxLength : s;
- memcpy(Buffer,&data[1],c);
- if(c<s) { data[c]=s-c; rb->Del(c); }
- else rb->Del(c+1);
- if(Buffer[2]!=0x80 || LOG(L_CORE_CIFULL)) {
- LDUMP(L_CORE_CI,Buffer,c,"%d.%d <-",cardIndex,Buffer[0]);
- readTimer.Set();
- }
- return c;
- }
- else {
- LDUMP(L_GEN_DEBUG,data,c,"internal: sc-ci %d rb frame sync got=%d avail=%d -",cardIndex,c,rb->Available());
- rb->Clear();
- }
- }
- }
- else cCondWait::SleepMs(CAM_READ_TIMEOUT);
- if(LOG(L_CORE_CIFULL) && readTimer.Elapsed()>2000) {
- PRINTF(L_CORE_CIFULL,"%d: read heartbeat",cardIndex);
- readTimer.Set();
- }
- return 0;
-}
-
-#define TPDU(data,slot) do { unsigned char *_d=(data); _d[0]=(slot); _d[1]=tcid; } while(0)
-#define TAG(data,tag,len) do { unsigned char *_d=(data); _d[0]=(tag); _d[1]=(len); } while(0)
-#define SB_TAG(data,sb) do { unsigned char *_d=(data); _d[0]=0x80; _d[1]=0x02; _d[2]=tcid; _d[3]=(sb); } while(0)
-#define PUT_TAG(data,len) do { unsigned char *_d=(data)-1; int _l=(len); _d[0]=_l; if(rb) rb->Put(_d,_l+1); } while(0)
-
-void cScCiAdapter::Write(const unsigned char *buff, int len)
-{
- cMutexLock lock(&ciMutex);
- if(cam && buff && len>=5) {
- unsigned char a[128], *b=&a[1];
- struct TPDU *tpdu=(struct TPDU *)buff;
- int slot=tpdu->slot;
- if(buff[2]!=0xA0 || buff[3]>0x01 || LOG(L_CORE_CIFULL))
- LDUMP(L_CORE_CI,buff,len,"%d.%d ->",cardIndex,slot);
- if(slots[slot]) {
- switch(tpdu->tag) {
- case 0x81: // T_RCV
- {
- TPDU(b,slot);
- int l=2, c;
- unsigned char *d=slots[slot]->Get(c);
- if(d) {
- int s=d[0];
- if(c>=s) {
- memcpy(&b[l],&d[1],s);
- l+=s;
- slots[slot]->Del(s+1);
- }
- else slots[slot]->Del(c);
- }
- SB_TAG(&b[l],0x00);
- PUT_TAG(b,l+4);
- break;
- }
- case 0x82: // T_CREATE_TC
- tcid=tpdu->data[0];
- TPDU(b,slot);
- TAG(&b[2],0x83,0x01); b[4]=tcid;
- SB_TAG(&b[5],0x00);
- PUT_TAG(b,9);
-
- static const unsigned char reqCAS[] = { 0xA0,0x07,0x01,0x91,0x04,0x00,0x03,0x00,0x41 };
- memcpy(b,reqCAS,sizeof(reqCAS));
- b[2]=tcid;
- a[0]=sizeof(reqCAS);
- slots[slot]->Put(a,sizeof(reqCAS)+1);
- break;
- case 0xA0: // T_DATA_LAST
- slots[slot]->Process(buff,len);
- TPDU(b,slot);
- SB_TAG(&b[2],slots[slot]->Available()>0 ? 0x80:0x00);
- PUT_TAG(b,6);
- break;
- }
- }
- }
- else PRINTF(L_CORE_CIFULL,"%d: short write (cam=%d buff=%d len=%d)",cardIndex,cam!=0,buff!=0,len);
-}
-
-bool cScCiAdapter::Reset(int Slot)
-{
- cMutexLock lock(&ciMutex);
- PRINTF(L_CORE_CI,"%d: reset of slot %d requested",cardIndex,Slot);
- return slots[Slot] ? slots[Slot]->Reset():false;
-}
-
-eModuleStatus cScCiAdapter::ModuleStatus(int Slot)
-{
- cMutexLock lock(&ciMutex);
- bool enable=ScSetup.CapCheck(cardIndex);
- if(!enable) CamStop();
- return (enable && cam && slots[Slot]) ? slots[Slot]->Status():msNone;
-}
-
-bool cScCiAdapter::Assign(cDevice *Device, bool Query)
-{
- return Device ? (Device==device) : true;
-}
-
-#endif //APIVERSNUM >= 10500
-
-// -- cDeCSA -------------------------------------------------------------------
-
-#define MAX_CSA_PIDS 8192
-#define MAX_CSA_IDX 16
-
-//#define DEBUG_CSA
-
-class cDeCSA {
-private:
- int cs;
- unsigned char **range;
- unsigned char pidmap[MAX_CSA_PIDS];
- void *keys[MAX_CSA_IDX];
- unsigned int even_odd[MAX_CSA_IDX];
- cMutex mutex;
- cCondVar wait;
- bool active;
- int cardindex;
- //
- bool GetKeyStruct(int idx);
-public:
- cDeCSA(int CardIndex);
- ~cDeCSA();
- bool Decrypt(unsigned char *data, int len, bool force);
- bool SetDescr(ca_descr_t *ca_descr, bool initial);
- bool SetCaPid(ca_pid_t *ca_pid);
- void SetActive(bool on);
- };
-
-cDeCSA::cDeCSA(int CardIndex)
-{
- cardindex=CardIndex;
- cs=get_suggested_cluster_size();
- PRINTF(L_CORE_CSA,"%d: clustersize=%d rangesize=%d",cardindex,cs,cs*2+5);
- range=MALLOC(unsigned char *,(cs*2+5));
- memset(keys,0,sizeof(keys));
- memset(even_odd,0,sizeof(even_odd));
- memset(pidmap,0,sizeof(pidmap));
-}
-
-cDeCSA::~cDeCSA()
-{
- for(int i=0; i<MAX_CSA_IDX; i++)
- if(keys[i]) free_key_struct(keys[i]);
- free(range);
-}
-
-void cDeCSA::SetActive(bool on)
-{
- active=on;
- PRINTF(L_CORE_CSA,"%d: set active %s",cardindex,active?"on":"off");
-}
-
-bool cDeCSA::GetKeyStruct(int idx)
-{
- if(!keys[idx]) keys[idx]=get_key_struct();
- return keys[idx]!=0;
-}
-
-bool cDeCSA::SetDescr(ca_descr_t *ca_descr, bool initial)
-{
- cMutexLock lock(&mutex);
- int idx=ca_descr->index;
- if(idx<MAX_CSA_IDX && GetKeyStruct(idx)) {
- if(!initial && active && ca_descr->parity==(even_odd[idx]&0x40)>>6) {
- PRINTF(L_CORE_CSA,"%d.%d: %s key in use",cardindex,idx,ca_descr->parity?"odd":"even");
- if(wait.TimedWait(mutex,100)) PRINTF(L_CORE_CSA,"%d.%d: successfully waited for release",cardindex,idx);
- else PRINTF(L_CORE_CSA,"%d.%d: timed out. setting anyways",cardindex,idx);
- }
- PRINTF(L_CORE_CSA,"%d.%d: %s key set",cardindex,idx,ca_descr->parity?"odd":"even");
- if(ca_descr->parity==0) set_even_control_word(keys[idx],ca_descr->cw);
- else set_odd_control_word(keys[idx],ca_descr->cw);
- }
- return true;
-}
-
-bool cDeCSA::SetCaPid(ca_pid_t *ca_pid)
-{
- cMutexLock lock(&mutex);
- if(ca_pid->index<MAX_CSA_IDX && ca_pid->pid<MAX_CSA_PIDS) {
- pidmap[ca_pid->pid]=ca_pid->index;
- PRINTF(L_CORE_CSA,"%d.%d: set pid %04x",cardindex,ca_pid->index,ca_pid->pid);
- }
- return true;
-}
-
-bool cDeCSA::Decrypt(unsigned char *data, int len, bool force)
-{
- cMutexLock lock(&mutex);
- int r=-2, ccs=0, currIdx=-1;
- bool newRange=true;
- range[0]=0;
- len-=(TS_SIZE-1);
- for(int l=0; l<len; l+=TS_SIZE) {
- if(data[l]!=TS_SYNC_BYTE) { // let higher level cope with that
- PRINTF(L_CORE_CSA,"%d: garbage in TS buffer",cardindex);
- break;
- }
- unsigned int ev_od=data[l+3]&0xC0;
- if(ev_od==0x80 || ev_od==0xC0) { // encrypted
- int idx=pidmap[((data[l+1]<<8)+data[l+2])&(MAX_CSA_PIDS-1)];
- if(currIdx<0 || idx==currIdx) { // same or no index
- currIdx=idx;
- if(ccs==0 && ev_od!=even_odd[idx]) {
- even_odd[idx]=ev_od;
- wait.Broadcast();
- PRINTF(L_CORE_CSA,"%d.%d: change to %s key",cardindex,idx,(ev_od&0x40)?"odd":"even");
- }
- if(newRange) {
- r+=2; newRange=false;
- range[r]=&data[l];
- range[r+2]=0;
- }
- range[r+1]=&data[l+TS_SIZE];
- if(++ccs>=cs) break;
- }
- else newRange=true; // other index, create hole
- }
- else { // unencrypted
- // nothing, we don't create holes for unencrypted packets
- }
- }
- if(r>=0) { // we have some range
- if(ccs>=cs || force) {
- if(GetKeyStruct(currIdx)) {
- int n=decrypt_packets(keys[currIdx],range);
-#ifdef DEBUG_CSA
- PRINTF(L_CORE_CSA,"%d.%d: decrypting ccs=%3d cs=%3d %s -> %3d decrypted",cardindex,currIdx,ccs,cs,ccs>=cs?"OK ":"INC",n);
-#endif
- if(n>0) return true;
- }
- }
-#ifdef DEBUG_CSA
- else PRINTF(L_CORE_CSA,"%d.%d: incomplete cluster ccs=%3d cs=%3d",cardindex,currIdx,ccs,cs);
-#endif
- }
- return false;
-}
-
-// -- cDeCsaTSBuffer -----------------------------------------------------------
-
-class cDeCsaTSBuffer : public cThread {
-private:
- int f;
- int cardIndex;
- bool delivered;
- cRingBufferLinear *ringBuffer;
- //
- cDeCSA *decsa;
- bool scActive;
- unsigned char *lastP;
- int lastCount;
- //
- virtual void Action(void);
-public:
- cDeCsaTSBuffer(int File, int Size, int CardIndex, cDeCSA *DeCsa, bool ScActive);
- ~cDeCsaTSBuffer();
- uchar *Get(void);
- void SetActive(bool ScActive);
- };
-
-cDeCsaTSBuffer::cDeCsaTSBuffer(int File, int Size, int CardIndex, cDeCSA *DeCsa, bool ScActive)
-{
- SetDescription("TS buffer on device %d", CardIndex);
- f=File; cardIndex=CardIndex; decsa=DeCsa;
- delivered=false;
- lastP=0; lastCount=0;
- ringBuffer=new cRingBufferLinear(Size,TS_SIZE,true,"FFdecsa-TS");
- ringBuffer->SetTimeouts(100,100);
- if(decsa) decsa->SetActive(true);
- SetActive(ScActive);
- Start();
-}
-
-cDeCsaTSBuffer::~cDeCsaTSBuffer()
-{
- Cancel(3);
- if(decsa) decsa->SetActive(false);
- delete ringBuffer;
-}
-
-void cDeCsaTSBuffer::SetActive(bool ScActive)
-{
- scActive=ScActive;
-}
-
-void cDeCsaTSBuffer::Action(void)
-{
- if(ringBuffer) {
- bool firstRead=true;
- cPoller Poller(f);
- while(Running()) {
- if(firstRead || Poller.Poll(100)) {
- firstRead=false;
- int r=ringBuffer->Read(f);
- if(r<0 && FATALERRNO) {
- if(errno==EOVERFLOW)
- esyslog("ERROR: driver buffer overflow on device %d",cardIndex);
- else { LOG_ERROR; break; }
- }
- }
- }
- }
-}
-
-uchar *cDeCsaTSBuffer::Get(void)
-{
- int Count=0;
- if(delivered) { ringBuffer->Del(TS_SIZE); delivered=false; }
- uchar *p=ringBuffer->Get(Count);
- if(p && Count>=TS_SIZE) {
- if(*p!=TS_SYNC_BYTE) {
- for(int i=1; i<Count; i++)
- if(p[i]==TS_SYNC_BYTE) { Count=i; break; }
- ringBuffer->Del(Count);
- esyslog("ERROR: skipped %d bytes to sync on TS packet on device %d",Count,cardIndex);
- return NULL;
- }
-
- if(scActive && (p[3]&0xC0)) {
- if(decsa) {
- if(!decsa->Decrypt(p,Count,(lastP==p && lastCount==Count))) {
- lastP=p; lastCount=Count;
- cCondWait::SleepMs(20);
- return NULL;
- }
- lastP=0;
- }
- else p[3]&=~0xC0; // FF hack
- }
-
- delivered=true;
- return p;
- }
- return NULL;
-}
-
-#endif //SASC
-
-// -- cScDvbDevice -------------------------------------------------------------
-
-int cScDvbDevice::budget=0;
-
-#ifndef SASC
-
-cScDvbDevice::cScDvbDevice(int n, int cafd)
-:cDvbDevice(n)
-{
- decsa=0; tsBuffer=0; cam=0;
-#if APIVERSNUM >= 10500
- ciadapter=0; hwciadapter=0;
-#endif
- memset(lrucaid,0,sizeof(lrucaid));
- fd_ca=cafd; fd_ca2=dup(fd_ca); fd_dvr=-1;
- softcsa=(fd_ca<0);
-}
-
-cScDvbDevice::~cScDvbDevice()
-{
- DetachAllReceivers();
- Cancel(3);
- EarlyShutdown();
- delete decsa;
- if(fd_ca>=0) close(fd_ca);
-#if APIVERSNUM >= 10500
- if(fd_ca2>=0) close(fd_ca2);
-#endif
-}
-
-void cScDvbDevice::EarlyShutdown(void)
-{
-#if APIVERSNUM >= 10500
- SetCamSlot(0);
- delete ciadapter; ciadapter=0;
- delete hwciadapter; hwciadapter=0;
-#endif
- if(cam) cam->Stop();
- delete cam; cam=0;
-}
-
-void cScDvbDevice::LateInit(void)
-{
- int n=CardIndex();
- if(DeviceNumber()!=n)
- PRINTF(L_GEN_ERROR,"CardIndex - DeviceNumber mismatch! Put SC plugin first on VDR commandline!");
- if(softcsa) {
- if(HasDecoder()) PRINTF(L_GEN_ERROR,"Card %d is a full-featured card but no ca device found!",n);
- }
- else if(ForceBudget(n)) {
- PRINTF(L_GEN_INFO,"Budget mode forced on card %d",n);
- softcsa=true;
- }
-
-#if APIVERSNUM >= 10500
- if(fd_ca2>=0) hwciadapter=cDvbCiAdapter::CreateCiAdapter(this,fd_ca2);
- cam=new cCam(this,n);
- ciadapter=new cScCiAdapter(this,n,cam);
-#else
- if(fd_ca2>=0) {
- ciHandler=cCiHandler::CreateCiHandler(fd_ca2);
- if(!ciHandler) close(fd_ca2);
- }
- cam=ScSetup.CapCheck(n) ? new cCam(this,n):0;
-#endif
- if(softcsa) {
- PRINTF(L_GEN_INFO,"Using software decryption on card %d",n);
- decsa=new cDeCSA(n);
- }
-}
-
-void cScDvbDevice::Shutdown(void)
-{
- for(int n=cDevice::NumDevices(); --n>=0;) {
- cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(n));
- if(dev) dev->EarlyShutdown();
- }
-}
-
-void cScDvbDevice::Startup(void)
-{
- if(ScSetup.ForceTransfer)
- SetTransferModeForDolbyDigital(2);
- for(int n=cDevice::NumDevices(); --n>=0;) {
- cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(n));
- if(dev) dev->LateInit();
- }
-}
-
-void cScDvbDevice::SetForceBudget(int n)
-{
- if(n>=0 && n<MAXDVBDEVICES) budget|=(1<<n);
-}
-
-bool cScDvbDevice::ForceBudget(int n)
-{
- return budget && (budget&(1<<n));
-}
-
-static int *vdr_nci=0, *vdr_ud=0, vdr_save_ud;
-
-void cScDvbDevice::Capture(void)
-{
-/*
- This is an extremly ugly hack to access VDRs device scan parameters, which are
- protected in this context. Heavily dependant on the actual symbol names
- created by the compiler. May fail in any future version!
-
- To get the actual symbol names of your VDR binary you may use the command:
- objdump -T <path-to-vdr>/vdr | grep -E "(useDevice|nextCardIndex)"
- Insert the symbol names below.
-*/
-#if __GNUC__ >= 3
- vdr_nci=(int *)dlsym(RTLD_DEFAULT,"_ZN7cDevice13nextCardIndexE");
- vdr_ud =(int *)dlsym(RTLD_DEFAULT,"_ZN7cDevice9useDeviceE");
-#else
- vdr_nci=(int *)dlsym(RTLD_DEFAULT,"_7cDevice.nextCardIndex");
- vdr_ud =(int *)dlsym(RTLD_DEFAULT,"_7cDevice.useDevice");
-#endif
- if(vdr_nci && vdr_ud) { vdr_save_ud=*vdr_ud; *vdr_ud=1<<30; }
-}
-
-bool cScDvbDevice::Initialize(void)
-{
- if(!vdr_nci || !vdr_ud) {
- PRINTF(L_GEN_ERROR,"Failed to locate VDR symbols. Plugin not operable");
- return false;
- }
- if(NumDevices()>0) {
- PRINTF(L_GEN_ERROR,"Number of devices != 0 on init. Put SC plugin first on VDR commandline! Aborting.");
- return false;
- }
- *vdr_nci=0; *vdr_ud=vdr_save_ud;
-
- int i, found=0;
- for(i=0; i<MAXDVBDEVICES; i++) {
- if(UseDevice(NextCardIndex())) {
- char name[128];
- DvbName(DEV_DVB_FRONTEND,i,name,sizeof(name));
- if(access(name,F_OK)==0) {
- PRINTF(L_GEN_DEBUG,"probing %s",name);
- int f=open(name,O_RDONLY);
- if(f>=0) {
- close(f);
- PRINTF(L_GEN_DEBUG,"capturing device %d",i);
- new cScDvbDevice(i,DvbOpen(DEV_DVB_CA,i,O_RDWR));
- found++;
- }
- else {
- if(errno!=ENODEV && errno!=EINVAL) PRINTF(L_GEN_ERROR,"open %s failed: %s",name,strerror(errno));
- break;
- }
- }
- else {
- if(errno!=ENOENT) PRINTF(L_GEN_ERROR,"access %s failed: %s",name,strerror(errno));
- break;
- }
- }
- else NextCardIndex(1);
- }
- NextCardIndex(MAXDVBDEVICES-i);
- if(found>0) PRINTF(L_GEN_INFO,"captured %d video device%s",found,found>1 ? "s" : "");
- else PRINTF(L_GEN_INFO,"no DVB device captured");
- return found>0;
-}
-
-#if APIVERSNUM >= 10501
-bool cScDvbDevice::HasCi(void)
-{
- return ciadapter || hwciadapter;
-}
-#endif
-
-#if APIVERSNUM >= 10500
-bool cScDvbDevice::Ready(void)
-{
- return (ciadapter ? ciadapter->Ready():true) &&
- (hwciadapter ? hwciadapter->Ready():true);
-}
-#endif
-
-bool cScDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On)
-{
- if(cam) cam->SetPid(Type,Handle->pid,On);
- tsMutex.Lock();
- if(tsBuffer) tsBuffer->SetActive(ScActive());
- tsMutex.Unlock();
- return cDvbDevice::SetPid(Handle,Type,On);
-}
-
-bool cScDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
-{
- lruMutex.Lock();
- int i=FindLRUPrg(Channel->Source(),Channel->Transponder(),Channel->Sid());
- if(i<0) i=MAX_LRU_CAID-1;
- if(i>0) memmove(&lrucaid[1],&lrucaid[0],sizeof(struct LruCaid)*i);
-#if APIVERSNUM >= 10500
- const caid_t *c=Channel->Caids();
- for(i=0; i<MAXCAIDS && *c; i++) lrucaid[0].caids[i]=*c++;
- lrucaid[0].caids[i]=0;
-#else
- for(i=0; i<=MAXCAIDS; i++) if((lrucaid[0].caids[i]=Channel->Ca(i))==0) break;
-#endif
- lrucaid[0].src=Channel->Source();
- lrucaid[0].tr=Channel->Transponder();
- lrucaid[0].prg=Channel->Sid();
- lruMutex.Unlock();
- if(cam) cam->Tune(Channel);
- bool ret=cDvbDevice::SetChannelDevice(Channel,LiveView);
- if(ret && cam) cam->PostTune();
- return ret;
-}
-
-bool cScDvbDevice::GetPrgCaids(int source, int transponder, int prg, caid_t *c)
-{
- cMutexLock lock(&lruMutex);
- int i=FindLRUPrg(source,transponder,prg);
- if(i>=0) {
- for(int j=0; j<MAXCAIDS && lrucaid[i].caids[j]; j++) *c++=lrucaid[i].caids[j];
- *c=0;
- return true;
- }
- return false;
-}
-
-int cScDvbDevice::FindLRUPrg(int source, int transponder, int prg)
-{
- for(int i=0; i<MAX_LRU_CAID; i++)
- if(lrucaid[i].src==source && lrucaid[i].tr==transponder && lrucaid[i].prg==prg) return i;
- return -1;
-}
-
-#if APIVERSNUM < 10500
-int cScDvbDevice::ProvidesCa(const cChannel *Channel) const
-{
- if(cam && Channel->Ca()>=CA_ENCRYPTED_MIN) {
- int j;
- caid_t ids[MAXCAIDS+1];
- for(j=0; j<=MAXCAIDS; j++) if((ids[j]=Channel->Ca(j))==0) break;
- if(cSystems::Provides(ids,!softcsa)>0) return 2;
- }
- return cDvbDevice::ProvidesCa(Channel);
-}
-
-bool cScDvbDevice::CiAllowConcurrent(void) const
-{
- return softcsa || ScSetup.ConcurrentFF>0;
-}
-
-void cScDvbDevice::CiStartDecrypting(void)
-{
- if(cam) {
- cSimpleList<cPrg> prgList;
- for(cCiCaProgramData *p=ciProgramList.First(); p; p=ciProgramList.Next(p)) {
- if(p->modified) {
- cPrg *prg=new cPrg(p->programNumber,cam->HasPrg(p->programNumber));
- if(prg) {
- for(cCiCaPidData *q=p->pidList.First(); q; q=p->pidList.Next(q)) {
- if(q->active)
- prg->pids.Add(new cPrgPid(q->streamType,q->pid));
- }
- prgList.Add(prg);
- }
- p->modified=false;
- }
- }
- for(int loop=1; loop<=2; loop++) // first delete, then add
- for(cPrg *prg=prgList.First(); prg; prg=prgList.Next(prg))
- if((loop==1)!=(prg->pids.Count()>0))
- cam->AddPrg(prg);
- }
- cDvbDevice::CiStartDecrypting();
-}
-#endif //APIVERSNUM < 10500
-
-bool cScDvbDevice::ScActive(void)
-{
-#if APIVERSNUM >= 10500
- return dynamic_cast<cScCamSlot *>(CamSlot())!=0;
-#else
- return cam && softcsa;
-#endif
-}
-
-bool cScDvbDevice::OpenDvr(void)
-{
- CloseDvr();
- fd_dvr=DvbOpen(DEV_DVB_DVR,CardIndex(),O_RDONLY|O_NONBLOCK,true);
- if(fd_dvr>=0) {
- tsMutex.Lock();
- tsBuffer=new cDeCsaTSBuffer(fd_dvr,MEGABYTE(2),CardIndex()+1,decsa,ScActive());
- tsMutex.Unlock();
- }
- return fd_dvr>=0;
-}
-
-void cScDvbDevice::CloseDvr(void)
-{
- tsMutex.Lock();
- delete tsBuffer; tsBuffer=0;
- tsMutex.Unlock();
- if(fd_dvr>=0) { close(fd_dvr); fd_dvr=-1; }
-}
-
-bool cScDvbDevice::GetTSPacket(uchar *&Data)
-{
- if(tsBuffer) { Data=tsBuffer->Get(); return true; }
- return false;
-}
-
-bool cScDvbDevice::SetCaDescr(ca_descr_t *ca_descr, bool initial)
-{
- if(!softcsa) {
- cMutexLock lock(&cafdMutex);
- return ioctl(fd_ca,CA_SET_DESCR,ca_descr)>=0;
- }
- else if(decsa) return decsa->SetDescr(ca_descr,initial);
- return false;
-}
-
-bool cScDvbDevice::SetCaPid(ca_pid_t *ca_pid)
-{
- if(!softcsa) {
- cMutexLock lock(&cafdMutex);
- return ioctl(fd_ca,CA_SET_PID,ca_pid)>=0;
- }
- else if(decsa) return decsa->SetCaPid(ca_pid);
- return false;
-}
-
-static unsigned int av7110_read(int fd, unsigned int addr)
-{
- ca_pid_t arg;
- arg.pid=addr;
- ioctl(fd,CA_GET_MSG,&arg);
- return arg.index;
-}
-
-#if 0
-static void av7110_write(int fd, unsigned int addr, unsigned int val)
-{
- ca_pid_t arg;
- arg.pid=addr;
- arg.index=val;
- ioctl(fd,CA_SEND_MSG,&arg);
-}
-#endif
-
-void cScDvbDevice::DumpAV7110(void)
-{
- if(LOG(L_CORE_AV7110)) {
-#define CODEBASE (0x2e000404+0x1ce00)
- cMutexLock lock(&cafdMutex);
- if(HasDecoder() && lastDump.Elapsed()>20000) {
- lastDump.Set();
- static unsigned int handles=0, hw_handles=0;
- static const unsigned int code[] = {
- 0xb5100040,0x4a095a12,0x48094282,0xd00b4b09,0x20000044,
- 0x5b1c4294,0xd0033001,0x281cdbf8,0xe001f7fe,0xfd14bc10
- };
- static const unsigned int mask[] = {
- 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,
- 0xffffffff,0xffffffff,0xffffffff,0xfffff800,0xf800ffff
- };
- if(!handles) {
- handles=1;
- PRINTF(L_CORE_AV7110,"searching handle tables");
- for(int i=0; i<0x2000; i+=4) {
- int j;
- for(j=0; j<20; j+=4) {
- int r=av7110_read(fd_ca,CODEBASE+i+j);
- if((r&mask[j/4])!=(code[j/4]&mask[j/4])) break;
- }
- if(j==20) {
- handles=av7110_read(fd_ca,CODEBASE+i+44);
- hw_handles=av7110_read(fd_ca,CODEBASE+i+52);
- PRINTF(L_CORE_AV7110,"found handles=%08x hw_handles=%08x at 0x%08x",handles,hw_handles,CODEBASE+i);
- if((handles>>16)!=0x2e08 || (hw_handles>>16)!=0x2e08) {
- PRINTF(L_CORE_AV7110,"seems to be invalid");
- }
- break;
- }
- }
- }
-
- unsigned int hdl=0, hwhdl=0;
- PRINTF(L_CORE_AV7110," : 64000080 64000400");
- for(int i=0; i<=31; i++) {
- unsigned int off80 =av7110_read(fd_ca,0x64000080+i*4);
- unsigned int off400=av7110_read(fd_ca,0x64000400+i*8);
- LBSTART(L_CORE_AV7110);
- LBPUT("handle %2d: %08x %08x %s pid=%04x idx=%d",
- i,off80,off400,off80&0x2000?"ACT":"---",off80&0x1fff,(off400&0x1e)>>1);
- if(handles>1 && i<=27) {
- if((i&1)==0) {
- hdl=av7110_read(fd_ca,handles+i*2);
- hwhdl=av7110_read(fd_ca,hw_handles+i*2);
- }
- unsigned int s=((~i)&1)<<4;
- LBPUT(" | %02d hdl=%04x hwfilt=%04x",i,(hdl>>s)&0xffff,(hwhdl>>s)&0xffff);
- }
- LBEND();
- }
- }
- }
-}
-
-#else //SASC
-
-cScDvbDevice::cScDvbDevice(int n, int cafd)
-:cDvbDevice(n)
-{
- softcsa=false;
- cam=new cCam(this,n);
-}
-
-cScDvbDevice::~cScDvbDevice()
-{
- delete cam;
-}
-
-void cScDvbDevice::Shutdown(void)
-{}
-
-void cScDvbDevice::Startup(void)
-{}
-
-void cScDvbDevice::SetForceBudget(int n)
-{}
-
-bool cScDvbDevice::ForceBudget(int n)
-{
- return true;
-}
-
-void cScDvbDevice::Capture(void)
-{}
-
-bool cScDvbDevice::Initialize(void)
-{
- return true;
-}
-
-bool cScDvbDevice::GetPrgCaids(int source, int transponder, int prg, caid_t *c)
-{
- return false;
-}
-
-bool cScDvbDevice::SetCaDescr(ca_descr_t *ca_descr, bool initial)
-{
- return false;
-}
-
-bool cScDvbDevice::SetCaPid(ca_pid_t *ca_pid)
-{
- return false;
-}
-
-void cScDvbDevice::DumpAV7110(void)
-{}
-
-#endif //SASC
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___CAM_H
-#define ___CAM_H
-
-#include <linux/dvb/ca.h>
-#include <vdr/dvbdevice.h>
-#include <vdr/thread.h>
-#include "data.h"
-#include "misc.h"
-
-class cChannel;
-
-class cEcmHandler;
-class cEcmData;
-class cLogger;
-class cHookManager;
-class cLogHook;
-class cDeCSA;
-class cDeCsaTSBuffer;
-class cScCiAdapter;
-class cScDvbDevice;
-class cPrg;
-
-// ----------------------------------------------------------------
-
-class cEcmCache : public cStructListPlain<cEcmData> {
-private:
- cEcmData *Exists(cEcmInfo *e);
-protected:
- virtual bool ParseLinePlain(const char *line);
-public:
- cEcmCache(void);
- void New(cEcmInfo *e);
- int GetCached(cSimpleList<cEcmInfo> *list, int sid, int Source, int Transponder);
- void Delete(cEcmInfo *e);
- void Flush(void);
- };
-
-extern cEcmCache ecmcache;
-
-// ----------------------------------------------------------------
-
-class cPrgPid : public cSimpleItem {
-private:
- int type, pid;
- bool proc;
-public:
- cPrgPid(int Type, int Pid) { type=Type; pid=Pid; proc=false; }
- int Pid(void) { return pid; }
- int Type(void) { return type; }
- bool Proc(void) { return proc; }
- void Proc(bool is) { proc=is; };
- };
-
-// ----------------------------------------------------------------
-
-class cPrg : public cSimpleItem {
-private:
- int prg;
- bool isUpdate;
-public:
- cSimpleList<cPrgPid> pids;
- //
- cPrg(int Prg, bool IsUpdate) { prg=Prg; isUpdate=IsUpdate; }
- int Prg(void) { return prg; }
- bool IsUpdate(void) { return isUpdate; }
- };
-
-// ----------------------------------------------------------------
-
-#if APIVERSNUM >= 10500
-typedef int caid_t;
-#else
-typedef unsigned short caid_t;
-#endif
-
-#define MAX_CW_IDX 16
-#define MAX_CI_SLOTS 8
-#ifdef VDR_MAXCAID
-#define MAX_CI_SLOT_CAIDS VDR_MAXCAID
-#else
-#define MAX_CI_SLOT_CAIDS 16
-#endif
-
-class cCam : private cMutex {
-private:
- int cardNum;
- cScDvbDevice *device;
- cSimpleList<cEcmHandler> handlerList;
- cLogger *logger;
- cHookManager *hookman;
- int source, transponder, liveVpid, liveApid;
- unsigned char indexMap[MAX_CW_IDX], lastCW[MAX_CW_IDX][2*8];
- //
- cEcmHandler *GetHandler(int sid, bool needZero, bool noshift);
- void RemHandler(cEcmHandler *handler);
- int GetFreeIndex(void);
- void LogStartup(void);
-public:
- cCam(cScDvbDevice *dev, int CardNum);
- virtual ~cCam();
- // EcmHandler API
- void WriteCW(int index, unsigned char *cw, bool force);
- void SetCWIndex(int pid, int index);
- void DumpAV7110(void);
- void LogEcmStatus(const cEcmInfo *ecm, bool on);
- bool GetPrgCaids(int source, int transponder, int prg, caid_t *c);
- void AddHook(cLogHook *hook);
- bool TriggerHook(int id);
- // Plugin API
- bool Active(bool log);
- void HouseKeeping(void);
- void Tune(const cChannel *channel);
- void PostTune(void);
- void SetPid(int type, int pid, bool on);
- void Stop(void);
- void AddPrg(cPrg *prg);
- bool HasPrg(int prg);
- char *CurrentKeyStr(int num);
- //
- bool IsSoftCSA(void);
- int Source(void) { return source; }
- int Transponder(void) { return transponder; }
- };
-
-void LogStatsDown(void);
-
-// ----------------------------------------------------------------
-
-#define MAX_LRU_CAID 10
-
-class cScDvbDevice : public cDvbDevice {
-private:
- cDeCSA *decsa;
- cDeCsaTSBuffer *tsBuffer;
- cMutex tsMutex;
-#if APIVERSNUM >= 10500
- cScCiAdapter *ciadapter;
- cCiAdapter *hwciadapter;
-#endif
- cCam *cam;
- int fd_dvr, fd_ca, fd_ca2;
- bool softcsa;
- cMutex cafdMutex;
- cTimeMs lastDump;
- struct LruCaid {
- int src, tr, prg;
- caid_t caids[MAXCAIDS+1];
- } lrucaid[MAX_LRU_CAID];
- cMutex lruMutex;
- static int budget;
- //
-#ifndef SASC
- void LateInit(void);
- void EarlyShutdown(void);
- int FindLRUPrg(int source, int transponder, int prg);
- bool ScActive(void);
-#endif //SASC
-protected:
-#ifndef SASC
-#if APIVERSNUM >= 10500
- virtual bool Ready(void);
-#else
- virtual void CiStartDecrypting(void);
- virtual bool CiAllowConcurrent(void) const;
-#endif
- virtual bool SetPid(cPidHandle *Handle, int Type, bool On);
- virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
- virtual bool OpenDvr(void);
- virtual void CloseDvr(void);
- virtual bool GetTSPacket(uchar *&Data);
-#endif //SASC
-public:
- cScDvbDevice(int n, int cafd);
- ~cScDvbDevice();
-#ifndef SASC
-#if APIVERSNUM >= 10501
- virtual bool HasCi(void);
-#endif
-#if APIVERSNUM < 10500
- virtual int ProvidesCa(const cChannel *Channel) const;
-#endif
-#endif //SASC
- static void Capture(void);
- static bool Initialize(void);
- static void Startup(void);
- static void Shutdown(void);
- static void SetForceBudget(int n);
- static bool ForceBudget(int n);
- virtual bool SetCaDescr(ca_descr_t *ca_descr, bool initial);
- virtual bool SetCaPid(ca_pid_t *ca_pid);
- void DumpAV7110(void);
- cCam *Cam(void) { return cam; }
- bool SoftCSA(void) { return softcsa; }
- virtual bool GetPrgCaids(int source, int transponder, int prg, caid_t *c);
- };
-
-#endif // ___CAM_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___COMMON_H
-#define ___COMMON_H
-
-// Debugging
-#define DEBUG
-//#define DEBUG_DYN
-#define DEBUG_LOG_FILE "/var/tmp/logger.log"
-
-#ifdef DEBUG
-#define d(x) { (x); }
-#else
-#define d(x) ;
-#endif
-
-#ifdef DEBUG_DYN
-#define dyn(x) { (x); }
-#else
-#define dyn(x) ;
-#endif
-
-#endif //___COMMON_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___CRYPTO_BN_H
-#define ___CRYPTO_BN_H
-
-#include <openssl/bn.h>
-
-// ----------------------------------------------------------------
-
-void RotateBytes(unsigned char *in, int n);
-void RotateBytes(unsigned char *out, const unsigned char *in, int n);
-
-// ----------------------------------------------------------------
-
-class cBN {
-private:
- BIGNUM big;
-public:
- cBN(void) { BN_init(&big); }
- ~cBN() { BN_free(&big); }
- operator BIGNUM* () { return &big; }
- BIGNUM *operator->() { return &big; }
- bool Get(const unsigned char *in, int n);
- bool GetLE(const unsigned char *in, int n);
- int Put(unsigned char *out, int n) const;
- int PutLE(unsigned char *out, int n) const;
- };
-
-class cBNctx {
-private:
- BN_CTX *ctx;
-public:
- cBNctx(void) { ctx=BN_CTX_new(); }
- ~cBNctx() { BN_CTX_free(ctx); }
- operator BN_CTX* () { return ctx; }
- };
-
-#endif //___CRYPTO_BN_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "crypto.h"
-#include "helper.h"
-#include "log.h"
-
-// -----------------------------------------------------------------------------
-
-void RotateBytes(unsigned char *out, const unsigned char *in, int n)
-{
- if(n>0) {
- out+=n;
- do { *(--out)=*(in++); } while(--n);
- }
-}
-
-void RotateBytes(unsigned char *in, int n)
-{
- if(n>1) {
- unsigned char *e=in+n-1;
- do {
- unsigned char temp=*in;
- *in++=*e;
- *e-- =temp;
- } while(in<e);
- }
-}
-
-// -- cBN ----------------------------------------------------------------------
-
-bool cBN::Get(const unsigned char *in, int n)
-{
- return BN_bin2bn(in,n,&big)!=0;
-}
-
-int cBN::Put(unsigned char *out, int n) const
-{
- int s=BN_num_bytes(&big);
- if(s>n) {
- unsigned char *buff=AUTOMEM(s);
- BN_bn2bin(&big,buff);
- memcpy(out,buff+s-n,n);
- }
- else if(s<n) {
- int l=n-s;
- memset(out,0,l);
- BN_bn2bin(&big,out+l);
- }
- else BN_bn2bin(&big,out);
- return s;
-}
-
-bool cBN::GetLE(const unsigned char *in, int n)
-{
- unsigned char *tmp=AUTOMEM(n);
- RotateBytes(tmp,in,n);
- return BN_bin2bn(tmp,n,&big)!=0;
-}
-
-int cBN::PutLE(unsigned char *out, int n) const
-{
- int s=Put(out,n);
- RotateBytes(out,n);
- return s;
-}
-
-// -- cIDEA --------------------------------------------------------------------
-
-#ifndef OPENSSL_HAS_IDEA
-#warning ** openssl lacks IDEA support. Using deprecated static support code. Update your openssl package.
-#include "support/i_cbc.c"
-#include "support/i_skey.c"
-#endif
-
-void cIDEA::Decrypt(unsigned char *data, int len, const unsigned char *key, unsigned char *iv) const
-{
- unsigned char v[8];
- if(!iv) { memset(v,0,sizeof(v)); iv=v; }
- IDEA_KEY_SCHEDULE ks;
- idea_set_encrypt_key(key,&ks);
- idea_cbc_encrypt(data,data,len&~7,&ks,iv,IDEA_DECRYPT);
-}
-
-int cIDEA::Encrypt(const unsigned char *data, int len, unsigned char *crypt, const unsigned char *key, unsigned char *iv) const
-{
- unsigned char v[8];
- if(!iv) { memset(v,0,sizeof(v)); iv=v; }
- len&=~7;
- IDEA_KEY_SCHEDULE ks;
- idea_set_encrypt_key(key,&ks);
- idea_cbc_encrypt(data,crypt,len,&ks,iv,IDEA_ENCRYPT);
- return len;
-}
-
-void cIDEA::SetEncKey(const unsigned char *key, IdeaKS *ks) const
-{
- idea_set_encrypt_key(key,ks);
-}
-
-void cIDEA::SetDecKey(const unsigned char *key, IdeaKS *ks) const
-{
- IDEA_KEY_SCHEDULE tmp;
- idea_set_encrypt_key(key,&tmp);
- idea_set_decrypt_key(&tmp,ks);
-}
-
-void cIDEA::Decrypt(unsigned char *data, int len, IdeaKS *ks, unsigned char *iv) const
-{
- unsigned char v[8];
- if(!iv) { memset(v,0,sizeof(v)); iv=v; }
- idea_cbc_encrypt(data,data,len&~7,ks,iv,IDEA_DECRYPT);
-}
-
-int cIDEA::Encrypt(const unsigned char *data, int len, unsigned char *crypt, IdeaKS *ks, unsigned char *iv) const
-{
- unsigned char v[8];
- if(!iv) { memset(v,0,sizeof(v)); iv=v; }
- idea_cbc_encrypt(data,crypt,len&~7,ks,iv,IDEA_ENCRYPT);
- return len;
-}
-
-// -- cRSA ---------------------------------------------------------------------
-
-bool cRSA::Input(cBN *d, const unsigned char *in, int n, bool LE) const
-{
- if(LE) return d->GetLE(in,n);
- else return d->Get(in,n);
-}
-
-int cRSA::Output(unsigned char *out, int n, cBN *r, bool LE) const
-{
- if(LE) return r->PutLE(out,n);
- else return r->Put(out,n);
-}
-
-int cRSA::RSA(unsigned char *out, const unsigned char *in, int n, const BIGNUM *exp, const BIGNUM *mod, bool LE) const
-{
- cBNctx ctx;
- cBN r, d;
- if(Input(&d,in,n,LE)) {
- if(BN_mod_exp(r,d,exp,mod,ctx)) return Output(out,n,&r,LE);
- PRINTF(L_GEN_ERROR,"rsa: mod-exp failed");
- }
- return 0;
-}
-
-int cRSA::RSA(BIGNUM *out, const unsigned char *in, int n, const BIGNUM *exp, const BIGNUM *mod, bool LE) const
-{
- cBNctx ctx;
- cBN d;
- if(Input(&d,in,n,LE)) {
- if(BN_mod_exp(out,d,exp,mod,ctx)) return BN_num_bytes(out);
- PRINTF(L_GEN_ERROR,"rsa: mod-exp failed");
- }
- return 0;
-}
-
-int cRSA::RSA(unsigned char *out, int n, BIGNUM *in, const BIGNUM *exp, const BIGNUM *mod, bool LE) const
-{
- cBNctx ctx;
- cBN r;
- if(BN_mod_exp(r,in,exp,mod,ctx)) return Output(out,n,&r,LE);
- PRINTF(L_GEN_ERROR,"rsa: mod-exp failed");
- return 0;
-}
-
-// -- cDes ---------------------------------------------------------------------
-
-const unsigned char cDes::_PC1[] = {
- 57,49,41,33,25,17, 9, 1,
- 58,50,42,34,26,18,10, 2,
- 59,51,43,35,27,19,11, 3,
- 60,52,44,36,63,55,47,39,
- 31,23,15, 7,62,54,46,38,
- 30,22,14, 6,61,53,45,37,
- 29,21,13, 5,28,20,12, 4
- };
-
-const unsigned char cDes::_PC2[] = {
- 14,17,11,24, 1, 5, 3,28,15, 6,21,10,
- 23,19,12, 4,26, 8, 16, 7,27,20,13, 2,
- 41,52,31,37,47,55, 30,40,51,45,33,48,
- 44,49,39,56,34,53, 46,42,50,36,29,32
- };
-
-const unsigned char cDes::_E[] = {
- 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,
- 8, 9,10,11,12,13, 12,13,14,15,16,17,
- 16,17,18,19,20,21, 20,21,22,23,24,25,
- 24,25,26,27,28,29, 28,29,30,31,32, 1
- };
-
-const unsigned char cDes::_P[] = {
- 16, 7,20,21, 29,12,28,17,
- 1,15,23,26, 5,18,31,10,
- 2, 8,24,14, 32,27, 3, 9,
- 19,13,30, 6, 22,11, 4,25
- };
-
-const unsigned char cDes::IP[] = {
- 58,50,42,34,26,18,10,2, 60,52,44,36,28,20,12,4,
- 62,54,46,38,30,22,14,6, 64,56,48,40,32,24,16,8,
- 57,49,41,33,25,17, 9,1, 59,51,43,35,27,19,11,3,
- 61,53,45,37,29,21,13,5, 63,55,47,39,31,23,15,7
- };
-
-const unsigned char cDes::FP[] = {
- 40,8,48,16,56,24,64,32, 39,7,47,15,55,23,63,31,
- 38,6,46,14,54,22,62,30, 37,5,45,13,53,21,61,29,
- 36,4,44,12,52,20,60,28, 35,3,43,11,51,19,59,27,
- 34,2,42,10,50,18,58,26, 33,1,41, 9,49,17,57,25
- };
-
-const unsigned char cDes::S[][64] = {
- { 0xe,0x0,0x4,0xf,0xd,0x7,0x1,0x4, 0x2,0xe,0xf,0x2,0xb,0xd,0x8,0x1,
- 0x3,0xa,0xa,0x6,0x6,0xc,0xc,0xb, 0x5,0x9,0x9,0x5,0x0,0x3,0x7,0x8,
- 0x4,0xf,0x1,0xc,0xe,0x8,0x8,0x2, 0xd,0x4,0x6,0x9,0x2,0x1,0xb,0x7,
- 0xf,0x5,0xc,0xb,0x9,0x3,0x7,0xe, 0x3,0xa,0xa,0x0,0x5,0x6,0x0,0xd
- },
- { 0xf,0x3,0x1,0xd,0x8,0x4,0xe,0x7, 0x6,0xf,0xb,0x2,0x3,0x8,0x4,0xe,
- 0x9,0xc,0x7,0x0,0x2,0x1,0xd,0xa, 0xc,0x6,0x0,0x9,0x5,0xb,0xa,0x5,
- 0x0,0xd,0xe,0x8,0x7,0xa,0xb,0x1, 0xa,0x3,0x4,0xf,0xd,0x4,0x1,0x2,
- 0x5,0xb,0x8,0x6,0xc,0x7,0x6,0xc, 0x9,0x0,0x3,0x5,0x2,0xe,0xf,0x9
- },
- { 0xa,0xd,0x0,0x7,0x9,0x0,0xe,0x9, 0x6,0x3,0x3,0x4,0xf,0x6,0x5,0xa,
- 0x1,0x2,0xd,0x8,0xc,0x5,0x7,0xe, 0xb,0xc,0x4,0xb,0x2,0xf,0x8,0x1,
- 0xd,0x1,0x6,0xa,0x4,0xd,0x9,0x0, 0x8,0x6,0xf,0x9,0x3,0x8,0x0,0x7,
- 0xb,0x4,0x1,0xf,0x2,0xe,0xc,0x3, 0x5,0xb,0xa,0x5,0xe,0x2,0x7,0xc
- },
- { 0x7,0xd,0xd,0x8,0xe,0xb,0x3,0x5, 0x0,0x6,0x6,0xf,0x9,0x0,0xa,0x3,
- 0x1,0x4,0x2,0x7,0x8,0x2,0x5,0xc, 0xb,0x1,0xc,0xa,0x4,0xe,0xf,0x9,
- 0xa,0x3,0x6,0xf,0x9,0x0,0x0,0x6, 0xc,0xa,0xb,0x1,0x7,0xd,0xd,0x8,
- 0xf,0x9,0x1,0x4,0x3,0x5,0xe,0xb, 0x5,0xc,0x2,0x7,0x8,0x2,0x4,0xe
- },
- { 0x2,0xe,0xc,0xb,0x4,0x2,0x1,0xc, 0x7,0x4,0xa,0x7,0xb,0xd,0x6,0x1,
- 0x8,0x5,0x5,0x0,0x3,0xf,0xf,0xa, 0xd,0x3,0x0,0x9,0xe,0x8,0x9,0x6,
- 0x4,0xb,0x2,0x8,0x1,0xc,0xb,0x7, 0xa,0x1,0xd,0xe,0x7,0x2,0x8,0xd,
- 0xf,0x6,0x9,0xf,0xc,0x0,0x5,0x9, 0x6,0xa,0x3,0x4,0x0,0x5,0xe,0x3
- },
- { 0xc,0xa,0x1,0xf,0xa,0x4,0xf,0x2, 0x9,0x7,0x2,0xc,0x6,0x9,0x8,0x5,
- 0x0,0x6,0xd,0x1,0x3,0xd,0x4,0xe, 0xe,0x0,0x7,0xb,0x5,0x3,0xb,0x8,
- 0x9,0x4,0xe,0x3,0xf,0x2,0x5,0xc, 0x2,0x9,0x8,0x5,0xc,0xf,0x3,0xa,
- 0x7,0xb,0x0,0xe,0x4,0x1,0xa,0x7, 0x1,0x6,0xd,0x0,0xb,0x8,0x6,0xd
- },
- { 0x4,0xd,0xb,0x0,0x2,0xb,0xe,0x7, 0xf,0x4,0x0,0x9,0x8,0x1,0xd,0xa,
- 0x3,0xe,0xc,0x3,0x9,0x5,0x7,0xc, 0x5,0x2,0xa,0xf,0x6,0x8,0x1,0x6,
- 0x1,0x6,0x4,0xb,0xb,0xd,0xd,0x8, 0xc,0x1,0x3,0x4,0x7,0xa,0xe,0x7,
- 0xa,0x9,0xf,0x5,0x6,0x0,0x8,0xf, 0x0,0xe,0x5,0x2,0x9,0x3,0x2,0xc
- },
- { 0xd,0x1,0x2,0xf,0x8,0xd,0x4,0x8, 0x6,0xa,0xf,0x3,0xb,0x7,0x1,0x4,
- 0xa,0xc,0x9,0x5,0x3,0x6,0xe,0xb, 0x5,0x0,0x0,0xe,0xc,0x9,0x7,0x2,
- 0x7,0x2,0xb,0x1,0x4,0xe,0x1,0x7, 0x9,0x4,0xc,0xa,0xe,0x8,0x2,0xd,
- 0x0,0xf,0x6,0xc,0xa,0x9,0xd,0x0, 0xf,0x3,0x3,0x5,0x5,0x6,0x8,0xb
- } };
-
-const unsigned char cDes::LS[] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 };
-
-/* actualy slower ... :-(
-#if defined __GNUC__ && __GNUC__ >= 2
-#define shiftin(V,R,n) ({unsigned int VV; \
- __asm__ ("btl %3,%2\n\tadcl %0,%0" : "=g" (VV) : "0" (V), "g" (R), "r" (n) : "cc"); \
- VV; })
-#else
-*/
-#define shiftin(V,R,n) ((V<<1)+(((R)>>(n))&1))
-#define rol28(V,n) ((V<<(n) ^ V>>(28-(n)))&0xfffffffL)
-#define ror28(V,n) ((V>>(n) ^ V<<(28-(n)))&0xfffffffL)
-
-#if defined __GNUC__ && __GNUC__ >= 2
-#if defined __i486__ || defined __pentium__ || defined __pentiumpro__ || defined __amd64__
-#define hash(T) ({unsigned int TT; \
- __asm__("bswapl %k0\n\trorw $8,%w0\n\tbswapl %k0" : "=g" (TT) : "0" (T) : "cc"); \
- TT; })
-#elif defined __i386__
-#define hash(T) ({unsigned int TT; \
- __asm__("rorl $16,%k0\n\trorw $8,%w0\n\troll $16,%k0" : "=g" (TT) : "0" (T) : "cc"); \
- TT; })
-#endif
-#endif
-#ifndef hash // fallback default
-#define hash(T) ((T&0x0000ffffL) | ((T>>8)&0x00ff0000L) | ((T<<8)&0xff000000L))
-#endif
-
-#define DESROUND(C,D,T) { \
- unsigned int s=0; \
- for(int j=7, k=0; j>=0; j--) { \
- unsigned int v=0, K=0; \
- for(int t=5; t>=0; t--, k++) { \
- v=shiftin(v,T,E[k]); \
- if(PC2[k]<29) K=shiftin(K,C,28-PC2[k]); \
- else K=shiftin(K,D,56-PC2[k]); \
- } \
- s=(s<<4) + S[7-j][v^K]; \
- } \
- T=0; \
- for(int j=31; j>=0; j--) T=shiftin(T,s,P[j]); \
- }
-
-#define DESHASH(T) { if(mode&DES_HASH) T=hash(T); }
-
-cDes::cDes(const unsigned char *pc1, const unsigned char *pc2)
-{
- PC1=pc1 ? pc1 : _PC1;
- PC2=pc2 ? pc2 : _PC2;
- for(int i=0; i<48; i++) E[i]=32-_E[i];
- for(int i=0; i<32; i++) P[i]=32-_P[31-i];
-}
-
-void cDes::Permute(unsigned char *data, const unsigned char *P, int n) const
-{
- unsigned char pin[8];
- for(int i=0, k=0; k<n; i++) {
- int p=0;
- for(int j=7; j>=0; j--,k++) {
- const int t=P[k]-1;
- p=shiftin(p,data[t>>3],7-(t&7));
- }
- pin[i]=p;
- }
- memcpy(data,pin,8);
-}
-
-void cDes::Des(unsigned char *data, const unsigned char *key, int mode) const
-{
- unsigned char mkey[8];
- if(mode&DES_PC1) {
- memcpy(mkey,key,sizeof(mkey));
- Permute(mkey,PC1,56);
- key=mkey;
- }
- if(mode&DES_IP) Permute(data,IP,64);
- unsigned int C=UINT32_BE(key ) >> 4;
- unsigned int D=UINT32_BE(key+3) & 0xfffffffL;
- unsigned int L=UINT32_BE(data );
- unsigned int R=UINT32_BE(data+4);
- if(!(mode&DES_RIGHT)) {
- for(int i=15; i>=0; i--) {
- C=rol28(C,LS[15-i]); D=rol28(D,LS[15-i]);
- unsigned int T=R;
- if(mode&DES_MOD) T=Mod(T,key[7]); // apply costum mod e.g. Viaccess
- DESROUND(C,D,T);
- DESHASH(T);
- T^=L; L=R; R=T;
- }
- }
- else {
- for(int i=15; i>=0; i--) {
- unsigned int T=R;
- if(mode&DES_MOD) T=Mod(T,key[7]); // apply costum mod e.g. Viaccess
- DESROUND(C,D,T);
- DESHASH(T);
- T^=L; L=R; R=T;
- C=ror28(C,LS[i]); D=ror28(D,LS[i]);
- }
- }
- BYTE4_BE(data ,R);
- BYTE4_BE(data+4,L);
- if(mode&DES_FP) Permute(data,FP,64);
-}
-
-// -- cAES ---------------------------------------------------------------------
-
-#ifndef OPENSSL_HAS_AES
-#warning ** openssl lacks AES support. Using deprecated static support code. Update your openssl package.
-#include "support/aes_core.c"
-#endif
-
-cAES::cAES(void)
-{
- active=false;
-}
-
-void cAES::SetKey(const unsigned char *key)
-{
- AES_set_decrypt_key(key,128,&dkey);
- AES_set_encrypt_key(key,128,&ekey);
- active=true;
-}
-
-int cAES::Encrypt(const unsigned char *data, int len, unsigned char *crypt) const
-{
- if(active) {
- len=(len+15)&(~15); // pad up to a multiple of 16
- for(int i=0; i<len; i+=16) AES_encrypt(data+i,crypt+i,(const AES_KEY *)&ekey);
- return len;
- }
- return -1;
-}
-
-void cAES::Decrypt(unsigned char *data, int len) const
-{
- if(active)
- for(int i=0; i<len; i+=16) AES_decrypt(data+i,data+i,(const AES_KEY *)&dkey);
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___CRYPTO_H
-#define ___CRYPTO_H
-
-//
-// NOTE: all crypto classes SHOULD be fully reentrant.
-// They may be called from different threads concurrently.
-//
-// NOTE: cAES is not fully reentrant. Encrypt/Decrypt are reentrant
-// (as AES_KEY is const there), but SetKey is not. Be carefull.
-//
-
-#define OPENSSL_ALGORITHM_DEFINES
-#include <openssl/opensslconf.h>
-#include <openssl/opensslv.h>
-
-#if OPENSSL_VERSION_NUMBER < 0x0090700fL
-#error Openssl version 0.9.7 or newer is strongly recomended
-#endif
-
-#include "crypto-bn.h"
-
-// ----------------------------------------------------------------
-
-#define DES_LEFT 0
-#define DES_RIGHT 1
-
-#define DES_HASH 8
-#define DES_PC1 16
-#define DES_IP 32
-#define DES_FP 64
-#define DES_MOD 128
-
-// common DES modes
-
-#define PRV_DES_ENCRYPT (DES_LEFT|DES_PC1|DES_IP|DES_FP)
-#define PRV_DES_DECRYPT (DES_RIGHT|DES_PC1|DES_IP|DES_FP)
-
-#define VIA_DES (DES_LEFT|DES_MOD)
-#define VIA_DES_HASH (DES_LEFT|DES_HASH|DES_MOD)
-#define SECA_DES_ENCR PRV_DES_ENCRYPT
-#define SECA_DES_DECR PRV_DES_DECRYPT
-#define NAGRA_DES_ENCR PRV_DES_ENCRYPT
-#define NAGRA_DES_DECR PRV_DES_DECRYPT
-
-class cDes {
-private:
- static const unsigned char _E[], _P[], _PC1[], _PC2[], IP[], FP[];
-protected:
- static const unsigned char S[][64], LS[];
- const unsigned char *PC1, *PC2;
- unsigned char E[48], P[32];
- //
- virtual unsigned int Mod(unsigned int R, unsigned int key7) const { return R; }
- void Permute(unsigned char *data, const unsigned char *P, int n) const;
-public:
- cDes(const unsigned char *pc1=0, const unsigned char *pc2=0);
- virtual ~cDes() {}
- void Des(unsigned char *data, const unsigned char *key, int mode) const;
- };
-
-// ----------------------------------------------------------------
-
-#if defined(OPENSSL_NO_AES) | defined(NO_AES) | OPENSSL_VERSION_NUMBER<0x0090700fL
-#include "support/aes.h"
-#else
-#define OPENSSL_HAS_AES
-#include <openssl/aes.h>
-#endif
-
-class cAES {
-private:
- bool active;
- AES_KEY dkey, ekey;
-protected:
- void SetKey(const unsigned char *key);
- void Decrypt(unsigned char *data, int len) const ;
- int Encrypt(const unsigned char *data, int len, unsigned char *crypt) const;
-public:
- cAES(void);
- };
-
-// ----------------------------------------------------------------
-
-#if defined(OPENSSL_NO_IDEA) | defined(NO_IDEA) | OPENSSL_VERSION_NUMBER<0x0090700fL
-#include "support/idea.h"
-#else
-#define OPENSSL_HAS_IDEA
-#include <openssl/idea.h>
-#endif
-
-typedef IDEA_KEY_SCHEDULE IdeaKS;
-
-class cIDEA {
-public:
- // single shot API
- void Decrypt(unsigned char *data, int len, const unsigned char *key, unsigned char *iv) const;
- int Encrypt(const unsigned char *data, int len, unsigned char *crypt, const unsigned char *key, unsigned char *iv) const;
- // multi shot API
- void SetEncKey(const unsigned char *key, IdeaKS *ks) const;
- void SetDecKey(const unsigned char *key, IdeaKS *ks) const;
- void Decrypt(unsigned char *data, int len, IdeaKS *ks, unsigned char *iv) const;
- int Encrypt(const unsigned char *data, int len, unsigned char *crypt, IdeaKS *ks, unsigned char *iv) const;
- };
-
-// ----------------------------------------------------------------
-
-class cRSA {
-private:
- bool Input(cBN *d, const unsigned char *in, int n, bool LE) const;
- int Output(unsigned char *out, int n, cBN *r, bool LE) const;
-public:
- int RSA(unsigned char *out, const unsigned char *in, int n, const BIGNUM *exp, const BIGNUM *mod, bool LE=true) const;
- int RSA(BIGNUM *out, const unsigned char *in, int n, const BIGNUM *exp, const BIGNUM *mod, bool LE=true) const;
- int RSA(unsigned char *out, int len, BIGNUM *in, const BIGNUM *exp, const BIGNUM *mod, bool LE=true) const;
- };
-
-#endif //___CRYPTO_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-
-#include "data.h"
-#include "misc.h"
-#include "scsetup.h"
-#include "log-core.h"
-#include "i18n.h"
-
-#define KEY_FILE "SoftCam.Key"
-#define EXT_AU_INT (15*60*1000) // ms interval for external AU
-#define EXT_AU_MIN ( 2*60*1000) // ms min. interval for external AU
-
-// -- cFileMap -----------------------------------------------------------------
-
-cFileMap::cFileMap(const char *Filename, bool Rw)
-{
- filename=strdup(Filename);
- rw=Rw;
- fd=-1; count=len=0; addr=0; failed=false;
-}
-
-cFileMap::~cFileMap()
-{
- Clean();
- free(filename);
-}
-
-bool cFileMap::IsFileMap(const char *Name, bool Rw)
-{
- return (!strcmp(Name,filename) && (!Rw || rw));
-}
-
-void cFileMap::Clean(void)
-{
- if(addr) { munmap(addr,len); addr=0; len=0; }
- if(fd>=0) { close(fd); fd=-1; }
-}
-
-bool cFileMap::Map(void)
-{
- cMutexLock lock(this);
- if(addr) { count++; return true; }
- if(!failed) {
- struct stat64 ds;
- if(!stat64(filename,&ds)) {
- if(S_ISREG(ds.st_mode)) {
- fd=open(filename,rw ? O_RDWR : O_RDONLY);
- if(fd>=0) {
- unsigned char *map=(unsigned char *)mmap(0,ds.st_size,rw ? (PROT_READ|PROT_WRITE):(PROT_READ),MAP_SHARED,fd,0);
- if(map!=MAP_FAILED) {
- addr=map; len=ds.st_size; count=1;
- return true;
- }
- else PRINTF(L_GEN_ERROR,"mapping failed on %s: %s",filename,strerror(errno));
- close(fd); fd=-1;
- }
- else PRINTF(L_GEN_ERROR,"error opening filemap %s: %s",filename,strerror(errno));
- }
- else PRINTF(L_GEN_ERROR,"filemap %s is not a regular file",filename);
- }
- else PRINTF(L_GEN_ERROR,"can't stat filemap %s: %s",filename,strerror(errno));
- failed=true; // don't try this one over and over again
- }
- return false;
-}
-
-bool cFileMap::Unmap(void)
-{
- cMutexLock lock(this);
- if(addr) {
- if(!(--count)) { Clean(); return true; }
- else Sync();
- }
- return false;
-}
-
-void cFileMap::Sync(void)
-{
- cMutexLock lock(this);
- if(addr) msync(addr,len,MS_ASYNC);
-}
-
-// -- cFileMaps ----------------------------------------------------------------
-
-cFileMaps filemaps;
-
-cFileMaps::cFileMaps(void)
-{
- cfgDir=0;
-}
-
-cFileMaps::~cFileMaps()
-{
- Clear();
- free(cfgDir);
-}
-
-void cFileMaps::SetCfgDir(const char *CfgDir)
-{
- free(cfgDir);
- cfgDir=strdup(CfgDir);
-}
-
-cFileMap *cFileMaps::GetFileMap(const char *name, const char *domain, bool rw)
-{
- cMutexLock lock(this);
- char path[256];
- snprintf(path,sizeof(path),"%s/%s/%s",cfgDir,domain,name);
- cFileMap *fm=First();
- while(fm) {
- if(fm->IsFileMap(path,rw)) return fm;
- fm=Next(fm);
- }
- fm=new cFileMap(path,rw);
- Add(fm);
- return fm;
-}
-
-// -- cStructItem --------------------------------------------------------------
-
-cStructItem::cStructItem(void)
-{
- comment=0; deleted=special=false;
-}
-
-cStructItem::~cStructItem()
-{
- free(comment);
-}
-
-void cStructItem::SetComment(const char *com)
-{
- free(comment);
- comment=com ? strdup(com):0;
-}
-
-bool cStructItem::Save(FILE *f)
-{
- fprintf(f,"%s%s\n",*ToString(false),comment?comment:"");
- return ferror(f)==0;
-}
-
-// -- cCommentItem -------------------------------------------------------------
-
-class cCommentItem : public cStructItem {
-public:
- cCommentItem(void);
- };
-
-cCommentItem::cCommentItem(void)
-{
- SetSpecial();
-}
-
-// -- cStructLoader ------------------------------------------------------------
-
-cStructLoader::cStructLoader(const char *Type, const char *Filename, int Flags)
-:lock(true)
-{
- path=0; mtime=0;
- type=Type; filename=Filename; flags=Flags&SL_CUSTOMMASK;
- cStructLoaders::Register(this);
-}
-
-cStructLoader::~cStructLoader()
-{
- free(path);
-}
-
-void cStructLoader::AddItem(cStructItem *n, const char *com, cStructItem *ref)
-{
- n->SetComment(com);
- ListLock(true);
- cStructItem *a=0;
- if(ref) { // insert before reference
- for(a=First(); a; a=Next(a))
- if(Next(a)==ref) break;
- }
- if(!a) { // insert before first non-special
- for(a=First(); a;) {
- cStructItem *nn=Next(a);
- if(nn && !nn->Special()) break;
- a=nn;
- }
- }
- Add(n,a);
- Modified();
- ListUnlock();
-}
-
-void cStructLoader::DelItem(cStructItem *d, bool keep)
-{
- if(d) {
- d->Delete();
- if(keep) {
- cStructItem *n=new cCommentItem;
- n->SetComment(cString::sprintf(";%s%s",*d->ToString(false),d->Comment()?d->Comment():""));
- ListLock(true);
- Add(n,d);
- ListUnlock();
- }
- Modified();
- }
-}
-
-cStructItem *cStructLoader::NextValid(cStructItem *it) const
-{
- while(it && !it->Valid()) it=Next(it);
- return it;
-}
-
-void cStructLoader::SetCfgDir(const char *cfgdir)
-{
- free(path);
- path=strdup(AddDirectory(cfgdir,filename));
-}
-
-time_t cStructLoader::MTime(bool log)
-{
- struct stat64 st;
- if(stat64(path,&st)!=0) {
- if(log) {
- PRINTF(L_GEN_ERROR,"failed fstat %s: %s",path,strerror(errno));
- PRINTF(L_GEN_WARN,"automatic reload of %s disabled",path);
- }
- st.st_mtime=0;
- }
- return st.st_mtime;
-}
-
-void cStructLoader::CheckAccess(void)
-{
- if(access(path,R_OK|W_OK)!=0) {
- if(errno!=EACCES)
- PRINTF(L_GEN_ERROR,"failed access %s: %s",path,strerror(errno));
- PRINTF(L_GEN_WARN,"no write permission on %s. Changes will not be saved!",path);
- SL_SETFLAG(SL_NOACCESS);
- }
- else SL_CLRFLAG(SL_NOACCESS);
-}
-
-bool cStructLoader::CheckUnmodified(void)
-{
- time_t curr_mtime=MTime(false);
- if(mtime && mtime<curr_mtime && SL_TSTFLAG(SL_WATCH)) {
- PRINTF(L_CORE_LOAD,"abort save as file %s has been changed externaly",path);
- return false;
- }
- return true;
-}
-
-bool cStructLoader::CheckDoSave(void)
-{
- return !SL_TSTFLAG(SL_DISABLED) && SL_TSTFLAG(SL_READWRITE)
- && !SL_TSTFLAG(SL_NOACCESS) && SL_TSTFLAG(SL_LOADED)
- && IsModified() && CheckUnmodified();
-}
-
-void cStructLoader::LoadFinished(void)
-{
- SL_CLRFLAG(SL_SHUTUP);
- if(!SL_TSTFLAG(SL_LOADED))
- PRINTF(L_CORE_LOAD,"loading %s terminated with error. Changes will not be saved!",path);
-}
-
-void cStructLoader::OpenFailed(void)
-{
- if(SL_TSTFLAG(SL_VERBOSE) && !SL_TSTFLAG(SL_SHUTUP)) {
- PRINTF(L_GEN_ERROR,"failed open %s: %s",path,strerror(errno));
- SL_SETFLAG(SL_SHUTUP);
- }
- if(SL_TSTFLAG(SL_MISSINGOK)) SL_SETFLAG(SL_LOADED);
- else SL_CLRFLAG(SL_LOADED);
-}
-
-void cStructLoader::Load(bool reload)
-{
- if(SL_TSTFLAG(SL_DISABLED) || (reload && !SL_TSTFLAG(SL_WATCH))) return;
- FILE *f=fopen(path,"r");
- if(f) {
- int curr_mtime=MTime(true);
- ListLock(true);
- bool doload=false;
- if(!reload) {
- Clear(); Modified(false);
- mtime=curr_mtime;
- doload=true;
- }
- else if(mtime<curr_mtime) {
- PRINTF(L_CORE_LOAD,"detected change of %s",path);
- if(IsModified())
- PRINTF(L_CORE_LOAD,"discarding in-memory changes");
- for(cStructItem *a=First(); a; a=Next(a)) DelItem(a);
- Modified(false);
- mtime=curr_mtime;
- doload=true;
- }
- if(doload) {
- SL_SETFLAG(SL_LOADED);
- PRINTF(L_GEN_INFO,"loading %s from %s",type,path);
- CheckAccess();
- int lineNum=0, num=0;
- char buff[4096];
- while(fgets(buff,sizeof(buff),f)) {
- lineNum++;
- if(!index(buff,'\n') && !feof(f)) {
- PRINTF(L_GEN_ERROR,"file %s readbuffer overflow line#%d",path,lineNum);
- SL_CLRFLAG(SL_LOADED);
- break;
- }
- strreplace(buff,'\n',0); strreplace(buff,'\r',0); // chomp
- bool hasContent=false;
- char *ls;
- for(ls=buff; *ls; ls++) {
- if(*ls==';' || *ls=='#') { // comment
- if(hasContent)
- while(ls>buff && ls[-1]<=' ') ls--; // search back to non-whitespace
- break;
- }
- if(*ls>' ') hasContent=true; // line contains something usefull
- }
- cStructItem *it=0;
- if(hasContent) {
- char save=*ls;
- *ls=0; it=ParseLine(skipspace(buff)); *ls=save;
- if(!it) {
- PRINTF(L_GEN_ERROR,"file %s has error in line #%d",path,lineNum);
- ls=buff;
- }
- else num++;
- }
- else ls=buff;
- if(!it) it=new cCommentItem;
- if(it) {
- it->SetComment(ls);
- Add(it);
- }
- else {
- PRINTF(L_GEN_ERROR,"out of memory loading file %s",path);
- SL_CLRFLAG(SL_LOADED);
- break;
- }
- }
- ListUnlock();
- PRINTF(L_CORE_LOAD,"loaded %d %s from %s",num,type,path);
- PostLoad();
- }
- else ListUnlock();
-
- fclose(f);
- LoadFinished();
- }
- else
- OpenFailed();
-}
-
-void cStructLoader::Purge(void)
-{
- if(!SL_TSTFLAG(SL_DISABLED) && !SL_TSTFLAG(SL_NOPURGE)) {
- ListLock(true);
- for(cStructItem *it=First(); it;) {
- cStructItem *n=Next(it);
- if(it->Deleted()) Del(it);
- it=n;
- }
- ListUnlock();
- }
-}
-
-void cStructLoader::Save(void)
-{
- if(CheckDoSave()) {
- cSafeFile f(path);
- if(f.Open()) {
- ListLock(false);
- for(cStructItem *it=First(); it; it=Next(it))
- if(!it->Deleted() && !it->Save(f)) break;
- f.Close();
- mtime=MTime(true);
- Modified(false);
- ListUnlock();
- PRINTF(L_CORE_LOAD,"saved %s to %s",type,path);
- }
- }
-}
-
-// -- cStructLoaderPlain -------------------------------------------------------
-
-cStructLoaderPlain::cStructLoaderPlain(const char *Type, const char *Filename, int Flags)
-:cStructLoader(Type,Filename,Flags)
-{}
-
-void cStructLoaderPlain::PreLoad(void)
-{
- ListLock(true);
- Clear(); Modified(false);
- ListUnlock();
-}
-
-void cStructLoaderPlain::Load(bool reload)
-{
- if(SL_TSTFLAG(SL_DISABLED) || reload) return;
- FILE *f=fopen(path,"r");
- if(f) {
- PreLoad();
- ListLock(true);
- SL_SETFLAG(SL_LOADED);
- PRINTF(L_GEN_INFO,"loading %s from %s",type,path);
- CheckAccess();
- int lineNum=0;
- char buff[4096];
- while(fgets(buff,sizeof(buff),f)) {
- lineNum++;
- if(!index(buff,'\n') && !feof(f)) {
- PRINTF(L_GEN_ERROR,"file %s readbuffer overflow line#%d",path,lineNum);
- SL_CLRFLAG(SL_LOADED);
- break;
- }
- strreplace(buff,'\n',0); strreplace(buff,'\r',0); // chomp
- bool hasContent=false;
- char *ls;
- for(ls=buff; *ls; ls++) {
- if(*ls==';' || *ls=='#') break;
- if(*ls>' ') hasContent=true;
- }
- if(hasContent) {
- *ls=0;
- if(!ParseLinePlain(skipspace(buff)))
- PRINTF(L_GEN_ERROR,"file %s has error in line #%d",path,lineNum);
- }
- }
- ListUnlock();
- PostLoad();
- fclose(f);
- LoadFinished();
- }
- else
- OpenFailed();
-}
-
-void cStructLoaderPlain::PreSave(FILE *f)
-{
- fprintf(f,"## This is a generated file. DO NOT EDIT!!\n"
- "## This file will be OVERWRITTEN WITHOUT WARNING!!\n");
-}
-
-void cStructLoaderPlain::Save(void)
-{
- if(CheckDoSave()) {
- cSafeFile f(path);
- if(f.Open()) {
- ListLock(false);
- PreSave(f);
- for(cStructItem *it=First(); it; it=Next(it))
- if(!it->Deleted() && !it->Save(f)) break;
- PostSave(f);
- f.Close();
- Modified(false);
- ListUnlock();
- PRINTF(L_CORE_LOAD,"saved %s to %s",type,path);
- }
- }
-}
-
-// -- cStructLoaders -----------------------------------------------------------
-
-#define RELOAD_TIMEOUT 20300 // ms
-#define PURGE_TIMEOUT 60700 // ms
-#define SAVE_TIMEOUT 5000 // ms
-
-cStructLoader *cStructLoaders::first=0;
-cTimeMs cStructLoaders::lastReload;
-cTimeMs cStructLoaders::lastPurge;
-cTimeMs cStructLoaders::lastSave;
-
-void cStructLoaders::Register(cStructLoader *ld)
-{
- PRINTF(L_CORE_DYN,"structloaders: registering loader %s",ld->type);
- ld->next=first;
- first=ld;
-}
-
-void cStructLoaders::SetCfgDir(const char *cfgdir)
-{
- for(cStructLoader *ld=first; ld; ld=ld->next)
- ld->SetCfgDir(cfgdir);
-}
-
-void cStructLoaders::Load(bool reload)
-{
- if(!reload || lastReload.TimedOut()) {
- for(cStructLoader *ld=first; ld; ld=ld->next) ld->Load(reload);
- lastReload.Set(RELOAD_TIMEOUT);
- }
-}
-
-void cStructLoaders::Save(bool force)
-{
- if(force || lastSave.TimedOut()) {
- for(cStructLoader *ld=first; ld; ld=ld->next) ld->Save();
- lastSave.Set(SAVE_TIMEOUT);
- }
-}
-
-void cStructLoaders::Purge(void)
-{
- if(lastPurge.TimedOut()) {
- for(cStructLoader *ld=first; ld; ld=ld->next) ld->Purge();
- lastPurge.Set(PURGE_TIMEOUT);
- }
-}
-
-// -- cPid ---------------------------------------------------------------------
-
-cPid::cPid(int Pid, int Section, int Mask, int Mode)
-{
- pid=Pid;
- sct=Section;
- mask=Mask;
- mode=Mode;
- filter=0;
-}
-
-// -- cPids --------------------------------------------------------------------
-
-void cPids::AddPid(int Pid, int Section, int Mask, int Mode)
-{
- if(!HasPid(Pid,Section,Mask,Mode)) {
- cPid *pid=new cPid(Pid,Section,Mask,Mode);
- Add(pid);
- }
-}
-
-bool cPids::HasPid(int Pid, int Section, int Mask, int Mode)
-{
- for(cPid *pid=First(); pid; pid=Next(pid))
- if(pid->pid==Pid && pid->sct==Section && pid->mask==Mask && pid->mode==Mode)
- return true;
- return false;
-}
-
-// -- cEcmInfo -----------------------------------------------------------------
-
-cEcmInfo::cEcmInfo(void)
-{
- Setup();
-}
-
-cEcmInfo::cEcmInfo(const cEcmInfo *e)
-{
- Setup(); SetName(e->name);
- ecm_pid=e->ecm_pid;
- ecm_table=e->ecm_table;
- caId=e->caId;
- emmCaId=e->emmCaId;
- provId=e->provId;
- Update(e);
- prgId=e->prgId;
- source=e->source;
- transponder=e->transponder;
-}
-
-cEcmInfo::cEcmInfo(const char *Name, int Pid, int CaId, int ProvId)
-{
- Setup(); SetName(Name);
- ecm_pid=Pid;
- caId=CaId;
- provId=ProvId;
-}
-
-cEcmInfo::~cEcmInfo()
-{
- ClearData();
- free(name);
-}
-
-void cEcmInfo::Setup(void)
-{
- cached=failed=false;
- name=0; data=0;
- prgId=source=transponder=-1;
- ecm_table=0x80; emmCaId=0;
-}
-
-bool cEcmInfo::Compare(const cEcmInfo *e)
-{
- return prgId==e->prgId && source==e->source && transponder==e->transponder &&
- caId==e->caId && ecm_pid==e->ecm_pid && provId==e->provId;
-}
-
-bool cEcmInfo::Update(const cEcmInfo *e)
-{
- return (e->data && (!data || e->dataLen!=dataLen)) ? AddData(e->data,e->dataLen) : false;
-}
-
-void cEcmInfo::SetSource(int PrgId, int Source, int Transponder)
-{
- prgId=PrgId;
- source=Source;
- transponder=Transponder;
-}
-
-void cEcmInfo::ClearData(void)
-{
- free(data); data=0;
-}
-
-bool cEcmInfo::AddData(const unsigned char *Data, int DataLen)
-{
- ClearData();
- data=MALLOC(unsigned char,DataLen);
- if(data) {
- memcpy(data,Data,DataLen);
- dataLen=DataLen;
- }
- else PRINTF(L_GEN_ERROR,"malloc failed in cEcmInfo::AddData()");
- return (data!=0);
-}
-
-void cEcmInfo::SetName(const char *Name)
-{
- free(name);
- name=strdup(Name);
-}
-
-// -- cPlainKey ----------------------------------------------------------------
-
-cPlainKey::cPlainKey(bool CanSupersede)
-{
- super=CanSupersede;
-}
-
-bool cPlainKey::Set(int Type, int Id, int Keynr, void *Key, int Keylen)
-{
- type=Type; id=Id; keynr=Keynr;
- return SetKey(Key,Keylen);
-}
-
-cString cPlainKey::PrintKeyNr(void)
-{
- return cString::sprintf("%02X",keynr);
-}
-
-int cPlainKey::IdSize(void)
-{
- return id>0xFF ? (id>0xFFFF ? 6 : 4) : 2;
-}
-
-cString cPlainKey::ToString(bool hide)
-{
- return cString::sprintf(hide ? "%c %.*X %s %.4s..." : "%c %.*X %s %s",type,IdSize(),id,*PrintKeyNr(),*Print());
-}
-
-// -- cMutableKey --------------------------------------------------------------
-
-cMutableKey::cMutableKey(bool Super)
-:cPlainKey(Super)
-{
- real=0;
-}
-
-cMutableKey::~cMutableKey()
-{
- delete real;
-}
-
-bool cMutableKey::SetKey(void *Key, int Keylen)
-{
- delete real;
- return (real=Alloc()) && real->SetKey(Key,Keylen);
-}
-
-bool cMutableKey::SetBinKey(unsigned char *Mem, int Keylen)
-{
- delete real;
- return (real=Alloc()) && real->SetBinKey(Mem,Keylen);
-}
-
-int cMutableKey::Size(void)
-{
- return real->Size();
-}
-
-bool cMutableKey::Cmp(void *Key, int Keylen)
-{
- return real->Cmp(Key,Keylen);
-}
-
-bool cMutableKey::Cmp(cPlainKey *k)
-{
- cMutableKey *mk=dynamic_cast<cMutableKey *>(k); // high magic ;)
- return real->Cmp(mk ? mk->real : k);
-}
-
-void cMutableKey::Get(void *mem)
-{
- real->Get(mem);
-}
-
-cString cMutableKey::Print(void)
-{
- return real->Print();
-}
-
-// ----------------------------------------------------------------
-
-class cPlainKeyDummy : public cPlainKey {
-private:
- char *str;
- int len;
-protected:
- virtual cString Print(void);
- virtual cString PrintKeyNr(void) { return ""; }
-public:
- cPlainKeyDummy(void);
- ~cPlainKeyDummy();
- virtual bool Parse(const char *line);
- virtual bool Cmp(void *Key, int Keylen) { return false; }
- virtual bool Cmp(cPlainKey *k) { return false; }
- virtual void Get(void *mem) {}
- virtual int Size(void) { return len; }
- virtual bool SetKey(void *Key, int Keylen);
- virtual bool SetBinKey(unsigned char *Mem, int Keylen);
- };
-
-cPlainKeyDummy::cPlainKeyDummy(void):
-cPlainKey(false)
-{
- str=0;
-}
-
-cPlainKeyDummy::~cPlainKeyDummy()
-{
- free(str);
-}
-
-bool cPlainKeyDummy::SetKey(void *Key, int Keylen)
-{
- len=Keylen;
- free(str);
- str=MALLOC(char,len+1);
- if(str) strn0cpy(str,(char *)Key,len+1);
- return str!=0;
-}
-
-bool cPlainKeyDummy::SetBinKey(unsigned char *Mem, int Keylen)
-{
- return SetKey(Mem,Keylen);
-}
-
-cString cPlainKeyDummy::Print(void)
-{
- return str;
-}
-
-bool cPlainKeyDummy::Parse(const char *line)
-{
- unsigned char sid[3];
- int len;
- if(GetChar(line,&type,1) && (len=GetHex(line,sid,3,false))) {
- type=toupper(type); id=Bin2Int(sid,len);
- char *l=strdup(line);
- line=skipspace(stripspace(l));
- SetKey((void *)line,strlen(line));
- free(l);
- return true;
- }
- return false;
-}
-
-// -- cPlainKeyTypeDummy -------------------------------------------------------
-
-class cPlainKeyTypeDummy : public cPlainKeyType {
-public:
- cPlainKeyTypeDummy(int Type):cPlainKeyType(Type,false) {}
- virtual cPlainKey *Create(void) { return new cPlainKeyDummy; }
- };
-
-// -- cPlainKeyType ------------------------------------------------------------
-
-cPlainKeyType::cPlainKeyType(int Type, bool Super)
-{
- type=Type;
- cPlainKeys::Register(this,Super);
-}
-
-// -- cLastKey -----------------------------------------------------------------
-
-cLastKey::cLastKey(void)
-{
- lastType=lastId=lastKeynr=-1;
-}
-
-bool cLastKey::NotLast(int Type, int Id, int Keynr)
-{
- if(lastType!=Type || lastId!=Id || lastKeynr!=Keynr) {
- lastType=Type; lastId=Id; lastKeynr=Keynr;
- return true;
- }
- return false;
-}
-
-// -- cPlainKeys ---------------------------------------------------------------
-
-const char *externalAU=0;
-
-cPlainKeys keys;
-
-cPlainKeyType *cPlainKeys::first=0;
-
-cPlainKeys::cPlainKeys(void)
-:cStructList<cPlainKey>("keys",KEY_FILE,SL_READWRITE|SL_MISSINGOK|SL_WATCH|SL_VERBOSE)
-{}
-
-void cPlainKeys::Register(cPlainKeyType *pkt, bool Super)
-{
- PRINTF(L_CORE_DYN,"registering key type %c%s",pkt->type,Super?" (super)":"");
- pkt->next=first;
- first=pkt;
-}
-
-void cPlainKeys::Trigger(int Type, int Id, int Keynr)
-{
- if(lastkey.NotLast(Type,Id,Keynr))
- PRINTF(L_CORE_AUEXTERN,"triggered from findkey (%s)",*KeyString(Type,Id,Keynr));
- ExternalUpdate();
-}
-
-cPlainKey *cPlainKeys::FindKey(int Type, int Id, int Keynr, int Size, cPlainKey *key)
-{
- key=FindKeyNoTrig(Type,Id,Keynr,Size,key);
- if(!key) Trigger(Type,Id,Keynr);
- return key;
-}
-
-cPlainKey *cPlainKeys::FindKeyNoTrig(int Type, int Id, int Keynr, int Size, cPlainKey *key)
-{
- ListLock(false);
- for(key=key?Next(key):First(); key; key=Next(key))
- if(key->type==Type && key->id==Id && key->keynr==Keynr && (Size<0 || key->Size()==Size))
- break;
- ListUnlock();
- return key;
-}
-
-cPlainKey *cPlainKeys::NewFromType(int type)
-{
- cPlainKeyType *pkt;
- for(pkt=first; pkt; pkt=pkt->next)
- if(pkt->type==type) return pkt->Create();
- PRINTF(L_CORE_LOAD,"unknown key type '%c', adding dummy",type);
- pkt=new cPlainKeyTypeDummy(type);
- return pkt->Create();
-}
-
-bool cPlainKeys::AddNewKey(cPlainKey *nk, const char *reason)
-{
- cPlainKey *k;
- for(k=0; (k=FindKeyNoTrig(nk->type,nk->id,nk->keynr,-1,k)); )
- if(k->Cmp(nk)) return false;
-
- cPlainKey *ref=0;
- cString ks=nk->ToString(true);
- PRINTF(L_GEN_INFO,"key update for ID %s",*ks);
- ums.Queue("%s %s",tr("Key update"),*ks);
- for(k=0; (k=FindKeyNoTrig(nk->type,nk->id,nk->keynr,nk->Size(),k)); ) {
- if(nk->CanSupersede()) {
- PRINTF(L_GEN_INFO,"supersedes key: %s",*k->ToString(true));
- DelItem(k,ScSetup.SuperKeys==0);
- }
- if(!ref) ref=k;
- }
- char stamp[32], com[256];
- time_t tt=time(0);
- struct tm tm_r;
- strftime(stamp,sizeof(stamp),"%d.%m.%Y %T",localtime_r(&tt,&tm_r));
- snprintf(com,sizeof(com)," ; %s %s",reason,stamp);
- AddItem(nk,com,ref);
- return true;
-}
-
-bool cPlainKeys::NewKey(int Type, int Id, int Keynr, void *Key, int Keylen)
-{
- cPlainKey *nk=NewFromType(Type);
- if(nk) {
- nk->Set(Type,Id,Keynr,Key,Keylen);
- return AddNewKey(nk,"from AU");
- }
- return false;
-}
-
-bool cPlainKeys::NewKeyParse(char *line, const char *reason)
-{
- cPlainKey *nk=ParseLine(line);
- return nk && AddNewKey(nk,reason);
-}
-
-cPlainKey *cPlainKeys::ParseLine(char *line)
-{
- char *s=skipspace(line);
- cPlainKey *k=NewFromType(toupper(*s));
- if(k && !k->Parse(line)) { delete k; k=0; }
- return k;
-}
-
-cString cPlainKeys::KeyString(int Type, int Id, int Keynr)
-{
- cPlainKey *pk=NewFromType(Type);
- char *s;
- if(pk) {
- pk->type=Type; pk->id=Id; pk->keynr=Keynr;
- asprintf(&s,"%c %.*X %s",Type,pk->IdSize(),Id,*pk->PrintKeyNr());
- delete pk;
- }
- else s=strdup("unknown");
- return cString(s,true);
-}
-
-void cPlainKeys::PostLoad(void)
-{
- ListLock(false);
- if(Count() && LOG(L_CORE_KEYS)) {
- for(cPlainKey *dat=First(); dat; dat=Next(dat))
- PRINTF(L_CORE_KEYS,"keys %s",*dat->ToString(false));
- }
- ListUnlock();
-}
-
-void cPlainKeys::HouseKeeping(void)
-{
- if(trigger.TimedOut()) {
- trigger.Set(EXT_AU_INT);
- if(externalAU) PRINTF(L_CORE_AUEXTERN,"triggered from housekeeping");
- ExternalUpdate();
- }
-}
-
-void cPlainKeys::ExternalUpdate(void)
-{
- if(externalAU && ScSetup.AutoUpdate>0) {
- if(last.TimedOut()) {
- Lock();
- if(!Active())
- Start();
- else PRINTF(L_CORE_AUEXTERN,"still running");
- Unlock();
- }
- else PRINTF(L_CORE_AUEXTERN,"denied, min. timeout not expired");
- }
-}
-
-void cPlainKeys::Action(void)
-{
- last.Set(EXT_AU_MIN);
- PRINTF(L_CORE_AUEXTERN,"starting...");
- cTimeMs start;
- cPipe pipe;
- if(pipe.Open(externalAU,"r")) {
- char buff[1024];
- while(fgets(buff,sizeof(buff),pipe)) {
- char *line=skipspace(stripspace(buff));
- if(line[0]==0 || line[0]==';' || line[0]=='#') continue;
- NewKeyParse(line,"from ExtAU");
- }
- }
- pipe.Close();
- PRINTF(L_CORE_AUEXTERN,"done (elapsed %d)",(int)start.Elapsed());
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___DATA_H
-#define ___DATA_H
-
-#include <vdr/thread.h>
-#include <vdr/tools.h>
-
-#include "misc.h"
-
-class cStructLoaders;
-class cLoaders;
-class cPidFilter;
-class cPlainKeys;
-
-// ----------------------------------------------------------------
-
-class cFileMap : public cSimpleItem, private cMutex {
-private:
- char *filename;
- bool rw;
- //
- int fd, len, count;
- unsigned char *addr;
- bool failed;
- //
- void Clean(void);
-public:
- cFileMap(const char *Filename, bool Rw);
- ~cFileMap();
- bool Map(void);
- bool Unmap(void);
- void Sync(void);
- int Size(void) const { return len; }
- unsigned char *Addr(void) const { return addr; }
- bool IsFileMap(const char *Name, bool Rw);
- };
-
-// ----------------------------------------------------------------
-
-class cFileMaps : public cSimpleList<cFileMap>, private cMutex {
-private:
- char *cfgDir;
-public:
- cFileMaps(void);
- ~cFileMaps();
- void SetCfgDir(const char *CfgDir);
- cFileMap *GetFileMap(const char *name, const char *domain, bool rw);
- };
-
-extern cFileMaps filemaps;
-
-//--------------------------------------------------------------
-
-class cStructItem : public cSimpleItem {
-private:
- char *comment;
- bool deleted, special;
-protected:
- void SetSpecial(void) { special=true; }
-public:
- cStructItem(void);
- virtual ~cStructItem();
- virtual cString ToString(bool hide) { return ""; }
- bool Save(FILE *f);
- //
- void SetComment(const char *com);
- const char *Comment(void) const { return comment; }
- void Delete(void) { deleted=true; }
- bool Deleted(void) const { return deleted; }
- bool Special(void) const { return special; }
- bool Valid(void) const { return !deleted && !special; }
- };
-
-//--------------------------------------------------------------
-
-#define SL_READWRITE 1
-#define SL_MISSINGOK 2
-#define SL_WATCH 4
-#define SL_VERBOSE 8
-#define SL_NOPURGE 16
-#define SL_CUSTOMMASK 0xFF
-#define SL_LOADED 0x100
-#define SL_MODIFIED 0x200
-#define SL_DISABLED 0x400
-#define SL_SHUTUP 0x800
-#define SL_NOACCESS 0x1000
-
-#define SL_SETFLAG(x) flags|=(x)
-#define SL_CLRFLAG(x) flags&=~(x)
-#define SL_TSTFLAG(x) (flags&(x))
-
-class cStructLoader : public cSimpleList<cStructItem> {
-friend class cStructLoaders;
-private:
- cStructLoader *next;
- cRwLock lock;
- //
-protected:
- int flags;
- const char *type, *filename;
- char *path;
- time_t mtime;
- //
- void CheckAccess(void);
- bool CheckUnmodified(void);
- void LoadFinished(void);
- void OpenFailed(void);
- bool CheckDoSave(void);
- time_t MTime(bool log);
- //
- virtual cStructItem *ParseLine(char *line)=0;
- void Modified(bool mod=true) { if(mod) SL_SETFLAG(SL_MODIFIED); else SL_CLRFLAG(SL_MODIFIED); }
- bool IsModified(void) const { return SL_TSTFLAG(SL_MODIFIED); }
- void ListLock(bool rw) { lock.Lock(rw); }
- void ListUnlock(void) { lock.Unlock(); }
- virtual void PostLoad(void) {}
-public:
- cStructLoader(const char *Type, const char *Filename, int Flags);
- virtual ~cStructLoader();
- void AddItem(cStructItem *n, const char *com, cStructItem *ref);
- void DelItem(cStructItem *d, bool keep=false);
- cStructItem *NextValid(cStructItem *it) const;
- //
- void SetCfgDir(const char *cfgdir);
- virtual void Load(bool reload);
- virtual void Save(void);
- void Purge(void);
- void Disable(void) { SL_SETFLAG(SL_DISABLED); }
- };
-
-//--------------------------------------------------------------
-
-template<class T> class cStructList : public cStructLoader {
-public:
- cStructList<T>(const char *Type, const char *Filename, int Flags):cStructLoader(Type,Filename,Flags) {}
- T *First(void) const { return (T *)NextValid(cStructLoader::First()); }
- T *Next(const T *item) const { return (T *)NextValid(cStructLoader::Next(item)); }
- };
-
-//--------------------------------------------------------------
-
-class cStructLoaderPlain : public cStructLoader {
-protected:
- virtual cStructItem *ParseLine(char *line) { return 0; }
- virtual bool ParseLinePlain(const char *line)=0;
- virtual void PreLoad(void);
- virtual void PreSave(FILE *f);
- virtual void PostSave(FILE *f) {};
-public:
- cStructLoaderPlain(const char *Type, const char *Filename, int Flags);
- virtual void Load(bool reload);
- virtual void Save(void);
- };
-
-//--------------------------------------------------------------
-
-template<class T> class cStructListPlain : public cStructLoaderPlain {
-public:
- cStructListPlain<T>(const char *Type, const char *Filename, int Flags):cStructLoaderPlain(Type,Filename,Flags) {}
- T *First(void) const { return (T *)NextValid(cStructLoaderPlain::First()); }
- T *Next(const T *item) const { return (T *)NextValid(cStructLoaderPlain::Next(item)); }
- };
-
-//--------------------------------------------------------------
-
-class cStructLoaders {
-friend class cStructLoader;
-private:
- static cStructLoader *first;
- static cTimeMs lastReload, lastPurge, lastSave;
- //
- static void Register(cStructLoader *ld);
-public:
- static void SetCfgDir(const char *cfgdir);
- static void Load(bool reload);
- static void Save(bool force=false);
- static void Purge(void);
- };
-
-// ----------------------------------------------------------------
-
-class cPid : public cSimpleItem {
-public:
- int pid, sct, mask, mode;
- cPidFilter *filter;
- //
- cPid(int Pid, int Section, int Mask, int Mode);
- };
-
-// ----------------------------------------------------------------
-
-class cPids : public cSimpleList<cPid> {
-public:
- void AddPid(int Pid, int Section, int Mask, int Mode=0);
- bool HasPid(int Pid, int Section, int Mask, int Mode=0);
- };
-
-// ----------------------------------------------------------------
-
-class cEcmInfo : public cStructItem {
-private:
- bool cached, failed;
- //
- void Setup(void);
-protected:
- int dataLen;
- unsigned char *data;
- //
- void ClearData(void);
-public:
- char *name;
- int ecm_pid, ecm_table;
- int caId, provId, emmCaId;
- int prgId, source, transponder;
- //
- cEcmInfo(void);
- cEcmInfo(const cEcmInfo *e);
- cEcmInfo(const char *Name, int Pid, int CaId, int ProvId);
- ~cEcmInfo();
- virtual cString ToString(bool hide=false) { return ""; }
- bool Compare(const cEcmInfo *e);
- bool Update(const cEcmInfo *e);
- void SetSource(int PrgId, int Source, int Transponder);
- void SetName(const char *Name);
- bool AddData(const unsigned char *Data, int DataLen);
- const unsigned char *Data(void) const { return data; }
- void Fail(bool st) { failed=st; }
- bool Failed(void) const { return failed; }
- void SetCached(void) { cached=true; }
- bool Cached(void) const { return cached; }
- };
-
-// ----------------------------------------------------------------
-
-class cMutableKey;
-
-class cPlainKey : public cStructItem {
-friend class cPlainKeys;
-friend class cMutableKey;
-private:
- bool super;
-protected:
- void SetSupersede(bool val) { super=val; }
- bool CanSupersede(void) const { return super; }
- virtual int IdSize(void);
- virtual cString Print(void)=0;
- virtual cString PrintKeyNr(void);
-public:
- int type, id, keynr;
- //
- cPlainKey(bool CanSupersede);
- virtual bool Parse(const char *line)=0;
- virtual cString ToString(bool hide);
- virtual bool Cmp(void *Key, int Keylen)=0;
- virtual bool Cmp(cPlainKey *k)=0;
- virtual void Get(void *mem)=0;
- virtual int Size(void)=0;
- bool Set(int Type, int Id, int Keynr, void *Key, int Keylen);
- virtual bool SetKey(void *Key, int Keylen)=0;
- virtual bool SetBinKey(unsigned char *Mem, int Keylen)=0;
- };
-
-// ----------------------------------------------------------------
-
-class cMutableKey : public cPlainKey {
-private:
- cPlainKey *real;
-protected:
- virtual cString Print(void);
- virtual cPlainKey *Alloc(void) const=0;
-public:
- cMutableKey(bool Super);
- virtual ~cMutableKey();
- virtual bool Cmp(void *Key, int Keylen);
- virtual bool Cmp(cPlainKey *k);
- virtual void Get(void *mem);
- virtual int Size(void);
- virtual bool SetKey(void *Key, int Keylen);
- virtual bool SetBinKey(unsigned char *Mem, int Keylen);
- };
-
-// ----------------------------------------------------------------
-
-class cPlainKeyType {
-friend class cPlainKeys;
-private:
- int type;
- cPlainKeyType *next;
-public:
- cPlainKeyType(int Type, bool Super);
- virtual ~cPlainKeyType() {}
- virtual cPlainKey *Create(void)=0;
- };
-
-// ----------------------------------------------------------------
-
-template<class PKT, int KT, bool SUP=true> class cPlainKeyTypeReg : public cPlainKeyType {
-public:
- cPlainKeyTypeReg(void):cPlainKeyType(KT,SUP) {}
- virtual cPlainKey *Create(void) { return new PKT(SUP); }
- };
-
-// ----------------------------------------------------------------
-
-class cLastKey {
-private:
- int lastType, lastId, lastKeynr;
-public:
- cLastKey(void);
- bool NotLast(int Type, int Id, int Keynr);
- };
-
-// ----------------------------------------------------------------
-
-extern const char *externalAU;
-
-class cPlainKeys : private cThread, public cStructList<cPlainKey> {
-friend class cPlainKeyType;
-private:
- static cPlainKeyType *first;
- cTimeMs trigger, last;
- cLastKey lastkey;
- //
- static void Register(cPlainKeyType *pkt, bool Super);
- cPlainKey *NewFromType(int type);
- bool AddNewKey(cPlainKey *nk, const char *reason);
- void ExternalUpdate(void);
-protected:
- virtual void Action(void);
- virtual void PostLoad(void);
-public:
- cPlainKeys(void);
- virtual cPlainKey *ParseLine(char *line);
- cPlainKey *FindKey(int Type, int Id, int Keynr, int Size, cPlainKey *key=0);
- cPlainKey *FindKeyNoTrig(int Type, int Id, int Keynr, int Size, cPlainKey *key=0);
- void Trigger(int Type, int Id, int Keynr);
- cString KeyString(int Type, int Id, int Keynr);
- bool NewKey(int Type, int Id, int Keynr, void *Key, int Keylen);
- bool NewKeyParse(char *line, const char *reason);
- void HouseKeeping(void);
- };
-
-extern cPlainKeys keys;
-
-#endif //___DATA_H
+++ /dev/null
-patches
-systems-pre
-.dependencies
-diff.exclude
-*.so
-*.a
-*.o
-*.save
-*.orig
-*.rej
-*.bak
-*.mo
-*.pot
-dump.txt
-.hg
-version.c
+++ /dev/null
-; Irdeto/Betacrypt cards\r
-;\r
-; AAAAAA BBBBBBBBBBBBBBBBBBBB CC DDDDDD EEEEEEEEEEEEEEEE\r
-;\r
-; AAAAAA - HS hex serial\r
-; BBBBBBBBBBBBBBBBBBBB - HMK hex master key\r
-; CC - provider\r
-; DDDDDD - provider ID\r
-; EEEEEEEEEEEEEEEE - PMK plain master key\r
-;\r
-123456 12345612345612345612 00 123456 1234567890123456 ; dummy\r
-\r
+++ /dev/null
-; Seca cards\r
-;\r
-; AAAA BBBBBBBB CCCCCCCCCCCCCCCC\r
-;\r
-; AAAA - provider ident\r
-; BBBBBB - shared address\r
-; CCCCCCCCCCCCCCCC - key 01\r
-;\r
-1234 123456 1234561234561234 ; dummy\r
+++ /dev/null
-;
-; Irdeto/Betacrypt
-;
-; I XX YY <16 characters>
-;
-; XX - provider
-; YY - key number
-;
-
-;
-; Seca
-;
-; S XXXX YY <16 characters/32 characters>
-; S XXXX [EMM] Mz <180 characters>
-; S XXXX [EMM] Ez <12 characters/180 characters>
-; S XXXX N51 M9 <258 characters>
-; S XXXX N51 E9 <2 characters>
-;
-; XXXX - provider ident
-; YY - key number
-; Mz / Ez - RSA key name (z = 1,3,5).
-; Exponent keys may be padded up to 180 chars.
-; Optional "EMM" for EMM RSA keys.
-; N51 - RSA keys for Nano 5109 handling.
-;
-
-;
-; Viaccess
-;
-; V XXXXXX YY <16 characters/32 characters>
-; V XXXXXX TPS <32 characters> ; old TPS keys. no longer used
-; V XXXXXX TPSMKy <32 characters> ; TPS masterkeys for AU y=0-7
-;
-; XXXXXX - provider ident
-; YY - key number
-;
-
-;
-; Nagra 1
-;
-; N XXXX YY <16 characters>
-; N XXXX E1 [ROMq] [PKv] [TYPw] <128 characters>
-; N XXXX N1 [ROMq] [PKv] [TYPw] <128 characters>
-; N XXXX N2 [ROMq] [TYPw] <128 characters>
-; N XXXX V [ROMq] [TYPw] <16 characters>
-;
-; Nagra 2
-;
-; N XXXX YY <32 characters> ; IDEA opkey (00/01)
-; N XXXX V <32 characters> ; IDEA verify key
-; N XXXX M1 <128 characters> ; RSA key
-; N XXXX NN ZZ <32/48/192 characters> ; EMM keys (literal 'NN'), some examples:
-; N XXXX NN 02 <32/48 characters> ; EMM-G IDEA key (former N XXXX 02)
-; N XXXX NN 03 <32 characters> ; EMM-G signature key
-; N XXXX NN 12 <192 characters> ; EMM-G RSA key (former N XXXX N2)
-; N XXXX NN 30 <32 characters> ; EMM-G 3DES key
-;
-; XXXX - provider ident
-; YY - key number
-; ZZ - EEPROM key number
-; ROMq - (optional) ROM specific keys (q = ROM number)
-; PKv - (optional) PK key number (v = 0,1,2)
-; TYPw - (optional) key type number (w = 0,1)
-;
-
-;
-; Conax
-;
-; C XX M <128 characters>
-; C XX E <128 characters>
-;
-; XX - key number
-;
-
-;
-; Cryptoworks
-;
-; W XXXX YY ZZ VV <32 characters> ; opkey
-; W XXXX YY ZZ VV <128 characters> ; RSA key (normaly ZZ=10)
-; W XXXX YY CC <12 characters> ; cardkey (literal 'CC')
-;
-; XXXX - caid
-; YY - provider ident
-; ZZ - keytype (20/31/10 derived from cardfiles EF20/EF31/EF10)
-; VV - keyid (00/01)
-;
-
-;
-; @SHL (SkyCrypt)
-;
-; Z 00 00 <16 characters>
-;
-
-;
-; Constant CW
-;
-; X YYYY freq:pol:src:sid <32 characters>
-;
-; YYYY - CA system id e.g. 0100
-; freq - frequency
-; pol - polarisation (v/h/r/l)
-; src - source
-; sid - service ID
-;
-; example:
-X 0d02 12670:v:S19.2E:23457 00000000000000000000000000000000
-; cable example (Z can be an arbitrary letter, is ignored)
-X 1801 346:Z:C:23457 00000000000000000000000000000000
+++ /dev/null
-; Viaccess cards
-;
-; AAAAAA BBBBBBBBBB CC DDDDDDDDDDDDDDDD
-;
-; AAAAAA - Provider ident
-; BBBBBBBBBB - Unique address (UA)
-; SSSSSSSS - Shared address (SA)
-; CC - Management key number
-; DDDDDDDDDDDDDDDD - Management key
-;
-123456 1234567890 12345678 01 1234561234561234 ; Dummy
+++ /dev/null
-#
-# Comment lines can start with # or ;
-#
-# every client line starts with the client name, followed by some arguments:
-# 'hostname' is the name of the server
-# 'port' is the port on the server
-# 'emm' is a flag to allow EMM transfers to the server
-# (0=disabled 1=enabled)
-# 'caid' (optional) caid on which this client should work
-# 'mask' (optional) mask for caid e.g. caid=1700 mask=FF00 would allow
-# anything between 1700 & 17FF.
-# Default is 1700 & FF00. If only caid is given mask is FFFF.
-# You may give multiple caid/mask values comma separated
-# (e.g. 1702,1722,0d0c/ff00).
-# 'username' is the login username
-# 'password' is the login password
-#
-# radegast client
-radegast:hostname:port:emm/caid/mask
-#
-# aroureos client
-# 'hexbase'
-# 'hexserial' card data for which EMM updates should be send
-aroureos:hostname:port:emm/caid/mask:hexbase:hexserial
-#
-# camd33 client (tcp protocol)
-# 'aeskey' is the AES key (32bytes), disable encryption if missing
-camd33:hostname:port:emm/caid/mask:username:password:aeskey
-#
-# camd35 client (udp protocol)
-camd35:hostname:port:emm/caid/mask:username:password
-#
-# cardd client
-cardd:hostname:port:emm/caid/mask:username:password
-#
-# buffy client
-# 'aeskey' is the AES key (32bytes), disable encryption if missing
-buffy:hostname:port:emm:username:password:aeskey
-#
-# newcamd client
-# 'cfgkey' is the config key (28bytes)
-newcamd:hostname:port:emm/caid/mask:username:password:cfgKey
-#
-# gbox client
-#
-# NOTE: hostname & port will be ignore. GBOX must be runnning on the local
-# machine. For convinience you should choose localhost:8004
-gbox:hostname:port:emm/caid/mask
+++ /dev/null
-#!/bin/bash
-#
-# This script is called from VDR to start/stop dialup-network
-#
-# argument 1: wanted action, one of start,stop
-#
-
-RUN="/var/tmp/vdr.dialup.run"
-
-action="$1"
-
-case "$action" in
-up)
- up ppp0
- touch "$RUN"
- sleep 2
- ;;
-down)
- down ppp0
- rm -f "$RUN"
- ;;
-esac
-
-exit 0
+++ /dev/null
-#!/bin/bash
-
-URL="http://www.some-host.com/aes/"
-
-key=`wget -q -O- -U "Mozilla" "--referer=$URL" "$URL" | sed -ne '/007C00/ s/^.*clef Pri//p' | sed -ne 's/<pre>.*$//p' | sed -ne 's/: [0-9]\{2\} ://gp' | sed -ne 's/[^0-9A-F]//gp'`
-if [ "aa$key" != "aa" ]; then
- echo "V 007C00 TPS $key"
-fi
+++ /dev/null
-;
-; Comment lines can start with # or ;
-;
-
-; Videoguard2
-;
-; NDS seed and boxid for camcrypt
-;
-; boxid - boxid (4 byte = 8 chars)
-; seed1 - 1st seed (64 byte = 128 chars)
-; seed2 - 2nd seed (64 byte = 128 chars)
-;
-; videoguard2: SEED seed1 seed2
-videoguard2: SEED 00112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233 00112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233
-;
-; videoguard2: BOXID boxid
-videoguard2: BOXID 11223344
-
-; Nagra
-;
-; boxkey and modulus for camcrypt
-;
-; prvid - provider ID (2 byte = 4 chars)
-; boxkey - boxkey (8 byte = 16 chars)
-; mod - modulus (64 byte = 128 chars)
-;
-; If IRDMOD is present, the given mod is used to decrypt the cammod from DT08
-; data. If IRDMOD is obmited, the given mod is used as cammod directly
-;
-; nagra: [prvid] IRDMOD boxkey mod
-nagra: [0501] IRDMOD 0011223344556677 00112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233
-;
-; nagra: [prvid] boxkey mod
-nagra: [1201] 0011223344556677 00112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233
-
-; Cryptoworks
-;
-; RSA modulus for camcrypt
-;
-; caid - caid identifying the provider
-; serial - serial number identifying the card
-; ipk - issuer public key (IPK), 64 bytes = 128 chars
-; ucpk - session key (calculated from ISK, IPK & exponent), 64 bytes = 128 chars
-; pin - pin number to disable parental rating
-;
-; Note: you need only one of them for your caid. IPK is more general (common for
-; all cards of a provider), while the UCPK is different for every single card.
-;
-; cryptoworks: IPK caid ipk
-cryptoworks: IPK 0d22 00112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233
-;
-; cryptoworks: UCPK serial ucpk
-cryptoworks: UCPK 0102030405 00112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233
-;
-; cryptoworks: PIN serial pin
-cryptoworks: PIN 0102030405 1234
-
-;
-; Irdeto/Betacrypt
-;
-; RSA certificate for camkey challenge
-;
-; acs - ACS version identifying the card (optional)
-; caid - caid for further identification of the card (optional)
-; mod - RSA modulus, usualy 128 bytes = 256 chars
-; exp - RSA exponent, usualy 1 byte = 2 chars
-;
-; Irdeto default certificate
-; irdeto: mod exp
-irdeto: 0011223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677 03
-;
-; a ACS specific certificate
-; irdeto: [acs] mod exp
-irdeto: [0604] 0011223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677 03
-;
-; a ACS/caid specific certificate
-; irdeto: [acs/caid] mod exp
-irdeto: [0384/1722] 0011223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677 03
-;
-; indicates that a card doesn't want/need RSA camkey exchange
-; NOTE: this is autodetected for ACS 0383/0384 cards (Z/non-Z mode)
-;
-; irdeto: [acs/caid] PLAIN
-irdeto: [0605/0622] PLAIN
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/poll.h>
-#include <unistd.h>
-
-#include <linux/dvb/dmx.h>
-
-#include <vdr/tools.h>
-
-#include "filter.h"
-#include "misc.h"
-#include "log-core.h"
-
-// -- cPidFilter ------------------------------------------------------------------
-
-cPidFilter::cPidFilter(const char *Id, int Num, int DvbNum, unsigned int IdleTime)
-{
- dvbNum=DvbNum;
- idleTime=IdleTime;
- id=0; fd=-1; active=false; forceRun=false; userData=0;
- asprintf(&id,"%s/%d",Id,Num);
- PRINTF(L_CORE_ACTION,"new filter '%s' on card %d (%d ms)",id,dvbNum,idleTime);
-}
-
-cPidFilter::~cPidFilter()
-{
- cMutexLock lock(this);
- if(fd>=0) {
- Stop();
- close(fd);
- }
- PRINTF(L_CORE_ACTION,"filter '%s' on card %d removed",id,dvbNum);
- free(id);
-}
-
-bool cPidFilter::Open(void)
-{
- cMutexLock lock(this);
- if(fd<0) {
- fd=DvbOpen(DEV_DVB_DEMUX,dvbNum,O_RDWR|O_NONBLOCK);
- if(fd>=0) return true;
- }
- return false;
-}
-
-void cPidFilter::Flush(void)
-{
- cMutexLock lock(this);
- if(fd>=0) {
- unsigned char buff[MAX_SECT_SIZE];
- while(read(fd,buff,sizeof(buff))>0);
- }
-}
-
-void cPidFilter::Start(int Pid, int Section, int Mask, int Mode, bool Crc)
-{
- cMutexLock lock(this);
- if(fd>=0) {
- Stop();
- struct dmx_sct_filter_params FilterParams;
- memset(&FilterParams,0,sizeof(FilterParams));
- FilterParams.filter.filter[0]=Section;
- FilterParams.filter.mask[0]=Mask;
- FilterParams.filter.mode[0]=Mode;
- FilterParams.flags=DMX_IMMEDIATE_START;
- if(Crc) FilterParams.flags|=DMX_CHECK_CRC;
- FilterParams.pid=Pid;
- if(ioctl(fd,DMX_SET_FILTER,&FilterParams)<0) {
- PRINTF(L_GEN_ERROR,"filter '%s': DMX_SET_FILTER failed: %s",id,strerror(errno));
- return;
- }
- pid=Pid;
- active=true;
-
- LBSTART(L_CORE_ACTION);
- LBPUT("filter '%s' -> pid=0x%04x sct=0x%02x/0x%02x/0x%02x crc=%d matching",id,Pid,Section,Mask,Mode,Crc);
- int mam =Mask & (~Mode);
- int manm=Mask & ~(~Mode);
- for(int i=0; i<256; i++) {
- int xxxor=Section ^ i;
- if((mam&xxxor) || (manm && !(manm&xxxor))) {}
- else
- LBPUT(" 0x%02x",i);
- }
- LBEND();
- }
-}
-
-void cPidFilter::Stop(void)
-{
- cMutexLock lock(this);
- if(fd>=0) {
- CHECK(ioctl(fd,DMX_STOP));
- active=false;
- }
-}
-
-void cPidFilter::SetBuffSize(int BuffSize)
-{
- cMutexLock lock(this);
- if(fd>=0) {
- Stop();
- int s=max(BuffSize,8192);
- CHECK(ioctl(fd,DMX_SET_BUFFER_SIZE,s));
- }
-}
-
-int cPidFilter::SetIdleTime(unsigned int IdleTime)
-{
- int i=idleTime;
- idleTime=IdleTime;
- return i;
-}
-
-void cPidFilter::Wakeup(void)
-{
- cMutexLock lock(this);
- forceRun=true;
- PRINTF(L_CORE_ACTION,"filter '%s': wakeup",id);
-}
-
-int cPidFilter::Pid(void)
-{
- return active ? pid : -1;
-}
-
-// -- cAction ------------------------------------------------------------------
-
-cAction::cAction(const char *Id, int DvbNum)
-{
- asprintf(&id,"%s %d",Id,DvbNum);
- dvbNum=DvbNum;
- unique=0; pri=-1;
- SetDescription("%s filter",id);
-}
-
-cAction::~cAction()
-{
- Cancel(2);
- DelAllFilter();
- PRINTF(L_CORE_ACTION,"%s: stopped",id);
- free(id);
-}
-
-cPidFilter *cAction::CreateFilter(const char *Id, int Num, int DvbNum, int IdleTime)
-{
- return new cPidFilter(Id,Num,DvbNum,IdleTime);
-}
-
-cPidFilter *cAction::NewFilter(int IdleTime)
-{
- Lock();
- cPidFilter *filter=CreateFilter(id,unique++,dvbNum,IdleTime);
- if(filter && filter->Open()) {
- if(!Active()) {
- Start();
- PRINTF(L_CORE_ACTION,"%s: started",id);
- }
- filters.Add(filter);
- }
- else {
- PRINTF(L_CORE_ACTION,"%s: filter '%s' failed to open",id,filter?filter->id:"XxX");
- delete filter;
- filter=0;
- }
- Unlock();
- return filter;
-}
-
-cPidFilter *cAction::IdleFilter(void)
-{
- Lock();
- cPidFilter *filter;
- for(filter=filters.First(); filter; filter=filters.Next(filter))
- if(!filter->Active()) break;
- Unlock();
- return filter;
-}
-
-void cAction::DelFilter(cPidFilter *filter)
-{
- Lock();
- filters.Del(filter);
- Unlock();
-}
-
-void cAction::DelAllFilter(void)
-{
- Lock();
- filters.Clear();
- unique=0;
- Unlock();
-}
-
-void cAction::Priority(int Pri)
-{
- pri=Pri;
-}
-
-void cAction::Action(void)
-{
- if(pri>0) SetPriority(pri);
- struct pollfd *pfd=0;
- while(Running()) {
- if(filters.Count()<=0) {
- cCondWait::SleepMs(100);
- }
- else {
- // first build pfd data
- Lock();
- delete pfd; pfd=new struct pollfd[filters.Count()];
- if(!pfd) {
- PRINTF(L_GEN_ERROR,"action %s: pollfd: out of memory",id);
- break;
- }
- int num=0;
- cPidFilter *filter;
- for(filter=filters.First(); filter; filter=filters.Next(filter)) {
- memset(&pfd[num],0,sizeof(struct pollfd));
- pfd[num].fd=filter->fd;
- pfd[num].events=POLLIN;
- num++;
- }
- Unlock();
-
- // now poll for data
- int r=poll(pfd,num,60);
- if(r<0) {
- PRINTF(L_GEN_ERROR,"action %s poll: %s",id,strerror(errno));
- break;
- }
- if(r>0) {
- for(r=0 ; r<num ; r++)
- if(pfd[r].revents&POLLIN) {
- Lock();
- for(filter=filters.First(); filter; filter=filters.Next(filter)) {
- if(filter->fd==pfd[r].fd) {
- unsigned char buff[MAX_SECT_SIZE];
- int n=read(filter->fd,buff,sizeof(buff));
- if(n<0 && errno!=EAGAIN) {
- if(errno==EOVERFLOW) PRINTF(L_GEN_ERROR,"action %s read: Buffer overflow",filter->id);
- else PRINTF(L_GEN_ERROR,"action %s read: %s",filter->id,strerror(errno));
- }
- if(n>0) {
- filter->lastTime.Set(); filter->forceRun=false;
- Process(filter,buff,n);
- // don't make any assumption about data-structs here
- // Process() may have changed them
- }
- break;
- }
- }
- Unlock();
- }
- }
-
- // call filters which are idle too long
- Lock();
- do {
- r=0;
- for(filter=filters.First(); filter; filter=filters.Next(filter)) {
- if(filter->forceRun || (filter->idleTime && filter->lastTime.Elapsed()>filter->idleTime)) {
- filter->lastTime.Set(); filter->forceRun=false;
- Process(filter,0,0);
- // don't make any assumption about data-structs here
- // Process() may have changed them
- r=1; break;
- }
- }
- } while(r);
- Unlock();
- }
- }
- delete pfd;
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___FILTER_H
-#define ___FILTER_H
-
-#include <vdr/thread.h>
-#include "misc.h"
-
-class cPidFilter;
-
-// ----------------------------------------------------------------
-
-#define MAX_SECT_SIZE 4096
-
-class cAction : protected cThread {
-private:
- char *id;
- int dvbNum, unique, pri;
- cSimpleList<cPidFilter> filters;
-protected:
- virtual void Process(cPidFilter *filter, unsigned char *data, int len)=0;
- virtual void Action(void);
- virtual cPidFilter *CreateFilter(const char *Id, int Num, int DvbNum, int IdleTime);
- //
- cPidFilter *NewFilter(int IdleTime);
- cPidFilter *IdleFilter(void);
- void DelFilter(cPidFilter *filter);
- void DelAllFilter(void);
- void Priority(int Pri);
-public:
- cAction(const char *Id, int DvbNum);
- virtual ~cAction();
- };
-
-// ----------------------------------------------------------------
-
-class cPidFilter : public cSimpleItem, private cMutex {
-friend class cAction;
-private:
- int dvbNum;
- unsigned int idleTime;
- cTimeMs lastTime;
- bool forceRun;
- //
- bool Open(void);
-protected:
- char *id;
- int fd;
- int pid;
- bool active;
-public:
- void *userData;
- //
- cPidFilter(const char *Id, int Num, int DvbNum, unsigned int IdleTime);
- virtual ~cPidFilter();
- void Flush(void);
- virtual void Start(int Pid, int Section, int Mask, int Mode, bool Crc);
- void Stop(void);
- void Wakeup(void);
- void SetBuffSize(int BuffSize);
- int SetIdleTime(unsigned int IdleTime);
- int Pid(void);
- bool Active(void) { return active; }
- };
-
-#endif //___FILTER_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___HELPER_H
-#define ___HELPER_H
-
-#include <byteswap.h>
-
-#if defined __i386__
-#define get_misalign(_a) *(_a)
-#define put_misalign(_b,_a) *(_a)=(_b)
-#else
-template<class T> inline T get_misalign(T *p)
-{ struct s { T v; } __attribute__((packed)); return ((s *)p)->v; }
-
-template<class T> inline void put_misalign(unsigned int v, T* p)
-{ struct s { T v; } __attribute__((packed)); ((s *)p)->v = v; }
-#endif
-
-#define UINT32_BE(a) bswap_32(get_misalign((unsigned int *)(a)))
-#define UINT16_BE(a) bswap_16(get_misalign((unsigned short *)(a)))
-#define UINT8_BE(a) *((unsigned char *)a)
-#define BYTE4_BE(a,b) put_misalign(bswap_32(b),(unsigned int *)(a))
-#define BYTE2_BE(a,b) put_misalign(bswap_16(b),(unsigned short *)(a))
-#define BYTE1_BE(a,b) *(unsigned char *)(a)=(b)
-
-#define UINT32_LE(a) get_misalign((unsigned int *)(a))
-#define UINT16_LE(a) get_misalign((unsigned short *)(a))
-#define UINT8_LE(a) *((unsigned char *)a)
-#define BYTE4_LE(a,b) put_misalign(b,(unsigned int *)(a))
-#define BYTE2_LE(a,b) put_misalign(b,(unsigned short *)(a))
-#define BYTE1_LE(a,b) *(unsigned char *)(a)=(b)
-
-#define __ror16_const(x,xx) ((((x)&0xFFFF)>>(xx)) | ((x)<<(16-(xx))))
-#define __rol16_const(x,xx) (((x)<<(xx)) | (((x)&0xFFFF)>>(16-(xx))))
-#define __sn8_const(b) ((((b)>>4)&0xf) + (((b)&0xf)<<4))
-
-#if defined __GNUC__ && __GNUC__ >= 2 && defined __i386__
-
-#define ror16(x,xx) ({ unsigned int v; \
- __asm__ ("rorw %2, %w0" : "=g" (v) : "0" (x), "i" (xx) : "cc"); \
- v; })
-#define rol16(x,xx) ({ unsigned int v; \
- __asm__ ("rolw %2, %w0" : "=g" (v) : "0" (x), "i" (xx) : "cc"); \
- v; })
-#define sn8(b) ({ unsigned char v; \
- if(__builtin_constant_p(b)) \
- v=__sn8_const(b); \
- else \
- __asm__ ("rorb $4, %b0" : "=g" (v) : "0" (b) : "cc"); \
- v; })
-
-#else //__GNUC__
-
-#define ror16(x,xx) __ror16_const(x,xx)
-#define rol16(x,xx) __rol16_const(x,xx)
-#define sn8(b) __sn8_const(b)
-
-#endif //__GNUC__
-
-static inline void __xxor(unsigned char *data, int len, const unsigned char *v1, const unsigned char *v2)
-{
- switch(len) { // looks ugly, but the compiler can optimize it very well ;)
- case 16:
- *((unsigned int *)data+3) = *((unsigned int *)v1+3) ^ *((unsigned int *)v2+3);
- *((unsigned int *)data+2) = *((unsigned int *)v1+2) ^ *((unsigned int *)v2+2);
- case 8:
- *((unsigned int *)data+1) = *((unsigned int *)v1+1) ^ *((unsigned int *)v2+1);
- case 4:
- *((unsigned int *)data+0) = *((unsigned int *)v1+0) ^ *((unsigned int *)v2+0);
- break;
- default:
- while(len--) *data++ = *v1++ ^ *v2++;
- break;
- }
-}
-#define xxor(d,l,v1,v2) __xxor(d,l,v1,v2)
-
-#endif // ___HELPER_H
+++ /dev/null
-/*
- * Auto generated file, do not edit
- * Will be overwritten/deleted without warning
- *
- * Edit the .po files if you want to update translations!!
- */
-
-#include "i18n.h"
-
-#if VDRVERSNUM < 10507
-
-const tI18nPhrase ScPhrases[] = {
-// START I18N
-// END I18N
- { NULL }
- };
-
-#endif
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___I18N_H
-#define ___I18N_H
-
-#include <vdr/i18n.h>
-
-#if APIVERSNUM < 10507
-extern const tI18nPhrase ScPhrases[];
-#define trNOOP(s) (s)
-#endif
-
-#endif //___I18N_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___LOG_CORE_H
-#define ___LOG_CORE_H
-
-#include "log.h"
-
-// ----------------------------------------------------------------
-
-#define L_CORE 1
-
-#define L_CORE_LOAD LCLASS(L_CORE,0x2)
-#define L_CORE_ACTION LCLASS(L_CORE,0x4)
-#define L_CORE_ECM LCLASS(L_CORE,0x8)
-#define L_CORE_ECMPROC LCLASS(L_CORE,0x10)
-#define L_CORE_PIDS LCLASS(L_CORE,0x20)
-#define L_CORE_AU LCLASS(L_CORE,0x40)
-#define L_CORE_AUSTATS LCLASS(L_CORE,0x80)
-#define L_CORE_AUEXTRA LCLASS(L_CORE,0x100)
-#define L_CORE_AUEXTERN LCLASS(L_CORE,0x200)
-#define L_CORE_CAIDS LCLASS(L_CORE,0x400)
-#define L_CORE_KEYS LCLASS(L_CORE,0x800)
-#define L_CORE_DYN LCLASS(L_CORE,0x1000)
-#define L_CORE_CSA LCLASS(L_CORE,0x2000)
-#define L_CORE_CI LCLASS(L_CORE,0x4000)
-#define L_CORE_AV7110 LCLASS(L_CORE,0x8000)
-#define L_CORE_NET LCLASS(L_CORE,0x10000)
-#define L_CORE_NETDATA LCLASS(L_CORE,0x20000)
-#define L_CORE_MSGCACHE LCLASS(L_CORE,0x40000)
-#define L_CORE_SERIAL LCLASS(L_CORE,0x80000)
-#define L_CORE_SC LCLASS(L_CORE,0x100000)
-#define L_CORE_HOOK LCLASS(L_CORE,0x200000)
-#define L_CORE_CIFULL LCLASS(L_CORE,0x400000)
-
-#define L_CORE_ALL LALL(L_CORE_CIFULL)
-
-#endif //___LOG_CORE_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___LOG_SC_H
-#define ___LOG_SC_H
-
-#include "log.h"
-
-#define L_SC_ERROR LCLASS(L_SC,0x2)
-#define L_SC_INIT LCLASS(L_SC,0x4)
-
-#define L_SC_LASTDEF L_SC_INIT
-#define L_SC_DEFDEF L_SC_ERROR|L_SC_INIT
-#define L_SC_DEFNAMES "error","init"
-
-#endif //___LOG_SC_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___LOG_SYS_H
-#define ___LOG_SYS_H
-
-#include "log.h"
-
-#define L_SYS_KEY LCLASS(L_SYS,0x2)
-#define L_SYS_ECM LCLASS(L_SYS,0x4)
-#define L_SYS_EMM LCLASS(L_SYS,0x8)
-#define L_SYS_CRYPTO LCLASS(L_SYS,0x10)
-#define L_SYS_VERBOSE LCLASS(L_SYS,0x20)
-
-#define L_SYS_LASTDEF L_SYS_VERBOSE
-#define L_SYS_DEFDEF L_SYS_KEY|L_SYS_ECM
-#define L_SYS_DEFNAMES "key","ecm","emm","crypto","verbose"
-
-#endif //___LOG_SYS_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <time.h>
-
-#include <vdr/tools.h>
-#include <vdr/thread.h>
-
-#include "log.h"
-#include "misc.h"
-
-#define LMOD_SUP 32
-#define LMOD_CFG_VALID 0x80000000
-
-struct LogConfig logcfg = {
- 1,0,0,0,0,
- 0,
- "/var/log/vdr-sc"
- };
-
-static const struct LogModule lm_general = {
- (LMOD_ENABLE|L_GEN_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_GEN_ALL)&LOPT_MASK,
- "general", { "error","warn","info","debug","misc" }
- };
-
-static const struct LogModule *mods[LMOD_SUP] = { &lm_general };
-static int config[LMOD_SUP] = { LMOD_ENABLE|L_GEN_ALL|LMOD_CFG_VALID };
-static int cmask[LMOD_SUP] = { LMOD_ENABLE|L_GEN_ALL };
-static cMutex logfileMutex;
-static FILE *logfile=0;
-static bool logfileShutup=false, logfileReopen=false;
-static long long logfileSize;
-
-static unsigned int lastCrc=0;
-static int lastC=0, lastCount=0;
-static cTimeMs lastTime;
-static cMutex lastMutex;
-
-// -- cLogging -----------------------------------------------------------------
-
-void (*cLogging::LogPrint)(const struct LogHeader *lh, const char *txt)=cLogging::PrivateLogPrint;
-
-bool cLogging::AddModule(int m, const struct LogModule *lm)
-{
- if(m<LMOD_SUP) {
- if(mods[m]) Printf(L_GEN_DEBUG,"duplicate logging module id %d (%s & %s)",m,mods[m]->Name,lm->Name);
- mods[m]=lm;
- if(config[m]&LMOD_CFG_VALID) UpgradeOptions(m);
- else SetModuleDefault(LCLASS(m,0));
-//printf("module %-16s added. mod=%x supp=%x def=%x cfg=%x\n",lm->Name,m,lm->OptSupported,lm->OptDefault,config[m]);
- }
- else Printf(L_GEN_DEBUG,"failed to add logging module %d (%s)",m,lm->Name);
- return true;
-}
-
-void cLogging::SetLogPrint(void (*lp)(const struct LogHeader *lh, const char *txt))
-{
- LogPrint=lp;
-}
-
-const struct LogModule *cLogging::GetModule(int c)
-{
- int m=LMOD(c);
- return m<LMOD_SUP ? mods[m] : 0;
-}
-
-bool cLogging::GetHeader(int c, struct LogHeader *lh)
-{
- const struct LogModule *lm=GetModule(c);
- if(lm) {
- if(!logcfg.noTimestamp) {
- time_t tt=time(0);
- struct tm tm_r;
- strftime(lh->stamp,sizeof(lh->stamp),"%b %e %T",localtime_r(&tt,&tm_r));
- }
- else lh->stamp[0]=0;
- int i, o=LOPT(c)&~LMOD_ENABLE;
- for(i=0; i<LOPT_NUM; i++,o>>=1) if(o&1) break;
- snprintf(lh->tag,sizeof(lh->tag),"%s.%s",lm->Name,(i>=1 && i<LOPT_NUM && lm->OptName[i-1])?lm->OptName[i-1]:"unknown");
- lh->c=c;
- return true;
- }
- return false;
-}
-
-void cLogging::LogLine(const struct LogHeader *lh, const char *txt, bool doCrc)
-{
- if(doCrc) {
- unsigned int crc=crc32_le(0,(const unsigned char *)txt,strlen(txt)+1);
- lastMutex.Lock();
- if(lastCrc==crc && lastC==lh->c && ++lastCount<4000000 && lastTime.Elapsed()<=30*1000) {
- lastMutex.Unlock();
- return;
- }
- else {
- unsigned int saveCrc=lastCrc;
- int saveCount=lastCount, saveC=lastC;
- lastTime.Set();
- lastCrc=crc; lastC=lh->c; lastCount=0;
- lastMutex.Unlock();
- if(saveCount>1) {
- struct LogHeader lh2;
- if(GetHeader(saveC,&lh2)) {
- char buff[128];
- snprintf(buff,sizeof(buff),"last message repeated %d times",saveCount);
- LogLine(&lh2,buff,false);
- }
- if(saveCrc==crc && saveC==lh->c) return;
- }
- }
- }
-
- LogPrint(lh,txt);
-}
-
-void cLogging::PrivateLogPrint(const struct LogHeader *lh, const char *txt)
-{
- if(logcfg.logFile) {
- logfileMutex.Lock();
- if(logfileReopen) {
- logfileReopen=false; logfileShutup=false;
- if(logfile) {
- PRINTF(L_GEN_DEBUG,"logfile closed, reopen as '%s'",logcfg.logFilename);
- fclose(logfile);
- logfile=0;
- }
- }
- if(!logfile && !logfileShutup) {
- logfile=fopen(logcfg.logFilename,"a");
- if(logfile) {
- setlinebuf(logfile);
- logfileSize=ftell(logfile);
- if(logfileSize<0) {
- logfileSize=0;
- PRINTF(L_GEN_ERROR,"cannot determine size of logfile '%s', assuming zero",logcfg.logFilename);
- }
- PRINTF(L_GEN_DEBUG,"logfile '%s' opened",logcfg.logFilename);
- }
- else {
- logfileShutup=true;
- PRINTF(L_GEN_ERROR,"failed to open logfile '%s': %s",logcfg.logFilename,strerror(errno));
- }
- }
- if(logfile) {
- int q=fprintf(logfile,"%s [%s] %s\n",lh->stamp,lh->tag,txt);
- if(q>0) logfileSize+=q;
-
- if(logcfg.maxFilesize>0 && logfileSize>((long long)logcfg.maxFilesize*1024)) {
- fprintf(logfile,"%s [%s] %s\n",lh->stamp,lh->tag,"logfile closed, filesize limit reached");
- fclose(logfile);
- logfile=0; logfileShutup=false;
- char *name;
- asprintf(&name,"%s.old",logcfg.logFilename);
- if(rename(logcfg.logFilename,name)) {
- logfileShutup=true;
- PRINTF(L_GEN_ERROR,"failed to rotate logfile: %s",strerror(errno));
- PRINTF(L_GEN_ERROR,"logging to file disabled!");
- }
- free(name);
- }
- }
- logfileMutex.Unlock();
- }
-
- if(logcfg.logCon)
- printf("%s [%s] %s\n",lh->stamp,lh->tag,txt);
-
- if(logcfg.logSys || LMOD(lh->c)==L_GEN) {
- int pri=-1;
- switch(lh->c) {
- case L_GEN_ERROR:
- case L_GEN_WARN: if(SysLogLevel>0) pri=LOG_ERR; break;
- case L_GEN_INFO: if(SysLogLevel>1) pri=LOG_INFO; break;
- case L_GEN_DEBUG: if(SysLogLevel>2) pri=LOG_DEBUG; break;
- case L_GEN_MISC: if(logcfg.logSys) pri=LOG_DEBUG; break;
- default: pri=LOG_DEBUG; break;
- }
- if(pri>=0)
- syslog(pri,"[%d] [%s] %s",cThread::ThreadId(),lh->tag,txt);
- }
-}
-
-bool cLogging::Enabled(int c)
-{
- int m=LMOD(c);
- int o=LOPT(c)|LMOD_CFG_VALID|LMOD_ENABLE;
- return m<LMOD_SUP && (config[m] & o)==o;
-}
-
-void cLogging::Printf(int c, const char *format, ...)
-{
- if(Enabled(c)) {
- struct LogHeader lh;
- if(GetHeader(c,&lh)) {
- char buff[1024];
- va_list ap;
- va_start(ap,format);
- vsnprintf(buff,sizeof(buff),format,ap);
- va_end(ap);
- LogLine(&lh,buff);
- }
- }
-}
-
-void cLogging::Puts(int c, const char *txt)
-{
- if(txt && Enabled(c)) {
- struct LogHeader lh;
- if(GetHeader(c,&lh)) {
- LogLine(&lh,txt);
- }
- }
-}
-
-void cLogging::PutLB(int c, cLineBuff *lb)
-{
- if(lb->Length()>0) {
- Puts(c,lb->Line());
- lb->Flush();
- }
-}
-
-void cLogging::Dump(int c, const void *data, int n, const char *format, ...)
-{
- if(Enabled(c)) {
- struct LogHeader lh;
- if(GetHeader(c,&lh)) {
- char buff[1024];
- va_list ap;
- va_start(ap,format);
- vsnprintf(buff,sizeof(buff),format,ap);
- va_end(ap);
- LogLine(&lh,buff);
- const unsigned char *d=(const unsigned char *)data;
- for(int i=0; i<n;) {
- int q=sprintf(buff,"%04x:",i);
- for(int l=0 ; l<16 && i<n ; l++) q+=sprintf(&buff[q]," %02x",d[i++]);
- LogLine(&lh,buff);
- }
- }
- }
-}
-
-void cLogging::LineDump(int c, const void *data, int n, const char *format, ...)
-{
- if(Enabled(c)) {
- struct LogHeader lh;
- if(GetHeader(c,&lh)) {
- char buff[4096];
- va_list ap;
- va_start(ap,format);
- unsigned int q=vsnprintf(buff,sizeof(buff),format,ap);
- va_end(ap);
- const unsigned char *d=(const unsigned char *)data;
- for(int i=0; i<n; i++) {
- if(q>=sizeof(buff)-8) {
- q+=snprintf(&buff[q],sizeof(buff)-q,"....");
- break;
- }
- q+=snprintf(&buff[q],sizeof(buff)-q," %02x",d[i]);
- }
- LogLine(&lh,buff);
- }
- }
-}
-
-void cLogging::SetModuleDefault(int c)
-{
- const struct LogModule *lm=GetModule(c);
- if(lm) {
- int m=LMOD(c);
- config[m]=(lm->OptDefault&LOPT_MASK)|LMOD_CFG_VALID;
- cmask[m] = lm->OptSupported&LOPT_MASK;
- }
-}
-
-void cLogging::SetModuleOptions(int c)
-{
- const struct LogModule *lm=GetModule(c);
- if(lm) config[LMOD(c)]=(LOPT(c)&(lm->OptSupported&LOPT_MASK))|LMOD_CFG_VALID;
-}
-
-int cLogging::GetModuleOptions(int c)
-{
- const struct LogModule *lm=GetModule(c);
- return lm ? LOPT(config[LMOD(c)]) : -1;
-}
-
-void cLogging::SetModuleOption(int c, bool on)
-{
- const struct LogModule *lm=GetModule(c);
- if(lm) {
- int m=LMOD(c);
- int o=LOPT(c)&(lm->OptSupported&LOPT_MASK);
- if(o) {
- if(on) config[m]|=o; else config[m]&=(~o);
- config[m]|=LMOD_CFG_VALID;
- }
- }
-}
-
-void cLogging::UpgradeOptions(int m)
-{
- const struct LogModule *lm=mods[m];
- if(lm) {
- config[m]&=(lm->OptSupported&LOPT_MASK);
- config[m]|=(lm->OptDefault&LOPT_MASK)&(~cmask[m]);
- cmask[m] =lm->OptSupported&LOPT_MASK;
- config[m]|=LMOD_CFG_VALID;
- }
-}
-
-const char *cLogging::GetModuleName(int c)
-{
- const struct LogModule *lm=GetModule(c);
- return lm ? lm->Name : 0;
-}
-
-const char *cLogging::GetOptionName(int c)
-{
- const struct LogModule *lm=GetModule(c);
- if(lm) {
- int o=LOPT(c)&~LMOD_ENABLE;
- if(lm->OptSupported & o) {
- int i;
- for(i=0; i<LOPT_NUM; i++,o>>=1) if(o&1) break;
- return (i>=1 && i<LOPT_NUM && lm->OptName[i-1]) ? lm->OptName[i-1] : 0;
- }
- }
- return 0;
-}
-
-bool cLogging::GetConfig(cLineBuff *lb)
-{
- lb->Flush();
- bool cont=false;
- for(int m=1; m<LMOD_SUP; m++)
- if(config[m]&LMOD_CFG_VALID) {
- lb->Printf("%s%d:%x:%x",cont?",":"",m,config[m]&~LMOD_CFG_VALID,cmask[m]);
- cont=true;
- }
- return cont;
-}
-
-void cLogging::ParseConfig(const char *txt)
-{
- int n=0, l, m, o, d;
- while(sscanf(&txt[n],"%d:%x:%x%n",&m,&o,&d,&l)==3) {
- if(m>=1 && m<LMOD_SUP) {
- config[m]=(o&LOPT_MASK)|LMOD_CFG_VALID;
- cmask[m] =(d&LOPT_MASK);
- UpgradeOptions(m);
- }
- n+=l;
- if(txt[n]!=',') break;
- n++;
- }
-}
-
-void cLogging::ReopenLogfile(void)
-{
- logfileMutex.Lock();
- logfileReopen=true;
- logfileMutex.Unlock();
-}
-
-int cLogging::GetClassByName(const char *name)
-{
- const char *s=index(name,'.');
- if(s) {
- unsigned int l=s-name;
- for(int m=1; m<LMOD_SUP; m++) {
- const struct LogModule *lm=mods[m];
- if(lm && strlen(lm->Name)==l && !strncasecmp(name,lm->Name,l)) {
- s++;
- if(!strcasecmp(s,"enable"))
- return LCLASS(m,1);
- for(int o=1; o<LOPT_NUM; o++)
- if((lm->OptSupported&(1<<o)) && lm->OptName[o-1] && !strcasecmp(s,lm->OptName[o-1]))
- return LCLASS(m,1<<o);
- break;
- }
- }
- }
- return -1;
-}
-
-// -- cUserMsg -----------------------------------------------------------------
-
-cUserMsg::cUserMsg(const char *m)
-{
- msg=strdup(m);
-}
-
-cUserMsg::~cUserMsg()
-{
- free(msg);
-}
-
-// -- cUserMsgs ----------------------------------------------------------------
-
-cUserMsgs ums;
-
-cUserMsgs::cUserMsgs(void)
-{
- mutex=new cMutex;
-}
-
-cUserMsgs::~cUserMsgs()
-{
- delete mutex;
-}
-
-void cUserMsgs::Queue(const char *fmt, ...)
-{
- if(logcfg.logUser) {
- char buff[1024];
- va_list ap;
- va_start(ap,fmt);
- vsnprintf(buff,sizeof(buff),fmt,ap);
- va_end(ap);
- mutex->Lock();
- Add(new cUserMsg(buff));
- mutex->Unlock();
- }
-}
-
-cUserMsg *cUserMsgs::GetQueuedMsg(void)
-{
- mutex->Lock();
- cUserMsg *um=First();
- if(um) Del(um,false);
- mutex->Unlock();
- return um;
-}
-
-// -- cLogLineBuff -------------------------------------------------------------
-
-cLogLineBuff::cLogLineBuff(int C)
-:cLineBuff(256)
-{
- c=C;
-}
-
-cLogLineBuff::~cLogLineBuff()
-{
- Flush();
-}
-
-void cLogLineBuff::Flush(void)
-{
- cLogging::PutLB(c,this);
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___LOG_H
-#define ___LOG_H
-
-#include "misc.h"
-
-class cMutex;
-
-// ----------------------------------------------------------------
-
-#define LOPT_NUM 24
-#define LOPT_MAX (1<<LOPT_NUM)
-#define LOPT_MASK (LOPT_MAX-1)
-#define LMOD_MAX (1<<(32-LOPT_NUM))
-#define LMOD_MASK (LMOD_MAX-1)
-#define LMOD_ENABLE 1
-
-#define LCLASS(m,o) ((((m)&LMOD_MASK)<<LOPT_NUM)|((o)&LOPT_MASK))
-#define LMOD(c) (((c)>>LOPT_NUM)&LMOD_MASK)
-#define LOPT(o) ((o)&LOPT_MASK)
-#define LALL(o) (((o)<<1)-1)
-
-#define ADD_MODULE(MOD,NAME) static bool __add_mod_ ## NAME = cLogging::AddModule(MOD,&NAME);
-
-#define PRINTF(c,...) cLogging::Printf((c),__VA_ARGS__)
-#define PUTS(c,t) cLogging::Puts((c),(t))
-#define PUTLB(c,lb) cLogging::PutLB((c),(lb))
-#define HEXDUMP(c,d,n,...) cLogging::Dump((c),(d),(n),__VA_ARGS__)
-#define LDUMP(c,d,n,...) cLogging::LineDump((c),(d),(n),__VA_ARGS__)
-#define LOG(c) cLogging::Enabled((c))
-
-// backward compatibility
-#define HexDump(d,n) do { int __n=(n); HEXDUMP(L_GEN_MISC,(d),__n,"dump: n=%d/0x%04x",__n,__n); } while(0)
-
-#define LBSTART(c) do { int __c=(c); if(LOG(__c)) { cLogLineBuff __llb(__c)
-#define LBSTARTF(c) do { int __c=(c); { cLogLineBuff __llb(__c)
-#define LBPUT(...) __llb.Printf(__VA_ARGS__)
-#define LBFLUSH() __llb.Flush()
-#define LBEND( ) } } while(0)
-
-// ----------------------------------------------------------------
-
-#define L_GEN 0
-#define L_GEN_ERROR LCLASS(L_GEN,0x2)
-#define L_GEN_WARN LCLASS(L_GEN,0x4)
-#define L_GEN_INFO LCLASS(L_GEN,0x8)
-#define L_GEN_DEBUG LCLASS(L_GEN,0x10)
-#define L_GEN_MISC LCLASS(L_GEN,0x20)
-
-#define L_GEN_ALL LALL(L_GEN_MISC)
-
-// ----------------------------------------------------------------
-
-struct LogConfig {
- int logCon, logFile, logSys, logUser, noTimestamp;
- int maxFilesize;
- char logFilename[128];
- };
-
-extern struct LogConfig logcfg;
-
-struct LogModule {
- int OptSupported, OptDefault;
- const char *Name, *OptName[LOPT_NUM];
- };
-
-struct LogHeader {
- int c;
- char stamp[32];
- char tag[64];
- };
-
-class cLogging {
-private:
- static void (*LogPrint)(const struct LogHeader *lh, const char *txt);
- //
- static void PrivateLogPrint(const struct LogHeader *lh, const char *txt);
- static bool GetHeader(int c, struct LogHeader *lh);
- static void LogLine(const struct LogHeader *lh, const char *txt, bool doCrc=true);
- static const struct LogModule *GetModule(int c);
- static void UpgradeOptions(int m);
-public:
- static bool AddModule(int m, const struct LogModule *dm);
- static void SetLogPrint(void (*lp)(const struct LogHeader *lh, const char *txt));
- //
- static void Printf(int c, const char *format, ...) __attribute__ ((format (printf,2,3)));
- static void Puts(int c, const char *txt);
- static void PutLB(int c, cLineBuff *lb);
- static void Dump(int c, const void *data, int n, const char *format, ...) __attribute__ ((format (printf,4,5)));
- static void LineDump(int c, const void *data, int n, const char *format, ...) __attribute__ ((format (printf,4,5)));
- static bool Enabled(int c);
- //
- static void SetModuleOptions(int c);
- static int GetModuleOptions(int c);
- static void SetModuleOption(int c, bool on);
- static void SetModuleDefault(int c);
- static const char *GetModuleName(int c);
- static const char *GetOptionName(int c);
- static void ParseConfig(const char *txt);
- static bool GetConfig(cLineBuff *lb);
- static void ReopenLogfile(void);
- static int GetClassByName(const char *name);
- };
-
-// ----------------------------------------------------------------
-
-class cUserMsg : public cSimpleItem {
-private:
- char *msg;
-public:
- cUserMsg(const char *m);
- ~cUserMsg();
- const char *Message(void) { return msg; };
- };
-
-// ----------------------------------------------------------------
-
-class cUserMsgs : public cSimpleList<cUserMsg> {
-private:
- cMutex *mutex;
-public:
- cUserMsgs(void);
- ~cUserMsgs();
- void Queue(const char *fmt, ...) __attribute__ ((format (printf,2,3)));
- cUserMsg *GetQueuedMsg(void);
- };
-
-extern cUserMsgs ums;
-
-// ----------------------------------------------------------------
-
-class cLogLineBuff : public cLineBuff {
-private:
- int c;
-public:
- cLogLineBuff(int C);
- ~cLogLineBuff();
- void Flush(void);
- };
-
-#endif //___LOG_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include <vdr/tools.h>
-#include <vdr/thread.h>
-
-#include "misc.h"
-
-// -----------------------------------------------------------------------------
-
-void DvbName(const char *Name, int n, char *buffer, int len)
-{
- snprintf(buffer,len,"/dev/dvb/adapter%d/%s%d",n,Name,0);
-}
-
-int DvbOpen(const char *Name, int n, int Mode, bool ReportError)
-{
- char FileName[128];
- DvbName(Name,n,FileName,sizeof(FileName));
- int fd=open(FileName,Mode);
- if(fd<0 && ReportError) LOG_ERROR_STR(FileName);
- return fd;
-}
-
-const char *HexStr(char *str, const unsigned char *mem, int len)
-{
- for(int i=0 ; i<len ; i++) sprintf(&str[i*2],"%02X",mem[i]);
- return str;
-}
-
-static int HexDigit(int asc)
-{
- if(asc>='A') return toupper(asc)-'A'+10;
- return asc-'0';
-}
-
-int GetChar(const char * &line, int *store, int count)
-{
- line=skipspace(line);
- const char *sline=line;
- *store=0;
- while(count) {
- if(line[0]==0 || !isalnum(line[0])) break;
- *store<<=8; *store+=line[0];
- line++; count--;
- }
- if(!count && (!*line || isspace(*line) || *line==';')) return sline-line;
- *store=0;
- line=sline;
- return 0;
-}
-
-static int GetHexBase(const char * &line, unsigned char *store, int count, bool fixedLen, bool asc)
-{
- line=skipspace(line);
- const char *sline=line;
- unsigned char *sstore=store;
- int scount=count;
- while(count) {
- if(line[0]==0 || line[1]==0 || !isxdigit(line[0]) || !isxdigit(line[1])) break;
- if(asc) {
- *store++=line[0]; *store++=line[1];
- }
- else {
- int d1=HexDigit(line[0]);
- int d0=HexDigit(line[1]);
- *store++=(d1<<4) + d0;
- }
- line+=2; count--;
- }
- if(asc) *store=0; // make sure strings are NULL terminated
- if((!count || (!fixedLen && count!=scount)) &&
- (!*line || isspace(*line) || *line==';' || *line==']' || *line=='/') ) return scount-count;
- memset(sstore,0,scount);
- line=sline;
- return 0;
-}
-
-int GetHex(const char * &line, unsigned char *store, int count, bool fixedLen)
-{
- return GetHexBase(line,store,count,fixedLen,false);
-}
-
-int GetHexAsc(const char * &line, unsigned char *store, int count)
-{
- return GetHexBase(line,store,count/2,true,true)*2;
-}
-
-unsigned long long Bin2LongLong(unsigned char *mem, int len)
-{
- unsigned long long k=0;
- for(int i=0 ; i<len ; i++) { k<<=8; k+=mem[i]; }
- return k;
-}
-
-bool CheckNull(const unsigned char *data, int len)
-{
- while(--len>=0) if(data[len]) return false;
- return true;
-}
-
-bool CheckFF(const unsigned char *data, int len)
-{
- while(--len>=0) if(data[len]!=0xFF) return false;
- return true;
-}
-
-unsigned char XorSum(const unsigned char *mem, int len)
-{
- unsigned char cs=0;
- while(len>0) { cs ^= *mem++; len--; }
- return cs;
-}
-
-// crc stuff taken from linux-2.6.0/lib/crc32.c
-/*
- * There are multiple 16-bit CRC polynomials in common use, but this is
- * *the* standard CRC-32 polynomial, first popularized by Ethernet.
- * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0
- */
-#define CRCPOLY_LE 0xedb88320
-
-unsigned int crc32_le(unsigned int crc, unsigned char const *p, int len)
-{
- crc^=0xffffffff; // zlib mod
- while(len--) {
- crc^=*p++;
- for(int i=0; i<8; i++)
- crc=(crc&1) ? (crc>>1)^CRCPOLY_LE : (crc>>1);
- }
- crc^=0xffffffff; // zlib mod
- return crc;
-}
-
-// -- cLineBuff -----------------------------------------------------------------
-
-cLineBuff::cLineBuff(int blocksize)
-{
- blockSize=blocksize;
- work=0;
- blen=wlen=0;
-}
-
-cLineBuff::~cLineBuff()
-{
- free(work);
-}
-
-void cLineBuff::Flush(void)
-{
- blen=0;
-}
-
-char *cLineBuff::Grab(void)
-{
- char *w=work;
- work=0; wlen=0;
- Flush();
- return w;
-}
-
-bool cLineBuff::Check(int num)
-{
- if(wlen-blen<num) {
- if(num<blockSize) num=blockSize;
- char *w=(char *)realloc(work,wlen+num);
- if(w) {
- wlen+=num;
- work=w;
- }
- }
- return work!=0;
-}
-
-void cLineBuff::Printf(const char *fmt, ...)
-{
- int q=120;
- while(Check(q)) {
- int s=wlen-blen;
- va_list ap;
- va_start(ap,fmt);
- q=vsnprintf(work+blen,s,fmt,ap);
- va_end(ap);
- if(q<s) {
- if(q>0) blen+=q;
- break;
- }
- // truncated
- q+=100;
- }
-}
-
-void cLineBuff::Strcat(const char *str)
-{
- if(str) Printf("%s",str);
-}
-
-void cLineBuff::Back(int n)
-{
- if(n>blen) blen=0; else blen-=n;
- if(work) work[blen]=0;
-}
-
-// -- cSimpleListBase --------------------------------------------------------------
-
-cSimpleListBase::cSimpleListBase(void)
-{
- first=last=0; count=0;
-}
-
-cSimpleListBase::~cSimpleListBase()
-{
- Clear();
-}
-
-void cSimpleListBase::Add(cSimpleItem *Item, cSimpleItem *After)
-{
- if(After) {
- Item->next=After->next;
- After->next=Item;
- }
- else {
- Item->next=0;
- if(last) last->next=Item;
- else first=Item;
- }
- if(!Item->next) last=Item;
- count++;
-}
-
-void cSimpleListBase::Ins(cSimpleItem *Item)
-{
- Item->next=first;
- first=Item;
- if(!Item->next) last=Item;
- count++;
-}
-
-void cSimpleListBase::Del(cSimpleItem *Item, bool Del)
-{
- if(first==Item) {
- first=Item->next;
- if(!first) last=0;
- }
- else {
- cSimpleItem *item=first;
- while(item) {
- if(item->next==Item) {
- item->next=Item->next;
- if(!item->next) last=item;
- break;
- }
- item=item->next;
- }
- }
- count--;
- if(Del) delete Item;
-}
-
-void cSimpleListBase::Clear(void)
-{
- while(first) Del(first);
- first=last=0; count=0;
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___MISC_H
-#define ___MISC_H
-
-#include <alloca.h>
-
-// ----------------------------------------------------------------
-
-#define WORD(buffer,index,mask) (((buffer[(index)]<<8) + buffer[(index)+1]) & mask)
-#define SCT_LEN(sct) (3+(((sct)[1]&0x0f)<<8)+(sct)[2])
-
-#define MBC(a,b) (((a)<<8)+(b))
-#define ADDC3(ab,c) ((ab)+((c)<<16))
-#define MBC3(a,b,c) ADDC3(MBC((a),(b)),(c))
-#define C2(x) (((x)>>8)&0xFF)
-#define C3(x) (((x)>>16)&0xFF)
-#define C2MASK 0xFFFF
-
-// replacement for variable-sized arrays
-#define AUTOARRAY(type,size) (type *)alloca(sizeof(type)*(size))
-#define AUTOMEM(size) (unsigned char *)alloca(size)
-
-// ----------------------------------------------------------------
-
-#define DEV_DVB_FRONTEND "frontend"
-#define DEV_DVB_DVR "dvr"
-#define DEV_DVB_DEMUX "demux"
-#define DEV_DVB_CA "ca"
-void DvbName(const char *Name, int n, char *buffer, int len);
-int DvbOpen(const char *Name, int n, int Mode, bool ReportError=false);
-
-const char *HexStr(char *str, const unsigned char *mem, int len);
-#define KeyStr(str,key) HexStr(str,key,8)
-
-int GetHex(const char * &line, unsigned char *store, int count, bool fixedLen=true);
-int GetHexAsc(const char * &line, unsigned char *store, int count);
-int GetChar(const char * &line, int *store, int count);
-unsigned long long Bin2LongLong(unsigned char *mem, int len);
-#define Bin2Int(mem,len) ((int)Bin2LongLong((mem),(len)))
-
-bool CheckNull(const unsigned char *data, int len);
-bool CheckFF(const unsigned char *data, int len);
-unsigned char XorSum(const unsigned char *mem, int len);
-unsigned int crc32_le(unsigned int crc, unsigned char const *p, int len);
-
-// ----------------------------------------------------------------
-
-class cLineBuff {
-private:
- int blockSize;
- char *work;
- int blen, wlen;
- //
- bool Check(int num);
-protected:
- char *Grab(void);
-public:
- cLineBuff(int blocksize);
- ~cLineBuff();
- void Printf(const char *fmt, ...) __attribute__ ((format (printf,2,3)));
- void Strcat(const char *str);
- void Flush(void);
- void Back(int n);
- const char *Line(void) const { return work; }
- int Length(void) const { return blen; }
- };
-
-// ----------------------------------------------------------------
-
-class cSimpleListBase;
-
-class cSimpleItem {
-friend class cSimpleListBase;
-private:
- cSimpleItem *next;
-public:
- virtual ~cSimpleItem() {}
- cSimpleItem *Next(void) const { return next; }
- };
-
-class cSimpleListBase {
-protected:
- cSimpleItem *first, *last;
- int count;
-public:
- cSimpleListBase(void);
- ~cSimpleListBase();
- void Add(cSimpleItem *Item, cSimpleItem *After=0);
- void Ins(cSimpleItem *Item);
- void Del(cSimpleItem *Item, bool Del=true);
- void Clear(void);
- int Count(void) const { return count; }
- };
-
-template<class T> class cSimpleList : public cSimpleListBase {
-public:
- T *First(void) const { return (T *)first; }
- T *Last(void) const { return (T *)last; }
- T *Next(const T *item) const { return (T *)item->cSimpleItem::Next(); }
- };
-
-#endif //___MISC_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-
-#include <vdr/thread.h>
-#include <vdr/tools.h>
-
-#include "network.h"
-#include "misc.h"
-#include "log-core.h"
-
-const char *netscript=0;
-int netTimeout=60*1000; // timeout for shutting down dialup-network
-
-// -- cNetWatcher ---------------------------------------------------------------
-
-class cNetWatcher : protected cThread {
-private:
- int count;
- cTimeMs down;
- bool netup, downDelay;
- cSimpleList<cNetSocket> socks;
- //
- int RunCommand(const char *cmd, const char *state);
-protected:
- virtual void Action(void);
-public:
- cNetWatcher(void);
- ~cNetWatcher();
- void Up(cNetSocket *so);
- void Down(cNetSocket *so);
- void Block(void) { Lock(); }
- void Unblock(void) { Unlock(); }
- };
-
-static cNetWatcher nw;
-
-cNetWatcher::cNetWatcher(void)
-:cThread("Netwatcher")
-{
- count=0; netup=downDelay=false;
-}
-
-cNetWatcher::~cNetWatcher()
-{
- Cancel(2);
- Lock();
- if(netup) RunCommand(netscript,"down");
- cNetSocket *so;
- while((so=socks.First())) socks.Del(so,false);
- Unlock();
-}
-
-void cNetWatcher::Up(cNetSocket *so)
-{
- Lock();
- socks.Add(so);
- if(!Active()) Start();
- if(netscript) {
- downDelay=false; netup=true;
- RunCommand(netscript,"up");
- count++;
- PRINTF(L_CORE_NET,"netwatch up (%d)",count);
- }
- else PRINTF(L_CORE_NET,"netwatch up");
- Unlock();
-}
-
-void cNetWatcher::Down(cNetSocket *so)
-{
- Lock();
- socks.Del(so,false);
- if(netscript) {
- if(--count==0) {
- downDelay=true;
- down.Set(netTimeout);
- }
- PRINTF(L_CORE_NET,"netwatch down (%d)",count);
- }
- else PRINTF(L_CORE_NET,"netwatch down");
- Unlock();
-}
-
-void cNetWatcher::Action(void)
-{
- while(Running()) {
- sleep(1);
- Lock();
- if(downDelay && down.TimedOut()) {
- PRINTF(L_CORE_NET,"netdown timeout expired");
- if(netup) {
- RunCommand(netscript,"down");
- netup=false;
- }
- downDelay=false;
- }
- for(cNetSocket *so=socks.First(); so;) {
- cNetSocket *next=socks.Next(so);
- so->Lock();
- if(so->connected && so->activity.TimedOut()) {
- PRINTF(L_CORE_NET,"idle timeout, disconnected %s:%d",so->hostname,so->port);
- so->Disconnect();
- }
- so->Unlock();
- so=next;
- }
- Unlock();
- }
-}
-
-int cNetWatcher::RunCommand(const char *cmd, const char *state)
-{
- char *tmp;
- asprintf(&tmp,"%s %s",cmd,state);
- PRINTF(L_CORE_NET,"netwatch cmd exec '%s'",tmp);
- int res=SystemExec(tmp);
- free(tmp);
- return res;
-}
-
-// -- cNetSocket ------------------------------------------------------------------
-
-cNetSocket::cNetSocket(int ConnectTimeout, int ReadWriteTimeout, int IdleTimeout, bool Udp)
-{
- hostname=0; sd=-1; connected=netup=false;
- udp=Udp; conTimeout=ConnectTimeout; rwTimeout=ReadWriteTimeout;
- idleTimeout=IdleTimeout*1000;
-}
-
-cNetSocket::~cNetSocket()
-{
- Disconnect();
- free(hostname);
-}
-
-void cNetSocket::Activity(void)
-{
- activity.Set(idleTimeout);
-}
-
-bool cNetSocket::GetAddr(struct sockaddr_in *saddr, const char *Hostname, int Port)
-{
- const struct hostent * const hostaddr=gethostbyname(Hostname);
- if(hostaddr) {
- saddr->sin_family=AF_INET;
- saddr->sin_port=htons(Port);
- saddr->sin_addr.s_addr=((struct in_addr *)hostaddr->h_addr)->s_addr;
- return true;
- }
- PRINTF(L_GEN_ERROR,"socket: name lookup error for %s",Hostname);
- return false;
-}
-
-int cNetSocket::GetSocket(bool Udp)
-{
- int proto=0;
- const struct protoent * const ptrp=getprotobyname(Udp?"udp":"tcp");
- if(ptrp) proto=ptrp->p_proto;
- int so;
- if((so=socket(PF_INET,Udp?SOCK_DGRAM:SOCK_STREAM,proto))>=0) {
- int flgs=fcntl(so,F_GETFL);
- if(flgs>=0) {
- if(fcntl(so,F_SETFL,flgs|O_NONBLOCK)==0)
- return so;
- else PRINTF(L_GEN_ERROR,"socket: fcntl SETFL failed: %s",strerror(errno));
- }
- else PRINTF(L_GEN_ERROR,"socket: fcntl GETFL failed: %s",strerror(errno));
- close(so);
- }
- else PRINTF(L_GEN_ERROR,"socket: socket failed: %s",strerror(errno));
- return -1;
-}
-
-bool cNetSocket::Connect(const char *Hostname, int Port, int timeout)
-{
- nw.Block();
- Lock();
- Disconnect();
- if(Hostname) {
- free(hostname);
- hostname=strdup(Hostname); port=Port;
- }
- if(timeout<0) timeout=conTimeout;
- nw.Up(this); netup=true;
- nw.Unblock();
- struct sockaddr_in socketAddr;
- if(GetAddr(&socketAddr,hostname,port) && (sd=GetSocket(udp))>=0) {
- PRINTF(L_CORE_NET,"connecting to %s:%d/%s (%d.%d.%d.%d)",
- hostname,port,udp?"udp":"tcp",
- (socketAddr.sin_addr.s_addr>> 0)&0xff,(socketAddr.sin_addr.s_addr>> 8)&0xff,(socketAddr.sin_addr.s_addr>>16)&0xff,(socketAddr.sin_addr.s_addr>>24)&0xff);
- if(connect(sd,(struct sockaddr *)&socketAddr,sizeof(socketAddr))==0)
- connected=true;
- else if(errno==EINPROGRESS) {
- if(Select(false,timeout)>0) {
- int r=-1;
- unsigned int l=sizeof(r);
- if(getsockopt(sd,SOL_SOCKET,SO_ERROR,&r,&l)==0) {
- if(r==0)
- connected=true;
- else PRINTF(L_GEN_ERROR,"socket: connect failed (late): %s",strerror(r));
- }
- else PRINTF(L_GEN_ERROR,"socket: getsockopt failed: %s",strerror(errno));
- }
- else PRINTF(L_GEN_ERROR,"socket: connect timed out");
- }
- else PRINTF(L_GEN_ERROR,"socket: connect failed: %s",strerror(errno));
-
- if(connected) { Activity(); Unlock(); return true; }
- }
- Unlock();
- Disconnect();
- return false;
-}
-
-
-bool cNetSocket::Bind(const char *Hostname, int Port)
-{
- nw.Block();
- Lock();
- Disconnect();
- if(Hostname) {
- free(hostname);
- hostname=strdup(Hostname); port=Port;
- }
- nw.Up(this); netup=true;
- nw.Unblock();
- struct sockaddr_in socketAddr;
- if(GetAddr(&socketAddr,hostname,port) && (sd=GetSocket(udp))>=0) {
- PRINTF(L_CORE_NET,"socket: binding to %s:%d/%s (%d.%d.%d.%d)",
- hostname,port,udp?"udp":"tcp",
- (socketAddr.sin_addr.s_addr>> 0)&0xff,(socketAddr.sin_addr.s_addr>> 8)&0xff,(socketAddr.sin_addr.s_addr>>16)&0xff,(socketAddr.sin_addr.s_addr>>24)&0xff);
- if(bind(sd,(struct sockaddr *)&socketAddr,sizeof(socketAddr))==0) {
- connected=true;
- Activity(); Unlock();
- return true;
- }
- else PRINTF(L_GEN_ERROR,"socket: bind failed: %s",strerror(errno));
- }
- Unlock();
- Disconnect();
- return false;
-}
-
-void cNetSocket::Disconnect(void)
-{
- nw.Block();
- cMutexLock lock(this);
- if(sd>=0) { close(sd); sd=-1; }
- connected=false;
- if(netup) { nw.Down(this); netup=false; }
- nw.Unblock();
-}
-
-void cNetSocket::Flush(void)
-{
- cMutexLock lock(this);
- if(sd>=0) {
- unsigned char buff[512];
- while(read(sd,buff,sizeof(buff))>0) Activity();
- }
-}
-
-int cNetSocket::Read(unsigned char *data, int len, int timeout)
-{
- cMutexLock lock(this);
- if(timeout<0) timeout=rwTimeout;
- int r=Select(true,timeout);
- if(r>0) {
- r=read(sd,data,len);
- if(r<0) PRINTF(L_GEN_ERROR,"socket: read failed: %s",strerror(errno));
- else if(r>0) HEXDUMP(L_CORE_NETDATA,data,r,"network read");
- }
- Activity();
- return r;
-}
-
-int cNetSocket::Write(const unsigned char *data, int len, int timeout)
-{
- cMutexLock lock(this);
- if(timeout<0) timeout=rwTimeout;
- int r=Select(false,timeout);
- if(r>0) {
- r=write(sd,data,len);
- if(r<0) PRINTF(L_GEN_ERROR,"socket: write failed: %s",strerror(errno));
- else if(r>0) HEXDUMP(L_CORE_NETDATA,data,r,"network write");
- }
- Activity();
- return r;
-}
-
-int cNetSocket::SendTo(const char *Host, int Port, const unsigned char *data, int len, int timeout)
-{
- cMutexLock lock(this);
- if(timeout<0) timeout=rwTimeout;
- int r=Select(false,timeout);
- if(r>0) {
- struct sockaddr_in saddr;
- if(GetAddr(&saddr,Host,Port)) {
- r=sendto(sd,data,len,0,(struct sockaddr *)&saddr,sizeof(saddr));
- if(r<0) PRINTF(L_GEN_ERROR,"socket: sendto %d.%d.%d.%d:%d failed: %s",(saddr.sin_addr.s_addr>> 0)&0xff,(saddr.sin_addr.s_addr>> 8)&0xff,(saddr.sin_addr.s_addr>>16)&0xff,(saddr.sin_addr.s_addr>>24)&0xff,Port,strerror(errno));
- else if(r>0) HEXDUMP(L_CORE_NETDATA,data,r,"network sendto %d.%d.%d.%d:%d",(saddr.sin_addr.s_addr>> 0)&0xff,(saddr.sin_addr.s_addr>> 8)&0xff,(saddr.sin_addr.s_addr>>16)&0xff,(saddr.sin_addr.s_addr>>24)&0xff,Port);
- }
- else r=-1;
- }
- Activity();
- return r;
-}
-
-int cNetSocket::Select(bool forRead, int timeout)
-{
- if(sd>=0) {
- fd_set fds;
- FD_ZERO(&fds); FD_SET(sd,&fds);
- struct timeval tv;
- tv.tv_sec=timeout; tv.tv_usec=0;
- int r=select(sd+1,forRead ? &fds:0,forRead ? 0:&fds,0,&tv);
- if(r>0) return 1;
- else if(r<0) {
- PRINTF(L_GEN_ERROR,"socket: select failed: %s",strerror(errno));
- return -1;
- }
- else {
- if(timeout>0) PRINTF(L_CORE_NET,"socket: select timed out (%d secs)",timeout);
- return 0;
- }
- }
- return -1;
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___NETWORK_H
-#define ___NETWORK_H
-
-#include <vdr/thread.h>
-#include <vdr/tools.h>
-#include "misc.h"
-
-// ----------------------------------------------------------------
-
-#define DEFAULT_CONNECT_TIMEOUT 20
-#define DEFAULT_READWRITE_TIMEOUT 3
-#define DEFAULT_IDLE_TIMEOUT 120
-
-extern const char *netscript;
-extern int netTimeout;
-
-// ----------------------------------------------------------------
-
-class cNetWatcher;
-
-class cNetSocket : public cSimpleItem, private cMutex {
-friend class cNetWatcher;
-private:
- int sd;
- char *hostname;
- int port, dummy, conTimeout, rwTimeout, idleTimeout;
- bool udp, connected, netup;
- cTimeMs activity;
- //
- int Select(bool forRead, int timeout);
- void Activity(void);
- bool GetAddr(struct sockaddr_in *saddr, const char *Hostname, int Port);
- int GetSocket(bool Udp);
-public:
- cNetSocket(int ConnectTimeout, int ReadWriteTimeout, int IdleTimeout, bool Udp=false);
- ~cNetSocket();
- bool Connect(const char *Hostname, int Port, int timeout=-1);
- bool Bind(const char *Hostname, int Port);
- void Disconnect(void);
- int Read(unsigned char *data, int len, int timeout=-1);
- int Write(const unsigned char *data, int len, int timeout=-1);
- int SendTo(const char *Host, int Port, const unsigned char *data, int len, int timeout=-1);
- void Flush(void);
- bool Connected(void) { return connected; }
- };
-
-#endif //___NETWORK_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___OPENSSL_COMPAT_H
-#define ___OPENSSL_COMPAT_H
-
-#include <openssl/opensslv.h>
-
-#if OPENSSL_VERSION_NUMBER >= 0x0090800fL || OPENSSL_VERSION_NUMBER < 0x0090705fL
-#define DES_CAST(x) ((DES_cblock *)(x))
-#else
-#define DES_CAST(x) (x)
-#endif
-
-#endif
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___OPTS_H
-#define ___OPTS_H
-
-#include "i18n.h"
-
-class cOsdMenu;
-
-// ----------------------------------------------------------------
-
-class cOpt {
-private:
- char *fullname;
- bool persistant;
-protected:
- const char *name, *title;
- //
- const char *FullName(const char *PreStr);
-public:
- cOpt(const char *Name, const char *Title);
- virtual ~cOpt();
- virtual void Parse(const char *Value)=0;
- virtual void Backup(void)=0;
- virtual bool Set(void)=0;
- virtual void Store(const char *PreStr)=0;
- virtual void Create(cOsdMenu *menu)=0;
- const char *Name(void) { return name; }
- void Persistant(bool per) { persistant=per; }
- bool Persistant(void) { return persistant; }
- };
-
-// ----------------------------------------------------------------
-
-class cOptInt : public cOpt {
-protected:
- int *storage, value, min, max;
-public:
- cOptInt(const char *Name, const char *Title, int *Storage, int Min, int Max);
- virtual void Parse(const char *Value);
- virtual void Backup(void);
- virtual bool Set(void);
- virtual void Store(const char *PreStr);
- virtual void Create(cOsdMenu *menu);
- };
-
-// ----------------------------------------------------------------
-
-class cOptSel : public cOptInt {
-private:
- const char **trStrings;
-protected:
- const char * const *strings;
-public:
- cOptSel(const char *Name, const char *Title, int *Storage, int NumStr, const char * const *Strings);
- virtual ~cOptSel();
- virtual void Create(cOsdMenu *menu);
- };
-
-// ----------------------------------------------------------------
-
-class cOptBool : public cOptInt {
-public:
- cOptBool(const char *Name, const char *Title, int *Storage);
- virtual void Create(cOsdMenu *menu);
- };
-
-// ----------------------------------------------------------------
-
-class cOptStr : public cOpt {
-protected:
- char *storage, *value;
- const char *allowed;
- int size;
-public:
- cOptStr(const char *Name, const char *Title, char *Storage, int Size, const char *Allowed);
- virtual ~cOptStr();
- virtual void Parse(const char *Value);
- virtual void Backup(void);
- virtual bool Set(void);
- virtual void Store(const char *PreStr);
- virtual void Create(cOsdMenu *menu);
- };
-
-// ----------------------------------------------------------------
-
-class cOpts {
-private:
- int numOpts, numAdd;
- const char *preStr;
- cOpt **opts;
-public:
- cOpts(const char *PreStr, int NumOpts);
- ~cOpts();
- void Add(cOpt *opt);
- bool Parse(const char *Name, const char *Value);
- bool Store(bool AsIs);
- void Backup(void);
- void Create(cOsdMenu *menu);
- };
-
-#endif //___OPTS_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "parse.h"
-#include "misc.h"
-#include "log.h"
-
-// -----------------------------------------------------------------------------
-
-void SetSctLen(unsigned char *data, int len)
-{
- data[1]=(len>>8) | 0x70;
- data[2]=len & 0xFF;
-}
-
-static void SortNanos(unsigned char *dest, const unsigned char *src, int len)
-{
- int w=0, c=-1;
- while(1) {
- int n=0x100;
- for(int j=0; j<len;) {
- int l=src[j+1]+2;
- if(src[j]==c) {
- if(w+l>len) {
- PRINTF(L_GEN_ERROR,"sortnanos: sanity check failed. Exceeding memory area. Probably corrupted nanos!");
- memset(dest,0,len); // zero out everything
- return;
- }
- memcpy(&dest[w],&src[j],l);
- w+=l;
- }
- else if(src[j]>c && src[j]<n)
- n=src[j];
- j+=l;
- }
- if(n==0x100) break;
- c=n;
- }
-}
-
-// -- cProviders ---------------------------------------------------------------
-
-void cProviders::AddProv(cProvider *p)
-{
- if(p) Add(p);
-}
-
-cProvider *cProviders::FindProv(const unsigned char *data)
-{
- cProvider *p=First();
- while(p) {
- if(p->MatchID(data)) break;
- p=Next(p);
- }
- return p;
-}
-
-cProvider *cProviders::MatchProv(const unsigned char *data)
-{
- cProvider *p=First();
- while(p) {
- if(p->MatchEMM(data)) break;
- p=Next(p);
- }
- return p;
-}
-
-// -- cAssSct ------------------------------------------------------------------
-
-cAssSct::cAssSct(const unsigned char *Data)
-{
- data=Data;
-}
-
-// -- cAssembleData ------------------------------------------------------------
-
-cAssembleData::cAssembleData(const unsigned char *Data)
-{
- data=Data;
- curr=0;
-}
-
-void cAssembleData::SetAssembled(const unsigned char *Data)
-{
- Add(new cAssSct(Data));
- curr=First();
-}
-
-const unsigned char *cAssembleData::Assembled(void)
-{
- const unsigned char *ret=0;
- if(First()) {
- if(curr) {
- ret=curr->Data();
- curr=Next(curr);
- }
- }
- else {
- ret=data;
- data=0;
- }
- return ret;
-}
-
-// -- cIdSet -------------------------------------------------------------------
-
-cIdSet::cIdSet(void)
-{
- card=0;
-}
-
-cIdSet::~cIdSet()
-{
- delete card;
-}
-
-void cIdSet::ResetIdSet(void)
-{
- delete card; card=0;
- Clear();
-}
-
-void cIdSet::SetCard(cCard *c)
-{
- delete card;
- card=c;
-}
-
-bool cIdSet::MatchEMM(const unsigned char *data)
-{
- return (card && card->MatchEMM(data)) || MatchProv(data);
-}
-
-bool cIdSet::MatchAndAssemble(cAssembleData *ad, int *updtype, cProvider **prov)
-{
- const unsigned char *data=ad->Data();
- cProvider *p;
- if(card && card->MatchEMM(data)) {
- if(updtype) *updtype=card->UpdateType(data);
- if(prov) *prov=0;
- if(card->Assemble(ad)>=0) return true;
- }
- else if((p=MatchProv(data))) {
- if(updtype) *updtype=p->UpdateType(data);
- if(prov) *prov=p;
- if(p->Assemble(ad)>=0) return true;
- }
- return false;
-}
-
-// -- cProviderIrdeto ----------------------------------------------------------
-
-cProviderIrdeto::cProviderIrdeto(unsigned char pb, const unsigned char *pi)
-{
- provBase=pb;
- memcpy(provId,pi,sizeof(provId));
-}
-
-bool cProviderIrdeto::MatchID(const unsigned char *data)
-{
- const unsigned int mode=cParseIrdeto::AddrBase(data);
- return (mode<0x10 && mode==provBase);
-}
-
-bool cProviderIrdeto::MatchEMM(const unsigned char *data)
-{
- const unsigned int len=cParseIrdeto::AddrLen(data);
- const unsigned int mode=cParseIrdeto::AddrBase(data);
- return ( mode<0x10 && len<=sizeof(provId)
- && mode==provBase && (!len || !memcmp(&data[4],provId,len)));
-}
-
-unsigned long long cProviderIrdeto::ProvId(void)
-{
- return (provId[0]<<24)+(provId[1]<<16)+(provId[2]<<8)+provBase;
-}
-
-// -- cCardIrdeto --------------------------------------------------------------
-
-cCardIrdeto::cCardIrdeto(unsigned char hb, const unsigned char *hs)
-{
- hexBase=hb;
- memcpy(hexSer,hs,sizeof(hexSer));
-}
-
-bool cCardIrdeto::MatchEMM(const unsigned char *data)
-{
- const unsigned int len=cParseIrdeto::AddrLen(data);
- const unsigned int mode=cParseIrdeto::AddrBase(data);
- return ( mode>=0x10 && len<=sizeof(hexSer)
- && mode==hexBase && (!len || !memcmp(&data[4],hexSer,len)));
-}
-
-int cCardIrdeto::UpdateType(const unsigned char *data)
-{
- switch(cParseIrdeto::AddrLen(data)) {
- case 0: return 0; // global
- case 1:
- case 2: return 2; // shared
- default: return 3; // unique
- }
-}
-
-// -- cParseIrdeto -------------------------------------------------------------
-
-unsigned int cParseIrdeto::AddrLen(const unsigned char *data)
-{
- return data[3] & 0x07;
-}
-
-unsigned int cParseIrdeto::AddrBase(const unsigned char *data)
-{
- return data[3] >> 3;
-}
-
-// -- cProviderSeca ------------------------------------------------------------
-
-cProviderSeca::cProviderSeca(const unsigned char *pi, const unsigned char *s)
-{
- memcpy(provId,pi,sizeof(provId));
- memcpy(sa,s,sizeof(sa));
-}
-
-bool cProviderSeca::MatchID(const unsigned char *data)
-{
- const unsigned char *id=cParseSeca::ProvIdPtr(data);
- return id && !memcmp(id,provId,sizeof(provId));
-}
-
-bool cProviderSeca::MatchEMM(const unsigned char *data)
-{
- return TID(data)==0x84 &&
- !memcmp(SID(data),provId,sizeof(provId)) && !memcmp(SA(data),sa,sizeof(sa));
-}
-
-unsigned long long cProviderSeca::ProvId(void)
-{
- return (provId[0]<<8)+provId[1];
-}
-
-// -- cCardSeca ----------------------------------------------------------------
-
-cCardSeca::cCardSeca(const unsigned char *u)
-{
- memcpy(ua,u,sizeof(ua));
-}
-
-bool cCardSeca::MatchEMM(const unsigned char *data)
-{
- return TID(data)==0x82 &&
- !memcmp(UA(data),ua,sizeof(ua));
-}
-
-// -- cParseSeca ---------------------------------------------------------------
-
-int cParseSeca::CmdLen(const unsigned char *data)
-{
- struct SecaCmd *s=(struct SecaCmd *)data;
- return ((s->cmdLen1&0x0f)<<8) | s->cmdLen2;
-}
-
-int cParseSeca::Payload(const unsigned char *data, const unsigned char **payload)
-{
- int l;
- switch(TID(data)) {
- case 0x80:
- case 0x81: l=sizeof(struct SecaEcm); break;
- case 0x82: l=sizeof(struct SecaEmmUnique); break;
- case 0x84: l=sizeof(struct SecaEmmShared); break;
- default: return -1;
- }
- if(payload) *payload=&data[l];
- return CmdLen(data)-l+sizeof(struct SecaCmd);
-}
-
-int cParseSeca::SysMode(const unsigned char *data)
-{
- switch(TID(data)) {
- case 0x80:
- case 0x81: return ((struct SecaEcm *)data)->sm; break;
- case 0x82: return ((struct SecaEmmUnique *)data)->sm; break;
- case 0x84: return ((struct SecaEmmShared *)data)->sm; break;
- default: return -1;
- }
-}
-
-int cParseSeca::KeyNr(const unsigned char *data)
-{
- switch(TID(data)) {
- case 0x80:
- case 0x81: return ((struct SecaEcm *)data)->keyNr; break;
- case 0x82: return ((struct SecaEmmUnique *)data)->keyNr; break;
- case 0x84: return ((struct SecaEmmShared *)data)->keyNr; break;
- default: return -1;
- }
-}
-
-const unsigned char *cParseSeca::ProvIdPtr(const unsigned char *data)
-{
- switch(TID(data)) {
- case 0x80:
- case 0x81: return ((struct SecaEcm *)data)->id;
- case 0x82: return ((struct SecaEmmUnique *)data)->id;
- case 0x84: return ((struct SecaEmmShared *)data)->id;
- }
- return 0;
-}
-
-int cParseSeca::ProvId(const unsigned char *data)
-{
- const unsigned char *id=cParseSeca::ProvIdPtr(data);
- return id ? (id[0]<<8)+id[1] : -1;
-}
-
-// -- cProviderViaccess --------------------------------------------------------
-
-cProviderViaccess::cProviderViaccess(void)
-{
- sharedEmm=0; sharedLen=sharedToggle=0;
-}
-
-cProviderViaccess::cProviderViaccess(const unsigned char *id, const unsigned char *s)
-{
- sharedEmm=0; sharedLen=sharedToggle=0;
- memcpy(ident,id,sizeof(ident));
- ident[2]&=0xf0;
- memcpy(sa,s,sizeof(sa));
-}
-
-cProviderViaccess::~cProviderViaccess()
-{
- free(sharedEmm);
-}
-
-bool cProviderViaccess::MatchID(const unsigned char *data)
-{
- const unsigned char *id=cParseViaccess::ProvIdPtr(data);
- return id && id[0]==ident[0] && id[1]==ident[1] && (id[2]&0xf0)==ident[2];
-}
-
-bool cProviderViaccess::MatchEMM(const unsigned char *data)
-{
- switch(data[0]) {
- case 0x8e:
- if(memcmp(&data[3],sa,sizeof(sa)-1)) break;
- if((data[6]&2)==0)
- return sharedEmm && MatchID(sharedEmm);
- // fall through
- case 0x8c:
- case 0x8d:
- return MatchID(data);
- }
- return false;
-}
-
-unsigned long long cProviderViaccess::ProvId(void)
-{
- return (ident[0]<<16)+(ident[1]<<8)+ident[2];
-}
-
-int cProviderViaccess::UpdateType(const unsigned char *data)
-{
- switch(data[0]) {
- case 0x8e: return 2; // shared
- case 0x8c:
- case 0x8d:
- default: return 0; // global
- }
-}
-
-int cProviderViaccess::Assemble(cAssembleData *ad)
-{
- const unsigned char *data=ad->Data();
- int len=SCT_LEN(data);
- switch(data[0]) {
- case 0x8C:
- case 0x8D:
- if(data[0]!=sharedToggle) {
- free(sharedEmm);
- sharedLen=len;
- sharedEmm=(unsigned char *)malloc(len);
- if(sharedEmm) memcpy(sharedEmm,data,sharedLen);
- sharedToggle=data[0];
- }
- break;
-
- case 0x8E:
- if(sharedEmm) {
- unsigned char *tmp=AUTOMEM(len+sharedLen);
- unsigned char *ass=(unsigned char *)cParseViaccess::NanoStart(data);
- len-=(ass-data);
- if((data[6]&2)==0) {
- const int addrlen=len-8;
- len=0;
- tmp[len++]=0x9e;
- tmp[len++]=addrlen;
- memcpy(&tmp[len],&ass[0],addrlen); len+=addrlen;
- tmp[len++]=0xf0;
- tmp[len++]=0x08;
- memcpy(&tmp[len],&ass[addrlen],8); len+=8;
- }
- else {
- memcpy(tmp,ass,len);
- }
- ass=(unsigned char *)cParseViaccess::NanoStart(sharedEmm);
- int l=sharedLen-(ass-sharedEmm);
- memcpy(&tmp[len],ass,l); len+=l;
-
- ass=(unsigned char *)malloc(len+7);
- if(ass) {
- memcpy(ass,data,7);
- SortNanos(ass+7,tmp,len);
- SetSctLen(ass,len+4);
- ad->SetAssembled(ass);
- return 1; // assembled
- }
- }
- break;
- }
- return -1; // ignore
-}
-
-// -- cCardViaccess ------------------------------------------------------------
-
-cCardViaccess::cCardViaccess(const unsigned char *u)
-{
- memcpy(ua,u,sizeof(ua));
-}
-
-bool cCardViaccess::MatchEMM(const unsigned char *data)
-{
- return data[0]==0x88 && !memcmp(&data[3],ua,sizeof(ua));
-}
-
-// -- cParseViaccess -----------------------------------------------------------
-
-const unsigned char *cParseViaccess::NanoStart(const unsigned char *data)
-{
- switch(data[0]) {
- case 0x88: return &data[8];
- case 0x8e: return &data[7];
- case 0x8c:
- case 0x8d: return &data[3];
- case 0x80:
- case 0x81: return &data[4];
- }
- return 0;
-}
-
-const unsigned char *cParseViaccess::CheckNano90(const unsigned char *data)
-{
- return CheckNano90FromNano(NanoStart(data));
-}
-
-const unsigned char *cParseViaccess::CheckNano90FromNano(const unsigned char *data)
-{
- if(data && data[0]==0x90 && data[1]==0x03) return data;
- return 0;
-}
-
-int cParseViaccess::KeyNr(const unsigned char *data)
-{
- return KeyNrFromNano(CheckNano90(data));
-}
-
-int cParseViaccess::KeyNrFromNano(const unsigned char *data)
-{
- return data ? data[4]&0x0f : -1;
-}
-
-const unsigned char *cParseViaccess::ProvIdPtr(const unsigned char *data)
-{
- data=CheckNano90(data);
- return data ? &data[2] : 0;
-}
-
-int cParseViaccess::ProvId(const unsigned char *data)
-{
- const unsigned char *id=cParseViaccess::ProvIdPtr(data);
- return id ? (id[0]<<16)+(id[1]<<8)+(id[2]&0xf0) : -1;
-}
-
-// -- cCardNagra2 --------------------------------------------------------------
-
-cCardNagra2::cCardNagra2(const unsigned char *a)
-{
- addr[0]=a[2];
- addr[1]=a[1];
- addr[2]=a[0];
- addr[3]=a[3];
-}
-
-bool cCardNagra2::MatchEMM(const unsigned char *data)
-{
- return data[0]==0x82 ||
- (data[0]==0x83 && !memcmp(&data[3],addr,(data[7]==0x10)?3:4));
-}
-
-int cCardNagra2::UpdateType(const unsigned char *data)
-{
- if(data[0]==0x83) return (data[7]==0x10) ? 2:3;
- return 0;
-}
-
-// -- cProviderConax -----------------------------------------------------------
-
-cProviderConax::cProviderConax(const unsigned char *a)
-{
- memcpy(addr,a,sizeof(addr));
-}
-
-bool cProviderConax::MatchID(const unsigned char *data)
-{
- return MatchEMM(data);
-}
-
-bool cProviderConax::MatchEMM(const unsigned char *data)
-{
- return !memcmp(&data[3],addr,sizeof(addr));
-}
-
-unsigned long long cProviderConax::ProvId(void)
-{
- return Bin2LongLong(addr,sizeof(addr));
-}
-
-// -- cCardConax ---------------------------------------------------------------
-
-cCardConax::cCardConax(const unsigned char *a)
-{
- memcpy(addr,a,sizeof(addr));
-}
-
-bool cCardConax::MatchEMM(const unsigned char *data)
-{
- return !memcmp(&data[3],addr,sizeof(addr));
-}
-
-// -- cProviderCryptoworks -----------------------------------------------------
-
-cProviderCryptoworks::cProviderCryptoworks(const unsigned char *a)
-{
- memcpy(addr,a,sizeof(addr));
-}
-
-bool cProviderCryptoworks::MatchID(const unsigned char *data)
-{
- return MatchEMM(data);
-}
-
-bool cProviderCryptoworks::MatchEMM(const unsigned char *data)
-{
- return false;
-}
-
-unsigned long long cProviderCryptoworks::ProvId(void)
-{
- return Bin2LongLong(addr,sizeof(addr));
-}
-
-// -- cCardCryptoworks----------------------------------------------------------
-
-cCardCryptoworks::cCardCryptoworks(const unsigned char *a)
-{
- memcpy(addr,a,sizeof(addr));
- sharedEmm=0; sharedLen=globalToggle=0; globalCrc=0;
-}
-
-cCardCryptoworks::~cCardCryptoworks()
-{
- free(sharedEmm);
-}
-
-bool cCardCryptoworks::MatchEMM(const unsigned char *data)
-{
- if((data[1]&0xF0)==0x70 && data[3]==0xA9 && data[4]==0xff) {
- switch(data[0]) {
- case 0x82: return !memcmp(&data[5],addr,sizeof(addr));
- case 0x84: return !memcmp(&data[5],addr,sizeof(addr)-1);
- case 0x86:
- case 0x88:
- case 0x89: return true;
- }
- }
- return false;
-}
-
-int cCardCryptoworks::UpdateType(const unsigned char *data)
-{
- switch(data[0]) {
- case 0x82: return 3; // unique
- case 0x84:
- case 0x86: return 2; // shared
- default: return 0; // global
- }
-}
-
-int cCardCryptoworks::Assemble(cAssembleData *ad)
-{
- const unsigned char *data=ad->Data();
- int len=SCT_LEN(data);
- switch(data[0]) {
- case 0x82:
- return 0; // no assemble needed
-
- case 0x84:
- free(sharedEmm);
- sharedEmm=(unsigned char *)malloc(len);
- if(sharedEmm) {
- memcpy(sharedEmm,data,len);
- sharedLen=len;
- }
- break;
-
- case 0x86:
- if(sharedEmm) {
- int alen=len-5 + sharedLen-12;
- unsigned char *tmp=AUTOMEM(alen);
- memcpy(tmp,&data[5],len-5);
- memcpy(tmp+len-5,&sharedEmm[12],sharedLen-12);
-
- unsigned char *ass=(unsigned char *)malloc(alen+12);
- if(!ass) return -1; // ignore
- memcpy(ass,sharedEmm,12);
- SortNanos(ass+12,tmp,alen);
- SetSctLen(ass,alen+9);
- free(sharedEmm); sharedEmm=0;
- if(ass[11]==alen) { // sanity check
- ad->SetAssembled(ass);
- return 1; // assembled
- }
- }
- break;
-
- case 0x88:
- case 0x89:
- if(data[0]!=globalToggle) {
- globalToggle=data[0];
- unsigned int crc=crc32_le(0,data+1,len-1);
- if(crc!=globalCrc) {
- globalCrc=crc;
- return 0; // no assemble needed
- }
- }
- break;
- }
- return -1; // ignore
-}
-
-// -- cProviderNDS -------------------------------------------------------------
-
-cProviderNDS::cProviderNDS(const unsigned char *s)
-{
- memcpy(sa,s,sizeof(sa));
-}
-
-bool cProviderNDS::MatchID(const unsigned char *data)
-{
- return MatchEMM(data);
-}
-
-bool cProviderNDS::MatchEMM(const unsigned char *data)
-{
- return cParseNDS::HasAddr(data,sa);
-}
-
-unsigned long long cProviderNDS::ProvId(void)
-{
- return Bin2LongLong(sa,sizeof(sa));
-}
-
-int cProviderNDS::Assemble(cAssembleData *ad)
-{
- return cParseNDS::Assemble(ad,sa);
-}
-
-// -- cCardNDS -----------------------------------------------------------------
-
-cCardNDS::cCardNDS(const unsigned char *u)
-{
- memcpy(ua,u,sizeof(ua));
-}
-
-bool cCardNDS::MatchEMM(const unsigned char *data)
-{
- return cParseNDS::HasAddr(data,ua);
-}
-
-int cCardNDS::Assemble(cAssembleData *ad)
-{
- return cParseNDS::Assemble(ad,ua);
-}
-
-// -- cParseNDS ----------------------------------------------------------------
-
-unsigned int cParseNDS::NumAddr(const unsigned char *data)
-{
- return ((data[3]&0x30)>>4)+1;
-}
-
-int cParseNDS::AddrMode(const unsigned char *data)
-{
- switch(data[3]&0xC0) {
- case 0x40: return 3;
- case 0x80: return 2;
- default: return 0;
- }
-}
-
-bool cParseNDS::HasAddr(const unsigned char *data, const unsigned char *a)
-{
- int s;
- switch(AddrMode(data)) {
- case 2: s=3; break;
- case 3: s=4; break;
- default: return true;
- }
- for(int l=NumAddr(data)-1; l>=0; l--) {
- if(!memcmp(&data[l*4+4],a,s)) return true;
- }
- return false;
-}
-
-const unsigned char *cParseNDS::PayloadStart(const unsigned char *data)
-{
- //return &data[4 + NumAddr(data)*4 + 2];
- if(AddrMode(data)==0) return &data[4];
- else return &data[4+NumAddr(data)*4];
-}
-
-int cParseNDS::PayloadSize(const unsigned char *data)
-{
- //return emm[2]+emm[3]+4-1+5;
- int l=SCT_LEN(data);
- if(AddrMode(data)==0) return l-(4);
- else return l-(4+NumAddr(data)*4);
-}
-
-int cParseNDS::Assemble(cAssembleData *ad, const unsigned char *a)
-{
- const unsigned char *data=ad->Data();
- int len=cParseNDS::PayloadSize(data);
- const unsigned char *pl=cParseNDS::PayloadStart(data);
- switch(cParseNDS::AddrMode(data)) {
- case 0:
- {
- int n=*(pl-1) & 0x01;
- for(int i=cParseNDS::NumAddr(data); i>0 && len>0; i--) {
- int l;
- if(n) {
- l=(((*pl & 0x3F)<<8) + *(pl+1)) << 1;
- pl+=2; len-=2;
- }
- else {
- l=(*pl & 0x3F) << 1;
- pl++; len--;
- }
- if(l>0 && l<=len) {
- unsigned char *ass=(unsigned char *)malloc(len+4); if(!ass) return -1; // ignore
- ass[0]=data[0];
- ass[3]=data[3]&0x0F;
- memcpy(&ass[4],pl,l);
- SetSctLen(ass,l+1);
- ad->SetAssembled(ass);
- pl+=l; len-=l;
- }
- }
- return 1; // assembled
- }
-
- case 2:
- case 3:
- {
- unsigned char *ass=(unsigned char *)malloc(len+8); if(!ass) return -1; // ignore
- ass[0]=data[0];
- ass[3]=data[3]&0x0F;
- memcpy(&ass[4],a,4);
- memcpy(&ass[8],pl,len);
- SetSctLen(ass,len+5);
- ad->SetAssembled(ass);
- return 1; // assembled
- }
- }
- return -1; // ignore
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___PARSE_H
-#define ___PARSE_H
-
-#include "misc.h"
-
-// ----------------------------------------------------------------
-
-void SetSctLen(unsigned char *data, int len);
-
-// ----------------------------------------------------------------
-
-class cAssSct : public cSimpleItem {
-private:
- const unsigned char *data;
-public:
- cAssSct(const unsigned char *Data);
- const unsigned char *Data(void) const { return data; }
- };
-
-class cAssembleData : private cSimpleList<cAssSct> {
-private:
- const unsigned char *data;
- cAssSct *curr;
-public:
- cAssembleData(const unsigned char *Data);
- void SetAssembled(const unsigned char *Data);
- const unsigned char *Assembled(void);
- const unsigned char *Data(void) const { return data; }
- };
-
-class cProvider : public cSimpleItem {
-public:
- virtual bool MatchID(const unsigned char *data)=0;
- virtual bool MatchEMM(const unsigned char *data)=0;
- virtual unsigned long long ProvId(void)=0;
- virtual int UpdateType(const unsigned char *data) { return 2; }
- virtual int Assemble(cAssembleData *ad) { return 0; }
- };
-
-class cProviders : public cSimpleList<cProvider> {
-public:
- void AddProv(cProvider *p);
- cProvider *FindProv(const unsigned char *data);
- cProvider *MatchProv(const unsigned char *data);
- };
-
-class cCard {
-public:
- virtual ~cCard() {}
- virtual bool MatchEMM(const unsigned char *data)=0;
- virtual int UpdateType(const unsigned char *data) { return 3; }
- virtual int Assemble(cAssembleData *ad) { return 0; }
- };
-
-class cIdSet : public cProviders {
-protected:
- cCard *card;
-public:
- cIdSet(void);
- ~cIdSet();
- void SetCard(cCard *c);
- void ResetIdSet(void);
- bool MatchEMM(const unsigned char *data);
- bool MatchAndAssemble(cAssembleData *ad, int *updtype, cProvider **p);
- };
-
-// -- IRDETO ------------------------------------------------------
-
-class cProviderIrdeto : public cProvider {
-public:
- unsigned char provBase;
- unsigned char provId[3];
- //
- cProviderIrdeto(void) {}
- cProviderIrdeto(unsigned char pb, const unsigned char *pi);
- virtual bool MatchID(const unsigned char *data);
- virtual bool MatchEMM(const unsigned char *data);
- virtual unsigned long long ProvId(void);
- };
-
-class cCardIrdeto : public cCard {
-public:
- unsigned char hexBase;
- unsigned char hexSer[3];
- //
- cCardIrdeto(void) {}
- cCardIrdeto(unsigned char hb, const unsigned char *hs);
- virtual bool MatchEMM(const unsigned char *data);
- virtual int UpdateType(const unsigned char *data);
- };
-
-class cParseIrdeto {
-public:
- static unsigned int AddrLen(const unsigned char *data);
- static unsigned int AddrBase(const unsigned char *data);
- };
-
-// -- SECA --------------------------------------------------------
-
-struct SecaCmd {
- unsigned char tid;
- unsigned char cmdLen1;
- unsigned char cmdLen2;
- };
-
-struct SecaEcm {
- struct SecaCmd cmd;
- unsigned char id[2];
- unsigned char unknown;
- unsigned char sm;
- unsigned char keyNr;
- };
-
-struct SecaEmmShared {
- struct SecaCmd cmd;
- unsigned char id[2];
- unsigned char sa[3];
- unsigned char sm;
- unsigned char keyNr;
- };
-
-struct SecaEmmUnique {
- struct SecaCmd cmd;
- unsigned char ua[6];
- unsigned char id[2];
- unsigned char sm;
- unsigned char keyNr;
- };
-
-#define TID(x) (((struct SecaCmd *)(x))->tid)
-#define SA(x) (((struct SecaEmmShared *)(x))->sa)
-#define SID(x) (((struct SecaEmmShared *)(x))->id)
-#define UA(x) (((struct SecaEmmUnique *)(x))->ua)
-#define UID(x) (((struct SecaEmmUnique *)(x))->id)
-
-class cProviderSeca : public cProvider {
-public:
- unsigned char provId[2];
- unsigned char sa[3];
- //
- cProviderSeca(void) {}
- cProviderSeca(const unsigned char *pi, const unsigned char *s);
- virtual bool MatchID(const unsigned char *data);
- virtual bool MatchEMM(const unsigned char *data);
- virtual unsigned long long ProvId(void);
- };
-
-class cCardSeca : public cCard {
-public:
- unsigned char ua[6];
- //
- cCardSeca(void) {}
- cCardSeca(const unsigned char *u);
- virtual bool MatchEMM(const unsigned char *data);
- };
-
-class cParseSeca {
-public:
- static int CmdLen(const unsigned char *data);
- static int Payload(const unsigned char *data, const unsigned char **payload);
- static int SysMode(const unsigned char *data);
- static int KeyNr(const unsigned char *data);
- static const unsigned char *ProvIdPtr(const unsigned char *data);
- static int ProvId(const unsigned char *data);
- };
-
-// -- VIACCESS -----------------------------------------------------
-
-class cProviderViaccess : public cProvider {
-private:
- unsigned char *sharedEmm;
- int sharedLen, sharedToggle;
-public:
- unsigned char ident[3];
- unsigned char sa[4];
- //
- cProviderViaccess(void);
- cProviderViaccess(const unsigned char *id, const unsigned char *s);
- virtual ~cProviderViaccess();
- virtual bool MatchID(const unsigned char *data);
- virtual bool MatchEMM(const unsigned char *data);
- virtual unsigned long long ProvId(void);
- virtual int UpdateType(const unsigned char *data);
- virtual int Assemble(cAssembleData *ad);
- };
-
-class cCardViaccess : public cCard {
-public:
- unsigned char ua[5];
- //
- cCardViaccess(void) {}
- cCardViaccess(const unsigned char *u);
- virtual bool MatchEMM(const unsigned char *data);
- };
-
-class cParseViaccess {
-public:
- static const unsigned char *NanoStart(const unsigned char *data);
- static const unsigned char *CheckNano90(const unsigned char *data);
- static const unsigned char *CheckNano90FromNano(const unsigned char *data);
- static int KeyNr(const unsigned char *data);
- static int KeyNrFromNano(const unsigned char *data);
- static const unsigned char *ProvIdPtr(const unsigned char *data);
- static int ProvId(const unsigned char *data);
- };
-
-// -- NAGRA 2 ------------------------------------------------------
-
-class cCardNagra2 : public cCard {
-public:
- unsigned char addr[4];
- //
- cCardNagra2(const unsigned char *a);
- virtual bool MatchEMM(const unsigned char *data);
- virtual int UpdateType(const unsigned char *data);
- };
-
-// -- CONAX --------------------------------------------------------
-
-class cProviderConax : public cProvider {
-public:
- unsigned char addr[7];
- //
- cProviderConax(const unsigned char *a);
- virtual bool MatchID(const unsigned char *data);
- virtual bool MatchEMM(const unsigned char *data);
- virtual unsigned long long ProvId(void);
- };
-
-class cCardConax : public cCard {
-public:
- unsigned char addr[7];
- //
- cCardConax(const unsigned char *a);
- virtual bool MatchEMM(const unsigned char *data);
- };
-
-// -- CRYPTOWORKS --------------------------------------------------
-
-class cProviderCryptoworks : public cProvider {
-public:
- unsigned char addr[5];
- //
- cProviderCryptoworks(const unsigned char *a);
- virtual bool MatchID(const unsigned char *data);
- virtual bool MatchEMM(const unsigned char *data);
- virtual unsigned long long ProvId(void);
- };
-
-class cCardCryptoworks : public cCard {
-private:
- unsigned char *sharedEmm;
- int sharedLen, globalToggle;
- unsigned int globalCrc;
-public:
- unsigned char addr[5];
- //
- cCardCryptoworks(const unsigned char *a);
- virtual ~cCardCryptoworks();
- virtual bool MatchEMM(const unsigned char *data);
- virtual int UpdateType(const unsigned char *data);
- virtual int Assemble(cAssembleData *ad);
- };
-
-// -- NDS -----------------------------------------------------------
-
-class cProviderNDS : public cProvider {
-public:
- unsigned char sa[4];
- //
- cProviderNDS(const unsigned char *s);
- virtual bool MatchID(const unsigned char *data);
- virtual bool MatchEMM(const unsigned char *data);
- virtual unsigned long long ProvId(void);
- virtual int Assemble(cAssembleData *ad);
- };
-
-class cCardNDS : public cCard {
-public:
- unsigned char ua[4];
- //
- cCardNDS(const unsigned char *u);
- virtual bool MatchEMM(const unsigned char *data);
- virtual int Assemble(cAssembleData *ad);
- };
-
-class cParseNDS {
-public:
- static unsigned int NumAddr(const unsigned char *data);
- static int AddrMode(const unsigned char *data);
- static bool IsSA(const unsigned char *data);
- static bool HasAddr(const unsigned char *data, const unsigned char *a);
- static const unsigned char *PayloadStart(const unsigned char *data);
- static int PayloadSize(const unsigned char *data);
- static int Assemble(cAssembleData *ad, const unsigned char *a);
- };
-
-#endif //___PARSE_H
+++ /dev/null
-diff -ur linux/drivers/media/dvb/ttpci/av7110_ca.c linux/drivers/media/dvb/ttpci/av7110_ca.c
---- linux/drivers/media/dvb/ttpci/av7110_ca.c 2004-01-09 14:44:57.000000000 +0100
-+++ linux/drivers/media/dvb/ttpci/av7110_ca.c 2005-09-02 16:52:08.000000000 +0200
-@@ -263,10 +263,31 @@
- }
-
- case CA_GET_MSG:
-- break;
-+ {
-+ ca_pid_t *arg = (ca_pid_t*) parg;
-+ u16 buf[4], res[2];
-+ buf[0]=0x0745;
-+ buf[1]=2;
-+ buf[2]=arg->pid >> 16;
-+ buf[3]=arg->pid & 0xFFFF;
-+ av7110_fw_request(av7110,buf,sizeof(buf),res,2);
-+ arg->index=(res[0]<<16) + res[1];
-+ break;
-+ }
-
- case CA_SEND_MSG:
-- break;
-+ {
-+ ca_pid_t *arg = (ca_pid_t*) parg;
-+ u16 buf[6], res[2];
-+ buf[0]=0x0746;
-+ buf[1]=4;
-+ buf[2]=arg->pid >> 16;
-+ buf[3]=arg->pid & 0xFFFF;
-+ buf[4]=arg->index >> 16;
-+ buf[5]=arg->index & 0xFFFF;
-+ av7110_fw_request(av7110,buf,sizeof(buf),res,2);
-+ break;
-+ }
-
- case CA_GET_DESCR_INFO:
- {
-@@ -295,6 +316,37 @@
- break;
- }
-
-+ case CA_SET_PID:
-+ {
-+ int handle;
-+ ca_pid_t *pid = (ca_pid_t*) parg;
-+
-+ if (pid->pid >= 0x1fff)
-+ return -EINVAL;
-+ if (pid->index < 0 || pid->index >= 16)
-+ return -EINVAL;
-+
-+ if (down_interruptible (&av7110->demux.mutex))
-+ return -ERESTARTSYS;
-+
-+ for(handle=0; handle<32; handle++) {
-+ struct dvb_demux_filter *dvbdmxfilter=av7110->handle2filter[handle];
-+ if(dvbdmxfilter) {
-+ struct dvb_demux_feed *feed=dvbdmxfilter->feed;
-+ if(feed && feed->state==DMX_STATE_GO && feed->pid==pid->pid) {
-+ /* we map the new cmd to CacheError as it's not
-+ implemented anyways, i.e. free. */
-+ av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, CacheError, 1,
-+ (handle<<8)|pid->index); /* hw handle / cw index*/
-+ break;
-+ }
-+ }
-+ }
-+
-+ up(&av7110->demux.mutex);
-+ break;
-+ }
-+
- default:
- return -EINVAL;
- }
+++ /dev/null
-diff -ur linux/drivers/media/dvb/ttpci/av7110_ca.c linux/drivers/media/dvb/ttpci/av7110_ca.c
---- linux/drivers/media/dvb/ttpci/av7110_ca.c 2004-01-09 14:44:57.000000000 +0100
-+++ linux/drivers/media/dvb/ttpci/av7110_ca.c 2006-05-09 19:49:42.000000000 +0200
-@@ -37,6 +37,9 @@
- #include <linux/poll.h>
- #include <linux/byteorder/swabb.h>
- #include <linux/smp_lock.h>
-+#ifndef LINUX_VERSION_CODE
-+#include <linux/version.h>
-+#endif
-
- #define DEBUG_VARIABLE av7110_debug
- extern int av7110_debug;
-@@ -263,10 +266,31 @@
- }
-
- case CA_GET_MSG:
-- break;
-+ {
-+ ca_pid_t *arg = (ca_pid_t*) parg;
-+ u16 buf[4], res[2];
-+ buf[0]=0x0745;
-+ buf[1]=2;
-+ buf[2]=arg->pid >> 16;
-+ buf[3]=arg->pid & 0xFFFF;
-+ av7110_fw_request(av7110,buf,sizeof(buf),res,2);
-+ arg->index=(res[0]<<16) + res[1];
-+ break;
-+ }
-
- case CA_SEND_MSG:
-- break;
-+ {
-+ ca_pid_t *arg = (ca_pid_t*) parg;
-+ u16 buf[6], res[2];
-+ buf[0]=0x0746;
-+ buf[1]=4;
-+ buf[2]=arg->pid >> 16;
-+ buf[3]=arg->pid & 0xFFFF;
-+ buf[4]=arg->index >> 16;
-+ buf[5]=arg->index & 0xFFFF;
-+ av7110_fw_request(av7110,buf,sizeof(buf),res,2);
-+ break;
-+ }
-
- case CA_GET_DESCR_INFO:
- {
-@@ -295,6 +319,45 @@
- break;
- }
-
-+ case CA_SET_PID:
-+ {
-+ int handle;
-+ ca_pid_t *pid = (ca_pid_t*) parg;
-+
-+ if (pid->pid >= 0x1fff)
-+ return -EINVAL;
-+ if (pid->index < 0 || pid->index >= 16)
-+ return -EINVAL;
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
-+ if (down_interruptible (&av7110->demux.mutex))
-+#else
-+ if (mutex_lock_interruptible (&av7110->demux.mutex))
-+#endif
-+ return -ERESTARTSYS;
-+
-+ for(handle=0; handle<32; handle++) {
-+ struct dvb_demux_filter *dvbdmxfilter=av7110->handle2filter[handle];
-+ if(dvbdmxfilter) {
-+ struct dvb_demux_feed *feed=dvbdmxfilter->feed;
-+ if(feed && feed->state==DMX_STATE_GO && feed->pid==pid->pid) {
-+ /* we map the new cmd to CacheError as it's not
-+ implemented anyways, i.e. free. */
-+ av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, CacheError, 1,
-+ (handle<<8)|pid->index); /* hw handle / cw index*/
-+ break;
-+ }
-+ }
-+ }
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
-+ up(&av7110->demux.mutex);
-+#else
-+ mutex_unlock(&av7110->demux.mutex);
-+#endif
-+ break;
-+ }
-+
- default:
- return -EINVAL;
- }
+++ /dev/null
---- linux/drivers/media/dvb/dvb-core/dvb_demux.c 2004-03-03 17:49:42.000000000 +0100
-+++ linux/drivers/media/dvb/dvb-core/dvb_demux.c 2004-04-05 12:44:59.000000000 +0200
-@@ -329,8 +329,8 @@
- ** in the following dvb_dmx_swfilter_section_new
- */
- #endif
-- dvb_dmx_swfilter_section_new(feed);
-- return 0;
-+ //dvb_dmx_swfilter_section_new(feed);
-+ //return 0;
- }
-
- if(buf[1] & 0x40)
+++ /dev/null
-diff -urN -X ex.vdr-sc7 vdr-1.4.7-orig/ci.c vdr-1.4.7-sc7/ci.c
---- vdr-1.4.7-orig/ci.c 2007-04-30 14:58:41.000000000 +0200
-+++ vdr-1.4.7-sc7/ci.c 2007-05-13 18:04:04.000000000 +0200
-@@ -1502,9 +1502,8 @@
- close(fd);
- }
-
--cCiHandler *cCiHandler::CreateCiHandler(const char *FileName)
-+cCiHandler *cCiHandler::CreateCiHandler(int fd_ca)
- {
-- int fd_ca = open(FileName, O_RDWR);
- if (fd_ca >= 0) {
- ca_caps_t Caps;
- if (ioctl(fd_ca, CA_GET_CAP, &Caps) == 0) {
-@@ -1520,8 +1519,7 @@
- esyslog("ERROR: no CAM slots found");
- }
- else
-- LOG_ERROR_STR(FileName);
-- close(fd_ca);
-+ LOG_ERROR_STR("CA_GET_CAP");
- }
- return NULL;
- }
-diff -urN -X ex.vdr-sc7 vdr-1.4.7-orig/ci.h vdr-1.4.7-sc7/ci.h
---- vdr-1.4.7-orig/ci.h 2006-08-12 11:43:31.000000000 +0200
-+++ vdr-1.4.7-sc7/ci.h 2007-06-24 19:46:39.000000000 +0200
-@@ -85,10 +85,12 @@
- class cCiCaProgramData : public cListObject {
- public:
- int programNumber;
-+ bool modified;
- cList<cCiCaPidData> pidList;
- cCiCaProgramData(int ProgramNumber)
- {
- programNumber = ProgramNumber;
-+ modified = true;
- }
- };
-
-@@ -96,6 +98,8 @@
- class cCiTransportLayer;
- class cCiTransportConnection;
-
-+#define VDR_IS_SC_PATCHED 402
-+
- class cCiHandler {
- private:
- cMutex mutex;
-@@ -123,7 +127,7 @@
- void SendCaPmt(void);
- public:
- ~cCiHandler();
-- static cCiHandler *CreateCiHandler(const char *FileName);
-+ static cCiHandler *CreateCiHandler(int fd_ca);
- ///< Creates a new cCiHandler for the given CA device.
- int NumSlots(void) { return numSlots; }
- ///< Returns the number of CAM slots provided by this CA device.
-diff -urN -X ex.vdr-sc7 vdr-1.4.7-orig/device.c vdr-1.4.7-sc7/device.c
---- vdr-1.4.7-orig/device.c 2006-09-03 12:13:25.000000000 +0200
-+++ vdr-1.4.7-sc7/device.c 2007-05-13 18:30:57.000000000 +0200
-@@ -395,6 +395,54 @@
- return false;
- }
-
-+void cDevice::CiStartDecrypting(void)
-+{
-+ if (ciHandler)
-+ ciHandler->StartDecrypting();
-+}
-+
-+void cDevice::CiSetSource(int Source, int Transponder)
-+{
-+ cMutexLock MutexLock(&ciListMutex);
-+ if (ciSource != Source || ciTransponder != Transponder)
-+ ciProgramList.Clear();
-+ ciSource = Source;
-+ ciTransponder = Transponder;
-+}
-+
-+void cDevice::CiAddPid(int ProgramNumber, int Pid, int StreamType)
-+{
-+ cMutexLock MutexLock(&ciListMutex);
-+ cCiCaProgramData *ProgramData = NULL;
-+ for (cCiCaProgramData *p = ciProgramList.First(); p; p = ciProgramList.Next(p)) {
-+ if (p->programNumber == ProgramNumber) {
-+ ProgramData = p;
-+ for (cCiCaPidData *q = p->pidList.First(); q; q = p->pidList.Next(q)) {
-+ if (q->pid == Pid)
-+ return;
-+ }
-+ }
-+ }
-+ if (!ProgramData)
-+ ciProgramList.Add(ProgramData = new cCiCaProgramData(ProgramNumber));
-+ ProgramData->pidList.Add(new cCiCaPidData(Pid, StreamType));
-+ ProgramData->modified=true;
-+}
-+
-+void cDevice::CiSetPid(int Pid, bool Active)
-+{
-+ cMutexLock MutexLock(&ciListMutex);
-+ for (cCiCaProgramData *p = ciProgramList.First(); p; p = ciProgramList.Next(p)) {
-+ for (cCiCaPidData *q = p->pidList.First(); q; q = p->pidList.Next(q)) {
-+ if (q->pid == Pid) {
-+ q->active = Active;
-+ p->modified = true;
-+ return;
-+ }
-+ }
-+ }
-+}
-+
- bool cDevice::AddPid(int Pid, ePidType PidType)
- {
- if (Pid || PidType == ptPcr) {
-@@ -424,6 +472,7 @@
- }
- if (ciHandler)
- ciHandler->SetPid(Pid, true);
-+ CiSetPid(Pid, true);
- }
- PRINTPIDS("a");
- return true;
-@@ -453,6 +502,7 @@
- }
- if (ciHandler)
- ciHandler->SetPid(Pid, true);
-+ CiSetPid(Pid, true);
- }
- }
- return true;
-@@ -481,6 +531,7 @@
- pidHandles[n].pid = 0;
- if (ciHandler)
- ciHandler->SetPid(Pid, false);
-+ CiSetPid(Pid, false);
- }
- }
- PRINTPIDS("E");
-@@ -663,6 +714,16 @@
- }
- #endif
- }
-+
-+ CiSetSource(Channel->Source(), Channel->Transponder());
-+ if (Channel->Ca() >= CA_ENCRYPTED_MIN) {
-+ CiAddPid(Channel->Sid(), Channel->Vpid(), 2);
-+ for (const int *Apid = Channel->Apids(); *Apid; Apid++)
-+ CiAddPid(Channel->Sid(), *Apid, 4);
-+ for (const int *Dpid = Channel->Dpids(); *Dpid; Dpid++)
-+ CiAddPid(Channel->Sid(), *Dpid, 0);
-+ }
-+
- if (NeedsDetachReceivers)
- DetachAllReceivers();
- if (SetChannelDevice(Channel, LiveView)) {
-@@ -672,8 +733,7 @@
- sectionHandler->SetStatus(true);
- }
- // Start decrypting any PIDs that might have been set in SetChannelDevice():
-- if (ciHandler)
-- ciHandler->StartDecrypting();
-+ CiStartDecrypting();
- }
- else
- Result = scrFailed;
-@@ -1258,8 +1318,7 @@
- Unlock();
- if (!Running())
- Start();
-- if (ciHandler)
-- ciHandler->StartDecrypting();
-+ CiStartDecrypting();
- return true;
- }
- }
-@@ -1286,8 +1345,7 @@
- else if (receiver[i])
- receiversLeft = true;
- }
-- if (ciHandler)
-- ciHandler->StartDecrypting();
-+ CiStartDecrypting();
- if (!receiversLeft)
- Cancel(3);
- }
-diff -urN -X ex.vdr-sc7 vdr-1.4.7-orig/device.h vdr-1.4.7-sc7/device.h
---- vdr-1.4.7-orig/device.h 2006-06-15 11:32:48.000000000 +0200
-+++ vdr-1.4.7-sc7/device.h 2007-05-13 18:04:04.000000000 +0200
-@@ -311,6 +311,14 @@
-
- protected:
- cCiHandler *ciHandler;
-+ int ciSource, ciTransponder;
-+ cList<cCiCaProgramData> ciProgramList;
-+ cMutex ciListMutex;
-+ virtual void CiStartDecrypting(void);
-+ virtual bool CiAllowConcurrent(void) const { return false; }
-+ void CiSetSource(int Source, int Transponder);
-+ void CiAddPid(int ProgramNumber, int Pid, int StreamType);
-+ void CiSetPid(int Pid, bool Active);
- public:
- cCiHandler *CiHandler(void) { return ciHandler; }
-
-diff -urN -X ex.vdr-sc7 vdr-1.4.7-orig/dvbdevice.c vdr-1.4.7-sc7/dvbdevice.c
---- vdr-1.4.7-orig/dvbdevice.c 2007-02-24 12:10:14.000000000 +0100
-+++ vdr-1.4.7-sc7/dvbdevice.c 2007-06-24 19:42:24.000000000 +0200
-@@ -419,7 +419,11 @@
- dvb_frontend_info feinfo;
- if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0) {
- frontendType = feinfo.type;
-- ciHandler = cCiHandler::CreateCiHandler(*cDvbName(DEV_DVB_CA, n));
-+ int fd_ca = DvbOpen(DEV_DVB_CA, n, O_RDWR);
-+ if(fd_ca>=0) {
-+ ciHandler = cCiHandler::CreateCiHandler(fd_ca);
-+ if(!ciHandler) close(fd_ca);
-+ }
- dvbTuner = new cDvbTuner(fd_frontend, CardIndex(), frontendType, ciHandler);
- }
- else
-@@ -776,8 +780,12 @@
- if (Channel->Vpid() && !HasPid(Channel->Vpid()) || Channel->Apid(0) && !HasPid(Channel->Apid(0))) {
- #ifdef DO_MULTIPLE_RECORDINGS
- #ifndef DO_MULTIPLE_CA_CHANNELS
-- if (Ca() >= CA_ENCRYPTED_MIN || Channel->Ca() >= CA_ENCRYPTED_MIN)
-- needsDetachReceivers = Ca() != Channel->Ca();
-+ if (Ca() >= CA_ENCRYPTED_MIN || Channel->Ca() >= CA_ENCRYPTED_MIN) {
-+ if(Channel->Ca()<CA_ENCRYPTED_MIN || CiAllowConcurrent())
-+ result = true;
-+ else
-+ needsDetachReceivers = Ca() != Channel->Ca();
-+ }
- else
- #endif
- if (!IsPrimaryDevice())
-@@ -927,7 +935,7 @@
- SetPid(&pidHandles[ptAudio], ptAudio, true);
- if (ciHandler) {
- ciHandler->SetPid(pidHandles[ptAudio].pid, true);
-- ciHandler->StartDecrypting();
-+ CiStartDecrypting();
- }
- }
- }
-diff -urN -X ex.vdr-sc7 vdr-1.4.7-orig/tools.c vdr-1.4.7-sc7/tools.c
---- vdr-1.4.7-orig/tools.c 2006-12-02 12:12:59.000000000 +0100
-+++ vdr-1.4.7-sc7/tools.c 2007-05-13 18:04:04.000000000 +0200
-@@ -542,9 +542,9 @@
-
- // --- cTimeMs ---------------------------------------------------------------
-
--cTimeMs::cTimeMs(void)
-+cTimeMs::cTimeMs(int Ms)
- {
-- Set();
-+ Set(Ms);
- }
-
- uint64_t cTimeMs::Now(void)
-diff -urN -X ex.vdr-sc7 vdr-1.4.7-orig/tools.h vdr-1.4.7-sc7/tools.h
---- vdr-1.4.7-orig/tools.h 2006-12-03 18:38:38.000000000 +0100
-+++ vdr-1.4.7-sc7/tools.h 2007-05-13 18:04:04.000000000 +0200
-@@ -162,7 +162,7 @@
- private:
- uint64_t begin;
- public:
-- cTimeMs(void);
-+ cTimeMs(int Ms = 0);
- static uint64_t Now(void);
- void Set(int Ms = 0);
- bool TimedOut(void);
+++ /dev/null
-# VDR plugin language source file.
-# Copyright (C) 2007 somebody
-# This file is distributed under the same license as the VDR package.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: VDR 1.5.9\n"
-"Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-07-11 20:28-0400\n"
-"PO-Revision-Date: 2007-08-27 12:45+0200\n"
-"Last-Translator: somebody\n"
-"Language-Team: somebody\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO-8859-15\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-msgid "Key update"
-msgstr "Key Update"
-
-msgid "off"
-msgstr "aus"
-
-msgid "SoftCAM"
-msgstr "SoftCAM"
-
-msgid "Current keys:"
-msgstr "Aktuelle Keys:"
-
-msgid "Key update status:"
-msgstr "Key update Status:"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [Seen keys]"
-msgstr " [Gefundene Keys]"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [New keys]"
-msgstr " [Neue Keys]"
-
-msgid "Smartcard"
-msgstr "Smartcard"
-
-msgid "Reset card"
-msgstr "Karte reseten"
-
-msgid "Really reset card?"
-msgstr "Karte wirklich reseten?"
-
-msgid "Module config"
-msgstr "Modul Einstellungen"
-
-msgid "Reset module to default"
-msgstr "Modul auf Standard zurücksetzen"
-
-msgid "Really reset module to default?"
-msgstr "Wirklich Modul auf Standard zurücksetzen?"
-
-msgid "Module"
-msgstr "Modul"
-
-msgid "Message logging"
-msgstr "Meldungsprotokolierung"
-
-msgid "Disable ALL modules"
-msgstr "ALLE Module ausschalten"
-
-msgid "Reset ALL modules to default"
-msgstr "ALLE Module auf Standard zurücksetzen"
-
-msgid "Really disable ALL modules?"
-msgstr "Wirklich ALLE Module ausschalten?"
-
-msgid "Really reset ALL modules to default?"
-msgstr "Wirklich ALLE Module auf Standard zurücksetzen?"
-
-msgid "Cryptsystem options"
-msgstr "Cryptsystem Optionen"
-
-msgid "Cryptsystem options..."
-msgstr "Cryptsystem Optionen..."
-
-msgid "Message logging..."
-msgstr "Meldungsprotokolierung..."
-
-msgid "Smartcard interface"
-msgstr "Smartcard Interface"
-
-msgid "(empty)"
-msgstr "(leer)"
-
-msgid "Status information..."
-msgstr "Status Informationen..."
-
-msgid "Flush ECM cache"
-msgstr "ECM Zwischenspeicher leeren"
-
-msgid "Reload files"
-msgstr "Dateien neu laden"
-
-msgid "Really flush ECM cache?"
-msgstr "ECM Zwischenspeicher wirklich leeren?"
-
-msgid "Really reload files?"
-msgstr "Dateien wirklich neu laden?"
-
-msgid "Active! Can't reload files now"
-msgstr "Aktiv! Kann Dateien jetzt nicht neu laden"
-
-msgid "(none)"
-msgstr "(keiner)"
-
-msgid "active CAIDs"
-msgstr "aktive CAIDs"
-
-msgid "all CAIDs"
-msgstr "alle CAIDs"
-
-msgid "comment out"
-msgstr "auskommentieren"
-
-msgid "remove"
-msgstr "entfernen"
-
-msgid "Update keys (AU)"
-msgstr "Keys updaten (AU)"
-
-msgid "Start AU on EPG scan"
-msgstr "AU starten bei EPG-Scan"
-
-msgid "Superseded keys"
-msgstr "Veraltete Keys"
-
-msgid "Concurrent FF streams"
-msgstr "Gleichzeitige FF Streams"
-
-msgid "Force TransferMode"
-msgstr "Transfermodus erzwingen"
-
-msgid "Prefer local systems"
-msgstr "Lokale Systeme bevorzugen"
-
-msgid "Active on DVB card"
-msgstr "Aktiv auf DVB Karte"
-
-msgid "Ignore CAID"
-msgstr "Ignoriere CAID"
-
-msgid "Log to console"
-msgstr "Meldungen auf Konsole"
-
-msgid "Log to file"
-msgstr "Meldungen in Datei"
-
-msgid "Filename"
-msgstr "Dateiname"
-
-msgid "Filesize limit (KB)"
-msgstr "Dateigrößenlimit (KB)"
-
-msgid "Log to syslog"
-msgstr "Meldungen in Syslog"
-
-msgid "Show user messages"
-msgstr "Benutzer Meldungen zeigen"
-
-msgid "A software emulated CAM"
-msgstr "Ein Software emuliertes CAM"
-
-msgid "undisclosed key"
-msgstr "unbekannter Key"
-
-msgid "allow ALL"
-msgstr "alle erlauben"
-
-msgid "block UNIQUE"
-msgstr "UNIQUE blocken"
-
-msgid "block SHARED"
-msgstr "SHARED blocken"
-
-msgid "block ALL"
-msgstr "alle blocken"
-
-msgid "SC-Seca: EMM updates"
-msgstr "SC-Seca: EMM updates"
-
-msgid "SC-Seca: activate PPV"
-msgstr "SC-Seca: PPV aktivieren"
-
-msgid "Nagra: min. ECM processing time"
-msgstr "Nagra: min. ECM Bearbeitungszeit"
-
-msgid "Nagra2: drop EMM-S packets"
-msgstr "Nagra2: EMM-S Pakete verwerfen"
-
-msgid "Nagra2: Enable AUXserver"
-msgstr "Nagra2: AUXserver aktivieren"
-
-msgid "Nagra2: AUXserver hostname"
-msgstr "Nagra2: AUXserver Hostname"
-
-msgid "Nagra2: AUXserver port"
-msgstr "Nagra2: AUXserver Port"
-
-msgid "Nagra2: AUXserver password"
-msgstr "Nagra2: AUXserver Passwort"
-
-msgid "don't touch"
-msgstr "nicht ändern"
-
-msgid "disable"
-msgstr "ausschalten"
-
-msgid "SC-Cryptoworks: Parental rating"
-msgstr "SC-Cryptoworks: Altersbeschränkung"
-
-msgid "Cardclient: connect immediately"
-msgstr "Cardclient: sofort verbinden"
+++ /dev/null
-# VDR plugin language source file.
-# Copyright (C) 2007 somebody
-# This file is distributed under the same license as the vdr-sc package.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: VDR 1.5.9\n"
-"Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-07-11 20:28-0400\n"
-"PO-Revision-Date: 2007-08-27 12:45+0200\n"
-"Last-Translator: somebody\n"
-"Language-Team: somebody\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO-8859-15\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-msgid "Key update"
-msgstr "Avaimen päivitys"
-
-msgid "off"
-msgstr "pois"
-
-msgid "SoftCAM"
-msgstr "SoftCAM"
-
-msgid "Current keys:"
-msgstr "Nykyiset avaimet:"
-
-msgid "Key update status:"
-msgstr "Tilausten päivitys:"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [Seen keys]"
-msgstr " [Löydetyt päivitykset]"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [New keys]"
-msgstr " [Uudet päivitykset]"
-
-msgid "Smartcard"
-msgstr "Älykortti"
-
-msgid "Reset card"
-msgstr "Nollaa kortti"
-
-msgid "Really reset card?"
-msgstr "Nollataanko kortti?"
-
-msgid "Module config"
-msgstr "Moduulin asetukset"
-
-msgid "Reset module to default"
-msgstr "Nollaa moduuli oletusarvoihin"
-
-msgid "Really reset module to default?"
-msgstr "Nollataanko moduuli oletusarvoihin?"
-
-msgid "Module"
-msgstr "Moduuli"
-
-msgid "Message logging"
-msgstr "Viestien tulostus"
-
-msgid "Disable ALL modules"
-msgstr "Poista kaikki moduulit käytöstä"
-
-msgid "Reset ALL modules to default"
-msgstr "Nollaa kaikki moduulit oletusarvoihin"
-
-msgid "Really disable ALL modules?"
-msgstr "Poistetaanko kaikki moduulit käytöstä?"
-
-msgid "Really reset ALL modules to default?"
-msgstr "Nollataanko kaikki moduulit oletusarvoihin?"
-
-msgid "Cryptsystem options"
-msgstr "Salausjärjestelmien asetukset"
-
-msgid "Cryptsystem options..."
-msgstr "Salausjärjestelmien asetukset..."
-
-msgid "Message logging..."
-msgstr "Viestien tulostus..."
-
-msgid "Smartcard interface"
-msgstr "Älykorttiliitäntä"
-
-msgid "(empty)"
-msgstr "(tyhjä)"
-
-msgid "Status information..."
-msgstr "Tilannetiedot..."
-
-msgid "Flush ECM cache"
-msgstr "Tyhjennä ECM-välimuisti"
-
-msgid "Reload files"
-msgstr "Lataa avaintiedostot uudelleen"
-
-msgid "Really flush ECM cache?"
-msgstr "Tyhjennetäänkö ECM-välimuisti?"
-
-msgid "Really reload files?"
-msgstr "Ladataanko avaintiedostot uudelleen?"
-
-msgid "Active! Can't reload files now"
-msgstr "Aktiivinen! Uudelleen lataus ei onnistu"
-
-msgid "(none)"
-msgstr "(ei)"
-
-msgid "active CAIDs"
-msgstr "aktiiviset CAID:t"
-
-msgid "all CAIDs"
-msgstr "kaikki CAID:t"
-
-msgid "comment out"
-msgstr "kommentoi"
-
-msgid "remove"
-msgstr "poista"
-
-msgid "Update keys (AU)"
-msgstr "Tilausten päivitys (AU)"
-
-msgid "Start AU on EPG scan"
-msgstr "Aloita AU EPG-päivityksessä"
-
-msgid "Superseded keys"
-msgstr "Vanhentuneet avaimet"
-
-msgid "Concurrent FF streams"
-msgstr "Yhtäaikainen salauksenpurku (FF)"
-
-msgid "Force TransferMode"
-msgstr "Pakota siirtotila"
-
-msgid "Prefer local systems"
-msgstr "Suosi paikallista salauksenpurkua"
-
-msgid "Active on DVB card"
-msgstr "Aktiivinen DVB-kortilla"
-
-msgid "Ignore CAID"
-msgstr "Jätä huomioimatta CAID"
-
-msgid "Log to console"
-msgstr "Tulosta konsoliin"
-
-msgid "Log to file"
-msgstr "Tulosta tiedostoon"
-
-msgid "Filename"
-msgstr "Tiedoston nimi"
-
-msgid "Filesize limit (KB)"
-msgstr "Tiedoston maksimikoko (KB)"
-
-msgid "Log to syslog"
-msgstr "Tulosta systeemilokiin"
-
-msgid "Show user messages"
-msgstr "Näytä käyttäjäviestit"
-
-msgid "A software emulated CAM"
-msgstr "Ohjelmistopohjainen salauksenpurku"
-
-msgid "undisclosed key"
-msgstr "tuntematon avain"
-
-msgid "allow ALL"
-msgstr "salli kaikki"
-
-msgid "block UNIQUE"
-msgstr "estä uniikit"
-
-msgid "block SHARED"
-msgstr "estä jaetut"
-
-msgid "block ALL"
-msgstr "estä kaikki"
-
-msgid "SC-Seca: EMM updates"
-msgstr "SC-Seca: EMM-päivitykset"
-
-msgid "SC-Seca: activate PPV"
-msgstr "SC-Seca: Aktivoi PPV"
-
-msgid "Nagra: min. ECM processing time"
-msgstr "Nagra: Min. ECM-prosessointiaika"
-
-msgid "Nagra2: drop EMM-S packets"
-msgstr "Nagra2: Hylkää EMM-S-paketit"
-
-msgid "Nagra2: Enable AUXserver"
-msgstr "Nagra2: Käytä AUX-palvelinta"
-
-msgid "Nagra2: AUXserver hostname"
-msgstr "Nagra2: AUX-palvelimen osoite"
-
-msgid "Nagra2: AUXserver port"
-msgstr "Nagra2: AUX-palvelimen portti"
-
-msgid "Nagra2: AUXserver password"
-msgstr "Nagra2: AUX-palvelimen salasana"
-
-msgid "don't touch"
-msgstr "älä koske"
-
-msgid "disable"
-msgstr "poista"
-
-msgid "SC-Cryptoworks: Parental rating"
-msgstr "SC-Cryptoworks: Ikäraja"
-
-msgid "Cardclient: connect immediately"
-msgstr "Korttiasiakas: Yhdistä välittömästi"
+++ /dev/null
-# VDR plugin language source file.
-# Copyright (C) 2007 somebody
-# This file is distributed under the same license as the vdr-sc package.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: VDR 1.5.9\n"
-"Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-07-11 20:28-0400\n"
-"PO-Revision-Date: 2007-08-27 12:45+0200\n"
-"Last-Translator: somebody\n"
-"Language-Team: somebody\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO-8859-1\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-msgid "Key update"
-msgstr "Mise à jour des clés"
-
-msgid "off"
-msgstr "off"
-
-msgid "SoftCAM"
-msgstr "SoftCAM"
-
-msgid "Current keys:"
-msgstr "Clés en cours:"
-
-msgid "Key update status:"
-msgstr "Statut de la mise à jour des clés:"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [Seen keys]"
-msgstr " [Clés trouvées]"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [New keys]"
-msgstr " [Nouvelles clés]"
-
-msgid "Smartcard"
-msgstr "Smartcard"
-
-msgid "Reset card"
-msgstr "Réinitialiser la carte"
-
-msgid "Really reset card?"
-msgstr "Réinitialiser la carte?"
-
-msgid "Module config"
-msgstr "Paramètrer le module"
-
-msgid "Reset module to default"
-msgstr "Réinitialiser le module"
-
-msgid "Really reset module to default?"
-msgstr "Réinitialiser le module?"
-
-msgid "Module"
-msgstr "Module"
-
-msgid "Message logging"
-msgstr "Message logué"
-
-msgid "Disable ALL modules"
-msgstr "Désactiver TOUS les modules"
-
-msgid "Reset ALL modules to default"
-msgstr "Réinitialiser TOUS les modules"
-
-msgid "Really disable ALL modules?"
-msgstr "Désactiver TOUS les modules?"
-
-msgid "Really reset ALL modules to default?"
-msgstr "Réinitialiser TOUS les modules?"
-
-msgid "Cryptsystem options"
-msgstr "Options Cryptsystem"
-
-msgid "Cryptsystem options..."
-msgstr "Options Cryptsystem..."
-
-msgid "Message logging..."
-msgstr "Message logué..."
-
-msgid "Smartcard interface"
-msgstr "Interface Smartcard"
-
-msgid "(empty)"
-msgstr "(vide)"
-
-msgid "Status information..."
-msgstr "Statut..."
-
-msgid "Flush ECM cache"
-msgstr "Vider le cache ECM"
-
-msgid "Reload files"
-msgstr "Recharger les fichiers"
-
-msgid "Really flush ECM cache?"
-msgstr "Vider le cache ECM?"
-
-msgid "Really reload files?"
-msgstr "Recharger les fichiers?"
-
-msgid "Active! Can't reload files now"
-msgstr "Actif! Impossible de recharger les fichiers"
-
-msgid "(none)"
-msgstr "(aucune)"
-
-msgid "active CAIDs"
-msgstr "CAIDs actifs"
-
-msgid "all CAIDs"
-msgstr "tous les CAIDs"
-
-msgid "comment out"
-msgstr "commenter"
-
-msgid "remove"
-msgstr "supprimer"
-
-msgid "Update keys (AU)"
-msgstr "Mise à jour des Clés (AU)"
-
-msgid "Start AU on EPG scan"
-msgstr "Démarrer AU lors du scan EPG"
-
-msgid "Superseded keys"
-msgstr "Clés obsolètes"
-
-msgid "Concurrent FF streams"
-msgstr "FF streams en parallèle"
-
-msgid "Force TransferMode"
-msgstr "Forcer le TransferMode"
-
-msgid "Prefer local systems"
-msgstr "Préférer les systèmes locaux"
-
-msgid "Active on DVB card"
-msgstr "Actif sur la carte DVB"
-
-msgid "Ignore CAID"
-msgstr "Ignorer les CAID"
-
-msgid "Log to console"
-msgstr "Logger dans la console"
-
-msgid "Log to file"
-msgstr "Logger dans un fichier"
-
-msgid "Filename"
-msgstr "Nom du fichier"
-
-msgid "Filesize limit (KB)"
-msgstr "Taille limite (Ko)"
-
-msgid "Log to syslog"
-msgstr "Logger dans Syslog"
-
-msgid "Show user messages"
-msgstr "Afficher les messages utilisateur"
-
-msgid "A software emulated CAM"
-msgstr "Un logiciel emulateur de CAM"
-
-msgid "undisclosed key"
-msgstr "clé non-révélée"
-
-msgid "allow ALL"
-msgstr "permettre TOUS"
-
-msgid "block UNIQUE"
-msgstr "bloquer UNIQUE"
-
-msgid "block SHARED"
-msgstr "bloquer PARTAGE"
-
-msgid "block ALL"
-msgstr "bloquer TOUS"
-
-msgid "SC-Seca: EMM updates"
-msgstr "SC-Seca: mise à jour EMM"
-
-msgid "SC-Seca: activate PPV"
-msgstr "SC-Seca: activer les PPV"
-
-msgid "Nagra: min. ECM processing time"
-msgstr "Nagra: temps de traitement min. ECM"
-
-msgid "Nagra2: drop EMM-S packets"
-msgstr "Nagra2: ignorer les packets EMM-S"
-
-msgid "Nagra2: Enable AUXserver"
-msgstr "Nagra2: Activer AUXserver"
-
-msgid "Nagra2: AUXserver hostname"
-msgstr "Nagra2: Hostname AUXserver"
-
-msgid "Nagra2: AUXserver port"
-msgstr "Nagra2: Port AUXserver"
-
-msgid "Nagra2: AUXserver password"
-msgstr "Nagra2: Mot de passe AUXserver"
-
-msgid "don't touch"
-msgstr "ne pas modifier"
-
-msgid "disable"
-msgstr "désactiver"
-
-msgid "SC-Cryptoworks: Parental rating"
-msgstr "SC-Cryptoworks: Contrôle parentale"
-
-msgid "Cardclient: connect immediately"
-msgstr "Cardclient: connecter immediatement"
+++ /dev/null
-# VDR plugin language source file.
-# Copyright (C) 2007 somebody
-# This file is distributed under the same license as the VDR package.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: VDR 1.5.11\n"
-"Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-07-11 20:28-0400\n"
-"PO-Revision-Date: 2007-11-01 16:45+0200\n"
-"Last-Translator: jv\n"
-"Language-Team: somebody\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-msgid "Key update"
-msgstr ""
-
-msgid "off"
-msgstr "ki"
-
-msgid "SoftCAM"
-msgstr "SoftCAM"
-
-msgid "Current keys:"
-msgstr "Jelenleg használt kulcs:"
-
-msgid "Key update status:"
-msgstr "Kulcsfrissítés állapota:"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [Seen keys]"
-msgstr " [Talált kulcsok]"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [New keys]"
-msgstr " [Új kulcsok]"
-
-msgid "Smartcard"
-msgstr "Smartcard"
-
-msgid "Reset card"
-msgstr "Kártya újraindítása"
-
-msgid "Really reset card?"
-msgstr "Valóban újraindítjuk?"
-
-msgid "Module config"
-msgstr "Modul konfig"
-
-msgid "Reset module to default"
-msgstr "Modul alapállapotba"
-
-msgid "Really reset module to default?"
-msgstr "Valóban resetáljuk a modult?"
-
-msgid "Module"
-msgstr "Modul"
-
-msgid "Message logging"
-msgstr "Üzenetek naplózása"
-
-msgid "Disable ALL modules"
-msgstr "Összes modul ki"
-
-msgid "Reset ALL modules to default"
-msgstr "Összes modul alapállapotba"
-
-msgid "Really disable ALL modules?"
-msgstr "Valóban kapcsoljuk ki az összes modult?"
-
-msgid "Really reset ALL modules to default?"
-msgstr "Valóban összes modul alapállapotba?"
-
-msgid "Cryptsystem options"
-msgstr "Kriptorendszer opciók"
-
-msgid "Cryptsystem options..."
-msgstr "Kriptorendszer opciók..."
-
-msgid "Message logging..."
-msgstr "Üzenetek naplózása..."
-
-msgid "Smartcard interface"
-msgstr "Smartcard interfész"
-
-msgid "(empty)"
-msgstr "(üres)"
-
-msgid "Status information..."
-msgstr "Státusz információ"
-
-msgid "Flush ECM cache"
-msgstr "ECM tár üritése"
-
-msgid "Reload files"
-msgstr "Fileok újraolvasása"
-
-msgid "Really flush ECM cache?"
-msgstr "Valóban üritsük az ECM tárat?"
-
-msgid "Really reload files?"
-msgstr "Biztos, hogy újraolvassuk a fileokat?"
-
-msgid "Active! Can't reload files now"
-msgstr "SC aktív! Nem tud újraolvasni."
-
-msgid "(none)"
-msgstr "(nincs)"
-
-msgid "active CAIDs"
-msgstr "aktív CAIDok"
-
-msgid "all CAIDs"
-msgstr "minden CAID"
-
-msgid "comment out"
-msgstr ""
-
-msgid "remove"
-msgstr ""
-
-msgid "Update keys (AU)"
-msgstr "Kulcsok automatikus frissítése (AU)"
-
-msgid "Start AU on EPG scan"
-msgstr ""
-
-msgid "Superseded keys"
-msgstr ""
-
-msgid "Concurrent FF streams"
-msgstr "Párhuzamos FF streamek"
-
-msgid "Force TransferMode"
-msgstr "Force TransferMode"
-
-msgid "Prefer local systems"
-msgstr "Helyi rendszerek előnyben"
-
-msgid "Active on DVB card"
-msgstr "Aktív a következő DVB kártyán"
-
-msgid "Ignore CAID"
-msgstr "CAID mellőzése"
-
-msgid "Log to console"
-msgstr "Naplózás a konzolon"
-
-msgid "Log to file"
-msgstr "Naplózás fileba"
-
-msgid "Filename"
-msgstr "File neve"
-
-msgid "Filesize limit (KB)"
-msgstr "Fileméret limit (KB)"
-
-msgid "Log to syslog"
-msgstr "Naplózás a rendszelogba"
-
-msgid "Show user messages"
-msgstr ""
-
-msgid "A software emulated CAM"
-msgstr "Szoftveresen emulált CAM"
-
-msgid "undisclosed key"
-msgstr "rejtett kulcs"
-
-msgid "allow ALL"
-msgstr "engedélyezd MIND"
-
-msgid "block UNIQUE"
-msgstr "tiltsd az EGYEDIt"
-
-msgid "block SHARED"
-msgstr "tiltsd a MEGOSZTOTTat"
-
-msgid "block ALL"
-msgstr "tiltsd MINDET"
-
-msgid "SC-Seca: EMM updates"
-msgstr "SC-Seca: EMM frissítés"
-
-msgid "SC-Seca: activate PPV"
-msgstr "SC-Seca: aktiváld a PPV-t"
-
-msgid "Nagra: min. ECM processing time"
-msgstr "Nagra: min. ECM feldolgozási idő"
-
-msgid "Nagra2: drop EMM-S packets"
-msgstr ""
-
-msgid "Nagra2: Enable AUXserver"
-msgstr ""
-
-msgid "Nagra2: AUXserver hostname"
-msgstr ""
-
-msgid "Nagra2: AUXserver port"
-msgstr ""
-
-msgid "Nagra2: AUXserver password"
-msgstr ""
-
-msgid "don't touch"
-msgstr "ne bántsd"
-
-msgid "disable"
-msgstr "kikapcsolva"
-
-msgid "SC-Cryptoworks: Parental rating"
-msgstr "SC-Cryptoworks: Szülői zár"
-
-msgid "Cardclient: connect immediately"
-msgstr "Kliens: csatlakozzon azonnal"
+++ /dev/null
-# VDR plugin language source file.
-# Copyright (C) 2007 somebody
-# This file is distributed under the same license as the vdr-sc package.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: VDR 1.5.9\n"
-"Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-07-11 20:28-0400\n"
-"PO-Revision-Date: 2007-08-27 12:45+0200\n"
-"Last-Translator: somebody\n"
-"Language-Team: somebody\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO-8859-15\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-msgid "Key update"
-msgstr "Aggiornamento chiavi"
-
-msgid "off"
-msgstr "disattivo"
-
-msgid "SoftCAM"
-msgstr "SoftCAM"
-
-msgid "Current keys:"
-msgstr "Chiavi in uso:"
-
-msgid "Key update status:"
-msgstr "Stato aggiornamento chiavi:"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [Seen keys]"
-msgstr " [Chiavi trovate]"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [New keys]"
-msgstr " [Nuove chiavi]"
-
-msgid "Smartcard"
-msgstr "Smartcard"
-
-msgid "Reset card"
-msgstr "Reimposta smartcard"
-
-msgid "Really reset card?"
-msgstr "Reimpostare smartcard?"
-
-msgid "Module config"
-msgstr "Configurazione modulo"
-
-msgid "Reset module to default"
-msgstr "Reimposta modulo predefinito"
-
-msgid "Really reset module to default?"
-msgstr "Reimpostare modulo predefinito?"
-
-msgid "Module"
-msgstr "Modulo"
-
-msgid "Message logging"
-msgstr "Messaggi di log"
-
-msgid "Disable ALL modules"
-msgstr "Disabilita TUTTI i moduli"
-
-msgid "Reset ALL modules to default"
-msgstr "Reimposta TUTTI i moduli predefiniti"
-
-msgid "Really disable ALL modules?"
-msgstr "Disabilitare TUTTI i moduli?"
-
-msgid "Really reset ALL modules to default?"
-msgstr "Reimpostare TUTTI i moduli predefiniti?"
-
-msgid "Cryptsystem options"
-msgstr "Opzioni sistemi di codifica"
-
-msgid "Cryptsystem options..."
-msgstr "Opzioni sistema codifica..."
-
-msgid "Message logging..."
-msgstr "Opzioni di log..."
-
-msgid "Smartcard interface"
-msgstr "Interfaccia Smartcard"
-
-msgid "(empty)"
-msgstr "(vuota)"
-
-msgid "Status information..."
-msgstr "Informazioni SoftCam"
-
-msgid "Flush ECM cache"
-msgstr "Svuota cache ECM"
-
-msgid "Reload files"
-msgstr "Ricarica il file delle chiavi"
-
-msgid "Really flush ECM cache?"
-msgstr "Svuotare cache ECM?"
-
-msgid "Really reload files?"
-msgstr "Ricaricare il file delle chiavi?"
-
-msgid "Active! Can't reload files now"
-msgstr "Chiave in uso! Impossibile ricaricare adesso"
-
-msgid "(none)"
-msgstr "(nessuna)"
-
-msgid "active CAIDs"
-msgstr "CAIDs attivi"
-
-msgid "all CAIDs"
-msgstr "tutti i CAIDs"
-
-msgid "comment out"
-msgstr "commenta"
-
-msgid "remove"
-msgstr "rimuovi"
-
-msgid "Update keys (AU)"
-msgstr "Aggiornamento chiavi (AU)"
-
-msgid "Start AU on EPG scan"
-msgstr "Avvia AU con la scansione EPG"
-
-msgid "Superseded keys"
-msgstr "Chiavi scadute"
-
-msgid "Concurrent FF streams"
-msgstr "Flussi simultanei schede FF"
-
-msgid "Force TransferMode"
-msgstr "Forza mod. trasferimento"
-
-msgid "Prefer local systems"
-msgstr "Preferisci sistemi locali"
-
-msgid "Active on DVB card"
-msgstr "Attiva sulla scheda DVB"
-
-msgid "Ignore CAID"
-msgstr "Ignora CAID"
-
-msgid "Log to console"
-msgstr "Log in console"
-
-msgid "Log to file"
-msgstr "Log in un file"
-
-msgid "Filename"
-msgstr "Nome file"
-
-msgid "Filesize limit (KB)"
-msgstr "Limite dimensione file (KB)"
-
-msgid "Log to syslog"
-msgstr "Log in registro di sistema"
-
-msgid "Show user messages"
-msgstr "Mostra messaggi utente"
-
-msgid "A software emulated CAM"
-msgstr "Un software di emulazione CAM"
-
-msgid "undisclosed key"
-msgstr "chiave nascosta"
-
-msgid "allow ALL"
-msgstr "permetti TUTTI"
-
-msgid "block UNIQUE"
-msgstr "blocca al SERIALE"
-
-msgid "block SHARED"
-msgstr "blocca al GRUPPO"
-
-msgid "block ALL"
-msgstr "blocca TUTTO"
-
-msgid "SC-Seca: EMM updates"
-msgstr "SC-Seca: aggiornamenti EMM"
-
-msgid "SC-Seca: activate PPV"
-msgstr "SC-Seca: attiva PPV"
-
-msgid "Nagra: min. ECM processing time"
-msgstr "Nagra: tempo min. esec. ECM"
-
-msgid "Nagra2: drop EMM-S packets"
-msgstr "Nagra2: elimina pacchetti EMM-S"
-
-msgid "Nagra2: Enable AUXserver"
-msgstr "Nagra2: abilita AUXserver"
-
-msgid "Nagra2: AUXserver hostname"
-msgstr "Nagra2: nome AUXserver"
-
-msgid "Nagra2: AUXserver port"
-msgstr "Nagra2: porta AUXserver"
-
-msgid "Nagra2: AUXserver password"
-msgstr "Nagra2: password AUXserver"
-
-msgid "don't touch"
-msgstr "non toccare"
-
-msgid "disable"
-msgstr "disabilita"
-
-msgid "SC-Cryptoworks: Parental rating"
-msgstr "SC-Cryptoworks: Filtro famiglia"
-
-msgid "Cardclient: connect immediately"
-msgstr "Cardclient: connetti subito"
+++ /dev/null
-# VDR plugin language source file.
-# Copyright (C) 2007 somebody
-# This file is distributed under the same license as the vdr-sc package.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: VDR 1.5.9\n"
-"Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-07-11 20:28-0400\n"
-"PO-Revision-Date: 2007-08-27 12:45+0200\n"
-"Last-Translator: somebody\n"
-"Language-Team: somebody\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO-8859-15\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-msgid "Key update"
-msgstr ""
-
-msgid "off"
-msgstr "uit"
-
-msgid "SoftCAM"
-msgstr "SoftCAM"
-
-msgid "Current keys:"
-msgstr "Huidige keys:"
-
-msgid "Key update status:"
-msgstr "Key update status:"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [Seen keys]"
-msgstr ""
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [New keys]"
-msgstr " [Nieuwe keys]"
-
-msgid "Smartcard"
-msgstr "Smartcard"
-
-msgid "Reset card"
-msgstr "Reset smartcard"
-
-msgid "Really reset card?"
-msgstr "Werkelijk smartcard resetten?"
-
-msgid "Module config"
-msgstr ""
-
-msgid "Reset module to default"
-msgstr ""
-
-msgid "Really reset module to default?"
-msgstr ""
-
-msgid "Module"
-msgstr ""
-
-msgid "Message logging"
-msgstr ""
-
-msgid "Disable ALL modules"
-msgstr ""
-
-msgid "Reset ALL modules to default"
-msgstr ""
-
-msgid "Really disable ALL modules?"
-msgstr ""
-
-msgid "Really reset ALL modules to default?"
-msgstr ""
-
-msgid "Cryptsystem options"
-msgstr ""
-
-msgid "Cryptsystem options..."
-msgstr ""
-
-msgid "Message logging..."
-msgstr ""
-
-msgid "Smartcard interface"
-msgstr "Smartcard interface"
-
-msgid "(empty)"
-msgstr "(leeg)"
-
-msgid "Status information..."
-msgstr "Status informatie..."
-
-msgid "Flush ECM cache"
-msgstr ""
-
-msgid "Reload files"
-msgstr "Opnieuw laden bestanden?"
-
-msgid "Really flush ECM cache?"
-msgstr ""
-
-msgid "Really reload files?"
-msgstr "Werkelijk opnieuw laden bestanden?"
-
-msgid "Active! Can't reload files now"
-msgstr "Actief! Kan bestanden niet herladen"
-
-msgid "(none)"
-msgstr "(geen)"
-
-msgid "active CAIDs"
-msgstr "actieve CAIDS"
-
-msgid "all CAIDs"
-msgstr "alle CAIDs"
-
-msgid "comment out"
-msgstr ""
-
-msgid "remove"
-msgstr ""
-
-msgid "Update keys (AU)"
-msgstr "Keys updaten (AU)"
-
-msgid "Start AU on EPG scan"
-msgstr ""
-
-msgid "Superseded keys"
-msgstr ""
-
-msgid "Concurrent FF streams"
-msgstr ""
-
-msgid "Force TransferMode"
-msgstr ""
-
-msgid "Prefer local systems"
-msgstr ""
-
-msgid "Active on DVB card"
-msgstr "Actief op DVB kaart"
-
-msgid "Ignore CAID"
-msgstr ""
-
-msgid "Log to console"
-msgstr ""
-
-msgid "Log to file"
-msgstr ""
-
-msgid "Filename"
-msgstr ""
-
-msgid "Filesize limit (KB)"
-msgstr ""
-
-msgid "Log to syslog"
-msgstr ""
-
-msgid "Show user messages"
-msgstr ""
-
-msgid "A software emulated CAM"
-msgstr "In software geëmuleerde CAM"
-
-msgid "undisclosed key"
-msgstr "onbekende key"
-
-msgid "allow ALL"
-msgstr "ALLES toestaan"
-
-msgid "block UNIQUE"
-msgstr "UNIEKE blokkeren"
-
-msgid "block SHARED"
-msgstr "GEDEELDE blokkeren"
-
-msgid "block ALL"
-msgstr "ALLES blokkeren"
-
-msgid "SC-Seca: EMM updates"
-msgstr "SC-Seca: EMM updates"
-
-msgid "SC-Seca: activate PPV"
-msgstr "SC-Seca: activeer PPV"
-
-msgid "Nagra: min. ECM processing time"
-msgstr "Nagra: min. ECM bewerkingstijd"
-
-msgid "Nagra2: drop EMM-S packets"
-msgstr ""
-
-msgid "Nagra2: Enable AUXserver"
-msgstr ""
-
-msgid "Nagra2: AUXserver hostname"
-msgstr ""
-
-msgid "Nagra2: AUXserver port"
-msgstr ""
-
-msgid "Nagra2: AUXserver password"
-msgstr ""
-
-msgid "don't touch"
-msgstr "niet wijzigen"
-
-msgid "disable"
-msgstr "uitschakelen"
-
-msgid "SC-Cryptoworks: Parental rating"
-msgstr "SC-Cryptoworks: Leeftijdsadvies"
-
-msgid "Cardclient: connect immediately"
-msgstr "Cardclient: direct contact maken"
+++ /dev/null
-# VDR plugin language source file.
-# Copyright (C) 2007 somebody
-# This file is distributed under the same license as the vdr-sc package.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: VDR 1.5.9\n"
-"Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-07-11 20:28-0400\n"
-"PO-Revision-Date: 2007-08-27 12:45+0200\n"
-"Last-Translator: somebody\n"
-"Language-Team: somebody\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO-8859-2\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-msgid "Key update"
-msgstr ""
-
-msgid "off"
-msgstr "wy³±cz"
-
-msgid "SoftCAM"
-msgstr "SoftCAM"
-
-msgid "Current keys:"
-msgstr "Obecne klucze:"
-
-msgid "Key update status:"
-msgstr "Stan aktualizacji kluczy:"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [Seen keys]"
-msgstr " [widzianych kluczy]"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [New keys]"
-msgstr " [nowych kluczy]"
-
-msgid "Smartcard"
-msgstr "Smartcard"
-
-msgid "Reset card"
-msgstr "Resetuj kartê"
-
-msgid "Really reset card?"
-msgstr "Na pewno zrestartowaæ kartê?"
-
-msgid "Module config"
-msgstr ""
-
-msgid "Reset module to default"
-msgstr ""
-
-msgid "Really reset module to default?"
-msgstr ""
-
-msgid "Module"
-msgstr ""
-
-msgid "Message logging"
-msgstr ""
-
-msgid "Disable ALL modules"
-msgstr ""
-
-msgid "Reset ALL modules to default"
-msgstr ""
-
-msgid "Really disable ALL modules?"
-msgstr ""
-
-msgid "Really reset ALL modules to default?"
-msgstr ""
-
-msgid "Cryptsystem options"
-msgstr ""
-
-msgid "Cryptsystem options..."
-msgstr ""
-
-msgid "Message logging..."
-msgstr ""
-
-msgid "Smartcard interface"
-msgstr "Interfejs Smartcard"
-
-msgid "(empty)"
-msgstr "(puste)"
-
-msgid "Status information..."
-msgstr "Informacje o stanie..."
-
-msgid "Flush ECM cache"
-msgstr ""
-
-msgid "Reload files"
-msgstr "Prze³aduj pliki"
-
-msgid "Really flush ECM cache?"
-msgstr ""
-
-msgid "Really reload files?"
-msgstr "Na pewno prze³adowaæ klucze?"
-
-msgid "Active! Can't reload files now"
-msgstr "Aktywny! Nie mo¿na teraz prze³adowaæ plików."
-
-msgid "(none)"
-msgstr "(brak)"
-
-msgid "active CAIDs"
-msgstr "aktywne CAID"
-
-msgid "all CAIDs"
-msgstr "wszystkie CAID"
-
-msgid "comment out"
-msgstr ""
-
-msgid "remove"
-msgstr ""
-
-msgid "Update keys (AU)"
-msgstr "Aktualizuj klucze (AU)"
-
-msgid "Start AU on EPG scan"
-msgstr ""
-
-msgid "Superseded keys"
-msgstr ""
-
-msgid "Concurrent FF streams"
-msgstr ""
-
-msgid "Force TransferMode"
-msgstr ""
-
-msgid "Prefer local systems"
-msgstr ""
-
-msgid "Active on DVB card"
-msgstr "Aktywny na karcie DVB"
-
-msgid "Ignore CAID"
-msgstr ""
-
-msgid "Log to console"
-msgstr ""
-
-msgid "Log to file"
-msgstr ""
-
-msgid "Filename"
-msgstr ""
-
-msgid "Filesize limit (KB)"
-msgstr ""
-
-msgid "Log to syslog"
-msgstr ""
-
-msgid "Show user messages"
-msgstr ""
-
-msgid "A software emulated CAM"
-msgstr "Programowo emulowany CAM"
-
-msgid "undisclosed key"
-msgstr "niejawny klucz"
-
-msgid "allow ALL"
-msgstr "dopu¶æ wszystkie"
-
-msgid "block UNIQUE"
-msgstr "blokuj unikaty"
-
-msgid "block SHARED"
-msgstr "blokuj dzielone"
-
-msgid "block ALL"
-msgstr "blokuj wszystkie"
-
-msgid "SC-Seca: EMM updates"
-msgstr "SC-Seca: aktualizacje EMM"
-
-msgid "SC-Seca: activate PPV"
-msgstr "SC-Seca: aktywuj PPV"
-
-msgid "Nagra: min. ECM processing time"
-msgstr "Nagra: min. czas przetwarzania ECM"
-
-msgid "Nagra2: drop EMM-S packets"
-msgstr ""
-
-msgid "Nagra2: Enable AUXserver"
-msgstr ""
-
-msgid "Nagra2: AUXserver hostname"
-msgstr ""
-
-msgid "Nagra2: AUXserver port"
-msgstr ""
-
-msgid "Nagra2: AUXserver password"
-msgstr ""
-
-msgid "don't touch"
-msgstr "nie dotykaj"
-
-msgid "disable"
-msgstr "wy³±cz"
-
-msgid "SC-Cryptoworks: Parental rating"
-msgstr "SC-Cryptoworks: wska¼nik rodzica"
-
-msgid "Cardclient: connect immediately"
-msgstr "Klient karty: pod³±cz natychmiast"
+++ /dev/null
-# VDR plugin language source file.
-# Copyright (C) 2007 somebody
-# This file is distributed under the same license as the vdr-sc package.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: VDR 1.5.9\n"
-"Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-07-11 20:28-0400\n"
-"PO-Revision-Date: 2008-03-13 15:43+0100\n"
-"Last-Translator: somebody\n"
-"Language-Team: ru\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO-8859-5\n"
-"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: KBabel 1.11.4\n"
-
-msgid "Key update"
-msgstr "¾ÑÝÞÒÛÕÝØÕ ÚÛîçÐ"
-
-msgid "off"
-msgstr "ÒëÚÛ"
-
-msgid "SoftCAM"
-msgstr "SoftCAM"
-
-msgid "Current keys:"
-msgstr "¸áßÞÛì×ãÕÜëÕ ÚÛîçØ:"
-
-msgid "Key update status:"
-msgstr "¾ÑÝÞÒÛÕÝØÕ ÚÛîçÕÙ:"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [Seen keys]"
-msgstr " [ÚÛîçÕÙ ÝÐÙÔÕÝÞ]"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [New keys]"
-msgstr " [ÝÞÒëå ÚÛîçÕÙ]"
-
-msgid "Smartcard"
-msgstr "ºÐàâÞçÚÐ"
-
-msgid "Reset card"
-msgstr "ÁÑàÞáØâì ÚÐàâÞçÚã"
-
-msgid "Really reset card?"
-msgstr "´ÕÙáâÒØâÕÛìÝÞ áÑàÞáØâì ÚÐàâÞçÚã?"
-
-msgid "Module config"
-msgstr "½ÐáâàÞÙÚÐ ÜÞÔãÛï"
-
-msgid "Reset module to default"
-msgstr "ÁÑàÞá ÜÞÔãÛï ßÞ ãÜÞÛçÐÝØî"
-
-msgid "Really reset module to default?"
-msgstr "´ÕÙáâÒØâÕÛìÝÞ áÑàÞáØâì ÜÞÔãÛì ßÞ ãÜÞÛçÐÝØî?"
-
-msgid "Module"
-msgstr "¼ÞÔãÛì"
-
-msgid "Message logging"
-msgstr "¿àÞâÞÚÞÛØàÞÒÐÝØÕ áÞÞÑéÕÝØÙ"
-
-msgid "Disable ALL modules"
-msgstr "²ëÚÛîçØâì ÒáÕ ÜÞÔãÛØ"
-
-msgid "Reset ALL modules to default"
-msgstr "ÁÑàÞáØâì ÒáÕ ÜÞÔãÛØ ßÞ ãÜÞÛçÐÝØî"
-
-msgid "Really disable ALL modules?"
-msgstr "´ÕÙáâÒØâÕÛìÝÞ ÒëÚÛîçØâì ÒáÕ ÜÞÔãÛØ?"
-
-msgid "Really reset ALL modules to default?"
-msgstr "´ÕÙáâÒØâÕÛìÝÞ áÑàÞáØâì ÒáÕ ÜÞÔãÛØ ßÞ ãÜÞÛçÐÝØî?"
-
-msgid "Cryptsystem options"
-msgstr "¾ßæØØ ÚàØßâÞáØáâÕÜ"
-
-msgid "Cryptsystem options..."
-msgstr "¾ßæØØ ÚàØßâÞáØáâÕÜ..."
-
-msgid "Message logging..."
-msgstr "¿àÞâÞÚÞÛØàÞÒÐÝØÕ áÞÞÑéÕÝØÙ..."
-
-msgid "Smartcard interface"
-msgstr "ºÐàâÞçÝëÙ ÜÞÔãÛì"
-
-msgid "(empty)"
-msgstr "(ßãáâÞ)"
-
-msgid "Status information..."
-msgstr "ÁÞáâÞïÝØÕ..."
-
-msgid "Flush ECM cache"
-msgstr "¾çØáâØâì Úíè ECM"
-
-msgid "Reload files"
-msgstr "¿ÕàÕ×ÐÓàãרâì äÐÙÛë"
-
-msgid "Really flush ECM cache?"
-msgstr "´ÕÙáâÒØâÕÛìÝÞ ÞçØáâØâì Úíè ECM?"
-
-msgid "Really reload files?"
-msgstr "´ÕÙáâÒØâÕÛìÝÞ ßÕàÕ×ÐÓàãרâì äÐÙÛë?"
-
-msgid "Active! Can't reload files now"
-msgstr "·ÐÝïâ! ½Õ ÜÞÓã ßÕàÕ×ÐÓàãרâì äÐÙÛë"
-
-msgid "(none)"
-msgstr "(ÝÕâ)"
-
-msgid "active CAIDs"
-msgstr "ÐÚâØÒÝëÕ CAID"
-
-msgid "all CAIDs"
-msgstr "ÒáÕ CAID"
-
-msgid "comment out"
-msgstr "×ÐÚÞÜÕÝâØàÞÒÐâì"
-
-msgid "remove"
-msgstr "ãÔÐÛØâì"
-
-msgid "Update keys (AU)"
-msgstr "¾ÑÝÞÒÛïâì ÚÛîçØ (AU)"
-
-msgid "Start AU on EPG scan"
-msgstr "ÁâÐàâ ÐÒâÞÞÑÝÞÒÛÕÝØï ßàØ EPG áÚÐÝØàÞÒÐÝØØ"
-
-msgid "Superseded keys"
-msgstr "ÃáâÐàÕÒèØÕ ÚÛîçØ"
-
-msgid "Concurrent FF streams"
-msgstr "¿ÐàÐÛÛÕÛìÝëÕ ßÞâÞÚØ FF"
-
-msgid "Force TransferMode"
-msgstr "²ëÝãÖÔÕÝÝëÙ TransferMode"
-
-msgid "Prefer local systems"
-msgstr "¿àÕÔßÞçØâÐâì ÛÞÚÐÛìÝëÕ áØáâÕÜë"
-
-msgid "Active on DVB card"
-msgstr "°ÚâØÒÝëÙ ÝÐ ßÛÐâÕ DVB"
-
-msgid "Ignore CAID"
-msgstr "¸ÓÝÞàØàÞÒÐâì CAID"
-
-msgid "Log to console"
-msgstr "ÁÞÞÑéÕÝØï Ò ÚÞÝáÞÛÕ"
-
-msgid "Log to file"
-msgstr "ÁÞÞÑéÕÝØï Ò äÐÙÛ"
-
-msgid "Filename"
-msgstr "½Ð×ÒÐÝØÕ äÐÙÛÐ"
-
-msgid "Filesize limit (KB)"
-msgstr "»ØÜØâ äÐÙÛÐ (Ú±)"
-
-msgid "Log to syslog"
-msgstr "ÁÞÞÑéÕÝØï Ò Syslog"
-
-msgid "Show user messages"
-msgstr "¿ÞÚÐ×Ðâì áÞÞÑéÕÝØï ßÞÛì×ÞÒÐâÕÛï"
-
-msgid "A software emulated CAM"
-msgstr "¿àÞÓàÐÜÜÝëÙ íÜãÛïâÞà CAM"
-
-msgid "undisclosed key"
-msgstr "ÝÕØ×ÒÕáâÝëÙ ÚÛîç"
-
-msgid "allow ALL"
-msgstr "ÒáÕ àÐ×àÕèØâì"
-
-msgid "block UNIQUE"
-msgstr "ÑÛÞÚØàÞÒÐâì UNIQUE"
-
-msgid "block SHARED"
-msgstr "ÑÛÞÚØàÞÒÐâì SHARED"
-
-msgid "block ALL"
-msgstr "ÒáÕ ÑÛÞÚØàÞÒÐâì"
-
-msgid "SC-Seca: EMM updates"
-msgstr "SC-Seca: ÞÑÝÞÒÛÕÝØï EMM"
-
-msgid "SC-Seca: activate PPV"
-msgstr "SC-Seca: ÐÚâØÒØàÞÒÐâì PPV"
-
-msgid "Nagra: min. ECM processing time"
-msgstr "Nagra: ÜØÝ. ÒàÕÜï ÞÑàÐÑÞâÚØ ECM"
-
-msgid "Nagra2: drop EMM-S packets"
-msgstr "½ÐÓàÐ2: ×ÐßàÕâ EMM-S ßÐÚÕâÞÒ"
-
-msgid "Nagra2: Enable AUXserver"
-msgstr "Nagra2: àÐ×àÕèØâì AUXserver"
-
-msgid "Nagra2: AUXserver hostname"
-msgstr "Nagra2: AUXserver ØÜï åÞáâÐ"
-
-msgid "Nagra2: AUXserver port"
-msgstr "Nagra2: AUXserver ßÞàâ"
-
-msgid "Nagra2: AUXserver password"
-msgstr "Nagra2: AUXserver ßÐàÞÛì"
-
-msgid "don't touch"
-msgstr "ÝÕ Ø×ÜÕÝïâì"
-
-msgid "disable"
-msgstr "ÒëÚÛîçØâì"
-
-msgid "SC-Cryptoworks: Parental rating"
-msgstr "SC-Cryptoworks: ÒÞ×àÐáâÝÞÕ ÞÓàÐÝØçÕÝØÕ"
-
-msgid "Cardclient: connect immediately"
-msgstr "Cardclient: áÞÕÔØÝØâì ÝÕÜÕÔÛÕÝÝÞ"
+++ /dev/null
-# VDR plugin language source file.
-# Copyright (C) 2007 somebody
-# This file is distributed under the same license as the vdr-sc package.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: VDR 1.5.9\n"
-"Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-07-11 20:28-0400\n"
-"PO-Revision-Date: 2007-08-27 12:45+0200\n"
-"Last-Translator: somebody\n"
-"Language-Team: somebody\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO-8859-1\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-msgid "Key update"
-msgstr ""
-
-msgid "off"
-msgstr "av"
-
-msgid "SoftCAM"
-msgstr "SoftCAM"
-
-msgid "Current keys:"
-msgstr "Aktuell nyckel:"
-
-msgid "Key update status:"
-msgstr "Nyckeluppdateringsstatus:"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [Seen keys]"
-msgstr " [Påträffade nycklar]"
-
-#. TRANSLATORS: 2 leading spaces!
-msgid " [New keys]"
-msgstr " [Nya nycklar]"
-
-msgid "Smartcard"
-msgstr "Smartcard"
-
-msgid "Reset card"
-msgstr "Nollställ kortet"
-
-msgid "Really reset card?"
-msgstr "Bekräfta nollställning av kortet?"
-
-msgid "Module config"
-msgstr ""
-
-msgid "Reset module to default"
-msgstr ""
-
-msgid "Really reset module to default?"
-msgstr ""
-
-msgid "Module"
-msgstr ""
-
-msgid "Message logging"
-msgstr ""
-
-msgid "Disable ALL modules"
-msgstr ""
-
-msgid "Reset ALL modules to default"
-msgstr ""
-
-msgid "Really disable ALL modules?"
-msgstr ""
-
-msgid "Really reset ALL modules to default?"
-msgstr ""
-
-msgid "Cryptsystem options"
-msgstr ""
-
-msgid "Cryptsystem options..."
-msgstr ""
-
-msgid "Message logging..."
-msgstr ""
-
-msgid "Smartcard interface"
-msgstr "Smartcard-gränssnitt"
-
-msgid "(empty)"
-msgstr "(tom)"
-
-msgid "Status information..."
-msgstr "Statusinformation..."
-
-msgid "Flush ECM cache"
-msgstr ""
-
-msgid "Reload files"
-msgstr "Ladda om filer"
-
-msgid "Really flush ECM cache?"
-msgstr ""
-
-msgid "Really reload files?"
-msgstr "Bekräfta omladdning av filer?"
-
-msgid "Active! Can't reload files now"
-msgstr "Aktiv! Kan inte ladda om filer nu"
-
-msgid "(none)"
-msgstr "(ingen)"
-
-msgid "active CAIDs"
-msgstr "aktiva CAID"
-
-msgid "all CAIDs"
-msgstr "alla CAID"
-
-msgid "comment out"
-msgstr ""
-
-msgid "remove"
-msgstr ""
-
-msgid "Update keys (AU)"
-msgstr "Nyckeluppdatering (AU)"
-
-msgid "Start AU on EPG scan"
-msgstr ""
-
-msgid "Superseded keys"
-msgstr ""
-
-msgid "Concurrent FF streams"
-msgstr ""
-
-msgid "Force TransferMode"
-msgstr ""
-
-msgid "Prefer local systems"
-msgstr ""
-
-msgid "Active on DVB card"
-msgstr "Aktiv på DVB-kort"
-
-msgid "Ignore CAID"
-msgstr "Ignorera CAID"
-
-msgid "Log to console"
-msgstr ""
-
-msgid "Log to file"
-msgstr ""
-
-msgid "Filename"
-msgstr ""
-
-msgid "Filesize limit (KB)"
-msgstr ""
-
-msgid "Log to syslog"
-msgstr ""
-
-msgid "Show user messages"
-msgstr ""
-
-msgid "A software emulated CAM"
-msgstr "En mjukvaruemulerad CAM"
-
-msgid "undisclosed key"
-msgstr "ej avslöjad nyckel"
-
-msgid "allow ALL"
-msgstr ""
-
-msgid "block UNIQUE"
-msgstr ""
-
-msgid "block SHARED"
-msgstr ""
-
-msgid "block ALL"
-msgstr ""
-
-msgid "SC-Seca: EMM updates"
-msgstr ""
-
-msgid "SC-Seca: activate PPV"
-msgstr ""
-
-msgid "Nagra: min. ECM processing time"
-msgstr ""
-
-msgid "Nagra2: drop EMM-S packets"
-msgstr ""
-
-msgid "Nagra2: Enable AUXserver"
-msgstr ""
-
-msgid "Nagra2: AUXserver hostname"
-msgstr ""
-
-msgid "Nagra2: AUXserver port"
-msgstr ""
-
-msgid "Nagra2: AUXserver password"
-msgstr ""
-
-msgid "don't touch"
-msgstr ""
-
-msgid "disable"
-msgstr ""
-
-msgid "SC-Cryptoworks: Parental rating"
-msgstr ""
-
-msgid "Cardclient: connect immediately"
-msgstr ""
+++ /dev/null
-#!/usr/bin/perl
-#
-# po2i18n - Convert plugin po files in into i18n.c-format
-#
-# See the README file for copyright information and how to reach the author.
-#
-
-use strict;
-use warnings;
-
-my @LANGS = (
- "en_US",
- "de_DE",
- "sl_SI",
- "it_IT",
- "nl_NL",
- "pt_PT",
- "fr_FR",
- "nn_NO",
- "fi_FI",
- "pl_PL",
- "es_ES",
- "el_GR",
- "sv_SE",
- "ro_RO",
- "hu_HU",
- "ca_ES",
- "ru_RU",
- "hr_HR",
- "et_EE",
- "da_DK",
- "cs_CZ",
- "tr_TR"
- );
-
-my %VERS = (
- "en_US" => 10200,
- "de_DE" => 10200,
- "sl_SI" => 10200,
- "it_IT" => 10200,
- "nl_NL" => 10200,
- "pt_PT" => 10200,
- "fr_FR" => 10200,
- "nn_NO" => 10200,
- "fi_FI" => 10200,
- "pl_PL" => 10200,
- "es_ES" => 10200,
- "el_GR" => 10200,
- "sv_SE" => 10200,
- "ro_RO" => 10200,
- "hu_HU" => 10200,
- "ca_ES" => 10200,
- "ru_RU" => 10302,
- "hr_HR" => 10307,
- "et_EE" => 10313,
- "da_DK" => 10316,
- "cs_CZ" => 10342,
- "tr_TR" => 10502
- );
-
-
-my %strings;
-
-foreach my $lang (@LANGS) { $strings{$lang} = { }; }
-
-
-sub LoadLanguage(*) {
- my ($lang) = @_;
-
- if (!open FILE, "<", "po/$lang.po") {
- return 0;
- }
-
- my $msgid = "";
- my $msgstr = "";
- my $last = 0; # 0=init, 1=msgid was last, 2=msgstr was last
-
- while (<FILE>) {
- chomp;
- my $line = $_;
-
- if ($line =~ /^msgid "(.*)"$/) {
- if ($last eq 2) {
- $strings{$lang}->{$msgid} = $msgstr;
- $strings{"en_US"}->{$msgid} = $msgid;
- }
- $msgid = $1;
- $last = 1;
- } elsif ($line =~ /^msgstr "(.*)"/) {
- $msgstr = $1;
- $last = 2;
- } elsif ($line =~ /^"(.*)"/) {
- if ($last eq 1) {
- $msgid = $msgid . $1;
- } elsif ($last eq 2) {
- $msgstr = $msgstr . $1;
- }
- }
- }
- if ($last eq 2) {
- $strings{$lang}->{$msgid} = $msgstr;
- $strings{"en_US"}->{$msgid} = $msgid;
- }
-
- close FILE;
-}
-
-
-
-foreach my $lang (@LANGS) {
- LoadLanguage($lang);
-}
-
-my @msgids = sort keys %{$strings{"en_US"}};
-
-
-my $silent = 0;
-
-while (<>) {
- my $line = $_;
-
- if ($line =~ /^\/\/ START I18N/) {
- print "// START I18N - automatically generated by po2i18n.pl\n";
- for my $msgid (@msgids) {
- next if $msgid eq "";
-
- my $head = " { ";
- my $endif = "";
- my $versnum = 10200;
-
- for my $lang (@LANGS) {
- if ($VERS{$lang} ne $versnum) {
- $versnum = $VERS{$lang};
- print $endif;
- print "#if VDRVERSNUM >= $versnum\n";
- $endif = "#endif\n";
- }
- my $msgstr = $strings{$lang}->{$msgid};
- $msgstr = "" if !defined $msgstr;
-
- print "$head\"$msgstr\",\n";
- $head = " ";
- }
- print $endif;
- print " },\n";
- }
- $silent = 1;
- }
-
- if (!$silent) { print $line; }
-
- if ($line =~ /^\/\/ END I18N/) {
- print "// END I18N - automatically generated by po2i18n.pl\n";
- $silent = 0;
- }
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <malloc.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <typeinfo>
-#ifndef STATICBUILD
-#include <dlfcn.h>
-#include <dirent.h>
-#include <fnmatch.h>
-#endif
-
-#include <vdr/plugin.h>
-#include <vdr/menuitems.h>
-#include <vdr/status.h>
-#include <vdr/dvbdevice.h>
-#include <vdr/channels.h>
-#include <vdr/ci.h>
-#include <vdr/interface.h>
-#include <vdr/menu.h>
-#include <vdr/tools.h>
-#include <vdr/config.h>
-
-#include "sc.h"
-#include "scsetup.h"
-#include "filter.h"
-#include "system.h"
-#include "cam.h"
-#include "smartcard.h"
-#include "data.h"
-#include "network.h"
-#include "misc.h"
-#include "opts.h"
-#include "i18n.h"
-#include "log-core.h"
-#include "version.h"
-
-#define MIN_VERS 1 // required VDR version
-#define MIN_MAJOR 4
-#define MIN_MINOR 6
-#define MINAPIVERSNUM 10405
-
-// some sanity checks
-#ifdef HAVE_SOFTCSA
-#error softcsa/ffdecsa patch MUST NOT be applied. Next time read the README first.
-#endif
-#if APIVERSNUM >= 10500
-#ifdef VDR_IS_SC_PATCHED
-#error You MUST NOT patch the VDR core. Next time read the README first.
-#endif
-#else //APIVERSNUM >= 10500
-#if !defined(VDR_IS_SC_PATCHED)
-#error You MUST patch the VDR core with the supplied patch. Next time read the README first.
-#endif
-#if VDR_IS_SC_PATCHED<402
-#error Your VDR core is patched with an outdated patch version. Please upgrade to the supplied version.
-#endif
-#endif //APIVERSNUM >= 10500
-#if APIVERSNUM<MINAPIVERSNUM
-#error Your VDR API version is too old. See README.
-#endif
-
-// SC API version number for loading shared libraries
-#define SCAPIVERS 20
-
-static cPlugin *ScPlugin;
-static cOpts *ScOpts, *LogOpts;
-static const char * const cfgsub="sc";
-
-static const struct LogModule lm_core = {
- (LMOD_ENABLE|L_CORE_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_CORE_LOAD|L_CORE_ECM|L_CORE_PIDS|L_CORE_AU|L_CORE_AUSTATS|L_CORE_CAIDS|L_CORE_NET|L_CORE_CI|L_CORE_SC|L_CORE_HOOK)&LOPT_MASK,
- "core",
- { "load","action","ecm","ecmProc","pids","au","auStats","auExtra","auExtern",
- "caids","keys","dynamic","csa","ci","av7110","net","netData","msgcache",
- "serial","smartcard","hook","ciFull" }
- };
-ADD_MODULE(L_CORE,lm_core)
-
-// --- cMenuEditCapItem --------------------------------------------------------
-
-class cMenuEditCapItem : public cMenuEditIntItem {
-protected:
- virtual void Set(void);
-public:
- cMenuEditCapItem(const char *Name, int *Value);
- eOSState ProcessKey(eKeys Key);
- };
-
-cMenuEditCapItem::cMenuEditCapItem(const char *Name, int *Value)
-:cMenuEditIntItem(Name, Value, 0)
-{
- Set();
-}
-
-void cMenuEditCapItem::Set(void)
-{
- if(!*value) SetValue(tr("off"));
- else cMenuEditIntItem::Set();
-}
-
-eOSState cMenuEditCapItem::ProcessKey(eKeys Key)
-{
- eOSState state = cMenuEditItem::ProcessKey(Key);
- if(state==osUnknown)
- state=cMenuEditIntItem::ProcessKey(Key);
- return state;
-}
-
-// --- cMenuEditHexItem ------------------------------------------------------
-
-class cMenuEditHexItem : public cMenuEditItem {
-private:
- bool abc, isOn;
- //
- void SetButtons(bool on);
-protected:
- int *value;
- int min, max;
- //
- virtual void Set(void);
-public:
- cMenuEditHexItem(const char *Name, int *Value, int Min=0, int Max=INT_MAX);
- virtual eOSState ProcessKey(eKeys Key);
- };
-
-cMenuEditHexItem::cMenuEditHexItem(const char *Name, int *Value, int Min, int Max)
-:cMenuEditItem(Name)
-{
- value=Value; min=Min; max=Max;
- if(*value<min) *value=min;
- else if(*value>max) *value=max;
- Set();
- abc=true; isOn=false;
-}
-
-void cMenuEditHexItem::SetButtons(bool on)
-{
- if(on) {
- if(abc) cSkinDisplay::Current()->SetButtons("A","B","C","D-F");
- else cSkinDisplay::Current()->SetButtons("D","E","F","A-C");
- isOn=true;
- }
- else {
- cSkinDisplay::Current()->SetButtons(0);
- isOn=false;
- }
-}
-
-void cMenuEditHexItem::Set(void)
-{
- char buf[16];
- snprintf(buf,sizeof(buf),"%X",*value);
- SetValue(buf);
-}
-
-eOSState cMenuEditHexItem::ProcessKey(eKeys Key)
-{
- switch(NORMALKEY(Key)) {
- case kUp:
- case kDown:
- if(isOn) SetButtons(false);
- break;
- default:
- if(!isOn) SetButtons(true);
- break;
- }
- eOSState state=cMenuEditItem::ProcessKey(Key);
- if(state!=osUnknown) return state;
-
- int newValue=*value;
- bool IsRepeat=Key & k_Repeat;
- Key=NORMALKEY(Key);
- switch(Key) {
- case kBlue:
- abc=!abc; SetButtons(true);
- break;
- case kRed:
- case kGreen:
- case kYellow:
- case k0 ... k9:
- {
- if(fresh) { newValue=0; fresh=false; }
- int add;
- if(Key>=kRed && Key<=kYellow) add=(abc ? 10:13)+(Key-kRed);
- else add=(Key-k0);
- newValue=newValue*16+add;
- break;
- }
- case kLeft:
- newValue=*value-1; fresh=true;
- if(!IsRepeat && newValue<min) newValue=max;
- break;
- case kRight:
- newValue=*value+1; fresh=true;
- if(!IsRepeat && newValue>max) newValue=min;
- break;
- default:
- if(*value<min) { *value=min; Set(); }
- if(*value>max) { *value=max; Set(); }
- return osUnknown;
- }
- if(newValue!=*value && (!fresh || min<=newValue) && newValue<=max) {
- *value=newValue;
- Set();
- }
- return osContinue;
-}
-
-// --- cScInfoItem -------------------------------------------------------------
-
-class cScInfoItem : public cOsdItem {
-private:
- void SetValue(const char *Name, const char *Value);
-public:
- cScInfoItem(const char *Name, int Value, eOSState State=osUnknown);
- cScInfoItem(const char *Name, const char *Value=0, eOSState State=osUnknown);
- };
-
-cScInfoItem::cScInfoItem(const char *Name, int Value, eOSState State)
-:cOsdItem(State)
-{
- char buf[16];
- snprintf(buf,sizeof(buf),"%d",Value);
- SetValue(Name,buf);
- if(State==osUnknown) SetSelectable(false);
-}
-
-cScInfoItem::cScInfoItem(const char *Name, const char *Value, eOSState State)
-:cOsdItem(State)
-{
- SetValue(Name,Value);
- if(State==osUnknown) SetSelectable(false);
-}
-
-void cScInfoItem::SetValue(const char *Name, const char *Value)
-{
- char *buff;
- asprintf(&buff,Value ? "%s:\t%s":"%s",Name,Value);
- SetText(buff,false);
- cStatus::MsgOsdCurrentItem(buff);
-}
-
-// --- cOpt --------------------------------------------------------------------
-
-cOpt::cOpt(const char *Name, const char *Title)
-{
- name=Name; title=Title;
- fullname=0; persistant=true;
-}
-
-cOpt::~cOpt()
-{
- free(fullname);
-}
-
-const char *cOpt::FullName(const char *PreStr)
-{
- if(PreStr) {
- free(fullname);
- asprintf(&fullname,"%s.%s",PreStr,name);
- return fullname;
- }
- else return name;
-}
-
-// --- cOptInt -----------------------------------------------------------------
-
-cOptInt::cOptInt(const char *Name, const char *Title, int *Storage, int Min, int Max)
-:cOpt(Name,Title)
-{
- storage=Storage; min=Min; max=Max;
-}
-
-void cOptInt::Parse(const char *Value)
-{
- *storage=atoi(Value);
-}
-
-void cOptInt::Backup(void)
-{
- value=*storage;
-}
-
-bool cOptInt::Set(void)
-{
- if(value!=*storage) { *storage=value; return true; }
- return false;
-}
-
-void cOptInt::Store(const char *PreStr)
-{
- ScPlugin->SetupStore(FullName(PreStr),*storage);
-}
-
-void cOptInt::Create(cOsdMenu *menu)
-{
- menu->Add(new cMenuEditIntItem(tr(title),&value,min,max));
-}
-
-// --- cOptSel -----------------------------------------------------------------
-
-cOptSel::cOptSel(const char *Name, const char *Title, int *Storage, int NumStr, const char * const *Strings)
-:cOptInt(Name,Title,Storage,0,NumStr)
-{
- strings=Strings;
- trStrings=0;
-}
-
-cOptSel::~cOptSel()
-{
- free(trStrings);
-}
-
-void cOptSel::Create(cOsdMenu *menu)
-{
- free(trStrings);
- if((trStrings=MALLOC(const char *,max))) {
- for(int i=0; i<max ; i++) trStrings[i]=tr(strings[i]);
- menu->Add(new cMenuEditStraItem(tr(title),&value,max,trStrings));
- }
-}
-
-// --- cOptBool -----------------------------------------------------------------
-
-cOptBool::cOptBool(const char *Name, const char *Title, int *Storage)
-:cOptInt(Name,Title,Storage,0,1)
-{}
-
-void cOptBool::Create(cOsdMenu *menu)
-{
- menu->Add(new cMenuEditBoolItem(tr(title),&value));
-}
-
-// --- cOptStr -----------------------------------------------------------------
-
-cOptStr::cOptStr(const char *Name, const char *Title, char *Storage, int Size, const char *Allowed)
-:cOpt(Name,Title)
-{
- storage=Storage; size=Size; allowed=Allowed;
- value=MALLOC(char,size);
-}
-
-cOptStr::~cOptStr()
-{
- free(value);
-}
-
-void cOptStr::Parse(const char *Value)
-{
- strn0cpy(storage,Value,size);
-}
-
-void cOptStr::Backup(void)
-{
- strn0cpy(value,storage,size);
-}
-
-bool cOptStr::Set(void)
-{
- if(strcmp(value,storage)) { strn0cpy(storage,value,size); return true; }
- return false;
-}
-
-void cOptStr::Store(const char *PreStr)
-{
- ScPlugin->SetupStore(FullName(PreStr),storage);
-}
-
-void cOptStr::Create(cOsdMenu *menu)
-{
- menu->Add(new cMenuEditStrItem(tr(title),value,size,allowed));
-}
-
-// --- cOptMInt ----------------------------------------------------------------
-
-class cOptMInt : public cOpt {
-protected:
- int *storage, *value;
- int size, mode, len;
-public:
- cOptMInt(const char *Name, const char *Title, int *Storage, int Size, int Mode);
- virtual ~cOptMInt();
- virtual void Parse(const char *Value);
- virtual void Backup(void);
- virtual bool Set(void);
- virtual void Store(const char *PreStr);
- virtual void Create(cOsdMenu *menu);
- };
-
-// mode: 0-Cap 1-Int 2-Hex
-
-cOptMInt::cOptMInt(const char *Name, const char *Title, int *Storage, int Size, int Mode)
-:cOpt(Name,Title)
-{
- storage=Storage; size=Size; mode=Mode; len=sizeof(int)*size;
- value=MALLOC(int,size);
-}
-
-cOptMInt::~cOptMInt()
-{
- free(value);
-}
-
-void cOptMInt::Parse(const char *Value)
-{
- memset(storage,0,len);
- int i=0;
- while(1) {
- char *p;
- const int c=strtol(Value,&p,mode>1 ? 16:10);
- if(p==Value || i>=size) return;
- if(c>0) storage[i++]=c;
- Value=p;
- }
-}
-
-void cOptMInt::Backup(void)
-{
- memcpy(value,storage,len);
-}
-
-bool cOptMInt::Set(void)
-{
- if(memcmp(value,storage,len)) {
- memset(storage,0,len);
- for(int i=0, k=0; i<size; i++) if(value[i]>0) storage[k++]=value[i];
- return true;
- }
- return false;
-}
-
-void cOptMInt::Store(const char *PreStr)
-{
- char b[256];
- int p=0;
- for(int i=0; i<size; i++)
- if(storage[i] || mode==0) p+=snprintf(b+p,sizeof(b)-p,mode>1 ? "%x ":"%d ",storage[i]);
- ScPlugin->SetupStore(FullName(PreStr),p>0?b:0);
-}
-
-void cOptMInt::Create(cOsdMenu *menu)
-{
- for(int i=0; i<size; i++) {
- const char *buff=tr(title);
- switch(mode) {
- case 0: menu->Add(new cMenuEditCapItem(buff,&value[i])); break;
- case 1: menu->Add(new cMenuEditIntItem(buff,&value[i],0,65535)); break;
- case 2: menu->Add(new cMenuEditHexItem(buff,&value[i],0,65535)); break;
- }
- if(value[i]==0) break;
- }
-}
-
-// --- cOpts -------------------------------------------------------------------
-
-cOpts::cOpts(const char *PreStr, int NumOpts)
-{
- preStr=PreStr;
- numOpts=NumOpts; numAdd=0;
- if((opts=MALLOC(cOpt *,numOpts))) memset(opts,0,sizeof(cOpt *)*numOpts);
-}
-
-cOpts::~cOpts()
-{
- if(opts) {
- for(int i=0; i<numOpts; i++) delete opts[i];
- free(opts);
- }
-}
-
-void cOpts::Add(cOpt *opt)
-{
- if(opts && numAdd<numOpts) opts[numAdd++]=opt;
-}
-
-bool cOpts::Parse(const char *Name, const char *Value)
-{
- if(opts) {
- for(int i=0; i<numAdd; i++)
- if(opts[i] && opts[i]->Persistant() && !strcasecmp(Name,opts[i]->Name())) {
- opts[i]->Parse(Value);
- return true;
- }
- }
- return false;
-}
-
-bool cOpts::Store(bool AsIs)
-{
- bool res=false;
- if(opts) {
- for(int i=0; i<numAdd; i++)
- if(opts[i]) {
- if(!AsIs && opts[i]->Set()) res=true;
- if(opts[i]->Persistant()) opts[i]->Store(preStr);
- }
- }
- return res;
-}
-
-void cOpts::Backup(void)
-{
- if(opts) {
- for(int i=0; i<numAdd; i++)
- if(opts[i]) opts[i]->Backup();
- }
-}
-
-void cOpts::Create(cOsdMenu *menu)
-{
- if(opts) {
- for(int i=0; i<numAdd; i++)
- if(opts[i]) opts[i]->Create(menu);
- }
-}
-
-// --- cMenuInfoSc -------------------------------------------------------------
-
-class cMenuInfoSc : public cOsdMenu {
-public:
- cMenuInfoSc(void);
- virtual eOSState ProcessKey(eKeys Key);
- };
-
-cMenuInfoSc::cMenuInfoSc(void)
-:cOsdMenu(tr("SoftCAM"),25)
-{
- Add(new cScInfoItem(tr("Current keys:")));
- for(int d=0; d<MAXDVBDEVICES; d++) {
- int n=0;
- char *ks;
- do {
- if((ks=cSoftCAM::CurrKeyStr(d,n))) {
- char buffer[32];
- snprintf(buffer,sizeof(buffer)," [%s %d:%d]","DVB",d+1,n+1);
- Add(new cScInfoItem(buffer,ks));
- free(ks);
- }
- n++;
- } while(ks);
- }
- if(Feature.KeyFile()) {
- Add(new cScInfoItem(tr("Key update status:")));
- int fk, nk;
- cSystem::KeyStats(fk,nk);
- // TRANSLATORS: 2 leading spaces!
- Add(new cScInfoItem(tr(" [Seen keys]"),fk));
- // TRANSLATORS: 2 leading spaces!
- Add(new cScInfoItem(tr(" [New keys]"), nk));
- }
- Display();
-}
-
-eOSState cMenuInfoSc::ProcessKey(eKeys Key)
-{
- eOSState state=cOsdMenu::ProcessKey(Key);
- if(state==osUnknown && Key==kOk) state=osBack;
- return state;
-}
-
-// --- cMenuInfoCard -----------------------------------------------------------
-
-class cMenuInfoCard : public cMenuText {
-private:
- int port;
- char infoStr[4096];
-public:
- cMenuInfoCard(int Port);
- virtual eOSState ProcessKey(eKeys Key);
- };
-
-cMenuInfoCard::cMenuInfoCard(int Port)
-:cMenuText(tr("Smartcard"),0,fontFix)
-{
- port=Port;
- smartcards.CardInfo(port,infoStr,sizeof(infoStr));
- SetText(infoStr);
- SetHelp(tr("Reset card"));
- Display();
-}
-
-eOSState cMenuInfoCard::ProcessKey(eKeys Key)
-{
- if(Key==kRed && Interface->Confirm(tr("Really reset card?"))) {
- smartcards.CardReset(port);
- return osEnd;
- }
- eOSState state=cMenuText::ProcessKey(Key);
- if(state==osUnknown) state=osContinue;
- return state;
-}
-
-// --- cLogOptItem -------------------------------------------------------------
-
-class cLogOptItem : public cMenuEditBoolItem {
-private:
- int o;
-public:
- cLogOptItem(const char *Name, int O, int *val);
- int Option(void) { return o; }
- };
-
-cLogOptItem::cLogOptItem(const char *Name, int O, int *val)
-:cMenuEditBoolItem(Name,val)
-{
- o=O;
-}
-
-// --- cMenuLogMod -------------------------------------------------------------
-
-class cMenuLogMod : public cOsdMenu {
-private:
- int m;
- int v[LOPT_NUM], cfg[LOPT_NUM];
- //
- void Store(void);
-public:
- cMenuLogMod(int M);
- virtual eOSState ProcessKey(eKeys Key);
- };
-
-cMenuLogMod::cMenuLogMod(int M)
-:cOsdMenu(tr("Module config"),33)
-{
- m=M;
- Add(new cOsdItem(tr("Reset module to default"),osUser9));
- const char *name=cLogging::GetModuleName(LCLASS(m,0));
- int o=cLogging::GetModuleOptions(LCLASS(m,0));
- if(o>=0) {
- for(int i=0; i<LOPT_NUM; i++) {
- const char *opt;
- if(i==0) opt="enable";
- else opt=cLogging::GetOptionName(LCLASS(m,1<<i));
- if(opt) {
- char buff[64];
- snprintf(buff,sizeof(buff),"%s.%s",name,opt);
- cfg[i]=(o&(1<<i)) ? 1:0;
- v[i]=1;
- Add(new cLogOptItem(buff,i,&cfg[i]));
- }
- else v[i]=0;
- }
- }
- Display();
-}
-
-void cMenuLogMod::Store(void)
-{
- int o=0;
- for(int i=0; i<LOPT_NUM; i++) if(v[i] && cfg[i]) o|=(1<<i);
- cLogging::SetModuleOptions(LCLASS(m,o));
- ScSetup.Store(false);
-}
-
-eOSState cMenuLogMod::ProcessKey(eKeys Key)
-{
- eOSState state=cOsdMenu::ProcessKey(Key);
- switch(state) {
- case osUser9:
- if(Interface->Confirm(tr("Really reset module to default?"))) {
- cLogging::SetModuleDefault(LCLASS(m,0));
- ScSetup.Store(false); state=osBack;
- }
- break;
-
- case osContinue:
- if(NORMALKEY(Key)==kLeft || NORMALKEY(Key)==kRight) {
- cLogOptItem *item=dynamic_cast<cLogOptItem *>(Get(Current()));
- if(item) {
- int o=item->Option();
- cLogging::SetModuleOption(LCLASS(m,1<<o),cfg[o]);
- }
- }
- break;
-
- case osUnknown:
- if(Key==kOk) { Store(); state=osBack; }
- break;
-
- default:
- break;
- }
- return state;
-}
-
-// --- cLogModItem -------------------------------------------------------------
-
-class cLogModItem : public cOsdItem {
-private:
- int m;
-public:
- cLogModItem(const char *Name, int M);
- int Module(void) { return m; }
- };
-
-cLogModItem::cLogModItem(const char *Name, int M)
-:cOsdItem(osUnknown)
-{
- m=M;
- char buf[64];
- snprintf(buf,sizeof(buf),"%s '%s'...",tr("Module"),Name);
- SetText(buf,true);
-}
-
-// --- cMenuLogSys -------------------------------------------------------------
-
-class cMenuLogSys : public cOsdMenu {
-private:
- void Store(void);
-public:
- cMenuLogSys(void);
- virtual eOSState ProcessKey(eKeys Key);
- };
-
-cMenuLogSys::cMenuLogSys(void)
-:cOsdMenu(tr("Message logging"),33)
-{
- LogOpts->Backup(); LogOpts->Create(this);
- Add(new cOsdItem(tr("Disable ALL modules"),osUser9));
- Add(new cOsdItem(tr("Reset ALL modules to default"),osUser8));
- for(int m=1; m<LMOD_MAX; m++) {
- const char *name=cLogging::GetModuleName(LCLASS(m,0));
- if(name)
- Add(new cLogModItem(name,m));
- }
- Display();
-}
-
-void cMenuLogSys::Store(void)
-{
- char *lf=strdup(logcfg.logFilename);
- ScSetup.Store(false);
- if(!lf || strcmp(lf,logcfg.logFilename))
- cLogging::ReopenLogfile();
- free(lf);
-}
-
-eOSState cMenuLogSys::ProcessKey(eKeys Key)
-{
- eOSState state=cOsdMenu::ProcessKey(Key);
- switch(state) {
- case osUser9:
- if(Interface->Confirm(tr("Really disable ALL modules?"))) {
- for(int m=1; m<LMOD_MAX; m++)
- cLogging::SetModuleOption(LCLASS(m,LMOD_ENABLE),false);
- Store(); state=osBack;
- }
- break;
-
- case osUser8:
- if(Interface->Confirm(tr("Really reset ALL modules to default?"))) {
- for(int m=1; m<LMOD_MAX; m++)
- cLogging::SetModuleDefault(LCLASS(m,0));
- Store(); state=osBack;
- }
- break;
-
- case osUnknown:
- if(Key==kOk) {
- cLogModItem *item=dynamic_cast<cLogModItem *>(Get(Current()));
- if(item) state=AddSubMenu(new cMenuLogMod(item->Module()));
- else { Store(); state=osBack; }
- }
- break;
-
- default:
- break;
- }
- return state;
-}
-
-// --- cMenuSysOpts -------------------------------------------------------------
-
-class cMenuSysOpts : public cOsdMenu {
-public:
- cMenuSysOpts(void);
- virtual eOSState ProcessKey(eKeys Key);
- };
-
-cMenuSysOpts::cMenuSysOpts(void)
-:cOsdMenu(tr("Cryptsystem options"),33)
-{
- for(cOpts *opts=0; (opts=cSystems::GetSystemOpts(opts==0));) {
- opts->Backup();
- opts->Create(this);
- }
- Display();
-}
-
-eOSState cMenuSysOpts::ProcessKey(eKeys Key)
-{
- eOSState state=cOsdMenu::ProcessKey(Key);
- switch(state) {
- case osContinue:
- if(NORMALKEY(Key)==kUp || NORMALKEY(Key)==kDown) {
- cOsdItem *item=Get(Current());
- if(item) item->ProcessKey(kNone);
- }
- break;
-
- case osUnknown:
- if(Key==kOk) { ScSetup.Store(false); state=osBack; }
- break;
-
- default:
- break;
- }
- return state;
-}
-
-// --- cMenuSetupSc ------------------------------------------------------------
-
-class cMenuSetupSc : public cMenuSetupPage {
-private:
- char *cfgdir;
-protected:
- virtual void Store(void);
-public:
- cMenuSetupSc(const char *CfgDir);
- virtual ~cMenuSetupSc();
- virtual eOSState ProcessKey(eKeys Key);
- };
-
-static eOSState portStates[] = { osUser1,osUser2,osUser3,osUser4 };
-#if MAX_PORTS!=4
-#error Update portStates[]
-#endif
-
-cMenuSetupSc::cMenuSetupSc(const char *CfgDir)
-{
- cfgdir=strdup(CfgDir);
- SetSection(tr("SoftCAM"));
-
- ScOpts->Backup(); LogOpts->Backup();
- for(cOpts *opts=0; (opts=cSystems::GetSystemOpts(opts==0));) opts->Backup();
-
- ScOpts->Create(this);
- Add(new cOsdItem(tr("Cryptsystem options..."),osUser5));
- Add(new cOsdItem(tr("Message logging..."),osUser6));
- if(Feature.SmartCard()) {
- char id[IDSTR_LEN];
- for(int i=0; smartcards.ListCard(i,id,sizeof(id)); i++) {
- char buff[32];
- snprintf(buff,sizeof(buff),"%s %d",tr("Smartcard interface"),i);
- if(id[0]) Add(new cScInfoItem(buff,id,portStates[i]));
- else Add(new cScInfoItem(buff,tr("(empty)")));
- }
- }
- Add(new cOsdItem(tr("Status information..."),osUser8));
- Add(new cOsdItem(tr("Flush ECM cache"),osUser7));
- Add(new cOsdItem(tr("Reload files"),osUser9));
-}
-
-cMenuSetupSc::~cMenuSetupSc()
-{
- free(cfgdir);
-}
-
-void cMenuSetupSc::Store(void)
-{
- ScSetup.Store(false);
-}
-
-eOSState cMenuSetupSc::ProcessKey(eKeys Key)
-{
- eOSState state = cOsdMenu::ProcessKey(Key);
- switch(state) {
- case osUser1...osUser4:
- if(Feature.SmartCard()) {
- for(unsigned int i=0; i<sizeof(portStates)/sizeof(eOSState); i++)
- if(portStates[i]==state) return(AddSubMenu(new cMenuInfoCard(i)));
- }
- state=osContinue;
- break;
-
- case osUser7:
- state=osContinue;
- if(Interface->Confirm(tr("Really flush ECM cache?"))) {
- ecmcache.Flush();
- state=osEnd;
- }
- break;
-
- case osUser8:
- return AddSubMenu(new cMenuInfoSc);
-
- case osUser6:
- return AddSubMenu(new cMenuLogSys);
-
- case osUser5:
- return AddSubMenu(new cMenuSysOpts);
-
- case osUser9:
- state=osContinue;
- if(!cSoftCAM::Active(true)) {
- if(Interface->Confirm(tr("Really reload files?"))) {
- Store();
- cSoftCAM::Load(cfgdir);
- state=osEnd;
- }
- }
- else
- Skins.Message(mtError,tr("Active! Can't reload files now"));
- break;
-
- case osContinue:
- if(NORMALKEY(Key)==kUp || NORMALKEY(Key)==kDown) {
- cOsdItem *item=Get(Current());
- if(item) item->ProcessKey(kNone);
- }
- break;
-
- case osUnknown:
- if(Key==kOk) { Store(); state=osBack; }
- break;
-
- default:
- break;
- }
- return state;
-}
-
-// --- cScSetup ---------------------------------------------------------------
-
-cScSetup ScSetup;
-
-cScSetup::cScSetup(void)
-{
- AutoUpdate=1;
- memset(ScCaps,0,sizeof(ScCaps));
- ScCaps[0]=1;
- ScCaps[1]=2;
- ConcurrentFF=0;
- memset(CaIgnore,0,sizeof(CaIgnore));
- LocalPriority=0;
- ForceTransfer=1;
- PrestartAU=0;
- SuperKeys=0;
-}
-
-void cScSetup::Check(void)
-{
- if(AutoUpdate==0)
- PRINTF(L_GEN_WARN,"Keys updates (AU) are disabled.");
- for(int i=0; i<MAXSCCAPS; i++)
- if(ScCaps[i]>=16) {
- PRINTF(L_GEN_WARN,"ScCaps contains unusual value. Check your config! (You can ignore this message if you have more than 16 dvb cards in your system ;)");
- break;
- }
-
- PRINTF(L_CORE_LOAD,"** Plugin config:");
- PRINTF(L_CORE_LOAD,"** Key updates (AU) are %s (%sprestart)",AutoUpdate?(AutoUpdate==1?"enabled (active CAIDs)":"enabled (all CAIDs)"):"DISABLED",PrestartAU?"":"no ");
- PRINTF(L_CORE_LOAD,"** Local systems %stake priority over cached remote",LocalPriority?"":"DON'T ");
- PRINTF(L_CORE_LOAD,"** Concurrent FF recordings are %sallowed",ConcurrentFF?"":"NOT ");
- PRINTF(L_CORE_LOAD,"** %sorce transfermode with digital audio",ForceTransfer?"F":"DON'T f");
- LBSTART(L_CORE_LOAD);
- LBPUT("** ScCaps are"); for(int i=0; i<MAXSCCAPS ; i++) LBPUT(" %d",ScCaps[i]);
- LBFLUSH();
- LBPUT("** Ignored CAIDs"); for(int i=0; i<MAXCAIGN ; i++) LBPUT(" %04X",CaIgnore[i]);
- LBEND();
-}
-
-void cScSetup::Store(bool AsIs)
-{
- if(ScOpts) ScOpts->Store(AsIs);
- cSystems::ConfigStore(AsIs);
- if(LogOpts) LogOpts->Store(AsIs);
- cLineBuff lb(128);
- if(cLogging::GetConfig(&lb))
- ScPlugin->SetupStore("LogConfig",lb.Line());
-}
-
-bool cScSetup::CapCheck(int n)
-{
- for(int j=0; j<MAXSCCAPS; j++)
- if(ScCaps[j] && ScCaps[j]==n+1) return true;
- return false;
-}
-
-bool cScSetup::Ignore(unsigned short caid)
-{
- for(int i=0; i<MAXCAIGN; i++)
- if(CaIgnore[i]==caid) return true;
- return false;
-}
-
-// --- cSoftCAM ---------------------------------------------------------------
-
-bool cSoftCAM::Load(const char *cfgdir)
-{
- if(!Feature.KeyFile()) keys.Disable();
- if(!Feature.SmartCard()) smartcards.Disable();
- cStructLoaders::Load(false);
- if(Feature.KeyFile() && keys.Count()<1)
- PRINTF(L_GEN_ERROR,"no keys loaded for softcam!");
- if(!cSystems::Init(cfgdir)) return false;
- return true;
-}
-
-void cSoftCAM::Shutdown(void)
-{
- cStructLoaders::Save(true);
- cSystems::Clean();
- smartcards.Shutdown();
- keys.Clear();
-}
-
-char *cSoftCAM::CurrKeyStr(int CardNum, int num)
-{
- cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(CardNum));
- char *str=0;
- if(dev) {
- if(dev->Cam()) str=dev->Cam()->CurrentKeyStr(num);
- if(!str && num==0 && ScSetup.CapCheck(CardNum)) str=strdup(tr("(none)"));
- }
- return str;
-}
-
-bool cSoftCAM::Active(bool log)
-{
- for(int n=cDevice::NumDevices(); --n>=0;) {
- cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(n));
- if(dev && dev->Cam() && dev->Cam()->Active(log)) return true;
- }
- return false;
-}
-
-void cSoftCAM::SetLogStatus(int CardNum, const cEcmInfo *ecm, bool on)
-{
- cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(CardNum));
- if(dev && dev->Cam()) dev->Cam()->LogEcmStatus(ecm,on);
-}
-
-void cSoftCAM::AddHook(int CardNum, cLogHook *hook)
-{
- cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(CardNum));
- if(dev && dev->Cam()) dev->Cam()->AddHook(hook);
-}
-
-bool cSoftCAM::TriggerHook(int CardNum, int id)
-{
- cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(CardNum));
- return dev && dev->Cam() && dev->Cam()->TriggerHook(id);
-}
-
-// --- cScHousekeeper ----------------------------------------------------------
-
-class cScHousekeeper : public cThread {
-protected:
- virtual void Action(void);
-public:
- cScHousekeeper(void);
- ~cScHousekeeper();
- };
-
-cScHousekeeper::cScHousekeeper(void)
-:cThread("SC housekeeper")
-{
- Start();
-}
-
-cScHousekeeper::~cScHousekeeper()
-{
- Cancel(3);
-}
-
-void cScHousekeeper::Action(void)
-{
- int c=0;
- while(Running()) {
- if(++c==20) {
- c=0;
- for(int n=cDevice::NumDevices(); --n>=0;) {
- cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(n));
- if(dev && dev->Cam()) dev->Cam()->HouseKeeping();
- }
- }
-
- if(Feature.KeyFile()) keys.HouseKeeping();
- if(!cSoftCAM::Active(false)) cStructLoaders::Purge();
- cStructLoaders::Load(true);
- cStructLoaders::Save();
-
- cCondWait::SleepMs(987);
- }
-}
-
-#ifndef STATICBUILD
-
-// --- cScDll ------------------------------------------------------------------
-
-class cScDll : public cSimpleItem {
-private:
- char *fileName;
- void *handle;
-public:
- cScDll(const char *FileName);
- ~cScDll();
- bool Load(void);
- };
-
-cScDll::cScDll(const char *FileName)
-{
- fileName=strdup(FileName);
- handle=0;
-}
-
-cScDll::~cScDll()
-{
- if(handle) dlclose(handle);
- free(fileName);
-}
-
-bool cScDll::Load(void)
-{
- char *base=rindex(fileName,'/');
- if(!base) base=fileName;
- PRINTF(L_CORE_DYN,"loading library: %s",base);
- if(!handle) {
- handle=dlopen(fileName,RTLD_NOW|RTLD_LOCAL);
- if(handle) return true;
- PRINTF(L_GEN_ERROR,"dload: %s: %s",base,dlerror());
- }
- return false;
-}
-
-// --- cScDlls -----------------------------------------------------------------
-
-#define LIBSC_PREFIX "libsc-"
-#define SO_INDICATOR ".so."
-
-class cScDlls : public cSimpleList<cScDll> {
-private:
- void *handle;
-public:
- cScDlls(void);
- ~cScDlls();
- bool Load(void);
- };
-
-cScDlls::cScDlls(void)
-{
- handle=0;
-}
-
-cScDlls::~cScDlls()
-{
- Clear();
- if(handle) dlclose(handle);
- PRINTF(L_CORE_DYN,"unload done");
-}
-
-bool cScDlls::Load(void)
-{
- Dl_info info;
- static int marker=0;
- if(!dladdr((void *)&marker,&info)) {
- PRINTF(L_GEN_ERROR,"dladdr: %s",dlerror());
- return false;
- }
-
- // we have to re-dlopen our selfs as VDR doesn't use RTLD_GLOBAL
- // but our symbols have to be available to the sub libs.
- handle=dlopen(info.dli_fname,RTLD_NOW|RTLD_GLOBAL);
- if(!handle) {
- PRINTF(L_GEN_ERROR,"dlopen myself: %s",dlerror());
- return false;
- }
-
- char *path=strdup(info.dli_fname);
- char *p;
- if((p=rindex(path,'/'))) *p=0;
- PRINTF(L_CORE_DYN,"library path %sn",path);
-
- char pat[32];
- snprintf(pat,sizeof(pat),"%s*-%d%s%s",LIBSC_PREFIX,SCAPIVERS,SO_INDICATOR,APIVERSION);
- bool res=true;
- cReadDir dir(path);
- struct dirent *e;
- while((e=dir.Next())) {
- if(!fnmatch(pat,e->d_name,FNM_PATHNAME|FNM_NOESCAPE)) {
- cScDll *dll=new cScDll(AddDirectory(path,e->d_name));
- if(dll) {
- if(!dll->Load()) res=false;
- Ins(dll);
- }
- }
- }
- free(path);
- return res;
-}
-
-#endif
-
-// --- cScPlugin ---------------------------------------------------------------
-
-class cScPlugin : public cPlugin {
-private:
-#ifndef STATICBUILD
- cScDlls dlls;
-#endif
- cScHousekeeper *keeper;
-public:
- cScPlugin(void);
- virtual ~cScPlugin();
- virtual const char *Version(void);
- virtual const char *Description(void);
- virtual const char *CommandLineHelp(void);
- virtual bool ProcessArgs(int argc, char *argv[]);
- virtual bool Initialize(void);
- virtual bool Start(void);
- virtual void Stop(void);
-#ifndef SASC
- virtual void MainThreadHook(void);
-#endif
- virtual cMenuSetupPage *SetupMenu(void);
- virtual bool SetupParse(const char *Name, const char *Value);
- virtual const char **SVDRPHelpPages(void);
- virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode);
- };
-
-cScPlugin::cScPlugin(void)
-{
- static const char *logg[] = { trNOOP("off"),trNOOP("active CAIDs"),trNOOP("all CAIDs") };
- static const char *skey[] = { trNOOP("comment out"),trNOOP("remove") };
- ScOpts=new cOpts(0,8);
- ScOpts->Add(new cOptSel ("AutoUpdate" ,trNOOP("Update keys (AU)") ,&ScSetup.AutoUpdate,3,logg));
- ScOpts->Add(new cOptBool ("PrestartAU" ,trNOOP("Start AU on EPG scan") ,&ScSetup.PrestartAU));
- ScOpts->Add(new cOptSel ("SuperKeys" ,trNOOP("Superseded keys") ,&ScSetup.SuperKeys,2,skey));
- ScOpts->Add(new cOptBool ("ConcurrentFF" ,trNOOP("Concurrent FF streams"),&ScSetup.ConcurrentFF));
- ScOpts->Add(new cOptBool ("ForceTranfer" ,trNOOP("Force TransferMode") ,&ScSetup.ForceTransfer));
- ScOpts->Add(new cOptBool ("LocalPriority",trNOOP("Prefer local systems") ,&ScSetup.LocalPriority));
- ScOpts->Add(new cOptMInt ("ScCaps" ,trNOOP("Active on DVB card") , ScSetup.ScCaps,MAXSCCAPS,0));
- ScOpts->Add(new cOptMInt ("CaIgnore" ,trNOOP("Ignore CAID") , ScSetup.CaIgnore,MAXCAIGN,2));
- LogOpts=new cOpts(0,6);
- LogOpts->Add(new cOptBool ("LogConsole" ,trNOOP("Log to console") ,&logcfg.logCon));
- LogOpts->Add(new cOptBool ("LogFile" ,trNOOP("Log to file") ,&logcfg.logFile));
- LogOpts->Add(new cOptStr ("LogFileName" ,trNOOP("Filename") ,logcfg.logFilename,sizeof(logcfg.logFilename),FileNameChars));
- LogOpts->Add(new cOptInt ("LogFileLimit",trNOOP("Filesize limit (KB)") ,&logcfg.maxFilesize,0,2000000));
- LogOpts->Add(new cOptBool ("LogSyslog" ,trNOOP("Log to syslog") ,&logcfg.logSys));
- LogOpts->Add(new cOptBool ("LogUserMsg" ,trNOOP("Show user messages") ,&logcfg.logUser));
-#ifndef STATICBUILD
- dlls.Load();
-#endif
- cScDvbDevice::Capture();
- keeper=0;
-}
-
-cScPlugin::~cScPlugin()
-{
- delete keeper;
- delete ScOpts;
- delete LogOpts;
-}
-
-bool cScPlugin::Initialize(void)
-{
- PRINTF(L_GEN_INFO,"SC version %s initializing",ScVersion);
- return cScDvbDevice::Initialize();
-}
-
-bool cScPlugin::Start(void)
-{
- PRINTF(L_GEN_INFO,"SC version %s starting",ScVersion);
- if(APIVERSNUM<MINAPIVERSNUM) {
- PRINTF(L_GEN_ERROR,"SC plugin needs at least VDR API version %d.%d.%d",MIN_VERS,MIN_MAJOR,MIN_MINOR);
- return false;
- }
- if(sizeof(int)!=4) {
- PRINTF(L_GEN_ERROR,"compiled with 'int' as %d bit. Only supporting 32 bit.",(int)sizeof(int)*8);
- return false;
- }
- if(sizeof(long long)!=8) {
- PRINTF(L_GEN_ERROR,"compiled with 'long long' as %d bit. Only supporting 64 bit.",(int)sizeof(long long)*8);
- return false;
- }
-
- ScPlugin=this;
-#if APIVERSNUM < 10507
- RegisterI18n(ScPhrases);
-#endif
- const char *cfgdir=ConfigDirectory(cfgsub);
- filemaps.SetCfgDir(cfgdir);
- cStructLoaders::SetCfgDir(cfgdir);
- ScSetup.Check();
- if(!cSoftCAM::Load(cfgdir)) return false;
- if(Feature.SmartCard()) {
-#ifdef DEFAULT_PORT
- smartcards.AddPort(DEFAULT_PORT);
-#endif
- smartcards.LaunchWatcher();
- }
- cScDvbDevice::Startup();
- keeper=new cScHousekeeper;
- return true;
-}
-
-void cScPlugin::Stop(void)
-{
- delete keeper; keeper=0;
- cScDvbDevice::Shutdown();
- LogStatsDown();
- cSoftCAM::Shutdown();
-#if APIVERSNUM < 10507
- RegisterI18n(NULL);
-#endif
- PRINTF(L_GEN_DEBUG,"SC cleanup done");
-}
-
-const char *cScPlugin::Version(void)
-{
- return ScVersion;
-}
-
-const char *cScPlugin::Description(void)
-{
- return tr("A software emulated CAM");
-}
-
-const char *cScPlugin::CommandLineHelp(void)
-{
- static char *help_str=0;
-
- free(help_str); // for easier orientation, this is column 80|
- asprintf(&help_str," -B N --budget=N forces DVB device N to budget mode (using FFdecsa)\n"
- " -I --inverse-cd use inverse CD detection for the next serial device\n"
- " -R --inverse-rst use inverse RESET for the next serial device\n"
- " -C FREQ --clock=FREQ use FREQ as clock for the card reader on the next\n"
- " serial device (rather than 3.5712 MHz\n"
- " -m MODE --mode=MODE cardreader mode for the next serial device:\n"
- " phoenix|smartreader\n"
- " (default: phoenix)\n"
- " -s DEV --serial=DEV activate Phoenix ISO interface on serial device DEV\n"
- " (default: %s)\n"
- " -d CMD --dialup=CMD call CMD to start/stop dialup-network\n"
- " (default: %s)\n"
- " -t SECS --timeout=SECS shutdown timeout for dialup-network\n"
- " (default: %d secs)\n",
- "none","none",netTimeout/1000
- );
- return help_str;
-}
-
-bool cScPlugin::ProcessArgs(int argc, char *argv[])
-{
- static struct option long_options[] = {
- { "serial", required_argument, NULL, 's' },
- { "mode", required_argument, NULL, 'm' },
- { "inverse-cd", no_argument, NULL, 'I' },
- { "inverse-rst", no_argument, NULL, 'R' },
- { "clock", required_argument, NULL, 'C' },
- { "dialup", required_argument, NULL, 'd' },
- { "external-au", required_argument, NULL, 'E' },
- { "budget", required_argument, NULL, 'B' },
- { NULL }
- };
-
- int c, option_index=0;
- bool invCD=false, invRST=false;
- int clock=0;
- char* mode=NULL;
- while((c=getopt_long(argc,argv,"d:m:s:t:B:C:E:IR",long_options,&option_index))!=-1) {
- switch (c) {
- case 'I': invCD=true; break;
- case 'R': invRST=true; break;
- case 'C': clock=atoi(optarg); break;
- case 'm': free(mode); mode=strdup(optarg); break;
- case 's': smartcards.AddPort(optarg,mode,invCD,invRST,clock); free(mode); mode=NULL; invCD=false; invRST=false; clock=0; break;
- case 'd': netscript=optarg; break;
- case 't': netTimeout=atoi(optarg)*1000; break;
- case 'E': externalAU=optarg; break;
- case 'B': cScDvbDevice::SetForceBudget(atoi(optarg)); break;
- default: free(mode); return false;
- }
- }
- free(mode);
- return true;
-}
-
-cMenuSetupPage *cScPlugin::SetupMenu(void)
-{
- return new cMenuSetupSc(ConfigDirectory(cfgsub));
-}
-
-bool cScPlugin::SetupParse(const char *Name, const char *Value)
-{
- if((ScOpts && ScOpts->Parse(Name,Value)) ||
- (LogOpts && LogOpts->Parse(Name,Value)) ||
- cSystems::ConfigParse(Name,Value)) ;
- else if(!strcasecmp(Name,"LogConfig")) cLogging::ParseConfig(Value);
- else return false;
- return true;
-}
-
-#ifndef SASC
-
-void cScPlugin::MainThreadHook(void)
-{
- int n=0;
- cUserMsg *um;
- while(++n<=10 && (um=ums.GetQueuedMsg())) {
- Skins.QueueMessage(mtInfo,um->Message());
- delete um;
- }
-}
-
-#endif //SASC
-
-const char **cScPlugin::SVDRPHelpPages(void)
-{
- static const char *HelpPages[] = {
- "RELOAD\n"
- " Reload all configuration files.",
- "KEY <string>\n",
- " Add key to the key database (as if it was received from EMM stream).",
- "LOG <on|off> <class>[,<class>...]\n"
- " Turn the given message class(es) on or off.",
- "LOGCFG\n"
- " Display available message classes and their status.",
- "LOGFILE <on|off> [<filename>]\n"
- " Enables/disables logging to file and optionaly sets the filename.",
- NULL
- };
- return HelpPages;
-}
-
-cString cScPlugin::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode)
-{
- if(!strcasecmp(Command,"RELOAD")) {
- if(cSoftCAM::Active(true)) {
- ReplyCode=550;
- return "Softcam active. Can't reload files now";
- }
- else {
- if(cSoftCAM::Load(ConfigDirectory(cfgsub)))
- return "Files reloaded successfully";
- else {
- ReplyCode=901;
- return "Reloading files not entirely successfull";
- }
- }
- }
- else if(!strcasecmp(Command,"KEY")) {
- if(Option && *Option) {
- if(keys.NewKeyParse(skipspace(Option),"from SVDR"))
- return "Key update successfull";
- else {
- ReplyCode=901;
- return "Key already known or invalid key format";
- }
- }
- else { ReplyCode=501; return "Missing args"; }
- }
- else if(!strcasecmp(Command,"LOG")) {
- if(Option && *Option) {
- char tmp[1024];
- strn0cpy(tmp,Option,sizeof(tmp));
- char *opt=tmp;
- opt=skipspace(opt);
- bool mode;
- if(!strncasecmp(opt,"ON ",3)) { mode=true; opt+=3; }
- else if(!strncasecmp(opt,"OFF ",4)) { mode=false; opt+=4; }
- else { ReplyCode=501; return "Bad mode, valid: on off"; }
- do {
- char *s=index(opt,',');
- if(s) *s++=0;
- int c=cLogging::GetClassByName(opt);
- if(c>=0) cLogging::SetModuleOption(c,mode);
- else { ReplyCode=501; return "Unknown message class"; }
- opt=s;
- } while(opt);
- ScSetup.Store(true);
- Setup.Save();
- return "Done";
- }
- else { ReplyCode=501; return "Missing args"; }
- }
- else if(!strcasecmp(Command,"LOGCFG")) {
- cLineBuff lb(256);
- for(int m=1; m<LMOD_MAX; m++) {
- const char *name=cLogging::GetModuleName(LCLASS(m,0));
- if(name) {
- int o=cLogging::GetModuleOptions(LCLASS(m,0));
- if(o>=0) {
- for(int i=0; i<LOPT_NUM; i++) {
- const char *opt;
- if(i==0) opt="enable";
- else opt=cLogging::GetOptionName(LCLASS(m,1<<i));
- if(opt)
- lb.Printf("%s.%s %s\n",name,opt,(o&(1<<i))?"on":"off");
- }
- }
- }
- }
- if(lb.Length()>0) return lb.Line();
- ReplyCode=901; return "No config available";
- }
- else if(!strcasecmp(Command,"LOGFILE")){
- if(Option && *Option) {
- char tmp[1024];
- strn0cpy(tmp,Option,sizeof(tmp));
- char *opt=tmp;
- opt=skipspace(opt);
- bool mode;
- if(!strncasecmp(opt,"ON",2)) { mode=true; opt+=2; }
- else if(!strncasecmp(opt,"OFF",3)) { mode=false; opt+=3; }
- else { ReplyCode=501; return "Bad mode, valid: on off"; }
- cLineBuff lb(256);
- if(mode) {
- logcfg.logFile=true;
- if(*opt==' ' || *opt=='\t') {
- opt=stripspace(skipspace(opt));
- strn0cpy(logcfg.logFilename,opt,sizeof(logcfg.logFilename));
- }
- lb.Printf("logging to file enabled, file %s",logcfg.logFilename);
- }
- else {
- logcfg.logFile=false;
- lb.Printf("logging to file disabled");
- }
- ScSetup.Store(true);
- Setup.Save();
- return lb.Line();
- }
- else { ReplyCode=501; return "Missing args"; }
- }
- return NULL;
-}
-
-VDRPLUGINCREATOR(cScPlugin); // Don't touch this!
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___SC_H
-#define ___SC_H
-
-class cEcmInfo;
-class cLogHook;
-
-// ----------------------------------------------------------------
-
-class cSoftCAM {
-public:
- static bool Load(const char *cfgdir);
- static void Shutdown(void);
- //
- static bool Active(bool log);
- static char *CurrKeyStr(int CardNum, int num);
- static void SetLogStatus(int CardNum, const cEcmInfo *ecm, bool on);
- static void AddHook(int CardNum, cLogHook *hook);
- static bool TriggerHook(int CardNum, int id);
- };
-
-#endif // ___SC_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___SC_SETUP_H
-#define ___SC_SETUP_H
-
-#define MAXSCCAPS 10
-#define MAXCAIGN 16
-
-// ----------------------------------------------------------------
-
-class cScSetup {
-public:
- int AutoUpdate;
- int ScCaps[MAXSCCAPS];
- int ConcurrentFF;
- int CaIgnore[MAXCAIGN];
- int LocalPriority;
- int ForceTransfer;
- int PrestartAU;
- int SuperKeys;
-public:
- cScSetup(void);
- void Check(void);
- void Store(bool AsIs);
- bool CapCheck(int n);
- bool Ignore(unsigned short caid);
- };
-
-extern cScSetup ScSetup;
-
-#endif
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/poll.h>
-#include <unistd.h>
-#include <termios.h>
-#include <linux/serial.h>
-#include <ctype.h>
-
-#include <vdr/tools.h>
-#include <vdr/thread.h>
-
-#include "smartcard.h"
-#include "misc.h"
-#include "log-core.h"
-
-#define DATAFILE "smartcard.conf"
-#define ISO_FREQ 3571200 // Hz
-
-//#define SER_EMU // use serial emulation (select one of the following)
-//#define EMU_SECA // fake Seca card
-//#define EMU_IRD // fake Irdeto/Beta card
-//#define EMU_IRD_384 // fake ACS 384, if undefined ACS 383
-//#define EMU_CRYPTO // fake Cryptoworks card
-//#define NO_PTS_PROTO // disable PTS protocol (baudrate changes)
-
-struct BaudRates {
- int real;
- speed_t apival;
- };
-
-static const struct BaudRates BaudRateTab[] = {
- { 9600, B9600 },
- { 19200, B19200 },
- { 38400, B38400 },
- { 57600, B57600 },
- { 115200, B115200 },
- { 230400, B230400 }
- };
-
-// -- cSerial ------------------------------------------------------------------
-
-class cSerial {
-private:
- char *devName;
- int devType;
- int fd;
- int currMode, statInv;
- bool invRST;
- //
- speed_t FindBaud(int baud);
-#ifdef SER_EMU
- unsigned char devBuff[1024], nextSW[SB_LEN];
- int buffCount, dataLen, record;
- bool cmdStart, rts, dsr, flag;
- int remTime;
-#endif
-public:
- cSerial(const char *DevName, int DevType, bool invCD, bool InvRST);
- ~cSerial();
- bool Open(void);
- bool SetMode(int mode, int baud=9600);
- int CurrentMode(void) const { return currMode; }
- void Flush(void);
- int Read(unsigned char *mem, int len, int timeout, int initialTimeout=0);
- int Write(const unsigned char *mem, int len, int delay=0);
- void ToggleRTS(void);
- bool CheckCAR(void);
- void Close(void);
- const char *DeviceName(void) const { return devName; }
- int DeviceType(void) const { return devType; }
- bool ConfigSmartReader(int F, int D, int fs, int N, int T, int inv);
- };
-
-cSerial::cSerial(const char *DevName, int DevType, bool invCD, bool InvRST)
-{
- devName=strdup(DevName);
- devType=DevType;
- statInv=invCD ? TIOCM_CAR:0;
- invRST=InvRST;
- fd=-1; currMode=SM_NONE;
-}
-
-cSerial::~cSerial()
-{
- Close();
- free(devName);
-}
-
-#ifndef SER_EMU
-
-bool cSerial::Open(void)
-{
- PRINTF(L_CORE_SERIAL,"%s: open serial port",devName);
- fd=open(devName,O_RDWR|O_NONBLOCK|O_NOCTTY);
- if(fd>=0) {
- PRINTF(L_CORE_SERIAL,"%s: set DTR/RTS",devName);
- unsigned int modembits;
- modembits=TIOCM_DTR; CHECK(ioctl(fd, TIOCMBIS, &modembits));
- modembits=TIOCM_RTS; CHECK(ioctl(fd, invRST?TIOCMBIS:TIOCMBIC, &modembits));
- PRINTF(L_CORE_SERIAL,"%s: init done",devName);
- return true;
- }
- else PRINTF(L_GEN_ERROR,"%s: open failed: %s",devName,strerror(errno));
- return false;
-}
-
-void cSerial::Close(void)
-{
- if(fd>=0) {
- PRINTF(L_CORE_SERIAL,"%s: shutting down",devName);
- Flush();
- unsigned int modembits=0;
- CHECK(ioctl(fd,TIOCMSET,&modembits));
- close(fd); fd=-1;
- PRINTF(L_CORE_SERIAL,"%s: shutdown done",devName);
- }
-}
-
-bool cSerial::ConfigSmartReader(int F, int D, int fs, int N, int T, int inv)
-{
- // Convert fs to kHz.
- fs/=1000;
-
- PRINTF(L_CORE_SERIAL,
- "%s: set SmartReader+ options: F=%d, D=%d, fs=%d, N=%d, T=%d, inv=%d",
- devName,F,D,fs,N,T,inv);
-
- // Set SmartReader+ in CMD mode.
- struct termios term;
- if(tcgetattr(fd,&term)==-1) {
- PRINTF(L_GEN_ERROR,"%s: tcgetattr failed: %s",devName,strerror(errno));
- return false;
- }
- term.c_cflag&=~CSIZE;
- term.c_cflag|=CS5;
- if(tcsetattr(fd,TCSADRAIN,&term)==-1) {
- PRINTF(L_GEN_ERROR,"%s: tcsetattr failed: %s",devName,strerror(errno));
- return false;
- }
-
- // Write SmartReader+ configuration commands.
- // Each command must be written with a separate write.
- unsigned char cmd[] =
- {
- 4,1,F>>8,F&0xff,D,
- 3,2,fs>>8,fs&0xff,
- 2,3,N,
- 2,4,T,
- 2,5,inv
- };
-
- unsigned int i=0;
- while(i<sizeof(cmd)) {
- int len=cmd[i++];
- if(Write(cmd+i,len)!=len) {
- return false;
- }
- i+=len;
- }
-
- // Send zero bits for 0.25 - 0.5 seconds.
- if(tcsendbreak(fd,0)==-1) {
- PRINTF(L_GEN_ERROR,"%s: tcsendbreak failed: %s",devName,strerror(errno));
- return false;
- }
-
- // Set SmartReader+ in DATA mode.
- term.c_cflag&=~CSIZE;
- term.c_cflag|=CS8;
- if(tcsetattr(fd,TCSADRAIN,&term)==-1) {
- PRINTF(L_GEN_ERROR,"%s: tcsetattr failed: %s",devName,strerror(errno));
- return false;
- }
-
- return true;
-}
-
-speed_t cSerial::FindBaud(int baud)
-{
- for(int i=0; i<(int)(sizeof(BaudRateTab)/sizeof(struct BaudRates)); i++) {
- int b=BaudRateTab[i].real;
- int d=((b-baud)*10000)/b;
- if(abs(d)<=300) {
- PRINTF(L_CORE_SERIAL,"%s: requested baudrate %d -> %d (%+.2f%%)",devName,baud,b,(float)d/100.0);
- return BaudRateTab[i].apival;
- }
- }
- PRINTF(L_CORE_SERIAL,"%s: requested baudrate %d -> custom",devName,baud);
- return B0;
-}
-
-bool cSerial::SetMode(int mode, int baud)
-{
- if(fd>=0) {
- speed_t bconst=FindBaud(baud);
- bool custom=false;
- if(bconst==B0) { custom=true; bconst=B38400; }
-
- struct termios tio;
- memset(&tio,0,sizeof(tio));
- LBSTARTF(L_CORE_SERIAL);
- LBPUT("%s: set serial options: %d,",devName,baud);
- tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL);
- if(!(mode&SM_1SB)) tio.c_cflag |= CSTOPB;
- tio.c_iflag = (INPCK | BRKINT);
- tio.c_cc[VMIN] = 1;
- cfsetispeed(&tio,bconst);
- cfsetospeed(&tio,bconst);
- switch(mode&SM_MASK) {
- case SM_8E2:
- LBPUT("8e%d",(mode&SM_1SB)?1:2);
- tio.c_cflag |= PARENB; break;
- case SM_8N2:
- LBPUT("8n%d",(mode&SM_1SB)?1:2);
- break;
- case SM_8O2:
- LBPUT("8o%d",(mode&SM_1SB)?1:2);
- tio.c_cflag |= (PARENB | PARODD); break;
- default:
- LBPUT("BAD MODE");
- return false;
- }
- LBEND();
-
- struct serial_struct s;
- if(ioctl(fd,TIOCGSERIAL,&s)<0) {
- PRINTF(L_GEN_ERROR,"%s: get serial failed: %s",devName,strerror(errno));
- return false;
- }
- if(!custom && ((s.flags&ASYNC_SPD_MASK)==ASYNC_SPD_CUST || s.custom_divisor!=0)) {
- s.custom_divisor=0;
- s.flags &= ~ASYNC_SPD_MASK;
- if(ioctl(fd,TIOCSSERIAL,&s)<0) {
- PRINTF(L_GEN_ERROR,"%s: set serial failed: %s",devName,strerror(errno));
- return false;
- }
- }
- if(!tcsetattr(fd,TCSANOW,&tio)) {
- if(custom) {
- s.custom_divisor=(s.baud_base+(baud/2))/baud;
- s.flags=(s.flags&~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
- PRINTF(L_CORE_SERIAL,"%s: custom: baud_base=%d baud=%d devisor=%d -> effective baudrate %d (%+.2f%% off)",devName,s.baud_base,baud,s.custom_divisor,s.baud_base/s.custom_divisor,(float)(s.baud_base/s.custom_divisor-baud)/(float)baud);
- if(ioctl(fd,TIOCSSERIAL,&s)<0) {
- PRINTF(L_GEN_ERROR,"%s: set serial failed: %s",devName,strerror(errno));
- return false;
- }
- }
- currMode=mode; Flush();
- return true;
- }
- else PRINTF(L_GEN_ERROR,"%s: tcsetattr failed: %s",devName,strerror(errno));
- }
- return false;
-}
-
-void cSerial::Flush(void)
-{
- if(fd>=0)
- CHECK(tcflush(fd,TCIOFLUSH));
-}
-
-int cSerial::Read(unsigned char *mem, int len, int timeout, int initialTimeout)
-{
- PRINTF(L_CORE_SERIAL,"%s: read len=%d timeout=%d:%d",devName,len,timeout,initialTimeout);
- bool incomplete=false;
- if(len<0) { len=-len; incomplete=true; }
- int to=initialTimeout>0 ? initialTimeout : timeout;
- int n=0;
- while(n<len) {
- int r=read(fd,mem+n,len-n);
- if(r<=0) {
- if(r==0) PRINTF(L_CORE_SERIAL,"%s: read bogus eof",devName);
- if(errno==EAGAIN) {
- struct pollfd u;
- u.fd=fd; u.events=POLLIN;
- r=poll(&u,1,to);
- if(r<0) {
- PRINTF(L_GEN_ERROR,"%s: read poll failed: %s",devName,strerror(errno));
- return -1;
- }
- else if(r==0) { // timeout
- PRINTF(L_CORE_SERIAL,"%s: read timeout (%d ms)",devName,to);
- if(n>0 && incomplete) break; // return bytes read so far
- return -2;
- }
- continue;
- }
- else {
- PRINTF(L_GEN_ERROR,"%s: read failed: %s",devName,strerror(errno));
- return -1;
- }
- }
- n+=r; to=timeout;
- }
- HEXDUMP(L_CORE_SERIAL,mem,n,"%s: read data",devName);
- return n;
-}
-
-int cSerial::Write(const unsigned char *mem, int len, int delay)
-{
- PRINTF(L_CORE_SERIAL,"%s: write len=%d delay=%d",devName,len,delay);
- HEXDUMP(L_CORE_SERIAL,mem,len,"%s: write data",devName);
- Flush();
- int n=0;
- while(n<len) {
- struct pollfd u;
- u.fd=fd; u.events=POLLOUT;
- int r;
- do {
- r=poll(&u,1,500);
- if(r<0) {
- PRINTF(L_GEN_ERROR,"%s: write poll failed: %s",devName,strerror(errno));
- return -1;
- }
- else if(r==0) { // timeout
- PRINTF(L_CORE_SERIAL,"%s: write timeout",devName);
- return -2;
- }
- } while(r<1);
- r=write(fd,mem+n,delay>0?1:len-n);
- if(r<0 && errno!=EAGAIN) {
- PRINTF(L_GEN_ERROR,"%s: write failed: %s",devName,strerror(errno));
- return -1;
- }
- if(r>0) n+=r;
- if(delay>0) cCondWait::SleepMs(delay);
- }
- return n;
-}
-
-void cSerial::ToggleRTS(void)
-{
- int mask=0;
- if(ioctl(fd,TIOCMGET,&mask)<0) { LOG_ERROR; return; }
- if(mask&TIOCM_RTS) { mask&=~TIOCM_RTS; PRINTF(L_CORE_SERIAL,"%s: toggle RTS, now off",devName); }
- else { mask|= TIOCM_RTS; PRINTF(L_CORE_SERIAL,"%s: toggle RTS, now on",devName); }
- CHECK(ioctl(fd,TIOCMSET,&mask));
- Flush();
-}
-
-bool cSerial::CheckCAR(void)
-{
- int status=0;
- if(ioctl(fd,TIOCMGET,&status)<0) { LOG_ERROR; return false; }
- PRINTF(L_CORE_SERIAL,"%s: CAR is %sactive (lines:%s%s%s%s%s%s%s%s%s)",
- devName,(status&TIOCM_CAR)?"in":"",
- (status&TIOCM_LE)?" LE":"", (status&TIOCM_DTR)?" DTR":"",
- (status&TIOCM_RTS)?" RTS":"",(status&TIOCM_ST)?" ST":"",
- (status&TIOCM_SR)?" SR":"", (status&TIOCM_CTS)?" CTS":"",
- (status&TIOCM_CAR)?" CAR":"",(status&TIOCM_RNG)?" RNG":"",
- (status&TIOCM_DSR)?" DSR":"" );
- status^=statInv; // invert status for broken cardreaders
- return !(status & TIOCM_CAR);
-}
-
-#else //SER_EMU
-
-//
-// emulator for a serial phoenix interface
-// (activate in smartcard.h)
-//
-
-bool cSerial::Open(void)
-{
- PRINTF(L_CORE_SERIAL,"serial: open serial port %s (emulator)",devName);
- PRINTF(L_CORE_SERIAL,"serial: init done");
- fd=1; buffCount=0; cmdStart=true; rts=false; flag=false;
- remTime=time(0); dsr=true;
- return true;
-}
-
-void cSerial::Close(void)
-{
- if(fd>=0) {
- PRINTF(L_CORE_SERIAL,"serial: shutting down ... ");
- fd=-1;
- PRINTF(L_CORE_SERIAL,"done");
- }
-}
-
-speed_t cSerial::FindBaud(int baud)
-{
- return B0;
-}
-
-bool cSerial::SetMode(int mode, int baud)
-{
- currMode=mode;
- Flush();
- return true;
-}
-
-void cSerial::Flush(void)
-{
- buffCount=0;
-}
-
-#define PUSH(mem,len) { memcpy(devBuff+buffCount,(mem),(len)); buffCount+=(len); }
-#define PUSHB(b) { devBuff[buffCount++]=(b); }
-
-int cSerial::Read(unsigned char *mem, int len, int timeout, int initialTimeout)
-{
- PRINTF(L_CORE_SERIAL,"serial: read len=%d timeout=%d",len,timeout);
- if(len<0) {
- len=-len;
- if(buffCount<len) len=buffCount;
- }
- if(buffCount<len) return -2; // timeout
- memcpy(mem,devBuff,len);
- memmove(devBuff,devBuff+len,buffCount-len);
- buffCount-=len;
- return len;
-}
-
-int cSerial::Write(const unsigned char *mem, int len, int delay)
-{
- PRINTF(L_CORE_SERIAL,"serial: write len=%d delay=%d",len,delay);
- Flush();
- cCondWait::SleepMs(300);
- PUSH(mem,len); // echo back
-#if defined(EMU_SECA)
- if(cmdStart && len==CMD_LEN) { // new INS
- PUSHB(mem[INS_IDX]); // ACK byte
- cmdStart=false;
- dataLen=mem[LEN_IDX];
- unsigned char data[256];
- memset(data,0,sizeof(data));
- nextSW[0]=0x90; nextSW[1]=0x00;
- bool readcmd=false;
- switch(mem[0]*256+mem[1]) {
- case 0xc13a:
- case 0xc10e:
- readcmd=true;
- break;
- case 0xc116:
- data[3]=0x04;
- readcmd=true;
- break;
- case 0xc112:
- data[1]=0x64;
- data[22]=0x1d; data[23]=0x84;
- readcmd=true;
- break;
- case 0xc132:
- data[1]=0xFF; data[2]=0xFF; data[3]=0xFF; data[4]=0xFF;
- data[5]=0xFF; data[6]=0xFF; data[7]=0xFF; data[8]=0xFF;
- readcmd=true;
- break;
- }
- if(readcmd) {
- PUSH(data,dataLen);
- PUSH(nextSW,2);
- cmdStart=true;
- }
- }
- else {
- dataLen-=len;
- if(dataLen<=0 && !cmdStart) {
- PUSH(nextSW,2);
- cmdStart=true;
- }
- }
-#elif defined(EMU_CRYPTO)
- if(cmdStart && len==CMD_LEN) { // new INS
- cmdStart=false;
- dataLen=mem[LEN_IDX];
- unsigned char data[256];
- memset(data,0,sizeof(data));
- nextSW[0]=0x90; nextSW[1]=0x00;
- bool readcmd=false;
- switch(mem[0]*256+mem[1]) {
- case 0xa4a4:
- switch(mem[5]*256+mem[6]) {
- case 0x2f01:
- case 0x0f00:
- case 0x0f20:
- //case 0x0f40:
- case 0x0f60:
- case 0x0e11:
- case 0x1f88:
- case 0x1f8c: nextSW[0]=0x9f; nextSW[1]=0x11; break;
- default: nextSW[0]=0x94; nextSW[1]=0x04; break;
- }
- break;
- case 0xa4a2:
- if(mem[2]==1) {
- if(mem[4]==3) {
- record=0x01;
- nextSW[0]=0x9f; nextSW[1]=0x26;
- }
- else {
- record=0x02;
- nextSW[0]=0x9f; nextSW[1]=0x42;
- }
- }
- else {
- record=mem[5];
- switch(record) {
- case 0x80: nextSW[0]=0x9f; nextSW[1]=0x07; break;
- case 0xD1: nextSW[0]=0x9f; nextSW[1]=0x04; break;
- case 0x9F: nextSW[0]=0x9f; nextSW[1]=0x03; break;
- case 0x9E: nextSW[0]=0x9f; nextSW[1]=0x42; break;
- case 0xD6:
- case 0xC0: nextSW[0]=0x9f; nextSW[1]=0x12; break;
- default: nextSW[0]=0x94; nextSW[1]=0x02; break;
- }
- }
- break;
- case 0xa4b2:
- readcmd=true;
- switch(record) {
- case 0x01:
- if(mem[3]==1) {
- nextSW[0]=0x94; nextSW[1]=0x02;
- dataLen=0;
- }
- else {
- dataLen=0x26;
- static const unsigned char resp[0x26] = {
- 0x83,0x01,0x88,
- 0x8c,0x03,0x40,0x30,0x40,
- 0x8d,0x04,0x16,0xac,0x16,0xba,
- 0xd5,0x10,'D','u','m','m','y',0,0,0,0,0,0,0,0x12,0x34,0x56,0x67,
- 0x8f,0x01,0x55,
- 0x91,0x01,0x40
- };
- memcpy(data,resp,sizeof(resp));
- }
- break;
- case 0x02:
- if(mem[3]==1) {
- nextSW[0]=0x94; nextSW[1]=0x02;
- dataLen=0;
- }
- else {
- dataLen=0x42;
- static const unsigned char resp[0x42] = {
- 0x83,0x01,0x88,
- 0x8c,0x03,0xA0,0x30,0x40,
- 0x8d,0x04,0x16,0xac,0x16,0xba,
- 0xd5,0x10,'D','u','m','m','y',0,0,0,0,0,0,0,0x12,0x34,0x56,0x67,
- 0x92,0x20,0x00 // ...
- };
- memcpy(data,resp,sizeof(resp));
- }
- break;
- case 0x80:
- dataLen=0x07;
- data[0]=0x80;
- data[1]=0x05;
- data[2]=0x5c;
- data[3]=0x0c;
- data[4]=0x00;
- data[5]=0xec;
- data[6]=0x0a;
- break;
- case 0xD1:
- dataLen=0x04;
- data[0]=0xd1;
- data[1]=0x02;
- data[2]=0x0d;
- data[3]=0x22;
- break;
- case 0x9F:
- dataLen=0x03;
- data[0]=0x9f;
- data[1]=0x01;
- data[2]=0x88;
- break;
- case 0x9E:
- {
- dataLen=0x42;
- static const unsigned char resp[0x42] = {
- 0x9E,0x40,
- 0x28,0xFE, /// ...
- };
- memcpy(data,resp,sizeof(resp));
- flag=true;
- break;
- }
- case 0xC0:
- case 0xD6:
- dataLen=0x12;
- data[0]=record;
- data[1]=0x10;
- memset(data+2,0,16);
- strcpy((char *)data+2,"Dum Issuer");
- break;
- }
- break;
- case 0xa4b8:
- readcmd=true;
- if(mem[2]==0) {
- dataLen=0x0C;
- memset(data,0,0x0c);
- data[0]=0xDF;
- data[1]=0x0A;
- data[4]=0xDF;
- data[5]=0x88;
- }
- else {
- dataLen=0;
- nextSW[0]=0x94; nextSW[1]=0x02;
- }
- break;
- case 0xa44c:
- nextSW[0]=0x9f; nextSW[1]=flag ? 0x42 : 0x1c;
- break;
- case 0xa4c0:
- readcmd=true;
- if(mem[4]==0x1c) {
- data[0]=0xdb;
- data[1]=0x10;
- memset(&data[2],0x45,16);
- data[18]=0xdf;
- data[19]=0x08;
- data[20]=0x50;
- data[23]=0x80;
- }
- else if(mem[4]==0x11) {
- memset(data,0,0x11);
- data[0]=0xdf;
- data[1]=0x0f;
- data[6]=0x3f;
- data[7]=0x6a;
- }
- else if(mem[4]==0x42) {
- static const unsigned char resp[0x42] = {
- 0xdf,0x40,
- 0x6d,0xbb,0x81, // ...
- };
- memcpy(data,resp,sizeof(resp));
- }
- break;
- }
- if(readcmd) {
- if(dataLen>0) {
- PUSHB(mem[INS_IDX]); // ACK byte
- PUSH(data,dataLen);
- }
- PUSH(nextSW,2);
- cmdStart=true;
- }
- else {
- PUSHB(mem[INS_IDX]); // ACK byte
- }
- }
- else {
- dataLen-=len;
- if(dataLen<=0 && !cmdStart) {
- PUSH(nextSW,2);
- cmdStart=true;
- }
- }
-#elif defined(EMU_IRD)
- static const struct Resp {
- unsigned int cmd;
- unsigned char data[MAX_LEN];
- } resp[] = {
-#ifdef EMU_IRD_384
- { 0x01020203,
- {0x01,0x02,0x00,0x00,0x02,0x00,0x00,0x10,0x03,0x84,0x00,0x00,0x00,0x17,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x45,0x52} },
- { 0x01020E02,
- {0x01,0x02,0x00,0x00,0x0e,0x02,0x00,0x40,0xa9,0x6d,0x73,0x97,0x9e,0xfc,0x9b,0x8e,0x5b,0x8c,0xfa,0xb2,0x0c,0xb2,0x57,0x0f,0xb2,0xf7,0x29,0x4e,0xa2,0xcb,0xbd,0x5b,0x52,0x74,0xb1,0x2a,0xb7,0xc5,0xd9,0x62,0x6d,0x37,0x6d,0x9d,0xa3,0xe9,0x61,0xbb,0x1b,0x2b,0x56,0xb7,0x86,0x0c,0xe6,0xb1,0x07,0x6f,0xe0,0xf8,0x8a,0xd3,0x05,0x83,0xf6,0x53,0x0e,0xd2,0x72,0xd5,0xc1,0x50} },
- { 0x01020E03,
- {0x01,0x02,0x00,0x00,0x0e,0x03,0x00,0x40,0xb6,0xde,0xa8,0xce,0x86,0x1c,0x42,0x72,0xa8,0x16,0x4b,0xf9,0xce,0x33,0xb5,0x43,0xd0,0x50,0xe6,0xa7,0xf1,0xcb,0x55,0x25,0x97,0x13,0xee,0x62,0x98,0xe7,0x17,0x50,0xeb,0x3b,0x59,0x10,0x0a,0xb6,0x2e,0x93,0x61,0x71,0x3c,0xe6,0xe2,0x2c,0x1e,0x7d,0xbd,0x6a,0x49,0xbb,0x04,0x5b,0xdf,0x2f,0xb7,0xa7,0x93,0xe0,0x3d,0x40,0x4e,0xd1} },
-#else
- { 0x01020203,
- {0x01,0x02,0x00,0x00,0x02,0x00,0x00,0x10,0x03,0x83,0x00,0x00,0x00,0x17,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x45,0x52} },
- { 0x01020E02,
- {0x01,0x02,0x00,0x00,0x0E,0x02,0x00,0x40,0x65,0xEF,0xD0,0xA7,0xF3,0x80,0x48,0x0E,0xC1,0x4B,0x41,0x6C,0xDB,0x68,0x47,0xE4,0x23,0xAD,0x96,0x12,0x07,0x58,0x58,0x29,0xE9,0x14,0x27,0x7F,0x7D,0xF8,0xC2,0x65,0x76,0x4D,0x75,0x04,0x7C,0x9B,0xAA,0x99,0x58,0xEA,0xE2,0x43,0xB5,0x03,0x05,0xD6,0x62,0x99,0xF5,0x18,0x16,0x4E,0xCF,0x49,0x11,0xBD,0xF3,0xEE,0xC3,0xCD,0x90,0x3B} },
- { 0x01020E03,
- {0x01,0x02,0x00,0x00,0x0E,0x03,0x00,0x40,0x9B,0x06,0xB5,0x0A,0x98,0xC6,0x2E,0x1D,0x71,0xA1,0xE8,0x84,0xAE,0x98,0x57,0xE9,0xE6,0xC2,0x97,0x46,0x25,0x7A,0x2B,0xA1,0xD5,0x33,0x18,0xDE,0x16,0xC1,0xAB,0x22,0x2C,0xC2,0x11,0x24,0x81,0x11,0xA8,0x39,0xE3,0xB1,0xDB,0x33,0x1A,0x93,0x31,0xB0,0x61,0xD8,0xDE,0x92,0x1F,0x29,0x20,0xD0,0x9E,0x0F,0x6A,0xF0,0x7C,0xBA,0xCD,0xCC} },
-#endif
- { 0x01020003,
- {0x01,0x02,0x00,0x00,0x00,0x03,0x00,0x14,0x37,0x30,0x31,0x32,0x30,0x36,0x39,0x33,0x34,0x37,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
- { 0x01020103,
- {0x01,0x02,0x00,0x00,0x01,0x00,0x00,0x10,0x00,0x17,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x01,0x04,0x00,0xF3,0x86,0x01,0x1A} },
- { 0x01021100,
- {0x01,0x02,0x58,0x00,0x11,0x00,0x00,0x00} },
- { 0x01020903,
- {0x01,0x02,0x55,0x00,0x09,0x03,0x00,0x00} },
- { 0x01020303,
- {0x01,0x02,0x00,0x00,0x03,0x03,0x02,0x18,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
- { 0x01020400,
- {0x01,0x02,0x54,0x00,0x04,0x00,0x00,0x00} },
- { 0x01050000,
- {0x01,0x05,0x9D,0x00,0x38,0x00,0x02,0x16,0x00,0x01,0x00,0x13,0xFF,0xFF,0x22,0x88,0xBF,0x02,0x70,0xFA,0x5F,0x80,0xFD,0x1E,0xD4,0xD6,0xF0,0xF1,0x81,0xB3} },
- { 0x01010000,
- {0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xFF} },
- { 0x00000000, // don't delete this one
- {} }
- };
- const unsigned int cmd=(mem[0]<<24) + (mem[1]<<16) + (mem[2]<<8) + mem[3];
- const struct Resp *r=&resp[0];
- while(1) {
- if(!r->cmd) {
- static const unsigned char fail[] = { 0x01,0x99,0x6f };
- PUSH(fail,sizeof(fail));
- break;
- }
- if(cmd==r->cmd) {
- const int len=r->data[7]+9-1;
- int cs=0x3f;
- for(int i=0 ; i<len ; i++) cs ^= r->data[i];
- PUSH(r->data,len);
- PUSHB(cs);
- break;
- }
- r++;
- }
-#else
-#error No serial emulation mode selected
-#endif
- return len;
-}
-
-void cSerial::ToggleRTS(void)
-{
- rts=!rts;
- if(!rts) {
-#if defined(EMU_SECA)
- static const unsigned char atr[] = { 0x3b,0x77,0x12,0x00,0x00,
- 0x60,0x60,0x03,0x0E,0x6C,0xB6,0xD6 };
-#elif defined(EMU_IRD)
- static const unsigned char atr[] = { 0x3B,0x9F,0x21,0x0E,
-#ifdef EMU_IRD_384
- 0x49,0x52,0x44,0x45,0x54,0x4f,0x20,0x41,0x43,0x53,0x03,0x84,0x55,0xff,0x80,0x6d };
-#else
- 0x49,0x52,0x44,0x45,0x54,0x4F,0x20,0x41,0x43,0x53,0x03,0x83,0x95,0x00,0x80,0x55 };
-#endif
-#elif defined(EMU_CRYPTO)
- static const unsigned char atr[] = { 0x3B,0x78,0x12,0x00,0x00,
- 0x65,0xC4,0x05,0x05,0x8F,0xF1,0x90,0x00 };
-#else
-#error No serial emulation mode selected
-#endif
- PUSH(atr,sizeof(atr));
- PRINTF(L_CORE_SERIAL,"serial: toggle RTS, now off");
- }
- else { PRINTF(L_CORE_SERIAL,"serial: toggle RTS, now on"); }
-}
-
-bool cSerial::CheckCAR(void)
-{
-#if 0
- if(time(0)>=remTime+30) {
- dsr=!dsr;
- remTime=time(0);
- }
-#endif
- return dsr;
-}
-
-#endif //SER_EMU
-
-// -- cInfoStr -----------------------------------------------------------------
-
-cInfoStr::cInfoStr(void)
-:cLineBuff(256)
-{
- current=0;
-}
-
-cInfoStr::~cInfoStr()
-{
- free(current);
-}
-
-bool cInfoStr::Get(char *buff, int len)
-{
- cMutexLock lock(&mutex);
- if(current && current[0]) {
- strn0cpy(buff,current,len);
- return true;
- }
- return false;
-}
-
-void cInfoStr::Begin(void)
-{
- Flush();
-}
-
-void cInfoStr::Finish()
-{
- cMutexLock lock(&mutex);
- free(current);
- current=Grab();
-}
-
-// -- cSmartCard ---------------------------------------------------------------
-
-static const int Ftable[16] = {
- 372,372,558,744,1116,1488,1860,0,0,512,768,1024,1536,2048,0,0
- };
-
-static const int fstable[16] = {
- 3571200,5000000,6000000, 8000000,12000000,16000000,20000000,0,
- 0,5000000,7500000,10000000,15000000,20000000, 0,0
-};
-
-static const float Dtable[16] = {
- 0.0,1.0,2.0,4.0,8.0,16.0,0.0,0.0,
- 0.0,0.0,0.5,0.25,0.125,0.0625,0.03125,0.015625
- };
-
-cSmartCard::cSmartCard(const struct CardConfig *Cfg, const struct StatusMsg *Msg)
-{
- cfg=Cfg; msg=Msg;
- ser=0; atr=0; idStr[0]=0; cardUp=false; needsReset=true;
-}
-
-bool cSmartCard::GetCardIdStr(char *str, int len)
-{
- strn0cpy(str,idStr,len);
- return (str[0]!=0);
-}
-
-bool cSmartCard::GetCardInfoStr(char *str, int len)
-{
- return infoStr.Get(str,len);
-}
-
-bool cSmartCard::Setup(cSerial *Ser, const struct Atr *Atr, int Id)
-{
- ser=Ser; atr=Atr; id=Id;
- if(cfg->SerMode==(ser->CurrentMode()&SM_MASK) && Init()) {
- cardUp=true; needsReset=false;
- return true;
- }
- return false;
-}
-
-#define NEED(x) { \
- if(len+(x)>Atr->atrLen) { \
- LBPUT("SHORT ATR"); \
- return false; \
- } \
- }
-
-bool cSmartCard::ParseAtr(struct Atr *Atr, int id, int clock)
-{
- // default values
- Atr->histLen=0; Atr->T=0; Atr->F=372; Atr->fs=clock; Atr->D=1.0; Atr->N=0;
- Atr->WI=10; Atr->BWI=4; Atr->CWI=0; Atr->Tspec=-1;
-
- const unsigned char *atr=Atr->atr;
- if(atr[0]==0x03) {
- PRINTF(L_CORE_SC,"%d: indirect convention detected",id);
- cSmartCard::Invert(Atr->atr,Atr->atrLen);
- Atr->convention=SM_INDIRECT;
- }
- else if(atr[0]==0x3F) {
- PRINTF(L_CORE_SC,"%d: indirect convention detected (converted)",id);
- Atr->convention=SM_INDIRECT_CONVERTED;
- }
- else if(atr[0]==0x3B) {
- PRINTF(L_CORE_SC,"%d: direct convention detected",id);
- Atr->convention=SM_DIRECT;
- }
- else {
- PRINTF(L_CORE_SC,"%d: byte mode not supported 0x%02x",id,atr[0]);
- return false;
- }
-
- // TS TO
- Atr->histLen=atr[1]&0x0F;
- int Y=atr[1]&0xF0, i=1, len=2;
- LBSTARTF(L_CORE_SC);
- LBPUT("%d: atr decoding TS=%02x hist=%d Y%d=%02x ",id,atr[0],Atr->histLen,i,Y);
- do {
- if(Y&0x10) { // TAi
- NEED(1);
- LBPUT("TA%d=%02x ",i,atr[len]);
- if(i==1) {
- Atr->TA1=atr[len];
- Atr->F=Ftable[(atr[len]>>4)&0x0F];
- Atr->fs=fstable[(atr[len]>>4)&0x0F];
- Atr->D=Dtable[ atr[len] &0x0F];
- LBPUT("F=%d, fs=%.4fMHz, D=%f ",Atr->F,Atr->fs/1000000.0,Atr->D);
- }
- else if(i==2) {
- Atr->Tspec=atr[len]&0x0F;
- LBPUT("Tspec=%d ",Atr->Tspec);
- }
- else if(i==3) {
- LBPUT("IFSC=%d ",atr[len]);
- }
- len++;
- }
- if(Y&0x20) { // TBi
- NEED(1);
- LBPUT("TB%d=%02x ",i,atr[len]);
- if(i==3) {
- Atr->BWI=(atr[len]>>4)&0x0F;
- Atr->CWI=atr[len]&0x0F;
- LBPUT("BWI=%d CWI=%d ",Atr->BWI,Atr->CWI);
- }
- len++;
- }
- if(Y&0x40) { // TCi
- NEED(1);
- LBPUT("TC%d=%02x ",i,atr[len]);
- if(i==1) {
- Atr->N=atr[len];
- LBPUT("N=%d ",Atr->N);
- }
- else if(i==2) {
- Atr->WI=atr[len];
- LBPUT("WI=%d ",Atr->WI);
- }
- else if(i==3) {
- LBPUT("CHK=%s ",atr[len]&1 ? "CRC16":"LRC");
- }
- len++;
- }
- if(Y&0x80) { // TDi
- NEED(1);
- LBPUT("TD%d=%02x ",i,atr[len]);
- if(i==1) {
- Atr->T=atr[len]&0x0F;
- LBPUT("T=%d ",Atr->T);
- }
- else {
- LBPUT("Tn=%d ",atr[len]&0x0F);
- }
- Y=atr[len]&0xF0;
- len++;
- }
- else Y=0;
- i++;
- LBPUT("Y%d=%02x ",i,Y);
- } while(Y);
- NEED(Atr->histLen);
- LBEND();
-
- LBSTART(L_CORE_SC);
- LBPUT("%d: historical:",id);
- for(int i=0 ; i<Atr->histLen ; i++) LBPUT(" %02x",atr[len+i]);
- LBFLUSH();
- LBPUT("%d: historical: '",id);
- for(int i=0 ; i<Atr->histLen ; i++) LBPUT("%c",isprint(atr[len+i]) ? atr[len+i] : '.');
- LBEND();
-
- memcpy(Atr->hist,&atr[len],Atr->histLen);
- len+=Atr->histLen;
-
- // TCK
- if(Atr->T!=0 && len+1<=Atr->atrLen) {
- len++;
- unsigned char cs=XorSum(atr+1,len-1);
- // according to the ISO the initial TS byte isn't checksumed, but
- // some cards do so. In this case the checksum is equal TS.
- if(cs==0) PRINTF(L_CORE_SC,"%d: atr checksum ok",id);
- else if(cs==atr[0]) PRINTF(L_CORE_SC,"iso: %d: atr checksum is TS (not ISO compliant)",id);
- else {
- PRINTF(L_CORE_SC,"%d: atr checksum FAILED (cs:%02x)",id,cs);
- return false;
- }
- }
- else PRINTF(L_CORE_SC,"%d: atr checksum not given/not required",id);
-
- if(Atr->atrLen>len) PRINTF(L_CORE_SC,"%d: long atr read=%d len=%d",id,Atr->atrLen,len);
- Atr->wwt=960*Atr->WI*Atr->F/(clock/1000);
- Atr->bwt=(int)(960*(float)(1<<Atr->BWI)*372/(clock/1000));
- PRINTF(L_CORE_SC,"%d: indicated wwt(T0)=%d ms, bwt(T1)=%d ms (at %.4f MHz)",id,Atr->wwt,Atr->bwt,(float)clock/1000000);
- return true;
-}
-
-void cSmartCard::Invert(unsigned char *data, int n)
-{
- static const unsigned char swaptab[] = { 15,7,11,3,13,5,9,1,14,6,10,2,12,4,8,0 };
- for(int i=n-1; i>=0; i--)
- data[i]=(swaptab[data[i]&0x0f]<<4) | swaptab[data[i]>>4];
-}
-
-int cSmartCard::SerRead(unsigned char *data, int len, int to)
-{
- if(atr->T==1 || atr->T==14) {
- int r=Read(data,len,to);
- if(r<0) Test(false);
- return r;
- }
- else {
- PRINTF(L_CORE_SC,"%d: SerRead() not allowed for ISO compliant cards (T=%d)",id,atr->T);
- return -1;
- }
-}
-
-int cSmartCard::SerWrite(const unsigned char *data, int len)
-{
- if(atr->T==1 || atr->T==14) {
- int r=Write(data,len);
- if(r<0) Test(false);
- return r;
- }
- else {
- PRINTF(L_CORE_SC,"%d: SerWrite() not allowed for ISO compliant cards (T=%d)",id,atr->T);
- return -1;
- }
-}
-
-int cSmartCard::Read(unsigned char *data, int len, int to)
-{
- int r=ser->Read(data,len,cfg->serTO,to);
- if(atr->convention==SM_INDIRECT && r>0) Invert(data,r);
- return r;
-}
-
-int cSmartCard::Write(const unsigned char *data, int len)
-{
- unsigned char *tmp=AUTOMEM(len);
- if(atr->convention==SM_INDIRECT) {
- memcpy(tmp,data,len);
- Invert(tmp,len);
- data=tmp;
- }
- int r=ser->Write(data,len);
- // Discard command echo.
- // NB! There is no command echo in SmartReader+ mode.
- if(ser->DeviceType()!=SM_SMARTREADER && r>0) {
- unsigned char *buff=AUTOMEM(r);
- int rr=ser->Read(buff,r,cfg->serTO);
- if(rr<0) r=rr;
- }
- return r;
-}
-
-int cSmartCard::Procedure(unsigned char ins, int restLen)
-{
- int r;
- unsigned char buff;
- LBSTARTF(L_CORE_SC);
- LBPUT("%d: <- PROC: ",id);
- do {
- do {
- if(Read(&buff,1,cfg->workTO)<=0) return -1;
- LBPUT("%02x ",buff);
- } while(buff==0x60);
-
- if((buff&0xF0)==0x60 || (buff&0xF0)==0x90) { // SW1/SW2
- sb[0]=buff;
- if(Read(&buff,1)<=0) return -1;
- LBPUT("%02x",buff);
- sb[1]=buff;
- return 0;
- }
- else {
- if((buff&0xFE)==(ins&0xFE)) r=restLen;
- else if((~buff&0xFE)==(ins&0xFE)) r=1;
- else {
- LBPUT("cannot handle procedure %02x (ins=%02x)",buff,ins);
- return -1;
- }
- if(r>restLen) {
- LBPUT("data overrun r=%d restLen=%d",r,restLen);
- return -1;
- }
- }
- } while(r==0);
- LBEND();
- return r;
-}
-
-bool cSmartCard::IsoRead(const unsigned char *cmd, unsigned char *data)
-{
- if(atr->T==0) { // only for ISO complaint cards
- LDUMP(L_CORE_SC,cmd,CMD_LEN,"%d: -> INS:",id);
- if(Write(cmd,CMD_LEN)<0) return Test(false);
- int tr=cmd[LEN_IDX] ? cmd[LEN_IDX] : 256;
- int len=0;
- while(1) {
- int r=Procedure(cmd[INS_IDX],tr-len);
- if(r<=0) return Test(r==0);
- if(Read(data+len,r)<0) return Test(false);
- LDUMP(L_CORE_SC,data+len,r,"%d: <- DATA:",id);
- len+=r;
- }
- }
- else PRINTF(L_CORE_SC,"%d: can't IsoRead() from incompatible card (T=%d)",id,atr->T);
- return false;
-}
-
-bool cSmartCard::IsoWrite(const unsigned char *cmd, const unsigned char *data)
-{
- if(atr->T==0) { // only for ISO complaint cards
- LDUMP(L_CORE_SC,cmd,CMD_LEN,"%d: -> INS:",id);
- if(Write(cmd,CMD_LEN)<0) return Test(false);
- int len=0;
- while(1) {
- int r=Procedure(cmd[INS_IDX],cmd[LEN_IDX]-len);
- if(r<=0) return Test(r==0);
- if(Write(data+len,r)<0) return Test(false);
- LDUMP(L_CORE_SC,data+len,r,"%d: -> DATA:",id);
- len+=r;
- }
- }
- else PRINTF(L_CORE_SC,"%d: can't IsoWrite() to incompatible card (T=%d)",id,atr->T);
- return false;
-}
-
-bool cSmartCard::Test(bool res)
-{
- if(!res) {
- TriggerReset();
- PRINTF(L_CORE_SC,"%d: reset triggered",id);
- }
- return res;
-}
-
-bool cSmartCard::Status(void)
-{
- const struct StatusMsg *m=msg;
- while(m->sb[0]!=0xFF) {
- if(sb[0]==m->sb[0] && (m->sb[1]==0xFF || sb[1]==m->sb[1])) {
- if(!m->retval) PRINTF(L_CORE_SC,"%d: %s (status: %02x %02x)",id,m->message,sb[0],sb[1]);
- return m->retval;
- }
- m++;
- }
- PRINTF(L_CORE_SC,"%d: unknown (status: %02x %02x)",id,sb[0],sb[1]);
- return false;
-}
-
-int cSmartCard::CheckSctLen(const unsigned char *data, int off)
-{
- int l=SCT_LEN(data);
- if(l+off > MAX_LEN) {
- PRINTF(L_CORE_SC,"section too long %d > %d",l,MAX_LEN-off);
- l=-1;
- }
- return l;
-}
-
-// -- cSmartCardData -----------------------------------------------------------
-
-cSmartCardData::cSmartCardData(int Ident)
-{
- ident=Ident;
-}
-
-// -- cSmartCardLink -----------------------------------------------------------
-
-cSmartCardLink::cSmartCardLink(const char *Name, int Id)
-{
- name=Name; id=Id;
- cSmartCards::Register(this);
-}
-
-// -- cSmartCards --------------------------------------------------------------
-
-cSmartCardLink *cSmartCards::first=0;
-
-cSmartCards smartcards;
-
-static const char *serModes[] = { 0,"8e2","8o2","8n2" };
-
-cSmartCards::cSmartCards(void)
-:cThread("SmartcardWatcher")
-,cStructList<cSmartCardData>("smartcard data",DATAFILE,SL_MISSINGOK|SL_WATCH|SL_VERBOSE)
-{
- for(int i=0 ; i<MAX_PORTS ; i++) ports[i].Serial=0;
- firstRun=true;
-}
-
-void cSmartCards::Register(cSmartCardLink *scl)
-{
- PRINTF(L_CORE_DYN,"registering %s smartcard (id %x)",scl->name,scl->id);
- scl->next=first;
- first=scl;
-}
-
-void cSmartCards::LaunchWatcher(void)
-{
- for(int i=0 ; i<MAX_PORTS ; i++)
- if(ports[i].Serial) { Start(); return; }
- firstRun=false;
- PRINTF(L_GEN_WARN,"no smartcard interface defined!");
-}
-
-void cSmartCards::Shutdown(void)
-{
- Cancel(3);
- mutex.Lock();
- for(int i=0 ; i<MAX_PORTS ; i++) {
- if(ports[i].Serial) {
- delete ports[i].Card;
- delete ports[i].Serial;
- ports[i].Serial=0;
- }
- }
- mutex.Unlock();
- ListLock(true); Clear(); ListUnlock();
-}
-
-bool cSmartCards::AddPort(const char *devName, const char *devType, bool invCD, bool invRST, int clock)
-{
- cMutexLock lock(&mutex);
- int devtype=SM_PHOENIX;
- if (devType && strcmp(devType,"smartreader")==0) {
- devtype=SM_SMARTREADER;
- }
- for(int i=0 ; i<MAX_PORTS ; i++) {
- if(!ports[i].Serial) {
- cSerial *ser=new cSerial(devName,devtype,invCD,invRST);
- if(ser && ser->Open()) {
- ports[i].Card=0;
- ports[i].CardId=0;
- ports[i].UseCount=0;
- ports[i].Dead=false;
- ports[i].PortNum=i;
- ports[i].Serial=ser;
- ports[i].Clock=clock ? clock : ISO_FREQ;
- PRINTF(L_CORE_LOAD,"smartcards: added serial port %s as port %d (%s CD, %s RESET, CLOCK %d)",
- devName,i,invCD?"inverse":"normal",invRST?"inverse":"normal",ports[i].Clock);
- return true;
- }
- PRINTF(L_GEN_ERROR,"failed to open serial port %s",devName);
- delete ser;
- return false;
- }
- else if(!strcmp(ports[i].Serial->DeviceName(),devName)) {
- PRINTF(L_GEN_ERROR,"duplicate serial port %s. Check your config!",devName);
- return false;
- }
- }
- PRINTF(L_GEN_ERROR,"only %d serial ports supported",MAX_PORTS);
- return false;
-}
-
-cStructItem *cSmartCards::ParseLine(char *line)
-{
- char *r=index(line,':');
- if(r)
- for(cSmartCardLink *scl=first; scl; scl=scl->next)
- if(!strncasecmp(scl->name,line,r-line)) {
- cSmartCardData *scd=scl->CreateData();
- if(scd && scd->Parse(r+1)) return scd;
- delete scd;
- break;
- }
- return 0;
-}
-
-cSmartCardData *cSmartCards::FindCardData(cSmartCardData *param)
-{
- ListLock(false);
- cSmartCardData *cd;
- for(cd=First(); cd; cd=Next(cd))
- if(cd->ident==param->ident && cd->Matches(param)) break;
- ListUnlock();
- return cd;
-}
-
-bool cSmartCards::HaveCard(int id)
-{
- cMutexLock lock(&mutex);
- while(Running() && firstRun) cond.Wait(mutex);
- for(int i=0 ; i<MAX_PORTS ; i++)
- if(ports[i].Serial && ports[i].CardId==id) return true;
- return false;
-}
-
-cSmartCard *cSmartCards::LockCard(int id)
-{
- mutex.Lock();
- while(Running() && firstRun) cond.Wait(mutex);
- for(int i=0 ; i<MAX_PORTS ; i++) {
- if(ports[i].Serial && ports[i].CardId==id) {
- ports[i].UseCount++;
- mutex.Unlock();
- cSmartCard *sc=ports[i].Card;
- sc->Lock();
- if(CardInserted(ports[i].Serial) && sc->CardUp() && !sc->NeedsReset())
- return sc;
- // if failed, unlock the card and decrement UseCount
- sc->Unlock();
- mutex.Lock();
- ports[i].UseCount--;
- cond.Broadcast();
- break;
- }
- }
- mutex.Unlock();
- return 0;
-}
-
-void cSmartCards::ReleaseCard(cSmartCard *sc)
-{
- sc->Unlock();
- mutex.Lock();
- for(int i=0 ; i<MAX_PORTS ; i++) {
- if(ports[i].Card==sc) {
- ports[i].UseCount--;
- cond.Broadcast();
- mutex.Unlock();
- return;
- }
- }
- mutex.Unlock();
- PRINTF(L_GEN_DEBUG,"internal: can't find port in cSmartCards::ReleaseCard()");
-}
-
-bool cSmartCards::CardInserted(cSerial *ser)
-{
- return ser->CheckCAR();
-}
-
-bool cSmartCards::CardReset(struct Port *port)
-{
- cSerial *ser=port->Serial;
- int clock = port->Clock;
-
- if(ser->DeviceType()==SM_SMARTREADER) {
- // Configure SmartReader+ with initial settings, ref ISO 7816 3.1.
- PRINTF(L_CORE_SC,"%d: resetting SmartReader+",port->PortNum);
- if(clock==ISO_FREQ) {
- // No fixed frequency specified; use ISO initial clock frequency.
- clock=fstable[0];
- }
- if(!ser->ConfigSmartReader(Ftable[0],Dtable[1],clock,0,0,0)) {
- return false;
- }
- }
-
- if(Reset(port)<2 || !cSmartCard::ParseAtr(&port->Atr,port->PortNum,clock))
- return false;
- if(!DoPTS(port)) {
- // reset card again and continue without PTS
- if(Reset(port)<2 || !cSmartCard::ParseAtr(&port->Atr,port->PortNum,clock))
- return false;
- }
- return true;
-}
-
-int cSmartCards::Reset(struct Port *port)
-{
- cSerial *ser=port->Serial;
- PRINTF(L_CORE_SC,"%d: reseting card (sermode %s)",port->PortNum,serModes[ser->CurrentMode()]);
- ser->ToggleRTS();
- cCondWait::SleepMs(100);
- ser->ToggleRTS();
- int r=ser->Read(port->Atr.atr,-MAX_ATR_LEN,800,2000);
- port->Atr.atrLen=r;
- if(r>0) LDUMP(L_CORE_SC,port->Atr.atr,r,"%d: <- ATR len=%d:",port->PortNum,r);
- return r;
-}
-
-bool cSmartCards::DoPTS(struct Port *port)
-{
- struct Atr *atr=&port->Atr;
- cSerial *ser=port->Serial;
- const int id=port->PortNum;
-
- if(ser->DeviceType()==SM_SMARTREADER) {
- // Configure SmartReader+ with work settings, ref ISO 7816 3.1.
- int inv;
- if((inv = atr->convention==SM_DIRECT ? 0 : 1)) {
- atr->convention = SM_INDIRECT_CONVERTED;
- }
- // Use ISO work clock frequency unless a fixed frequency is specified.
- int clock=port->Clock==ISO_FREQ ? atr->fs : port->Clock;
- if(!ser->ConfigSmartReader(atr->F,atr->D,clock,atr->N,atr->T,inv)) {
- return false;
- }
- PRINTF(L_CORE_SC,"%d: SmartReader+ mode: fs=%.4fMHz",id,clock/1000000.0);
- return true;
- }
-
- if(atr->F!=372 || atr->D!=1.0) { // PTS required
- int baud=(int)((float)port->Clock*atr->D/atr->F);
- PRINTF(L_CORE_SC,"%d: PTS cycle: calculated baudrate %d",id,baud);
-
- if(atr->Tspec<0) {
- PRINTF(L_CORE_SC,"%d: negotiable mode",id);
-#ifdef NO_PTS_PROTO
- PRINTF(L_CORE_SC,"%d: PTS disabled at compile time!!!",id);
- return true;
-#else
- unsigned char req[4], conf[16];
- req[0]=0xFF;
- req[1]=0x10 | atr->T;
- req[2]=atr->TA1;
- req[3]=XorSum(req,3);
- LDUMP(L_CORE_SC,req,4,"%d: PTS request:",id);
- if(ser->Write(req,4)!=4) {
- PRINTF(L_CORE_SC,"%d: PTS request, write failed",id);
- return false;
- }
- if(ser->Read(conf,4,100,100)!=4) {
- PRINTF(L_CORE_SC,"%d: PTS request, echo readback failed",id);
- return false;
- }
- int n=ser->Read(conf,-16,200,1000);
- if(n>0) LDUMP(L_CORE_SC,conf,n,"%d: PTS confirm:",id);
- if(n<1 || conf[0]!=0xFF || XorSum(conf,n)!=0) {
- PRINTF(L_CORE_SC,"%d: PTS confirm, bad format",id);
- return false;
- }
- if(n<4 || conf[1]!=req[1] || conf[2]!=req[2]) {
- PRINTF(L_CORE_SC,"%d: PTS not confirmed",id);
- return false;
- }
-#endif // NO_PTS_PROTO
- }
- else
- PRINTF(L_CORE_SC,"%d: specific mode Tspec=%d",id,atr->Tspec);
-
- int mode=ser->CurrentMode();
- if(atr->N==255) mode|=SM_1SB;
- if(!ser->SetMode(mode,baud)) {
- PRINTF(L_CORE_SC,"%d: setting baudrate %d failed",id,baud);
- return false;
- }
- }
- return true;
-}
-
-void cSmartCards::SetPort(struct Port *port, cSmartCard *sc, int id, bool dead)
-{
- mutex.Lock();
- while(port->UseCount) cond.Wait(mutex);
- delete port->Card;
- port->Card=sc;
- port->CardId=id;
- port->Dead=dead;
- port->UseCount=0;
- mutex.Unlock();
-}
-
-void cSmartCards::Action(void)
-{
- while(Running()) {
- for(int i=0 ; i<MAX_PORTS ;) {
- struct Port *port=&ports[i];
- cSerial *ser=port->Serial;
- if(ser) {
- if(port->Card) {
- cSmartCard *sc=port->Card;
- sc->Lock();
- if(!CardInserted(ser)) {
- sc->Unlock(); sc=0;
- PRINTF(L_CORE_SC,"%d: card removed (UseCount=%d)",port->PortNum,port->UseCount);
- SetPort(port,0,0,false);
- }
- else if(sc->NeedsReset()) {
- PRINTF(L_CORE_SC,"%d: card reset requested",port->PortNum);
- if(!ser->SetMode(ser->CurrentMode()&SM_MASK)
- || !CardReset(port)
- || !sc->Setup(ser,&port->Atr,port->PortNum)) {
- sc->Unlock(); sc=0;
- PRINTF(L_CORE_SC,"%d: card re-init failed",port->PortNum);
- SetPort(port,0,0,true);
- }
- }
- if(sc) sc->Unlock();
- }
- else if(CardInserted(ser)) {
- if(!port->Dead) {
- PRINTF(L_CORE_SC,"%d: new card inserted",port->PortNum);
- for(int mode=SM_NONE+1 ; mode<SM_MAX ; mode++) {
- if(ser->SetMode(mode)) {
- if(CardReset(port)) {
- cSmartCardLink *scl=first;
- while(scl) {
- PRINTF(L_CORE_SC,"%d: checking for %s card",port->PortNum,scl->name);
- cSmartCard *sc=scl->Create();
- if(sc && sc->Setup(ser,&port->Atr,port->PortNum)) {
- SetPort(port,sc,scl->id,false);
- goto next; // ugly, any better solution?
- }
- delete sc;
- scl=scl->next;
- }
- PRINTF(L_CORE_SC,"%d: no card handler found",port->PortNum);
- }
- else PRINTF(L_CORE_SC,"%d: reset/atr error",port->PortNum);
- }
- else PRINTF(L_CORE_SC,"%d: failed to set serial mode %s",port->PortNum,serModes[mode]);
- }
- port->Dead=true;
- PRINTF(L_CORE_SC,"%d: can't initialise new card, ignoring port until card reinserted",port->PortNum);
- }
- }
- else {
- if(port->Dead) PRINTF(L_CORE_SC,"%d: card removed, port reactivated",port->PortNum);
- port->Dead=false;
- }
- }
-next: i++;
- }
- if(firstRun) {
- mutex.Lock();
- cond.Broadcast();
- firstRun=false;
- mutex.Unlock();
- }
- cCondWait::SleepMs(300);
- }
-}
-
-bool cSmartCards::ListCard(int num, char *str, int len)
-{
- if(num>=MAX_PORTS || !ports[num].Serial) return false;
- str[0]=0;
- mutex.Lock();
- cSmartCard *sc=ports[num].Card;
- if(sc) {
- if(!sc->GetCardIdStr(str,len)) {
- cSmartCardLink *scl=first;
- while(scl) {
- if(scl->id==ports[num].CardId) {
- strn0cpy(str,scl->name,len);
- break;
- }
- scl=scl->next;
- }
- }
- }
- mutex.Unlock();
- return true;
-}
-
-bool cSmartCards::CardInfo(int num, char *str, int len)
-{
- bool res=false;
- if(num<MAX_PORTS && ports[num].Serial) {
- str[0]=0;
- mutex.Lock();
- cSmartCard *sc=ports[num].Card;
- if(sc) res=sc->GetCardInfoStr(str,len);
- mutex.Unlock();
- }
- return res;
-}
-
-void cSmartCards::CardReset(int num)
-{
- if(num<MAX_PORTS && ports[num].Serial) {
- mutex.Lock();
- cSmartCard *sc=ports[num].Card;
- if(sc) sc->TriggerReset();
- mutex.Unlock();
- }
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___SMARTCARD_H
-#define ___SMARTCARD_H
-
-#include <vdr/thread.h>
-#include "data.h"
-#include "misc.h"
-
-// ----------------------------------------------------------------
-
-#define MAX_LEN 256 // max. response length
-#define CMD_LEN 5 // command length
-#define INS_IDX 1 // INS index
-#define LEN_IDX 4 // LEN index
-
-#define SB_LEN 2 // status byte (SB) len
-#define MAX_ATR_LEN 33 // max. ATR length
-#define MAX_HIST 15 // max. number of historical characters
-#define IDSTR_LEN 25 // lenght of card identify string
-
-#define MAKE_SC_ID(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d))
-
-// ----------------------------------------------------------------
-
-class cSerial;
-class cSmartCards;
-
-// ----------------------------------------------------------------
-
-class cInfoStr : public cLineBuff {
-private:
- cMutex mutex;
- char *current;
-public:
- cInfoStr(void);
- ~cInfoStr();
- // Query API
- bool Get(char *buff, int len);
- // Construct API
- void Begin(void);
- void Finish();
- };
-
-// ----------------------------------------------------------------
-
-#define SM_NONE 0
-#define SM_8E2 1
-#define SM_8O2 2
-#define SM_8N2 3
-#define SM_MAX 4
-#define SM_MASK 0x1F
-#define SM_1SB 0x80
-
-#define SM_DIRECT 0
-#define SM_INDIRECT 1
-#define SM_INDIRECT_CONVERTED 2
-
-#define SM_PHOENIX 0
-#define SM_SMARTREADER 1
-
-struct CardConfig {
- int SerMode;
- int workTO, serTO; // values in ms
- };
-
-struct StatusMsg {
- unsigned char sb[SB_LEN];
- const char *message;
- bool retval;
- };
-
-struct Atr {
- int T, F, fs, N, WI, BWI, CWI, TA1, Tspec;
- float D;
- int wwt, bwt;
- int atrLen, histLen;
- int convention;
- unsigned char atr[MAX_ATR_LEN];
- unsigned char hist[MAX_HIST];
- };
-
-class cSmartCard : protected cMutex {
-friend class cSmartCards;
-private:
- cSerial *ser;
- const struct CardConfig *cfg;
- const struct StatusMsg *msg;
- bool cardUp, needsReset;
- int id;
- //
- int Procedure(unsigned char ins, int restLen);
- int Read(unsigned char *data, int len, int to=0);
- int Write(const unsigned char *data, int len);
-protected:
- const struct Atr *atr;
- unsigned char sb[SB_LEN];
- char idStr[IDSTR_LEN];
- cInfoStr infoStr;
- //
- int SerRead(unsigned char *data, int len, int to=0);
- int SerWrite(const unsigned char *data, int len);
- bool IsoRead(const unsigned char *cmd, unsigned char *data);
- bool IsoWrite(const unsigned char *cmd, const unsigned char *data);
- bool Status(void);
- bool Test(bool res);
- int CheckSctLen(const unsigned char *data, int off);
- void TriggerReset(void) { needsReset=true; }
- static void Invert(unsigned char *data, int n);
-public:
- cSmartCard(const struct CardConfig *Cfg, const struct StatusMsg *Msg);
- virtual ~cSmartCard() {};
- virtual bool Init(void)=0;
- virtual bool Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)=0;
- virtual bool Update(int pid, int caid, const unsigned char *data) { return false; }
- virtual bool CanHandle(unsigned short CaId) { return true; }
- //
- bool Setup(cSerial *Ser, const struct Atr *Atr, int Id);
- static bool ParseAtr(struct Atr *atr, int id, int clock);
- bool CardUp(void) { return cardUp; }
- bool NeedsReset(void) { return needsReset; }
- bool GetCardIdStr(char *str, int len);
- bool GetCardInfoStr(char *str, int len);
- };
-
-// ----------------------------------------------------------------
-
-class cSmartCardData : public cStructItem {
-friend class cSmartCards;
-protected:
- int ident;
-public:
- cSmartCardData(int Ident);
- virtual ~cSmartCardData() {}
- virtual bool Parse(const char *line)=0;
- virtual bool Matches(cSmartCardData *cmp)=0;
- };
-
-// ----------------------------------------------------------------
-
-class cSmartCardLink {
-friend class cSmartCards;
-private:
- cSmartCardLink *next;
- const char *name;
- int id;
-public:
- cSmartCardLink(const char *Name, int Id);
- virtual ~cSmartCardLink() {}
- virtual cSmartCard *Create(void)=0;
- virtual cSmartCardData *CreateData(void) { return 0; }
- int ID(void) { return id; }
- };
-
-// ----------------------------------------------------------------
-
-#define MAX_PORTS 4
-
-struct Port {
- cSerial *Serial;
- bool Dead;
- cSmartCard *Card;
- int CardId, UseCount, PortNum, Clock;
- struct Atr Atr;
- };
-
-class cSmartCards : private cThread, public cStructList<cSmartCardData> {
-friend class cSmartCardLink;
-private:
- static cSmartCardLink *first;
- cMutex mutex;
- cCondVar cond;
- struct Port ports[MAX_PORTS];
- bool firstRun;
- //
- static void Register(cSmartCardLink *scl);
- bool CardInserted(cSerial *ser);
- bool CardReset(struct Port *port);
- int Reset(struct Port *port);
- bool DoPTS(struct Port *port);
- void SetPort(struct Port *port, cSmartCard *sc, int id, bool dead);
-protected:
- virtual void Action(void);
- virtual cStructItem *ParseLine(char *line);
-public:
- cSmartCards(void);
- void Shutdown(void);
- // to be called ONLY from a system class!
- bool HaveCard(int id);
- cSmartCard *LockCard(int id);
- void ReleaseCard(cSmartCard *sc);
- cSmartCardData *FindCardData(cSmartCardData *param);
- // to be called ONLY from frontend thread!
- bool AddPort(const char *devName, const char *devType, bool invCD, bool invRST, int clock);
- void LaunchWatcher(void);
- bool ListCard(int num, char *str, int len);
- bool CardInfo(int num, char *str, int len);
- void CardReset(int num);
- };
-
-extern cSmartCards smartcards;
-
-#endif //___SMARTCARD_H
+++ /dev/null
-#ifndef HEADER_AES_H\r
-#define HEADER_AES_H\r
-\r
-/*\r
-#ifdef OPENSSL_NO_AES\r
-#error AES is disabled.\r
-#endif\r
-*/\r
-\r
-#define AES_ENCRYPT 1\r
-#define AES_DECRYPT 0\r
-\r
-/* Because array size can't be a const in C, the following two are macros.\r
- Both sizes are in bytes. */\r
-#define AES_MAXNR 14\r
-#define AES_BLOCK_SIZE 16\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-#if defined(_MSC_VER) && !defined(OPENSSL_SYS_WINCE)\r
-# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)\r
-# define GETU32(p) SWAP(*((u32 *)(p)))\r
-# define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }\r
-#else\r
-# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))\r
-# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }\r
-#endif\r
-\r
-typedef unsigned long u32;\r
-typedef unsigned short u16;\r
-typedef unsigned char u8;\r
-\r
-#define MAXKC (256/32)\r
-#define MAXKB (256/8)\r
-#define MAXNR 14\r
-\r
-/* This controls loop-unrolling in aes_core.c */\r
-#undef FULL_UNROLL\r
-\r
-/* This should be a hidden type, but EVP requires that the size be known */\r
-struct aes_key_st {\r
- unsigned long rd_key[4 *(AES_MAXNR + 1)];\r
- int rounds;\r
-};\r
-typedef struct aes_key_st AES_KEY;\r
-\r
-const char *AES_options(void);\r
-\r
-int AES_set_encrypt_key(const unsigned char *userKey, const int bits,\r
- AES_KEY *key);\r
-int AES_set_decrypt_key(const unsigned char *userKey, const int bits,\r
- AES_KEY *key);\r
-\r
-void AES_encrypt(const unsigned char *in, unsigned char *out,\r
- const AES_KEY *key);\r
-void AES_decrypt(const unsigned char *in, unsigned char *out,\r
- const AES_KEY *key);\r
-\r
-void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,\r
- const AES_KEY *key, const int enc);\r
-void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,\r
- const unsigned long length, const AES_KEY *key,\r
- unsigned char *ivec, const int enc);\r
-void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,\r
- const unsigned long length, const AES_KEY *key,\r
- unsigned char *ivec, int *num, const int enc);\r
-void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,\r
- const unsigned long length, const AES_KEY *key,\r
- unsigned char *ivec, int *num);\r
-void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,\r
- const unsigned long length, const AES_KEY *key,\r
- unsigned char ivec[AES_BLOCK_SIZE],\r
- unsigned char ecount_buf[AES_BLOCK_SIZE],\r
- unsigned int *num);\r
-\r
-\r
-#ifdef __cplusplus\r
-}\r
-#endif\r
-\r
-#endif /* !HEADER_AES_H */\r
+++ /dev/null
-#include <assert.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include "aes.h"\r
-\r
-static const u32 Te0[256] = {\r
- 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,\r
- 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,\r
- 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,\r
- 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,\r
- 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,\r
- 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,\r
- 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,\r
- 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,\r
- 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,\r
- 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,\r
- 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,\r
- 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,\r
- 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,\r
- 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,\r
- 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,\r
- 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,\r
- 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,\r
- 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,\r
- 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,\r
- 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,\r
- 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,\r
- 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,\r
- 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,\r
- 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,\r
- 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,\r
- 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,\r
- 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,\r
- 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,\r
- 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,\r
- 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,\r
- 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,\r
- 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,\r
- 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,\r
- 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,\r
- 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,\r
- 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,\r
- 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,\r
- 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,\r
- 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,\r
- 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,\r
- 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,\r
- 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,\r
- 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,\r
- 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,\r
- 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,\r
- 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,\r
- 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,\r
- 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,\r
- 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,\r
- 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,\r
- 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,\r
- 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,\r
- 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,\r
- 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,\r
- 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,\r
- 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,\r
- 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,\r
- 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,\r
- 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,\r
- 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,\r
- 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,\r
- 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,\r
- 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,\r
- 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,\r
-};\r
-static const u32 Te1[256] = {\r
- 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,\r
- 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,\r
- 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,\r
- 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,\r
- 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,\r
- 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,\r
- 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,\r
- 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,\r
- 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,\r
- 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,\r
- 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,\r
- 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,\r
- 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,\r
- 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,\r
- 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,\r
- 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,\r
- 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,\r
- 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,\r
- 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,\r
- 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,\r
- 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,\r
- 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,\r
- 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,\r
- 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,\r
- 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,\r
- 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,\r
- 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,\r
- 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,\r
- 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,\r
- 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,\r
- 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,\r
- 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,\r
- 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,\r
- 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,\r
- 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,\r
- 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,\r
- 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,\r
- 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,\r
- 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,\r
- 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,\r
- 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,\r
- 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,\r
- 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,\r
- 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,\r
- 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,\r
- 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,\r
- 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,\r
- 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,\r
- 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,\r
- 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,\r
- 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,\r
- 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,\r
- 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,\r
- 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,\r
- 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,\r
- 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,\r
- 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,\r
- 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,\r
- 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,\r
- 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,\r
- 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,\r
- 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,\r
- 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,\r
- 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,\r
-};\r
-static const u32 Te2[256] = {\r
- 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,\r
- 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,\r
- 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,\r
- 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,\r
- 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,\r
- 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,\r
- 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,\r
- 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,\r
- 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,\r
- 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,\r
- 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,\r
- 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,\r
- 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,\r
- 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,\r
- 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,\r
- 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,\r
- 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,\r
- 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,\r
- 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,\r
- 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,\r
- 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,\r
- 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,\r
- 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,\r
- 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,\r
- 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,\r
- 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,\r
- 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,\r
- 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,\r
- 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,\r
- 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,\r
- 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,\r
- 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,\r
- 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,\r
- 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,\r
- 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,\r
- 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,\r
- 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,\r
- 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,\r
- 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,\r
- 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,\r
- 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,\r
- 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,\r
- 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,\r
- 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,\r
- 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,\r
- 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,\r
- 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,\r
- 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,\r
- 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,\r
- 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,\r
- 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,\r
- 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,\r
- 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,\r
- 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,\r
- 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,\r
- 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,\r
- 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,\r
- 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,\r
- 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,\r
- 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,\r
- 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,\r
- 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,\r
- 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,\r
- 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,\r
-};\r
-static const u32 Te3[256] = {\r
-\r
- 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,\r
- 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,\r
- 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,\r
- 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,\r
- 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,\r
- 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,\r
- 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,\r
- 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,\r
- 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,\r
- 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,\r
- 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,\r
- 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,\r
- 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,\r
- 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,\r
- 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,\r
- 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,\r
- 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,\r
- 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,\r
- 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,\r
- 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,\r
- 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,\r
- 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,\r
- 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,\r
- 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,\r
- 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,\r
- 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,\r
- 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,\r
- 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,\r
- 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,\r
- 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,\r
- 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,\r
- 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,\r
- 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,\r
- 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,\r
- 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,\r
- 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,\r
- 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,\r
- 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,\r
- 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,\r
- 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,\r
- 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,\r
- 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,\r
- 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,\r
- 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,\r
- 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,\r
- 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,\r
- 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,\r
- 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,\r
- 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,\r
- 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,\r
- 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,\r
- 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,\r
- 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,\r
- 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,\r
- 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,\r
- 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,\r
- 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,\r
- 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,\r
- 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,\r
- 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,\r
- 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,\r
- 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,\r
- 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,\r
- 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,\r
-};\r
-static const u32 Te4[256] = {\r
- 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,\r
- 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,\r
- 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,\r
- 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,\r
- 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,\r
- 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,\r
- 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,\r
- 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,\r
- 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,\r
- 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,\r
- 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,\r
- 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,\r
- 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,\r
- 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,\r
- 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,\r
- 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,\r
- 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,\r
- 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,\r
- 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,\r
- 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,\r
- 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,\r
- 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,\r
- 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,\r
- 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,\r
- 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,\r
- 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,\r
- 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,\r
- 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,\r
- 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,\r
- 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,\r
- 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,\r
- 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,\r
- 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,\r
- 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,\r
- 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,\r
- 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,\r
- 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,\r
- 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,\r
- 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,\r
- 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,\r
- 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,\r
- 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,\r
- 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,\r
- 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,\r
- 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,\r
- 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,\r
- 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,\r
- 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,\r
- 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,\r
- 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,\r
- 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,\r
- 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,\r
- 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,\r
- 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,\r
- 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,\r
- 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,\r
- 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,\r
- 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,\r
- 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,\r
- 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,\r
- 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,\r
- 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,\r
- 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,\r
- 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,\r
-};\r
-static const u32 Td0[256] = {\r
- 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,\r
- 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,\r
- 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,\r
- 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,\r
- 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,\r
- 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,\r
- 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,\r
- 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,\r
- 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,\r
- 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,\r
- 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,\r
- 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,\r
- 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,\r
- 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,\r
- 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,\r
- 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,\r
- 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,\r
- 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,\r
- 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,\r
- 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,\r
- 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,\r
- 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,\r
- 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,\r
- 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,\r
- 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,\r
- 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,\r
- 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,\r
- 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,\r
- 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,\r
- 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,\r
- 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,\r
- 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,\r
- 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,\r
- 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,\r
- 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,\r
- 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,\r
- 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,\r
- 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,\r
- 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,\r
- 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,\r
- 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,\r
- 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,\r
- 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,\r
- 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,\r
- 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,\r
- 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,\r
- 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,\r
- 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,\r
- 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,\r
- 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,\r
- 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,\r
- 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,\r
- 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,\r
- 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,\r
- 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,\r
- 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,\r
- 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,\r
- 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,\r
- 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,\r
- 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,\r
- 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,\r
- 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,\r
- 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,\r
- 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,\r
-};\r
-static const u32 Td1[256] = {\r
- 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,\r
- 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,\r
- 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,\r
- 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,\r
- 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,\r
- 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,\r
- 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,\r
- 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,\r
- 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,\r
- 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,\r
- 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,\r
- 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,\r
- 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,\r
- 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,\r
- 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,\r
- 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,\r
- 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,\r
- 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,\r
- 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,\r
- 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,\r
- 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,\r
- 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,\r
- 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,\r
- 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,\r
- 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,\r
- 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,\r
- 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,\r
- 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,\r
- 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,\r
- 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,\r
- 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,\r
- 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,\r
- 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,\r
- 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,\r
- 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,\r
- 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,\r
- 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,\r
- 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,\r
- 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,\r
- 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,\r
- 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,\r
- 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,\r
- 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,\r
- 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,\r
- 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,\r
- 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,\r
- 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,\r
- 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,\r
- 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,\r
- 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,\r
- 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,\r
- 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,\r
- 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,\r
- 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,\r
- 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,\r
- 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,\r
- 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,\r
- 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,\r
- 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,\r
- 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,\r
- 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,\r
- 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,\r
- 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,\r
- 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,\r
-};\r
-static const u32 Td2[256] = {\r
- 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,\r
- 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,\r
- 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,\r
- 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,\r
- 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,\r
- 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,\r
- 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,\r
- 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,\r
- 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,\r
- 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,\r
- 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,\r
- 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,\r
- 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,\r
- 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,\r
- 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,\r
- 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,\r
- 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,\r
- 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,\r
- 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,\r
- 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,\r
-\r
- 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,\r
- 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,\r
- 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,\r
- 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,\r
- 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,\r
- 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,\r
- 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,\r
- 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,\r
- 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,\r
- 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,\r
- 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,\r
- 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,\r
- 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,\r
- 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,\r
- 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,\r
- 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,\r
- 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,\r
- 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,\r
- 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,\r
- 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,\r
- 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,\r
- 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,\r
- 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,\r
- 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,\r
- 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,\r
- 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,\r
- 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,\r
- 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,\r
- 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,\r
- 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,\r
- 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,\r
- 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,\r
- 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,\r
- 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,\r
- 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,\r
- 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,\r
- 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,\r
- 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,\r
- 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,\r
- 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,\r
- 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,\r
- 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,\r
- 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,\r
- 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,\r
-};\r
-static const u32 Td3[256] = {\r
- 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,\r
- 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,\r
- 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,\r
- 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,\r
- 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,\r
- 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,\r
- 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,\r
- 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,\r
- 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,\r
- 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,\r
- 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,\r
- 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,\r
- 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,\r
- 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,\r
- 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,\r
- 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,\r
- 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,\r
- 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,\r
- 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,\r
- 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,\r
- 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,\r
- 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,\r
- 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,\r
- 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,\r
- 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,\r
- 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,\r
- 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,\r
- 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,\r
- 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,\r
- 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,\r
- 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,\r
- 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,\r
- 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,\r
- 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,\r
- 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,\r
- 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,\r
- 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,\r
- 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,\r
- 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,\r
- 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,\r
- 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,\r
- 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,\r
- 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,\r
- 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,\r
- 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,\r
- 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,\r
- 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,\r
- 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,\r
- 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,\r
- 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,\r
- 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,\r
- 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,\r
- 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,\r
- 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,\r
- 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,\r
- 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,\r
- 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,\r
- 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,\r
- 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,\r
- 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,\r
- 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,\r
- 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,\r
- 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,\r
- 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,\r
-};\r
-static const u32 Td4[256] = {\r
- 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,\r
- 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,\r
- 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,\r
- 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,\r
- 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,\r
- 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,\r
- 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,\r
- 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,\r
- 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,\r
- 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,\r
- 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,\r
- 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,\r
- 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,\r
- 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,\r
- 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,\r
- 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,\r
- 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,\r
- 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,\r
- 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,\r
- 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,\r
- 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,\r
- 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,\r
- 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,\r
- 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,\r
- 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,\r
- 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,\r
- 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,\r
- 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,\r
- 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,\r
- 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,\r
- 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,\r
- 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,\r
- 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,\r
- 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,\r
- 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,\r
- 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,\r
- 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,\r
- 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,\r
- 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,\r
- 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,\r
- 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,\r
- 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,\r
- 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,\r
- 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,\r
- 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,\r
- 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,\r
- 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,\r
- 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,\r
- 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,\r
- 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,\r
- 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,\r
- 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,\r
- 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,\r
- 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,\r
- 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,\r
- 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,\r
- 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,\r
- 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,\r
- 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,\r
- 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,\r
- 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,\r
- 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,\r
- 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,\r
- 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,\r
-};\r
-static const u32 rcon[] = {\r
- 0x01000000, 0x02000000, 0x04000000, 0x08000000,\r
- 0x10000000, 0x20000000, 0x40000000, 0x80000000,\r
- 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */\r
-};\r
-\r
-/**\r
- * Expand the cipher key into the encryption key schedule.\r
- */\r
-int AES_set_encrypt_key(const unsigned char *userKey, const int bits,\r
- AES_KEY *key) {\r
-\r
- u32 *rk;\r
- int i = 0;\r
- u32 temp;\r
-\r
- if (!userKey || !key)\r
- return -1;\r
- if (bits != 128 && bits != 192 && bits != 256)\r
- return -2;\r
-\r
- rk = key->rd_key;\r
-\r
- if (bits==128)\r
- key->rounds = 10;\r
- else if (bits==192)\r
- key->rounds = 12;\r
- else\r
- key->rounds = 14;\r
-\r
- rk[0] = GETU32(userKey );\r
- rk[1] = GETU32(userKey + 4);\r
- rk[2] = GETU32(userKey + 8);\r
- rk[3] = GETU32(userKey + 12);\r
- if (bits == 128) {\r
- while (1) {\r
- temp = rk[3];\r
- rk[4] = rk[0] ^\r
- (Te4[(temp >> 16) & 0xff] & 0xff000000) ^\r
- (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^\r
- (Te4[(temp ) & 0xff] & 0x0000ff00) ^\r
- (Te4[(temp >> 24) ] & 0x000000ff) ^\r
- rcon[i];\r
- rk[5] = rk[1] ^ rk[4];\r
- rk[6] = rk[2] ^ rk[5];\r
- rk[7] = rk[3] ^ rk[6];\r
- if (++i == 10) {\r
- return 0;\r
- }\r
- rk += 4;\r
- }\r
- }\r
- rk[4] = GETU32(userKey + 16);\r
- rk[5] = GETU32(userKey + 20);\r
- if (bits == 192) {\r
- while (1) {\r
- temp = rk[ 5];\r
- rk[ 6] = rk[ 0] ^\r
- (Te4[(temp >> 16) & 0xff] & 0xff000000) ^\r
- (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^\r
- (Te4[(temp ) & 0xff] & 0x0000ff00) ^\r
- (Te4[(temp >> 24) ] & 0x000000ff) ^\r
- rcon[i];\r
- rk[ 7] = rk[ 1] ^ rk[ 6];\r
- rk[ 8] = rk[ 2] ^ rk[ 7];\r
- rk[ 9] = rk[ 3] ^ rk[ 8];\r
- if (++i == 8) {\r
- return 0;\r
- }\r
- rk[10] = rk[ 4] ^ rk[ 9];\r
- rk[11] = rk[ 5] ^ rk[10];\r
- rk += 6;\r
- }\r
- }\r
- rk[6] = GETU32(userKey + 24);\r
- rk[7] = GETU32(userKey + 28);\r
- if (bits == 256) {\r
- while (1) {\r
- temp = rk[ 7];\r
- rk[ 8] = rk[ 0] ^\r
- (Te4[(temp >> 16) & 0xff] & 0xff000000) ^\r
- (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^\r
- (Te4[(temp ) & 0xff] & 0x0000ff00) ^\r
- (Te4[(temp >> 24) ] & 0x000000ff) ^\r
- rcon[i];\r
- rk[ 9] = rk[ 1] ^ rk[ 8];\r
- rk[10] = rk[ 2] ^ rk[ 9];\r
- rk[11] = rk[ 3] ^ rk[10];\r
- if (++i == 7) {\r
- return 0;\r
- }\r
- temp = rk[11];\r
- rk[12] = rk[ 4] ^\r
- (Te4[(temp >> 24) ] & 0xff000000) ^\r
- (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^\r
- (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^\r
- (Te4[(temp ) & 0xff] & 0x000000ff);\r
- rk[13] = rk[ 5] ^ rk[12];\r
- rk[14] = rk[ 6] ^ rk[13];\r
- rk[15] = rk[ 7] ^ rk[14];\r
-\r
- rk += 8;\r
- }\r
- }\r
- return 0;\r
-}\r
-\r
-/**\r
- * Expand the cipher key into the decryption key schedule.\r
- */\r
-int AES_set_decrypt_key(const unsigned char *userKey, const int bits,\r
- AES_KEY *key) {\r
-\r
- u32 *rk;\r
- int i, j, status;\r
- u32 temp;\r
-\r
- /* first, start with an encryption schedule */\r
- status = AES_set_encrypt_key(userKey, bits, key);\r
- if (status < 0)\r
- return status;\r
-\r
- rk = key->rd_key;\r
-\r
- /* invert the order of the round keys: */\r
- for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) {\r
- temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;\r
- temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;\r
- temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;\r
- temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;\r
- }\r
- /* apply the inverse MixColumn transform to all round keys but the first and the last: */\r
- for (i = 1; i < (key->rounds); i++) {\r
- rk += 4;\r
- rk[0] =\r
- Td0[Te4[(rk[0] >> 24) ] & 0xff] ^\r
- Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^\r
- Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^\r
- Td3[Te4[(rk[0] ) & 0xff] & 0xff];\r
- rk[1] =\r
- Td0[Te4[(rk[1] >> 24) ] & 0xff] ^\r
- Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^\r
- Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^\r
- Td3[Te4[(rk[1] ) & 0xff] & 0xff];\r
- rk[2] =\r
- Td0[Te4[(rk[2] >> 24) ] & 0xff] ^\r
- Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^\r
- Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^\r
- Td3[Te4[(rk[2] ) & 0xff] & 0xff];\r
- rk[3] =\r
- Td0[Te4[(rk[3] >> 24) ] & 0xff] ^\r
- Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^\r
- Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^\r
- Td3[Te4[(rk[3] ) & 0xff] & 0xff];\r
- }\r
- return 0;\r
-}\r
-\r
-/*\r
- * Encrypt a single block\r
- * in and out can overlap\r
- */\r
-void AES_encrypt(const unsigned char *in, unsigned char *out,\r
- const AES_KEY *key) {\r
-\r
- const u32 *rk;\r
- u32 s0, s1, s2, s3, t0, t1, t2, t3;\r
-#ifndef FULL_UNROLL\r
- int r;\r
-#endif /* ?FULL_UNROLL */\r
-\r
- assert(in && out && key);\r
- rk = key->rd_key;\r
-\r
- /*\r
- * map byte array block to cipher state\r
- * and add initial round key:\r
- */\r
- s0 = GETU32(in ) ^ rk[0];\r
- s1 = GETU32(in + 4) ^ rk[1];\r
- s2 = GETU32(in + 8) ^ rk[2];\r
- s3 = GETU32(in + 12) ^ rk[3];\r
-#ifdef FULL_UNROLL\r
- /* round 1: */\r
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];\r
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];\r
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];\r
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];\r
- /* round 2: */\r
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];\r
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];\r
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];\r
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];\r
- /* round 3: */\r
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];\r
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];\r
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];\r
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];\r
- /* round 4: */\r
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];\r
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];\r
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];\r
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];\r
- /* round 5: */\r
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];\r
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];\r
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];\r
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];\r
- /* round 6: */\r
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];\r
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];\r
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];\r
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];\r
- /* round 7: */\r
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];\r
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];\r
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];\r
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];\r
- /* round 8: */\r
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];\r
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];\r
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];\r
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];\r
- /* round 9: */\r
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];\r
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];\r
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];\r
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];\r
- if (key->rounds > 10) {\r
- /* round 10: */\r
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];\r
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];\r
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];\r
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];\r
- /* round 11: */\r
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];\r
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];\r
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];\r
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];\r
- if (key->rounds > 12) {\r
- /* round 12: */\r
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];\r
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];\r
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];\r
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];\r
- /* round 13: */\r
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];\r
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];\r
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];\r
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];\r
- }\r
- }\r
- rk += key->rounds << 2;\r
-#else /* !FULL_UNROLL */\r
- /*\r
- * Nr - 1 full rounds:\r
- */\r
- r = key->rounds >> 1;\r
- for (;;) {\r
- t0 =\r
- Te0[(s0 >> 24) ] ^\r
- Te1[(s1 >> 16) & 0xff] ^\r
- Te2[(s2 >> 8) & 0xff] ^\r
- Te3[(s3 ) & 0xff] ^\r
- rk[4];\r
- t1 =\r
- Te0[(s1 >> 24) ] ^\r
- Te1[(s2 >> 16) & 0xff] ^\r
- Te2[(s3 >> 8) & 0xff] ^\r
- Te3[(s0 ) & 0xff] ^\r
- rk[5];\r
- t2 =\r
- Te0[(s2 >> 24) ] ^\r
- Te1[(s3 >> 16) & 0xff] ^\r
- Te2[(s0 >> 8) & 0xff] ^\r
- Te3[(s1 ) & 0xff] ^\r
- rk[6];\r
- t3 =\r
- Te0[(s3 >> 24) ] ^\r
- Te1[(s0 >> 16) & 0xff] ^\r
- Te2[(s1 >> 8) & 0xff] ^\r
- Te3[(s2 ) & 0xff] ^\r
- rk[7];\r
-\r
- rk += 8;\r
- if (--r == 0) {\r
- break;\r
- }\r
-\r
- s0 =\r
- Te0[(t0 >> 24) ] ^\r
- Te1[(t1 >> 16) & 0xff] ^\r
- Te2[(t2 >> 8) & 0xff] ^\r
- Te3[(t3 ) & 0xff] ^\r
- rk[0];\r
- s1 =\r
- Te0[(t1 >> 24) ] ^\r
- Te1[(t2 >> 16) & 0xff] ^\r
- Te2[(t3 >> 8) & 0xff] ^\r
- Te3[(t0 ) & 0xff] ^\r
- rk[1];\r
- s2 =\r
- Te0[(t2 >> 24) ] ^\r
- Te1[(t3 >> 16) & 0xff] ^\r
- Te2[(t0 >> 8) & 0xff] ^\r
- Te3[(t1 ) & 0xff] ^\r
- rk[2];\r
- s3 =\r
- Te0[(t3 >> 24) ] ^\r
- Te1[(t0 >> 16) & 0xff] ^\r
- Te2[(t1 >> 8) & 0xff] ^\r
- Te3[(t2 ) & 0xff] ^\r
- rk[3];\r
- }\r
-#endif /* ?FULL_UNROLL */\r
- /*\r
- * apply last round and\r
- * map cipher state to byte array block:\r
- */\r
- s0 =\r
- (Te4[(t0 >> 24) ] & 0xff000000) ^\r
- (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^\r
- (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^\r
- (Te4[(t3 ) & 0xff] & 0x000000ff) ^\r
- rk[0];\r
- PUTU32(out , s0);\r
- s1 =\r
- (Te4[(t1 >> 24) ] & 0xff000000) ^\r
- (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^\r
- (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^\r
- (Te4[(t0 ) & 0xff] & 0x000000ff) ^\r
- rk[1];\r
- PUTU32(out + 4, s1);\r
- s2 =\r
- (Te4[(t2 >> 24) ] & 0xff000000) ^\r
- (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^\r
- (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^\r
- (Te4[(t1 ) & 0xff] & 0x000000ff) ^\r
- rk[2];\r
- PUTU32(out + 8, s2);\r
- s3 =\r
- (Te4[(t3 >> 24) ] & 0xff000000) ^\r
- (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^\r
- (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^\r
- (Te4[(t2 ) & 0xff] & 0x000000ff) ^\r
- rk[3];\r
- PUTU32(out + 12, s3);\r
-}\r
-\r
-/*\r
- * Decrypt a single block\r
- * in and out can overlap\r
- */\r
-void AES_decrypt(const unsigned char *in, unsigned char *out,\r
- const AES_KEY *key) {\r
-\r
- const u32 *rk;\r
- u32 s0, s1, s2, s3, t0, t1, t2, t3;\r
-#ifndef FULL_UNROLL\r
- int r;\r
-#endif /* ?FULL_UNROLL */\r
-\r
- assert(in && out && key);\r
- rk = key->rd_key;\r
-\r
- /*\r
- * map byte array block to cipher state\r
- * and add initial round key:\r
- */\r
- s0 = GETU32(in ) ^ rk[0];\r
- s1 = GETU32(in + 4) ^ rk[1];\r
- s2 = GETU32(in + 8) ^ rk[2];\r
- s3 = GETU32(in + 12) ^ rk[3];\r
-#ifdef FULL_UNROLL\r
- /* round 1: */\r
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];\r
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];\r
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];\r
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];\r
- /* round 2: */\r
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];\r
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];\r
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];\r
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];\r
- /* round 3: */\r
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];\r
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];\r
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];\r
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];\r
- /* round 4: */\r
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];\r
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];\r
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];\r
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];\r
- /* round 5: */\r
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];\r
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];\r
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];\r
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];\r
- /* round 6: */\r
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];\r
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];\r
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];\r
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];\r
- /* round 7: */\r
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];\r
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];\r
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];\r
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];\r
- /* round 8: */\r
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];\r
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];\r
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];\r
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];\r
- /* round 9: */\r
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];\r
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];\r
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];\r
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];\r
- if (key->rounds > 10) {\r
- /* round 10: */\r
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];\r
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];\r
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];\r
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];\r
- /* round 11: */\r
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];\r
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];\r
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];\r
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];\r
- if (key->rounds > 12) {\r
- /* round 12: */\r
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];\r
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];\r
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];\r
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];\r
- /* round 13: */\r
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];\r
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];\r
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];\r
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];\r
- }\r
- }\r
- rk += key->rounds << 2;\r
-#else /* !FULL_UNROLL */\r
- /*\r
- * Nr - 1 full rounds:\r
- */\r
- r = key->rounds >> 1;\r
- for (;;) {\r
- t0 =\r
- Td0[(s0 >> 24) ] ^\r
- Td1[(s3 >> 16) & 0xff] ^\r
- Td2[(s2 >> 8) & 0xff] ^\r
- Td3[(s1 ) & 0xff] ^\r
- rk[4];\r
- t1 =\r
- Td0[(s1 >> 24) ] ^\r
- Td1[(s0 >> 16) & 0xff] ^\r
- Td2[(s3 >> 8) & 0xff] ^\r
- Td3[(s2 ) & 0xff] ^\r
- rk[5];\r
- t2 =\r
- Td0[(s2 >> 24) ] ^\r
- Td1[(s1 >> 16) & 0xff] ^\r
- Td2[(s0 >> 8) & 0xff] ^\r
- Td3[(s3 ) & 0xff] ^\r
- rk[6];\r
- t3 =\r
- Td0[(s3 >> 24) ] ^\r
- Td1[(s2 >> 16) & 0xff] ^\r
- Td2[(s1 >> 8) & 0xff] ^\r
- Td3[(s0 ) & 0xff] ^\r
- rk[7];\r
-\r
- rk += 8;\r
- if (--r == 0) {\r
- break;\r
- }\r
-\r
- s0 =\r
- Td0[(t0 >> 24) ] ^\r
- Td1[(t3 >> 16) & 0xff] ^\r
- Td2[(t2 >> 8) & 0xff] ^\r
- Td3[(t1 ) & 0xff] ^\r
- rk[0];\r
- s1 =\r
- Td0[(t1 >> 24) ] ^\r
- Td1[(t0 >> 16) & 0xff] ^\r
- Td2[(t3 >> 8) & 0xff] ^\r
- Td3[(t2 ) & 0xff] ^\r
- rk[1];\r
- s2 =\r
- Td0[(t2 >> 24) ] ^\r
- Td1[(t1 >> 16) & 0xff] ^\r
- Td2[(t0 >> 8) & 0xff] ^\r
- Td3[(t3 ) & 0xff] ^\r
- rk[2];\r
- s3 =\r
- Td0[(t3 >> 24) ] ^\r
- Td1[(t2 >> 16) & 0xff] ^\r
- Td2[(t1 >> 8) & 0xff] ^\r
- Td3[(t0 ) & 0xff] ^\r
- rk[3];\r
- }\r
-#endif /* ?FULL_UNROLL */\r
- /*\r
- * apply last round and\r
- * map cipher state to byte array block:\r
- */\r
- s0 =\r
- (Td4[(t0 >> 24) ] & 0xff000000) ^\r
- (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^\r
- (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^\r
- (Td4[(t1 ) & 0xff] & 0x000000ff) ^\r
- rk[0];\r
- PUTU32(out , s0);\r
- s1 =\r
- (Td4[(t1 >> 24) ] & 0xff000000) ^\r
- (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^\r
- (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^\r
- (Td4[(t2 ) & 0xff] & 0x000000ff) ^\r
- rk[1];\r
- PUTU32(out + 4, s1);\r
- s2 =\r
- (Td4[(t2 >> 24) ] & 0xff000000) ^\r
- (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^\r
- (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^\r
- (Td4[(t3 ) & 0xff] & 0x000000ff) ^\r
- rk[2];\r
- PUTU32(out + 8, s2);\r
- s3 =\r
- (Td4[(t3 >> 24) ] & 0xff000000) ^\r
- (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^\r
- (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^\r
- (Td4[(t0 ) & 0xff] & 0x000000ff) ^\r
- rk[3];\r
- PUTU32(out + 12, s3);\r
-}\r
-\r
-void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,\r
- const unsigned long length, const AES_KEY *key,\r
- unsigned char *ivec, const int enc) {\r
-\r
- unsigned long n;\r
- unsigned long len = length;\r
- unsigned char tmp[AES_BLOCK_SIZE];\r
-\r
- assert(in && out && key && ivec);\r
- assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc));\r
-\r
- if (AES_ENCRYPT == enc) {\r
- while (len >= AES_BLOCK_SIZE) {\r
- for(n=0; n < AES_BLOCK_SIZE; ++n)\r
- tmp[n] = in[n] ^ ivec[n];\r
- AES_encrypt(tmp, out, key);\r
- memcpy(ivec, out, AES_BLOCK_SIZE);\r
- len -= AES_BLOCK_SIZE;\r
- in += AES_BLOCK_SIZE;\r
- out += AES_BLOCK_SIZE;\r
- }\r
- if (len) {\r
- for(n=0; n < len; ++n)\r
- tmp[n] = in[n] ^ ivec[n];\r
- for(n=len; n < AES_BLOCK_SIZE; ++n)\r
- tmp[n] = ivec[n];\r
- AES_encrypt(tmp, tmp, key);\r
- memcpy(out, tmp, AES_BLOCK_SIZE);\r
- memcpy(ivec, tmp, AES_BLOCK_SIZE);\r
- } \r
- } else {\r
- while (len >= AES_BLOCK_SIZE) {\r
- memcpy(tmp, in, AES_BLOCK_SIZE);\r
- AES_decrypt(in, out, key);\r
- for(n=0; n < AES_BLOCK_SIZE; ++n)\r
- out[n] ^= ivec[n];\r
- memcpy(ivec, tmp, AES_BLOCK_SIZE);\r
- len -= AES_BLOCK_SIZE;\r
- in += AES_BLOCK_SIZE;\r
- out += AES_BLOCK_SIZE;\r
- }\r
- if (len) {\r
- memcpy(tmp, in, AES_BLOCK_SIZE);\r
- AES_decrypt(tmp, tmp, key);\r
- for(n=0; n < len; ++n)\r
- out[n] ^= ivec[n];\r
- memcpy(ivec, tmp, AES_BLOCK_SIZE);\r
- } \r
- }\r
-}\r
-\r
-void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,\r
- const unsigned long length, const AES_KEY *key,\r
- unsigned char *ivec, int *num, const int enc) {\r
-\r
- unsigned int n;\r
- unsigned long l = length;\r
- unsigned char c;\r
-\r
- assert(in && out && key && ivec && num);\r
-\r
- n = *num;\r
-\r
- if (enc) {\r
- while (l--) {\r
- if (n == 0) {\r
- AES_encrypt(ivec, ivec, key);\r
- }\r
- ivec[n] = *(out++) = *(in++) ^ ivec[n];\r
- n = (n+1) % AES_BLOCK_SIZE;\r
- }\r
- } else {\r
- while (l--) {\r
- if (n == 0) {\r
- AES_encrypt(ivec, ivec, key);\r
- }\r
- c = *(in);\r
- *(out++) = *(in++) ^ ivec[n];\r
- ivec[n] = c;\r
- n = (n+1) % AES_BLOCK_SIZE;\r
- }\r
- }\r
-\r
- *num=n;\r
-}\r
-\r
-/* increment counter (128-bit int) by 1 */\r
-static void AES_ctr128_inc(unsigned char *counter) {\r
- unsigned long c;\r
-\r
- /* Grab bottom dword of counter and increment */\r
-#ifdef L_ENDIAN\r
- c = GETU32(counter + 0);\r
- c++;\r
- PUTU32(counter + 0, c);\r
-#else\r
- c = GETU32(counter + 12);\r
- c++;\r
- PUTU32(counter + 12, c);\r
-#endif\r
-\r
- /* if no overflow, we're done */\r
- if (c)\r
- return;\r
-\r
- /* Grab 1st dword of counter and increment */\r
-#ifdef L_ENDIAN\r
- c = GETU32(counter + 4);\r
- c++;\r
- PUTU32(counter + 4, c);\r
-#else\r
- c = GETU32(counter + 8);\r
- c++;\r
- PUTU32(counter + 8, c);\r
-#endif\r
-\r
- /* if no overflow, we're done */\r
- if (c)\r
- return;\r
-\r
- /* Grab 2nd dword of counter and increment */\r
-#ifdef L_ENDIAN\r
- c = GETU32(counter + 8);\r
- c++;\r
- PUTU32(counter + 8, c);\r
-#else\r
- c = GETU32(counter + 4);\r
- c++;\r
- PUTU32(counter + 4, c);\r
-#endif\r
-\r
- /* if no overflow, we're done */\r
- if (c)\r
- return;\r
-\r
- /* Grab top dword of counter and increment */\r
-#ifdef L_ENDIAN\r
- c = GETU32(counter + 12);\r
- c++;\r
- PUTU32(counter + 12, c);\r
-#else\r
- c = GETU32(counter + 0);\r
- c++;\r
- PUTU32(counter + 0, c);\r
-#endif\r
-\r
-}\r
-\r
-void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,\r
- const unsigned long length, const AES_KEY *key,\r
- unsigned char ivec[AES_BLOCK_SIZE],\r
- unsigned char ecount_buf[AES_BLOCK_SIZE],\r
- unsigned int *num) {\r
-\r
- unsigned int n;\r
- unsigned long l=length;\r
-\r
-// assert(in && out && key && counter && num);\r
- assert(in && out && key && num);\r
- assert(*num < AES_BLOCK_SIZE);\r
-\r
- n = *num;\r
-\r
- while (l--) {\r
- if (n == 0) {\r
- AES_encrypt(ivec, ecount_buf, key);\r
- AES_ctr128_inc(ivec);\r
- }\r
- *(out++) = *(in++) ^ ecount_buf[n];\r
- n = (n+1) % AES_BLOCK_SIZE;\r
- }\r
-\r
- *num=n;\r
-}\r
-\r
-void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,\r
- const AES_KEY *key, const int enc) {\r
-\r
- assert(in && out && key);\r
- assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc));\r
-\r
- if (AES_ENCRYPT == enc)\r
- AES_encrypt(in, out, key);\r
- else\r
- AES_decrypt(in, out, key);\r
-}\r
-\r
-const char *AES_version="AES";\r
-\r
-const char *AES_options(void) {\r
-#ifdef FULL_UNROLL\r
- return "aes(full)";\r
-#else \r
- return "aes(partial)";\r
-#endif\r
-}\r
-\r
-void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,\r
- const unsigned long length, const AES_KEY *key,\r
- unsigned char *ivec, int *num) {\r
-\r
- unsigned int n;\r
- unsigned long l=length;\r
-\r
- assert(in && out && key && ivec && num);\r
-\r
- n = *num;\r
-\r
- while (l--) {\r
- if (n == 0) {\r
- AES_encrypt(ivec, ivec, key);\r
- }\r
- *(out++) = *(in++) ^ ivec[n];\r
- n = (n+1) % AES_BLOCK_SIZE;\r
- }\r
-\r
- *num=n;\r
-}\r
+++ /dev/null
-/* crypto/idea/i_cbc.c */
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to. The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code. The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * "This product includes cryptographic software written by
- * Eric Young (eay@cryptsoft.com)"
- * The word 'cryptographic' can be left out if the rouines from the library
- * being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- * the apps directory (application code) you must include an acknowledgement:
- * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed. i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-#include "idea.h"
-#include "idea_lcl.h"
-
-void idea_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
- IDEA_KEY_SCHEDULE *ks, unsigned char *iv, int encrypt)
- {
- register unsigned long tin0,tin1;
- register unsigned long tout0,tout1,xor0,xor1;
- register long l=length;
- unsigned long tin[2];
-
- if (encrypt)
- {
- n2l(iv,tout0);
- n2l(iv,tout1);
- iv-=8;
- for (l-=8; l>=0; l-=8)
- {
- n2l(in,tin0);
- n2l(in,tin1);
- tin0^=tout0;
- tin1^=tout1;
- tin[0]=tin0;
- tin[1]=tin1;
- idea_encrypt(tin,ks);
- tout0=tin[0]; l2n(tout0,out);
- tout1=tin[1]; l2n(tout1,out);
- }
- if (l != -8)
- {
- n2ln(in,tin0,tin1,l+8);
- tin0^=tout0;
- tin1^=tout1;
- tin[0]=tin0;
- tin[1]=tin1;
- idea_encrypt(tin,ks);
- tout0=tin[0]; l2n(tout0,out);
- tout1=tin[1]; l2n(tout1,out);
- }
- l2n(tout0,iv);
- l2n(tout1,iv);
- }
- else
- {
- n2l(iv,xor0);
- n2l(iv,xor1);
- iv-=8;
- for (l-=8; l>=0; l-=8)
- {
- n2l(in,tin0); tin[0]=tin0;
- n2l(in,tin1); tin[1]=tin1;
- idea_encrypt(tin,ks);
- tout0=tin[0]^xor0;
- tout1=tin[1]^xor1;
- l2n(tout0,out);
- l2n(tout1,out);
- xor0=tin0;
- xor1=tin1;
- }
- if (l != -8)
- {
- n2l(in,tin0); tin[0]=tin0;
- n2l(in,tin1); tin[1]=tin1;
- idea_encrypt(tin,ks);
- tout0=tin[0]^xor0;
- tout1=tin[1]^xor1;
- l2nn(tout0,tout1,out,l+8);
- xor0=tin0;
- xor1=tin1;
- }
- l2n(xor0,iv);
- l2n(xor1,iv);
- }
- tin0=tin1=tout0=tout1=xor0=xor1=0;
- tin[0]=tin[1]=0;
- }
-
-void idea_encrypt(unsigned long *d, IDEA_KEY_SCHEDULE *key)
- {
- register IDEA_INT *p;
- register unsigned long x1,x2,x3,x4,t0,t1,ul;
-
- x2=d[0];
- x1=(x2>>16);
- x4=d[1];
- x3=(x4>>16);
-
- p= &(key->data[0][0]);
-
- E_IDEA(0);
- E_IDEA(1);
- E_IDEA(2);
- E_IDEA(3);
- E_IDEA(4);
- E_IDEA(5);
- E_IDEA(6);
- E_IDEA(7);
-
- x1&=0xffff;
- idea_mul(x1,x1,*p,ul); p++;
-
- t0= x3+ *(p++);
- t1= x2+ *(p++);
-
- x4&=0xffff;
- idea_mul(x4,x4,*p,ul);
-
- d[0]=(t0&0xffff)|((x1&0xffff)<<16);
- d[1]=(x4&0xffff)|((t1&0xffff)<<16);
- }
+++ /dev/null
-/* crypto/idea/i_skey.c */
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to. The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code. The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * "This product includes cryptographic software written by
- * Eric Young (eay@cryptsoft.com)"
- * The word 'cryptographic' can be left out if the rouines from the library
- * being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- * the apps directory (application code) you must include an acknowledgement:
- * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed. i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-#include "idea.h"
-#include "idea_lcl.h"
-
-static IDEA_INT inverse(unsigned int xin);
-void idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks)
- {
- int i;
- register IDEA_INT *kt,*kf,r0,r1,r2;
-
- kt= &(ks->data[0][0]);
- n2s(key,kt[0]); n2s(key,kt[1]); n2s(key,kt[2]); n2s(key,kt[3]);
- n2s(key,kt[4]); n2s(key,kt[5]); n2s(key,kt[6]); n2s(key,kt[7]);
-
- kf=kt;
- kt+=8;
- for (i=0; i<6; i++)
- {
- r2= kf[1];
- r1= kf[2];
- *(kt++)= ((r2<<9) | (r1>>7))&0xffff;
- r0= kf[3];
- *(kt++)= ((r1<<9) | (r0>>7))&0xffff;
- r1= kf[4];
- *(kt++)= ((r0<<9) | (r1>>7))&0xffff;
- r0= kf[5];
- *(kt++)= ((r1<<9) | (r0>>7))&0xffff;
- r1= kf[6];
- *(kt++)= ((r0<<9) | (r1>>7))&0xffff;
- r0= kf[7];
- *(kt++)= ((r1<<9) | (r0>>7))&0xffff;
- r1= kf[0];
- if (i >= 5) break;
- *(kt++)= ((r0<<9) | (r1>>7))&0xffff;
- *(kt++)= ((r1<<9) | (r2>>7))&0xffff;
- kf+=8;
- }
- }
-
-void idea_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk)
- {
- int r;
- register IDEA_INT *fp,*tp,t;
-
- tp= &(dk->data[0][0]);
- fp= &(ek->data[8][0]);
- for (r=0; r<9; r++)
- {
- *(tp++)=inverse(fp[0]);
- *(tp++)=((int)(0x10000L-fp[2])&0xffff);
- *(tp++)=((int)(0x10000L-fp[1])&0xffff);
- *(tp++)=inverse(fp[3]);
- if (r == 8) break;
- fp-=6;
- *(tp++)=fp[4];
- *(tp++)=fp[5];
- }
-
- tp= &(dk->data[0][0]);
- t=tp[1];
- tp[1]=tp[2];
- tp[2]=t;
-
- t=tp[49];
- tp[49]=tp[50];
- tp[50]=t;
- }
-
-/* taken directly from the 'paper' I'll have a look at it later */
-static IDEA_INT inverse(unsigned int xin)
- {
- long n1,n2,q,r,b1,b2,t;
-
- if (xin == 0)
- b2=0;
- else
- {
- n1=0x10001;
- n2=xin;
- b2=1;
- b1=0;
-
- do {
- r=(n1%n2);
- q=(n1-r)/n2;
- if (r == 0)
- { if (b2 < 0) b2=0x10001+b2; }
- else
- {
- n1=n2;
- n2=r;
- t=b2;
- b2=b1-q*b2;
- b1=t;
- }
- } while (r != 0);
- }
- return((IDEA_INT)b2);
- }
+++ /dev/null
-/* crypto/idea/idea.h */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to. The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code. The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * "This product includes cryptographic software written by
- * Eric Young (eay@cryptsoft.com)"
- * The word 'cryptographic' can be left out if the rouines from the library
- * being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- * the apps directory (application code) you must include an acknowledgement:
- * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed. i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-#ifndef HEADER_IDEA_H
-#define HEADER_IDEA_H
-
-/*#include <openssl/opensslconf.h>*/ /* IDEA_INT, OPENSSL_NO_IDEA */
-#define IDEA_INT unsigned int
-
-/*
-#ifdef OPENSSL_NO_IDEA
-#error IDEA is disabled.
-#endif
-*/
-
-#define IDEA_ENCRYPT 1
-#define IDEA_DECRYPT 0
-
-#define IDEA_BLOCK 8
-#define IDEA_KEY_LENGTH 16
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct idea_key_st
- {
- IDEA_INT data[9][6];
- } IDEA_KEY_SCHEDULE;
-
-const char *idea_options(void);
-void idea_ecb_encrypt(const unsigned char *in, unsigned char *out,
- IDEA_KEY_SCHEDULE *ks);
-void idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks);
-void idea_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk);
-void idea_cbc_encrypt(const unsigned char *in, unsigned char *out,
- long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,int enc);
-void idea_cfb64_encrypt(const unsigned char *in, unsigned char *out,
- long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,
- int *num,int enc);
-void idea_ofb64_encrypt(const unsigned char *in, unsigned char *out,
- long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, int *num);
-void idea_encrypt(unsigned long *in, IDEA_KEY_SCHEDULE *ks);
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-/* crypto/idea/idea_lcl.h */
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to. The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code. The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * "This product includes cryptographic software written by
- * Eric Young (eay@cryptsoft.com)"
- * The word 'cryptographic' can be left out if the rouines from the library
- * being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- * the apps directory (application code) you must include an acknowledgement:
- * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed. i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-/* The new form of this macro (check if the a*b == 0) was suggested by
- * Colin Plumb <colin@nyx10.cs.du.edu> */
-/* Removal of the inner if from from Wei Dai 24/4/96 */
-#define idea_mul(r,a,b,ul) \
-ul=(unsigned long)a*b; \
-if (ul != 0) \
- { \
- r=(ul&0xffff)-(ul>>16); \
- r-=((r)>>16); \
- } \
-else \
- r=(-(int)a-b+1); /* assuming a or b is 0 and in range */ \
-
-#ifdef undef
-#define idea_mul(r,a,b,ul,sl) \
-if (a == 0) r=(0x10001-b)&0xffff; \
-else if (b == 0) r=(0x10001-a)&0xffff; \
-else { \
- ul=(unsigned long)a*b; \
- sl=(ul&0xffff)-(ul>>16); \
- if (sl <= 0) sl+=0x10001; \
- r=sl; \
- }
-#endif
-
-/* 7/12/95 - Many thanks to Rhys Weatherley <rweather@us.oracle.com>
- * for pointing out that I was assuming little endian
- * byte order for all quantities what idea
- * actually used bigendian. No where in the spec does it mention
- * this, it is all in terms of 16 bit numbers and even the example
- * does not use byte streams for the input example :-(.
- * If you byte swap each pair of input, keys and iv, the functions
- * would produce the output as the old version :-(.
- */
-
-/* NOTE - c is not incremented as per n2l */
-#define n2ln(c,l1,l2,n) { \
- c+=n; \
- l1=l2=0; \
- switch (n) { \
- case 8: l2 =((unsigned long)(*(--(c)))) ; \
- case 7: l2|=((unsigned long)(*(--(c))))<< 8; \
- case 6: l2|=((unsigned long)(*(--(c))))<<16; \
- case 5: l2|=((unsigned long)(*(--(c))))<<24; \
- case 4: l1 =((unsigned long)(*(--(c)))) ; \
- case 3: l1|=((unsigned long)(*(--(c))))<< 8; \
- case 2: l1|=((unsigned long)(*(--(c))))<<16; \
- case 1: l1|=((unsigned long)(*(--(c))))<<24; \
- } \
- }
-
-/* NOTE - c is not incremented as per l2n */
-#define l2nn(l1,l2,c,n) { \
- c+=n; \
- switch (n) { \
- case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \
- case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
- case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
- case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
- case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \
- case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
- case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
- case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
- } \
- }
-
-#undef n2l
-#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24L, \
- l|=((unsigned long)(*((c)++)))<<16L, \
- l|=((unsigned long)(*((c)++)))<< 8L, \
- l|=((unsigned long)(*((c)++))))
-
-#undef l2n
-#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \
- *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
- *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
- *((c)++)=(unsigned char)(((l) )&0xff))
-
-#undef s2n
-#define s2n(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
- *((c)++)=(unsigned char)(((l)>> 8L)&0xff))
-
-#undef n2s
-#define n2s(c,l) (l =((IDEA_INT)(*((c)++)))<< 8L, \
- l|=((IDEA_INT)(*((c)++))) )
-
-#ifdef undef
-/* NOTE - c is not incremented as per c2l */
-#define c2ln(c,l1,l2,n) { \
- c+=n; \
- l1=l2=0; \
- switch (n) { \
- case 8: l2 =((unsigned long)(*(--(c))))<<24; \
- case 7: l2|=((unsigned long)(*(--(c))))<<16; \
- case 6: l2|=((unsigned long)(*(--(c))))<< 8; \
- case 5: l2|=((unsigned long)(*(--(c)))); \
- case 4: l1 =((unsigned long)(*(--(c))))<<24; \
- case 3: l1|=((unsigned long)(*(--(c))))<<16; \
- case 2: l1|=((unsigned long)(*(--(c))))<< 8; \
- case 1: l1|=((unsigned long)(*(--(c)))); \
- } \
- }
-
-/* NOTE - c is not incremented as per l2c */
-#define l2cn(l1,l2,c,n) { \
- c+=n; \
- switch (n) { \
- case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
- case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
- case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
- case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \
- case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
- case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
- case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
- case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \
- } \
- }
-
-#undef c2s
-#define c2s(c,l) (l =((unsigned long)(*((c)++))) , \
- l|=((unsigned long)(*((c)++)))<< 8L)
-
-#undef s2c
-#define s2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
- *((c)++)=(unsigned char)(((l)>> 8L)&0xff))
-
-#undef c2l
-#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \
- l|=((unsigned long)(*((c)++)))<< 8L, \
- l|=((unsigned long)(*((c)++)))<<16L, \
- l|=((unsigned long)(*((c)++)))<<24L)
-
-#undef l2c
-#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
- *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
- *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
- *((c)++)=(unsigned char)(((l)>>24L)&0xff))
-#endif
-
-#define E_IDEA(num) \
- x1&=0xffff; \
- idea_mul(x1,x1,*p,ul); p++; \
- x2+= *(p++); \
- x3+= *(p++); \
- x4&=0xffff; \
- idea_mul(x4,x4,*p,ul); p++; \
- t0=(x1^x3)&0xffff; \
- idea_mul(t0,t0,*p,ul); p++; \
- t1=(t0+(x2^x4))&0xffff; \
- idea_mul(t1,t1,*p,ul); p++; \
- t0+=t1; \
- x1^=t1; \
- x4^=t0; \
- ul=x2^t0; /* do the swap to x3 */ \
- x2=x3^t1; \
- x3=ul;
-
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <malloc.h>
-#include <ctype.h>
-
-#include <vdr/tools.h>
-
-#include "system-common.h"
-#include "smartcard.h"
-#include "data.h"
-#include "crypto-bn.h"
-
-// -- cHexKey ------------------------------------------------------------------
-
-cHexKey::cHexKey(bool Super)
-:cPlainKey(Super)
-{
- key=0;
-}
-
-cHexKey::~cHexKey()
-{
- free(key);
-}
-
-bool cHexKey::SetKey(void *Key, int Keylen)
-{
- keylen=Keylen;
- free(key); key=MALLOC(unsigned char,keylen);
- if(key) memcpy(key,Key,keylen);
- return key!=0;
-}
-
-bool cHexKey::SetBinKey(unsigned char *Mem, int Keylen)
-{
- return SetKey(Mem,Keylen);
-}
-
-bool cHexKey::Cmp(void *Key, int Keylen)
-{
- return keylen==Keylen && memcmp(key,Key,keylen)==0;
-}
-
-bool cHexKey::Cmp(cPlainKey *k)
-{
- cHexKey *hk=dynamic_cast<cHexKey *>(k); // downcast
- return hk && Cmp(hk->key,hk->keylen);
-}
-
-void cHexKey::Get(void *mem)
-{
- memcpy(mem,key,keylen);
-}
-
-cString cHexKey::Print(void)
-{
- char *str=(char *)malloc(keylen*2+2);
- if(str) HexStr(str,key,keylen);
- return cString(str,true);
-}
-
-// -- cBNKey -------------------------------------------------------------------
-
-cBNKey::cBNKey(bool Super, bool Rotate)
-:cPlainKey(Super)
-{
- key=new cBN; rotate=Rotate;
-}
-
-cBNKey::~cBNKey()
-{
- delete key;
-}
-
-bool cBNKey::SetKey(void *Key ,int Keylen)
-{
- keylen=Keylen;
- return BN_copy(*key,(BIGNUM *)Key)!=0;
-}
-
-bool cBNKey::SetBinKey(unsigned char *Mem, int Keylen)
-{
- keylen=Keylen;
- return rotate ? key->GetLE(Mem,Keylen) : key->Get(Mem,Keylen);
-}
-
-bool cBNKey::Cmp(void *Key, int Keylen)
-{
- return BN_cmp(*key,(BIGNUM *)Key)==0;
-}
-
-bool cBNKey::Cmp(cPlainKey *k)
-{
- cBNKey *bk=dynamic_cast<cBNKey *>(k); // downcast
- return bk && BN_cmp(*key,*bk->key)==0;
-}
-
-void cBNKey::Get(void *mem)
-{
- BN_copy((BIGNUM *)mem,*key);
-}
-
-cString cBNKey::Print(void)
-{
- unsigned char *mem=AUTOMEM(keylen);
- if(rotate) key->PutLE(mem,keylen); else key->Put(mem,keylen);
- char *str=(char *)malloc(keylen*2+2);
- if(str) HexStr(str,mem,keylen);
- return cString(str,true);
-}
-
-// -- cDualKey -----------------------------------------------------------------
-
-cDualKey::cDualKey(bool Super, bool Rotate)
-:cMutableKey(Super)
-{
- rotate=Rotate;
-}
-
-cPlainKey *cDualKey::Alloc(void) const
-{
- if(IsBNKey()) return new cBNKey(CanSupersede(),rotate);
- else return new cHexKey(CanSupersede());
-}
-
-// -- cPlainKeyStd ---------------------------------------------------------------
-
-#define PLAINLEN_STD 8
-
-cPlainKeyStd::cPlainKeyStd(bool Super)
-:cHexKey(Super)
-{}
-
-bool cPlainKeyStd::Parse(const char *line)
-{
- unsigned char sid[3], skeynr, skey[PLAINLEN_STD];
- int len;
- if(GetChar(line,&type,1) && (len=GetHex(line,sid,3,false)) &&
- GetHex(line,&skeynr,1) && GetHex(line,skey,PLAINLEN_STD)) {
- type=toupper(type); id=Bin2Int(sid,len); keynr=skeynr;
- SetBinKey(skey,PLAINLEN_STD);
- return true;
- }
- return false;
-}
-
-// -- cSystemScCore ------------------------------------------------------------
-
-cSystemScCore::cSystemScCore(const char *Name, int Pri, int ScId, const char *ScName)
-:cSystem(Name,Pri)
-{
- scId=ScId; scName=ScName;
-}
-
-bool cSystemScCore::ProcessECM(const cEcmInfo *ecm, unsigned char *source)
-{
- bool res=false;
- cSmartCard *card=smartcards.LockCard(scId);
- if(card) {
- res=card->Decode(ecm,source,cw);
- smartcards.ReleaseCard(card);
- if(res) KeyOK(scName);
- }
- return res;
-}
-
-void cSystemScCore::ProcessEMM(int pid, int caid, unsigned char *buffer)
-{
- cSmartCard *card=smartcards.LockCard(scId);
- if(card) {
- card->Update(pid,caid,buffer);
- smartcards.ReleaseCard(card);
- }
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___SYSTEM_COMMON_H
-#define ___SYSTEM_COMMON_H
-
-#include "data.h"
-#include "system.h"
-
-// ----------------------------------------------------------------
-
-class cHexKey : public cPlainKey {
-private:
- int keylen;
- unsigned char *key;
-protected:
- virtual bool SetKey(void *Key, int Keylen);
- virtual bool SetBinKey(unsigned char *Mem, int Keylen);
- virtual cString Print(void);
- virtual bool Cmp(void *Key, int Keylen);
- virtual bool Cmp(cPlainKey *k);
- virtual void Get(void *mem);
- virtual int Size(void) { return keylen; }
-public:
- cHexKey(bool Super);
- virtual ~cHexKey();
- virtual bool Parse(const char *line) { return false; }
- };
-
-// ----------------------------------------------------------------
-
-class cBN;
-
-class cBNKey : public cPlainKey {
-private:
- bool rotate;
- int keylen;
- cBN *key;
-protected:
- virtual bool SetKey(void *Key, int Keylen);
- virtual bool SetBinKey(unsigned char *Mem, int Keylen);
- virtual cString Print(void);
- virtual bool Cmp(void *Key, int Keylen);
- virtual bool Cmp(cPlainKey *k);
- virtual void Get(void *mem);
- virtual int Size(void) { return keylen; }
-public:
- cBNKey(bool Super, bool Rotate=false);
- virtual ~cBNKey();
- virtual bool Parse(const char *line) { return false; }
- };
-
-// ----------------------------------------------------------------
-
-class cDualKey : public cMutableKey {
-private:
- bool rotate;
-protected:
- virtual bool IsBNKey(void) const=0;
- virtual cPlainKey *Alloc(void) const;
-public:
- cDualKey(bool Super, bool Rotate);
- };
-
-// ----------------------------------------------------------------
-
-class cPlainKeyStd : public cHexKey {
-public:
- cPlainKeyStd(bool Super);
- virtual bool Parse(const char *line);
- };
-
-// ----------------------------------------------------------------
-
-template<class T> class cCardInfos : public cStructList<T> {
-public:
- cCardInfos(const char *Type, const char *Filename, int fl):cStructList<T>(Type,Filename,fl|SL_MISSINGOK|SL_WATCH) {}
- virtual cStructItem *ParseLine(char *line)
- {
- T *k=new T;
- if(k && !k->Parse(line)) { delete k; k=0; }
- return k;
- }
- };
-
-// ----------------------------------------------------------------
-
-class cSystemScCore : public cSystem {
-private:
- int scId;
- const char *scName;
-public:
- cSystemScCore(const char *Name, int Pri, int ScId, const char *ScName);
- virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *data);
- virtual void ProcessEMM(int pid, int caid, unsigned char *data);
- };
-
-#endif //___SYSTEM_COMMON_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <vdr/tools.h>
-
-#include "sc.h"
-#include "scsetup.h"
-#include "system.h"
-#include "data.h"
-#include "opts.h"
-#include "log-core.h"
-#include "i18n.h"
-
-// --- cFeature ----------------------------------------------------------------
-
-cFeature Feature;
-
-bool cFeature::keyfile=false;
-bool cFeature::smartcard=false;
-
-void cFeature::NeedsKeyFile(void)
-{
- if(!keyfile) PRINTF(L_CORE_DYN,"feature: using feature KEYFILE");
- keyfile=true;
-}
-
-void cFeature::NeedsSmartCard(void)
-{
- if(!smartcard) PRINTF(L_CORE_DYN,"feature: using feature SMARTCARD");
- smartcard=true;
-}
-
-// -- cKeySnoop ----------------------------------------------------------------
-
-cKeySnoop::cKeySnoop(cSystem *Sys, int Type, int Id, int Keynr)
-{
- ok=false;
- sys=Sys; type=Type; id=Id; keynr=Keynr;
-}
-
-cKeySnoop::~cKeySnoop()
-{
- if(!ok) sys->KeyFail(type,id,keynr);
-}
-
-void cKeySnoop::OK(cPlainKey *pk)
-{
- sys->KeyOK(pk);
- ok=true;
-}
-
-// -- cLogHook -----------------------------------------------------------------
-
-cLogHook::cLogHook(int Id, const char *Name)
-{
- id=Id; name=Name;
- bailOut=false;
-}
-
-// -- cSystem ------------------------------------------------------------------
-
-#define MAX_CHID 10
-
-struct EcmCheck {
- union {
- struct {
- bool startFlag;
- int current, chids[MAX_CHID];
- } sys06;
- } caid;
- };
-
-int cSystem::foundKeys=0;
-int cSystem::newKeys=0;
-
-cSystem::cSystem(const char *Name, int Pri)
-{
- name=Name; pri=Pri;
- currentKeyStr[0]=0; doLog=true; cardNum=-1; logecm=0;
- check=new struct EcmCheck;
- memset(check,0,sizeof(struct EcmCheck));
- // default config
- maxEcmTry=2; // try to get a key X times from the same ECM pid (default)
- hasLogger=false;
- needsLogger=false;
- local=true;
- needsDescrData=false;
- constant=false;
-}
-
-cSystem::~cSystem()
-{
- delete check;
- if(logecm) cSoftCAM::SetLogStatus(cardNum,logecm,false);
- delete logecm;
-}
-
-void cSystem::StartLog(const cEcmInfo *ecm, int caid)
-{
- if(!logecm || logecm->caId!=caid) {
- if(logecm) cSoftCAM::SetLogStatus(cardNum,logecm,false);
- delete logecm;
- logecm=new cEcmInfo(ecm);
- logecm->caId=caid; logecm->emmCaId=0;
- cSoftCAM::SetLogStatus(cardNum,logecm,true);
- }
-}
-
-void cSystem::ParseCADescriptor(cSimpleList<cEcmInfo> *ecms, unsigned short sysId, unsigned short source, const unsigned char *data, int len)
-{
- const int pid=WORD(data,2,0x1FFF);
- switch(sysId>>8) {
- case 0x01: // Seca style
- for(int p=2; p<len; p+=15) {
- cEcmInfo *n=new cEcmInfo(name,WORD(data,p,0x1FFF),sysId,WORD(data,p+2,0xFFFF));
- if(data[p+4]==0xFF) n->AddData(&data[p+5],10);
- ecms->Add(n);
- }
- break;
- case 0x05: // Viaccess style
- for(int p=4; p<len; p+=2+data[p+1])
- if(data[p]==0x14)
- ecms->Add(new cEcmInfo(name,pid,sysId,(data[p+2]<<16)|(data[p+3]<<8)|(data[p+4]&0xF0)));
- break;
- default: // default style
- {
- cEcmInfo *n=new cEcmInfo(name,pid,sysId,0);
- if((sysId==0x1234) || (source==0x8334) || (source==0x838e)) { // BEV
- n->ecm_table=0x8e;
- n->emmCaId=0x1801;
- }
- ecms->Add(n);
- break;
- }
- }
-}
-
-void cSystem::ParseCAT(cPids *pids, const unsigned char *buffer)
-{
- if(buffer[0]==0x09) {
- int caid=WORD(buffer,2,0xFFFF);
- int pid=WORD(buffer,4,0x1FFF);
- switch(caid>>8) {
- case 0x01: // Seca style (82/84)
- if(buffer[1]>4) {
- pids->AddPid(pid,0x82,0xFF); // Unique updates
- for(int i=7, nn=buffer[6] ; nn ; nn--,i+=4)
- pids->AddPid(WORD(buffer,i,0x1FFF),0x84,0xFF); // Shared updates
- }
- break;
- case 0x05: // Viaccess style (88/8c/8d/8e)
- pids->AddPid(pid,0x8B,0xFE,0x07); // mismatching 89/8f
- break;
- case 0x0d: // Cryptoworks style (82/84/86/88/89)
- pids->AddPid(pid,0x80,0xFF,0x06);
- pids->AddPid(pid,0x88,0xFE);
- break;
- case 0x18: // Nagra style, Nagra1(82) Nagra2(82/83)
- pids->AddPid(pid,0x82,caid==0x1801 ? 0xFE:0xFF);
- break;
- default: // default style (82)
- pids->AddPid(pid,0x82,0xFF);
- break;
- }
- }
-}
-
-int cSystem::CheckECM(const cEcmInfo *ecm, const unsigned char *data, bool sync)
-{
- switch(ecm->caId>>8) {
- case 0x06: // Irdeto
- {
- const int cur=data[4];
- const int max=data[5];
- const int chid=WORD(data,6,0xFFFF);
- // if multiple channel id's, use current one only
- if(sync && ecm->caId==0x0604 && check->caid.sys06.current>0 && chid!=check->caid.sys06.current) {
- PRINTF(L_CORE_ECMPROC,"ecmcheck(%s): chid %04x != current %04x",name,chid,check->caid.sys06.current);
- return 2;
- }
- // search for fake channel id's on Stream
- if(!sync && max>0 && max<MAX_CHID) {
- if(cur==0) check->caid.sys06.startFlag=true;
- if(check->caid.sys06.startFlag) {
- if(cur<=max) check->caid.sys06.chids[cur]=chid;
- if(cur==max) {
- for(int i=0 ; i<max ; i++) {
- if(check->caid.sys06.chids[i]==0) {
- check->caid.sys06.startFlag=false;
- PRINTF(L_CORE_ECMPROC,"ecmcheck(%s): zero chid",name);
- return 1;
- }
- for(int j=i+1 ; j<=max ; j++) {
- if(check->caid.sys06.chids[i]==check->caid.sys06.chids[j]) {
- check->caid.sys06.startFlag=false;
- PRINTF(L_CORE_ECMPROC,"ecmcheck(%s): duplicate chid %04x",name,check->caid.sys06.chids[i]);
- return 1;
- }
- }
- }
- }
- }
- }
- break;
- }
- }
- return 0;
-}
-
-void cSystem::CheckECMResult(const cEcmInfo *ecm, const unsigned char *data, bool result)
-{
- switch(ecm->caId>>8) {
- case 0x06: // Irdeto
- check->caid.sys06.current=result ? WORD(data,6,0xFFFF) : 0;
- break;
- }
-}
-
-void cSystem::KeyOK(cPlainKey *pk)
-{
- if(lastkey.NotLast(pk->type,pk->id,pk->keynr)) {
- strn0cpy(currentKeyStr,pk->ToString(false),sizeof(currentKeyStr));
- PRINTF(L_CORE_ECM,"system: using key %s",*pk->ToString(true));
- doLog=true;
- }
-}
-
-void cSystem::KeyOK(const char *txt)
-{
- snprintf(currentKeyStr,sizeof(currentKeyStr),"%s (%s)\n",txt?txt:name,tr("undisclosed key"));
- doLog=true;
-}
-
-void cSystem::KeyFail(int type, int id, int keynr)
-{
- keys.Trigger(type,id,keynr);
- if(lastkey.NotLast(type,id,keynr) && doLog)
- PRINTF(L_CORE_ECM,"system: no key found for %s",*keys.KeyString(type,id,keynr));
-}
-
-// -- cSystemLink --------------------------------------------------------------
-
-cSystemLink::cSystemLink(const char *Name, int Pri)
-{
- name=Name; pri=Pri;
- opts=0; noFF=false;
- cSystems::Register(this);
-}
-
-cSystemLink::~cSystemLink()
-{
- delete opts;
-}
-
-// -- cSystems -----------------------------------------------------------------
-
-cSystemLink *cSystems::first=0;
-int cSystems::nextSysIdent=0x1000;
-
-void cSystems::Register(cSystemLink *sysLink)
-{
- PRINTF(L_CORE_DYN,"systems: registering CA system %s, pri %d, ident %04X",sysLink->name,sysLink->pri,nextSysIdent);
- sysLink->next=first;
- sysLink->sysIdent=nextSysIdent++;
- first=sysLink;
-}
-
-int cSystems::Provides(const unsigned short *SysIds, bool ff)
-{
- int n=0;
- for(; *SysIds; SysIds++) {
- if(ScSetup.Ignore(*SysIds)) continue;
- cSystemLink *sl=first;
- while(sl) {
- if(sl->CanHandle(*SysIds)) {
- if(sl->noFF && ff) return 0;
- n++;
- break;
- }
- sl=sl->next;
- }
- }
- return n;
-}
-
-cSystemLink *cSystems::FindByName(const char *Name)
-{
- cSystemLink *sl=first;
- while(sl) {
- if(!strcasecmp(sl->name,Name)) return sl;
- sl=sl->next;
- }
- return 0;
-}
-
-cSystemLink *cSystems::FindById(unsigned short SysId, bool ff, int oldPri)
-{
- // all pri's are negative!
- // oldPri = 0 -> get highest pri system
- // oldPri < 0 -> get highest pri system with pri<oldPri
- // oldPri > 0 -> get lowest pri system
-
- cSystemLink *sl=first, *csl=0;
- while(sl) {
- if((!ff || !sl->noFF) && sl->CanHandle(SysId)
- && sl->pri<oldPri
- && (!csl
- || (oldPri<=0 && sl->pri>csl->pri)
- || (oldPri>0 && sl->pri<csl->pri)
- )
- ) csl=sl;
- sl=sl->next;
- }
- return csl;
-}
-
-cSystemLink *cSystems::FindByIdent(int ident)
-{
- cSystemLink *sl=first;
- while(sl) {
- if(sl->sysIdent==ident) return sl;
- sl=sl->next;
- }
- return 0;
-}
-
-cSystem *cSystems::FindBySysName(unsigned short SysId, bool ff, const char *Name)
-{
- cSystemLink *sl=FindByName(Name);
- if(sl && (!ff || !sl->noFF) && !ScSetup.Ignore(SysId) && sl->CanHandle(SysId)) return sl->Create();
- return 0;
-}
-
-cSystem *cSystems::FindBySysId(unsigned short SysId, bool ff, int oldPri)
-{
- if(!ScSetup.Ignore(SysId)) {
- cSystemLink *csl=FindById(SysId,ff,oldPri);
- if(csl) return csl->Create();
- }
- return 0;
-}
-
-int cSystems::FindIdentBySysId(unsigned short SysId, bool ff, int &Pri)
-{
- if(!ScSetup.Ignore(SysId)) {
- cSystemLink *csl=FindById(SysId,ff,Pri);
- if(csl) {
- Pri=csl->pri;
- return csl->sysIdent;
- }
- }
- return 0;
-}
-
-cSystem *cSystems::FindBySysIdent(int ident)
-{
- cSystemLink *csl=FindByIdent(ident);
- return csl ? csl->Create() : 0;
-}
-
-bool cSystems::Init(const char *cfgdir)
-{
- PRINTF(L_CORE_LOAD,"** registered systems:");
- for(cSystemLink *sl=first; sl; sl=sl->next)
- PRINTF(L_CORE_LOAD,"** %-16s (pri %3d)",sl->name,sl->pri);
- for(cSystemLink *sl=first; sl; sl=sl->next)
- if(!sl->Init(cfgdir)) return false;
- return true;
-}
-
-void cSystems::Clean(void)
-{
- for(cSystemLink *sl=first; sl; sl=sl->next) sl->Clean();
-}
-
-bool cSystems::ConfigParse(const char *Name, const char *Value)
-{
- char sysName[32];
- unsigned int i;
- for(i=0; Name[i] && Name[i]!='.' && i<sizeof(sysName); i++)
- sysName[i]=Name[i];
- if(Name[i]) {
- sysName[i]=0; i++;
- cSystemLink *sl=FindByName(sysName);
- if(sl && sl->opts) return sl->opts->Parse(&Name[i],Value);
- }
- return false;
-}
-
-void cSystems::ConfigStore(bool AsIs)
-{
- for(cSystemLink *sl=first; sl; sl=sl->next)
- if(sl->opts && sl->opts->Store(AsIs)) sl->NewConfig();
-}
-
-cOpts *cSystems::GetSystemOpts(bool start)
-{
- static cSystemLink *sl=0;
- sl=(start || !sl) ? first : sl->next;
- while(sl) {
- if(sl->opts) return sl->opts;
- sl=sl->next;
- }
- return 0;
-}
-
-// -- cMsgCache ----------------------------------------------------------------
-
-#define FREE 0x00 // modes
-#define FAIL1 0x01
-#define FAIL2 0x3D
-#define FAILN 0x3E
-#define GOOD 0x3F
-#define MASK 0x3F
-#define QUEUED 0x40
-#define WAIT 0x80
-
-struct Cache {
- int crc;
- int mode;
- };
-
-cMsgCache::cMsgCache(int NumCache, int StoreSize)
-{
- numCache=NumCache;
- storeSize=StoreSize;
- ptr=0; stores=0; maxFail=2;
- caches=MALLOC(struct Cache,numCache);
- if(caches) {
- Clear();
- if(storeSize>0) {
- stores=MALLOC(unsigned char,numCache*storeSize);
- if(!stores) PRINTF(L_GEN_ERROR,"msgcache: no memory for store area");
- }
- }
- else PRINTF(L_GEN_ERROR,"msgcache: no memory for cache");
-}
-
-cMsgCache::~cMsgCache()
-{
- free(caches);
- free(stores);
-}
-
-void cMsgCache::SetMaxFail(int maxfail)
-{
- maxFail=min(maxfail,FAILN);
- PRINTF(L_CORE_MSGCACHE,"%d/%p: maxFail set to %d",getpid(),this,maxFail);
-}
-
-void cMsgCache::Clear(void)
-{
- cMutexLock lock(&mutex);
- memset(caches,0,sizeof(struct Cache)*numCache);
- ptr=0;
- PRINTF(L_CORE_MSGCACHE,"%d/%p: clear",getpid(),this);
-}
-
-struct Cache *cMsgCache::FindMsg(int crc)
-{
- int i=ptr;
- while(1) {
- if(--i<0) i=numCache-1;
- struct Cache * const s=&caches[i];
- if(!s->mode) break;
- if(s->crc==crc) return s;
- if(i==ptr) break;
- }
- return 0;
-}
-
-// returns:
-// -1 - msg cached as failed (max failed)
-// 0 - msg cached as good, result stored
-// >0 - msg not cached, queue id
-int cMsgCache::Get(const unsigned char *msg, int len, unsigned char *store)
-{
- int crc=crc32_le(0,msg,len);
- cMutexLock lock(&mutex);
- if(!caches || (storeSize>0 && !stores)) return -1; // sanity
- struct Cache *s;
- while((s=FindMsg(crc))) {
- if(!(s->mode&QUEUED)) break;
- s->mode|=WAIT;
- PRINTF(L_CORE_MSGCACHE,"%d/%p: msg already queued. waiting to complete",getpid(),this);
- wait.Wait(mutex);
- }
- int id;
- if(!s) {
- while(1) {
- s=&caches[ptr];
- if(!(s->mode&QUEUED)) break;
- s->mode|=WAIT;
- PRINTF(L_CORE_MSGCACHE,"%d/%p: queue overwrite protection id=%d",getpid(),this,ptr+1);
- wait.Wait(mutex); // don't overwrite queued msg's
- }
- id=ptr+1;
- s->crc=crc;
- s->mode=QUEUED;
- PRINTF(L_CORE_MSGCACHE,"%d/%p: queued msg with id=%d",getpid(),this,id);
- ptr++; if(ptr>=numCache) { ptr=0; PRINTF(L_CORE_MSGCACHE,"msgcache: roll-over (%d)",numCache); }
- return id;
- }
- else {
- id=(s-&caches[0])+1;
- if(s->mode==GOOD) {
- if(store && storeSize>0)
- memcpy(store,&stores[(id-1)*storeSize],storeSize);
- PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as GOOD (%d)",getpid(),this,id);
- return 0;
- }
- else if(s->mode>=FAIL1 && s->mode<=FAIL2) {
- PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as FAIL%d (%d)",getpid(),this,s->mode,id);
- s->mode|=QUEUED;
- return id;
- }
- else {
- PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as FAILN (%d)",getpid(),this,id);
- return -1;
- }
- }
-}
-
-int cMsgCache::Cache(int id, bool result, const unsigned char *store)
-{
- cMutexLock lock(&mutex);
- if(id<1 || !caches || (storeSize>0 && !stores)) return 0; // sanity
- struct Cache *s=&caches[id-1];
- LBSTARTF(L_CORE_MSGCACHE);
- LBPUT("%d/%p: de-queued msg with id=%d ",getpid(),this,id);
- if(s->mode&WAIT) wait.Broadcast();
- if(result) {
- if(store && storeSize>0)
- memcpy(&stores[(id-1)*storeSize],store,storeSize);
- s->mode=GOOD;
- LBPUT("(GOOD)");
- return 0;
- }
- else {
- int m=s->mode&MASK;
- if(m==GOOD)
- m=s->mode=FREE;
- if(m==FREE || (m>=FAIL1 && m<=FAIL2)) {
- s->mode=(s->mode&MASK)+1;
- if(s->mode<maxFail)
- LBPUT("(FAIL%d)",s->mode);
- else
- m=s->mode=FAILN;
- }
- if(m==FAILN)
- LBPUT("(FAILN)");
- return s->mode;
- }
- LBEND();
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___SYSTEM_H
-#define ___SYSTEM_H
-
-#include <vdr/tools.h>
-
-#include "data.h"
-#include "misc.h"
-
-// ----------------------------------------------------------------
-
-#define SYSTEM_MASK 0xFF00
-
-// ----------------------------------------------------------------
-
-class cEcmInfo;
-class cPlainKey;
-class cSystem;
-class cSystems;
-class cLogger;
-class cOpts;
-class cHookManager;
-
-// ----------------------------------------------------------------
-
-class cFeature {
-private:
- static bool keyfile, smartcard;
-public:
- void NeedsKeyFile(void);
- void NeedsSmartCard(void);
- bool KeyFile(void) const { return keyfile; }
- bool SmartCard(void) const { return smartcard; }
- };
-
-extern cFeature Feature;
-
-// ----------------------------------------------------------------
-
-class cKeySnoop {
-private:
- cSystem *sys;
- int type, id, keynr;
- bool ok;
-public:
- cKeySnoop(cSystem *Sys, int Type, int Id, int Keynr);
- ~cKeySnoop();
- void OK(cPlainKey *pk);
- };
-
-// ----------------------------------------------------------------
-
-class cLogHook : public cSimpleItem {
-friend class cHookManager;
-private:
- int cardNum, id;
- const char *name;
- cTimeMs delay;
- bool bailOut;
-protected:
- cPids pids;
-public:
- cLogHook(int Id, const char *Name);
- virtual ~cLogHook() {}
- virtual void Process(int pid, unsigned char *data)=0;
- void BailOut(void) { bailOut=true; }
- };
-
-// ----------------------------------------------------------------
-
-struct EcmCheck;
-
-class cSystem : public cSimpleItem {
-friend class cKeySnoop;
-private:
- static int foundKeys, newKeys;
- int pri, cardNum;
- cLastKey lastkey;
- char *lastTxt;
- char currentKeyStr[48];
- struct EcmCheck *check;
- cEcmInfo *logecm;
-protected:
- const char *name;
- unsigned char cw[16];
- bool doLog;
- // config details
- int maxEcmTry;
- bool local, hasLogger, needsLogger, needsDescrData, constant;
- //
- void KeyOK(cPlainKey *pk);
- void KeyOK(const char *txt);
- void KeyFail(int type, int id, int keynr);
- void StartLog(const cEcmInfo *ecm, int caid);
-public:
- cSystem(const char *Name, int Pri);
- virtual ~cSystem();
- virtual int CheckECM(const cEcmInfo *ecm, const unsigned char *data, bool sync);
- virtual void CheckECMResult(const cEcmInfo *ecm, const unsigned char *data, bool result);
- virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *buffer)=0;
- virtual void ProcessEMM(int pid, int caid, unsigned char *buffer) {};
- virtual void ParseCADescriptor(cSimpleList<cEcmInfo> *ecms, unsigned short sysId, unsigned short source, const unsigned char *data, int len);
- virtual void ParseCAT(cPids *pids, const unsigned char *buffer);
- unsigned char *CW(void) { return cw; }
- void DoLog(bool Log) { doLog=Log; }
- int Pri(void) { return pri; }
- const char *CurrentKeyStr(void) { return currentKeyStr; }
- const char *Name(void) { return name; }
- int CardNum(void) { return cardNum; }
- void CardNum(int CardNum) { cardNum=CardNum; }
- int MaxEcmTry(void) { return maxEcmTry; }
- bool HasLogger(void) { return hasLogger; }
- bool NeedsLogger(void) { return needsLogger; }
- bool Local(void) { return local; }
- bool NeedsData(void) { return needsDescrData; }
- bool Constant(void) { return constant; }
- static void FoundKey(void) { foundKeys++; }
- static void NewKey(void) { newKeys++; }
- static void KeyStats(int &fk, int &nk) { fk=foundKeys; nk=newKeys; }
- };
-
-// ----------------------------------------------------------------
-
-class cSystemLink {
-friend class cSystems;
-private:
- int sysIdent;
-protected:
- cSystemLink *next;
- const char *name;
- int pri;
- cOpts *opts;
- bool noFF;
-public:
- cSystemLink(const char *Name, int Pri);
- virtual ~cSystemLink();
- virtual bool CanHandle(unsigned short SysId)=0;
- virtual cSystem *Create(void)=0;
- virtual bool Init(const char *cfgdir) { return true; }
- virtual void Clean(void) {}
- virtual void NewConfig(void) {}
- };
-
-// ----------------------------------------------------------------
-
-class cSystems {
-friend class cSystemLink;
-private:
- static cSystemLink *first;
- static int nextSysIdent;
- //
- static void Register(cSystemLink *sysLink);
- static cSystemLink *FindByName(const char *Name);
- static cSystemLink *FindById(unsigned short SysId, bool ff, int oldPri);
- static cSystemLink *FindByIdent(int ident);
-public:
- static int Provides(const unsigned short *SysIds, bool ff);
- static cSystem *FindBySysId(unsigned short SysId, bool ff, int oldPri);
- static cSystem *FindBySysName(unsigned short SysId, bool ff, const char *Name);
- static int FindIdentBySysId(unsigned short SysId, bool ff, int &Pri);
- static cSystem *FindBySysIdent(int ident);
- static bool Init(const char *cfgdir);
- static void Clean(void);
- //
- static bool ConfigParse(const char *Name, const char *Value);
- static void ConfigStore(bool AsIs);
- static cOpts *GetSystemOpts(bool start);
- };
-
-// ----------------------------------------------------------------
-
-struct Cache;
-
-class cMsgCache {
-private:
- struct Cache *caches;
- unsigned char *stores;
- int numCache, ptr, storeSize, maxFail;
- cMutex mutex;
- cCondVar wait;
- //
- struct Cache *FindMsg(int crc);
-public:
- cMsgCache(int NumCache, int StoreSize);
- ~cMsgCache();
- int Cache(int id, bool result, const unsigned char *store);
- int Get(const unsigned char *msg, int len, unsigned char *store);
- void Clear(void);
- void SetMaxFail(int max);
- };
-
-#endif //___SYSTEM_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "cc.h"
-#include "network.h"
-#include "parse.h"
-
-// -- cCardClientAroureos ------------------------------------------------------
-
-class cCardClientAroureos : public cCardClient, protected cIdSet {
-private:
- cNetSocket so;
- //
- bool ParseCardConfig(const char *config, int *num);
-protected:
- virtual bool Login(void);
-public:
- cCardClientAroureos(const char *Name);
- virtual bool Init(const char *config);
- virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw);
- virtual bool ProcessEMM(int caSys, const unsigned char *source);
- };
-
-static cCardClientLinkReg<cCardClientAroureos> __aroureos("Aroureos");
-
-cCardClientAroureos::cCardClientAroureos(const char *Name)
-:cCardClient(Name)
-,so(DEFAULT_CONNECT_TIMEOUT,5,DEFAULT_IDLE_TIMEOUT)
-{}
-
-bool cCardClientAroureos::ParseCardConfig(const char *config, int *num)
-{
- int hb, hs;
- int startNum=*num;
- if(sscanf(&config[*num],":%x:%x%n",&hb,&hs,num)==2) {
- *num+=startNum;
- unsigned char h[3];
- h[0]=(hs>>16)&0xFF;
- h[1]=(hs>> 8)&0xFF;
- h[2]=(hs>> 0)&0xFF;
- PRINTF(L_CC_LOGIN,"%s: hexser %02X%02X%02X hexbase %02X",name,h[0],h[1],h[2],hb);
- ResetIdSet();
- SetCard(new cCardIrdeto(hb,&h[0]));
- }
- return true;
-}
-
-bool cCardClientAroureos::Init(const char *config)
-{
- cMutexLock lock(this);
- so.Disconnect();
- int num=0;
- return ParseStdConfig(config,&num) &&
- ParseCardConfig(config,&num);
-}
-
-bool cCardClientAroureos::Login(void)
-{
- so.Disconnect();
- if(!so.Connect(hostname,port)) return false;
- PRINTF(L_CC_LOGIN,"%s: connected to %s:%d",name,hostname,port);
- if(!emmAllowed) PRINTF(L_CC_EMM,"%s: EMM disabled from config",name);
- return true;
-}
-
-bool cCardClientAroureos::ProcessEMM(int caSys, const unsigned char *source)
-{
- if(emmAllowed) {
- cMutexLock lock(this);
- if(MatchEMM(source)) {
- const int length=SCT_LEN(source);
- int id=msEMM.Get(source,length,0);
- if(id>0) {
- unsigned char *buff=AUTOMEM(length+8);
- memcpy(buff,"EMM",3);
- memcpy(&buff[3],source,length);
- SendMsg(&so,buff,length+3);
- msEMM.Cache(id,true,0);
- }
- return true;
- }
- }
- return false;
-}
-
-bool cCardClientAroureos::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw)
-{
- cMutexLock lock(this);
- so.Flush();
- const int len=SCT_LEN(source);
- if(len<=93) {
- unsigned char buff[128];
- memcpy(buff,"ECM",3);
- memcpy(&buff[3],source,len);
-
- if(!SendMsg(&so,buff,96)) return false;
- int n=RecvMsg(&so,buff,sizeof(buff));
- if(n>0) {
- memcpy(cw,buff,16);
- for(n=0; n<16; n++) if(cw[n]) break;
- if(n<16) return true;
- }
- }
- return false;
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <byteswap.h>
-
-#include "cc.h"
-#include "network.h"
-#include "crypto.h"
-#include "misc.h"
-#include "parse.h"
-
-#include <openssl/md5.h>
-
-#define CCVERSION "3.37"
-#define CCTIMEOUT 5000 // ms
-
-// -- cCardClientCommon --------------------------------------------------------
-
-class cCardClientCommon : public cCardClient, public cAES, protected cIdSet {
-private:
- bool conReply, logReply, doAES;
- bool exclusive;
- int minMsgLen;
- cCondVar sleepCond;
- cTimeMs time;
-protected:
- cNetSocket so;
- bool emmProcessing;
- char username[11], password[11];
- //
- virtual bool Login(void);
- bool ParseKeyConfig(const char *config, int *num);
- bool ParseUserConfig(const char *config, int *num);
- virtual bool SendMsg(cNetSocket *so, const unsigned char *data, int len);
- virtual int RecvMsg(cNetSocket *so, unsigned char *data, int len, int to=-1);
- virtual void HandleEMMRequest(const unsigned char *buff, int len) {}
- virtual bool CanHandleEMM(int SysId) { return false; }
-public:
- cCardClientCommon(const char *Name, bool ConReply, bool LogReply, bool DoAES, int MinMsgLen);
- virtual bool Init(const char *config);
- virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw);
- virtual bool ProcessEMM(int caSys, const unsigned char *source);
- };
-
-cCardClientCommon::cCardClientCommon(const char *Name, bool ConReply, bool LogReply, bool DoAES, int MinMsgLen)
-:cCardClient(Name)
-,so(DEFAULT_CONNECT_TIMEOUT,CCTIMEOUT/1000,DEFAULT_IDLE_TIMEOUT)
-{
- conReply=ConReply; logReply=LogReply; doAES=DoAES; minMsgLen=MinMsgLen;
- emmProcessing=exclusive=false;
-}
-
-bool cCardClientCommon::ParseUserConfig(const char *config, int *num)
-{
- int startNum=*num;
- if(sscanf(&config[*num],":%10[^:]:%10[^:]%n",username,password,num)==2) {
- *num+=startNum;
- PRINTF(L_CC_CORE,"%s: username=%s password=%s",name,username,password);;
- return true;
- }
- return false;
-}
-
-bool cCardClientCommon::ParseKeyConfig(const char *config, int *num)
-{
- char hexkey[33];
- int startNum=*num;
- if(sscanf(&config[*num],":%32[^:]%n",hexkey,num)==1) {
- *num+=startNum;
- PRINTF(L_CC_CORE,"%s: key=%s",name,hexkey);
- unsigned char binkey[16];
- memset(binkey,0,sizeof(binkey));
- const char *line=hexkey;
- int n=GetHex(line,binkey,sizeof(binkey),false);
- if(n!=(int)sizeof(binkey))
- PRINTF(L_CC_CAMD,"warning AES key not %d bytes long",(int)sizeof(binkey));
- LDUMP(L_CC_CAMD,binkey,16,"AES activated key =");
- SetKey(binkey);
- }
- return true;
-}
-
-bool cCardClientCommon::SendMsg(cNetSocket *so, const unsigned char *data, int len)
-{
- unsigned char *buff2=AUTOMEM(minMsgLen);
- if(len<minMsgLen) {
- memcpy(buff2,data,len);
- memset(buff2+len,0,minMsgLen-len);
- data=buff2; len=minMsgLen;
- }
- unsigned char *buff=AUTOMEM(len+16);
- const int l=Encrypt(data,len,buff);
- if(l>0) { data=buff; len=l; }
- return cCardClient::SendMsg(so,data,len);
-}
-
-int cCardClientCommon::RecvMsg(cNetSocket *so, unsigned char *data, int len, int to)
-{
- int n=cCardClient::RecvMsg(so,data,len,to);
- if(n>0) {
- if(n&15) PRINTF(L_CC_CAMD,"AES crypted message length not a multiple of 16");
- Decrypt(data,n);
- }
- return n;
-}
-
-bool cCardClientCommon::Init(const char *config)
-{
- cMutexLock lock(this);
- so.Disconnect();
- int num=0;
- if(ParseStdConfig(config,&num) &&
- ParseUserConfig(config,&num) &&
- (!doAES || ParseKeyConfig(config,&num))) {
- return (emmAllowed && logReply && Immediate()) ? Login() : true;
- }
- return false;
-}
-
-bool cCardClientCommon::Login(void)
-{
- so.Disconnect();
- if(!so.Connect(hostname,port)) return false;
- PRINTF(L_CC_LOGIN,"%s: connected to %s:%d (%s)",name,hostname,port,name);
- emmProcessing=false;
-
- unsigned char buff[128];
- if(conReply) {
- if(RecvMsg(&so,buff,sizeof(buff))!=16) {
- PRINTF(L_CC_CAMD,"bad connect reply");
- return false;
- }
- }
-
- memset(buff,0,32);
- int user_len=strlen(username)+1;
- memcpy(buff+1,username,user_len);
- int pass_len=strlen(password)+1;
- memcpy(buff+1+user_len+1,password,pass_len);
- int vers_len=strlen(CCVERSION)+1;
- memcpy(buff+1+user_len+pass_len+1,CCVERSION,vers_len);
- PRINTF(L_CC_CAMD,"login user='%s' password=hidden version=%s",username,CCVERSION);
- if(!SendMsg(&so,buff,32)) return false;
-
- if(emmAllowed && logReply) {
- PRINTF(L_CC_CAMD,"waiting for login reply ...");
- int r=RecvMsg(&so,buff,sizeof(buff));
- if(r>0) HandleEMMRequest(buff,r);
- }
- PRINTF(L_CC_LOGIN,"%s: login done",name);
- return true;
-}
-
-bool cCardClientCommon::ProcessEMM(int caSys, const unsigned char *source)
-{
- if(emmAllowed && CanHandleEMM(caSys)) {
- cMutexLock lock(this);
- if(MatchEMM(source)) {
- const int length=SCT_LEN(source);
- int id=msEMM.Get(source,length,0);
- if(id>0) {
- unsigned char *buff=AUTOMEM(length+32);
- buff[0]=0x03;
- buff[1]=(caSys>>8);
- buff[2]=(caSys&0xFF);
- memcpy(buff+3,((cCardIrdeto *)card)->hexSer,3);
- buff[6]=((cCardIrdeto *)card)->hexBase;
- memcpy(&buff[7],source,length);
- //PRINTF(L_CC_CAMD,"%s: sending EMM for caid 0x%04X",name,caSys);
- SendMsg(&so,buff,length+7);
- msEMM.Cache(id,true,0);
- }
- return true;
- }
- }
- return false;
-}
-
-bool cCardClientCommon::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw)
-{
- Lock();
- bool res=false;
- while(exclusive) sleepCond.Wait(*this);
- if((so.Connected() || Login()) && (!emmProcessing || CanHandle(ecm->caId))) {
- const int length=SCT_LEN(source);
- unsigned char *buff=AUTOMEM(length+32);
- int n;
- while((n=RecvMsg(&so,buff,16,0))>0) HandleEMMRequest(buff,n);
- buff[0]=0x02;
- buff[1]=(ecm->caId>>8);
- buff[2]=(ecm->caId&0xFF);
- memset(&buff[3],0,4);
- memcpy(&buff[7],source,length);
- if(SendMsg(&so,buff,length+7)) {
- exclusive=true;
- time.Set(CCTIMEOUT);
- do {
- sleepCond.TimedWait(*this,50);
- while((n=RecvMsg(&so,buff,32,0))>0) {
- if(n>=21 && buff[0]==2) {
- if(!CheckNull(buff+5,16)) {
- if(!res) {
- memcpy(cw,buff+5,16);
- res=true;
- }
- else PRINTF(L_CC_CAMD,"unexpected CW packet");
- }
- else {
- PRINTF(L_CC_ECM,"%s: server is unable to handle ECM",name);
- n=-1;
- break;
- }
- }
- else HandleEMMRequest(buff,n);
- }
- } while(!res && n>=0 && !time.TimedOut());
- if(!res && time.TimedOut()) PRINTF(L_CC_ECM,"%s: CW request timed out",name);
- exclusive=false;
- sleepCond.Broadcast();
- }
- }
- Unlock();
- return res;
-}
-
-// -- cCardClientCamd33 --------------------------------------------------------
-
-class cCardClientCamd33 : public cCardClientCommon {
-private:
- int CAID;
- unsigned char lastEmmReq[32];
-protected:
- virtual void HandleEMMRequest(const unsigned char *buff, int len);
- virtual bool CanHandleEMM(int SysId);
-public:
- cCardClientCamd33(const char *Name);
- virtual bool CanHandle(unsigned short SysId);
- };
-
-static cCardClientLinkReg<cCardClientCamd33> __camd33("Camd33");
-
-cCardClientCamd33::cCardClientCamd33(const char *Name)
-:cCardClientCommon(Name,true,true,true,0)
-{
- CAID=0;
- memset(lastEmmReq,0,sizeof(lastEmmReq));
-}
-
-bool cCardClientCamd33::CanHandle(unsigned short SysId)
-{
- return CanHandleEMM(SysId) || cCardClient::CanHandle(SysId);
-}
-
-bool cCardClientCamd33::CanHandleEMM(int SysId)
-{
- return (emmProcessing && SysId==CAID);
-}
-
-void cCardClientCamd33::HandleEMMRequest(const unsigned char *buff, int len)
-{
- if(len>=13 && buff[0]==0 && !CheckNull(buff,len) && memcmp(buff,lastEmmReq,13)) {
- emmProcessing=false;
- CAID=buff[1]*256+buff[2];
- ResetIdSet();
- switch(CAID>>8) {
- case 0x17:
- case 0x06:
- SetCard(new cCardIrdeto(buff[6],&buff[3]));
- AddProv(new cProviderIrdeto(0,&buff[7]));
- AddProv(new cProviderIrdeto(2,&buff[10]));
- memcpy(lastEmmReq,buff,13);
- PRINTF(L_CC_LOGIN,"%s: CAID: %04x HexSerial: %02X%02X%02X, HexBase: %02X",name,CAID,buff[3],buff[4],buff[5],buff[6]);
- PRINTF(L_CC_LOGIN,"%s: Provider00: %02X%02X%02X, Provider10: %02X%02X%02X",name,buff[7],buff[8],buff[9],buff[10],buff[11],buff[12]);
- if(!emmAllowed) PRINTF(L_CC_EMM,"%s: EMM disabled from config",name);
- emmProcessing=true;
- break;
- }
- }
-}
-
-// -- cCardClientCardd ---------------------------------------------------------
-
-class cCardClientCardd : public cCardClientCommon {
-public:
- cCardClientCardd(const char *Name);
- };
-
-static cCardClientLinkReg<cCardClientCardd> __cardd("Cardd");
-
-cCardClientCardd::cCardClientCardd(const char *Name)
-:cCardClientCommon(Name,false,true,false,96)
-{}
-
-// -- cCardClientBuffy ---------------------------------------------------------
-
-#define MAX_CAIDS 16
-
-class cCardClientBuffy : public cCardClientCommon {
-private:
- unsigned short CAIDs[MAX_CAIDS], numCAIDs;
-protected:
- virtual bool Login(void);
-public:
- cCardClientBuffy(const char *Name);
- virtual bool Init(const char *config);
- virtual bool CanHandle(unsigned short SysId);
- };
-
-static cCardClientLinkReg<cCardClientBuffy> __buffy("Buffy");
-
-cCardClientBuffy::cCardClientBuffy(const char *Name)
-:cCardClientCommon(Name,true,false,true,0)
-{}
-
-bool cCardClientBuffy::Init(const char *config)
-{
- cMutexLock lock(this);
- if(cCardClientCommon::Init(config)) {
- return Immediate() ? Login() : true;
- }
- return false;
-}
-
-bool cCardClientBuffy::CanHandle(unsigned short SysId)
-{
- cMutexLock lock(this);
- for(int i=0; i<numCAIDs; i++) if(CAIDs[i]==SysId) return true;
- return false;
-}
-
-bool cCardClientBuffy::Login(void)
-{
- cMutexLock lock(this);
- if(!cCardClientCommon::Login()) return false;
-
- unsigned char buff[128];
- memset(buff,0,sizeof(buff));
- buff[0]=0x0A;
- if(!SendMsg(&so,buff,32)) return false;
- int n=RecvMsg(&so,buff,sizeof(buff));
- if(n<0) return false;
- for(int i=1; i<n && numCAIDs<MAX_CAIDS; i+=2) {
- unsigned short caid=(buff[i+1]<<8)+buff[i];
- if(caid==0xFFFF) break;
- if(caid) CAIDs[numCAIDs++]=caid;
- }
- LBSTART(L_CC_LOGIN);
- LBPUT("%s: CAIDs ",name);
- for(int i=0; i<numCAIDs && CAIDs[i]; i++) LBPUT("%04X ",CAIDs[i]);
- LBEND();
- return true;
-}
-
-// -- cCardClientCamd35 --------------------------------------------------------
-
-struct CmdBlock {
- unsigned int ucrc;
- struct {
- unsigned char cmd; // 0
- unsigned char len; // 1
- unsigned char pad[2]; // 2 XXXX
- unsigned int crc; // 4
- } udp_header;
- struct {
- unsigned short srvID; // 8
- unsigned short casID; // 10
- unsigned int prvID; // 12
- unsigned short pinID; // 16
- unsigned char pad2[2];// 18 XXXX
- } service;
- unsigned char data[2]; // 20
- };
-
-#define CBSIZE(cb) (sizeof((cb)->udp_header)+sizeof((cb)->service))
-#define UCSIZE(cb) (sizeof((cb)->ucrc))
-#define HDSIZE(cb) (CBSIZE(cb)+UCSIZE(cb))
-
-struct EmmReq02 {
- unsigned short caid;
- unsigned char hex[4];
- unsigned char D0, D2, D3;
- };
-
-struct EmmReq05 {
- unsigned short caids[8]; // 0
- int caidCount; // 16
- unsigned char ua[6]; // 20
- unsigned short provMap; // 26
- struct { // 28
- unsigned char prov[2];
- unsigned char sa[3];
- } provInfo[16];
- unsigned char D0, D2, D3; // 108
- };
-
-class cCardClientCamd35 : public cCardClient, public cAES, private cIdSet {
-private:
- unsigned int ucrc;
- unsigned short pinid;
- bool exclusive, emmCmd06;
- cCondVar sleepCond;
- cTimeMs time;
-protected:
- cNetSocket so;
- bool emmProcessing;
- char username[33], password[33];
- int numCaids, Caids[8];
- unsigned char Dx[8];
- int lastEmmReq;
- //
- virtual bool Login(void);
- bool ParseUserConfig(const char *config, int *num);
- bool SendBlock(struct CmdBlock *cb, int datalen);
- int RecvBlock(struct CmdBlock *cb, int maxlen, int to);
- void HandleEMMRequest(const struct CmdBlock *cb);
- bool CanHandleEMM(unsigned short SysId);
-public:
- cCardClientCamd35(const char *Name);
- virtual bool Init(const char *config);
- virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw);
- virtual bool ProcessEMM(int caSys, const unsigned char *data);
- };
-
-static cCardClientLinkReg<cCardClientCamd35> __camd35("Camd35");
-
-cCardClientCamd35::cCardClientCamd35(const char *Name)
-:cCardClient(Name)
-,so(DEFAULT_CONNECT_TIMEOUT,CCTIMEOUT/1000,DEFAULT_IDLE_TIMEOUT,true)
-{
- emmProcessing=exclusive=emmCmd06=false; pinid=0; numCaids=0; lastEmmReq=0;
- memset(Dx,0,sizeof(Dx));
-}
-
-bool cCardClientCamd35::ParseUserConfig(const char *config, int *num)
-{
- int startNum=*num;
- if(sscanf(&config[*num],":%32[^:]:%32[^:]%n",username,password,num)==2) {
- *num+=startNum;
- ucrc=bswap_32(crc32_le(0,MD5((unsigned char *)username,strlen(username),0),16));
- PRINTF(L_CC_CORE,"%s: username=%s password=%s ucrc=%08x",name,username,password,ucrc);;
- SetKey(MD5((unsigned char *)password,strlen(password),0));
- return true;
- }
- return false;
-}
-
-bool cCardClientCamd35::SendBlock(struct CmdBlock *cb, int datalen)
-{
- cb->udp_header.len=datalen;
- cb->udp_header.crc=bswap_32(crc32_le(0,&cb->data[0],datalen));
- datalen+=CBSIZE(cb);
- unsigned char *buff=AUTOMEM(datalen+UCSIZE(cb)+16);
- *((unsigned int *)buff)=ucrc;
- HEXDUMP(L_CC_CAMDEXTR,cb,datalen+UCSIZE(cb),"send:");
- const int l=Encrypt((unsigned char *)cb+UCSIZE(cb),datalen,buff+UCSIZE(cb));
- if(l<=0) return false;
- return cCardClient::SendMsg(&so,buff,l+UCSIZE(cb));
-}
-
-int cCardClientCamd35::RecvBlock(struct CmdBlock *cb, int maxlen, int to)
-{
- int n=cCardClient::RecvMsg(&so,(unsigned char *)cb,maxlen,to);
- if(n<=0) return n;
- if((unsigned int)n>=CBSIZE(cb)+UCSIZE(cb)) {
- if(cb->ucrc==ucrc) {
- Decrypt((unsigned char *)cb+UCSIZE(cb),n-UCSIZE(cb));
- if((unsigned int)n<cb->udp_header.len+CBSIZE(cb)+UCSIZE(cb))
- PRINTF(L_CC_CAMD35,"packet length doesn't match data length");
- else if(cb->udp_header.crc!=bswap_32(crc32_le(0,&cb->data[0],cb->udp_header.len)))
- PRINTF(L_CC_CAMD35,"data crc failed");
- else {
- HEXDUMP(L_CC_CAMDEXTR,cb,n,"recv:");
- return n;
- }
- }
- else PRINTF(L_CC_CAMD35,"wrong ucrc: got %08x, want %08x",cb->ucrc,ucrc);
- }
- else PRINTF(L_CC_CAMD35,"short packet received");
- return -1;
-}
-
-bool cCardClientCamd35::Init(const char *config)
-{
- cMutexLock lock(this);
- so.Disconnect();
- int num=0;
- return (ParseStdConfig(config,&num) && ParseUserConfig(config,&num));
-}
-
-bool cCardClientCamd35::Login(void)
-{
- so.Disconnect();
- if(!so.Connect(hostname,port)) return false;
- PRINTF(L_CC_LOGIN,"%s: connected to %s:%d (%s)",name,hostname,port,name);
- emmProcessing=false; lastEmmReq=0;
- PRINTF(L_CC_LOGIN,"%s: login done",name);
- return true;
-}
-
-void cCardClientCamd35::HandleEMMRequest(const struct CmdBlock *cb)
-{
- int c=crc32_le(0,cb->data,cb->udp_header.len);
- if(c!=lastEmmReq) {
- lastEmmReq=c;
- ResetIdSet();
- if(cb->udp_header.cmd==0x02 && cb->udp_header.len>=9) {
- struct EmmReq02 *req=(struct EmmReq02 *)cb->data;
- numCaids=1;
- Caids[0]=bswap_16(req->caid);
- SetCard(new cCardIrdeto(req->hex[3],&req->hex[0]));
- Dx[0]=req->D0;
- Dx[2]=req->D2;
- Dx[3]=req->D3;
- char str[20];
- PRINTF(L_CC_LOGIN,"%s: CAID: %04x HexSerial: %s, HexBase: %02X (D0-%d D2-%d D3-%d)\n",
- name,Caids[0],HexStr(str,((cCardIrdeto *)card)->hexSer,3),((cCardIrdeto *)card)->hexBase,
- Dx[0],Dx[2],Dx[3]);
- if(!emmProcessing || emmCmd06) PRINTF(L_CC_CAMD35,"got cmd 02, doing cmd02 EMM");
- emmCmd06=false;
- }
- else if(cb->udp_header.cmd==0x05 && cb->udp_header.len>=111) {
- struct EmmReq05 *req=(struct EmmReq05 *)cb->data;
- numCaids=bswap_32(req->caidCount);
- for(int i=numCaids-1; i>=0; i--) Caids[i]=bswap_16(req->caids[i]);
- LBSTARTF(L_CC_LOGIN);
- LBPUT("%s: CAIDS:",name);
- for(int i=numCaids-1; i>=0; i--) LBPUT(" %04x",Caids[i]);
- char str[20], str2[20];
- LBPUT(" ua=%s",HexStr(str,req->ua,6));
- switch(Caids[0]>>8) {
- case 0x17:
- case 0x06: SetCard(new cCardIrdeto(req->ua[3],&req->ua[0])); break;
- case 0x01: SetCard(new cCardSeca(&req->ua[0])); break;
- case 0x0d: SetCard(new cCardCryptoworks(&req->ua[0])); break;
- case 0x05: SetCard(new cCardViaccess(&req->ua[0])); break;
- default:
- LBPUT(" (unhandled)");
- break;
- }
- LBPUT(" providers");
- int map=bswap_16(req->provMap);
-// for(int i=0; i<15; i++) //XXX not sure what actualy is the correct
-// if(map & (1<<i)) { //XXX interpretation of provMap
- for(int i=0; i<map && i<15; i++) {
- LBPUT(" %d:%s/%s",i,HexStr(str,req->provInfo[i].prov,2),HexStr(str2,req->provInfo[i].sa,3));
- if(!CheckNull(req->provInfo[i].sa,3) && !CheckFF(req->provInfo[i].sa,3)) {
- switch(Caids[0]>>8) {
- case 0x17:
- case 0x06: AddProv(new cProviderIrdeto(req->provInfo[i].prov[0],req->provInfo[i].sa)); break;
- case 0x01: AddProv(new cProviderSeca(req->provInfo[i].prov,req->provInfo[i].sa)); break;
- default:
- LBPUT(" <unhandled>");
- break;
- }
- }
- }
- Dx[0]=req->D0;
- Dx[2]=req->D2;
- Dx[3]=req->D3;
- LBPUT(" (D0-%d D2-%d D3-%d)",Dx[0],Dx[2],Dx[3]);
- LBEND();
-
- if(!emmProcessing || !emmCmd06) PRINTF(L_CC_CAMD35,"got cmd 05, doing cmd06 EMM");
- emmCmd06=true;
- }
- else return;
-
- if(!emmAllowed) PRINTF(L_CC_EMM,"%s: EMM disabled from config",name);
- emmProcessing=true;
- }
-}
-
-bool cCardClientCamd35::CanHandleEMM(unsigned short SysId)
-{
- for(int i=numCaids-1; i>=0; i--) if(SysId==Caids[i]) return true;
- return false;
-}
-
-bool cCardClientCamd35::ProcessEMM(int caSys, const unsigned char *data)
-{
- if(emmProcessing && emmAllowed) {
- cMutexLock lock(this);
- PRINTF(L_CC_CAMDEXTR,"got EMM caSys=%.4x",caSys);
- if(CanHandleEMM(caSys)) {
- LDUMP(L_CC_CAMDEXTR,&data[0],10,"EMM starts with");
- int upd;
- cProvider *p;
- cAssembleData ad(data);
- if(MatchAndAssemble(&ad,&upd,&p)) {
- PRINTF(L_CC_CAMDEXTR,"EMM matched upd=%d provId=%.4llx",upd,p ? p->ProvId() : 0);
- while((data=ad.Assembled())) {
- LDUMP(L_CC_CAMDEXTR,&data[0],10,"processing assembled EMM");
- if(Dx[upd]) {
- unsigned char buff[300];
- memset(buff,0xff,sizeof(buff));
- struct CmdBlock *cb=(struct CmdBlock *)buff;
- cb->udp_header.cmd=emmCmd06 ? 0x06 : 0x02;
- cb->service.srvID=0;
- cb->service.casID=bswap_16(caSys);
- cb->service.prvID=bswap_32(p ? p->ProvId() : 0);
- cb->service.pinID=pinid++;
- int len=SCT_LEN(data), off=0;
- switch(caSys>>8) {
- case 0x0d:
- {
- static const unsigned char head[] = { 0x8F,0x70,0x00,0xA4,0x42,0x00,0x00,0x00 };
- int c, n;
- switch(data[0]) {
- case 0x82: c=0x42; n=10; break;
- case 0x84: c=0x48; n=9; break;
- case 0x88:
- case 0x89: c=0x44; n=5; break;
- default: continue;
- }
- if(len<n) continue;
- off=sizeof(head);
- memcpy(&cb->data[0],head,off);
- cb->data[3+1]=c;
- cb->data[3+4]=len-n;
- SetSctLen(&cb->data[0],len-n+5);
- data+=n; len-=n;
- break;
- }
- }
- if(len+off<=255) {
- memcpy(&cb->data[off],data,len);
- int id=msEMM.Get(&cb->data[0],len+off,0);
- if(id>0) {
- SendBlock(cb,len+off);
- msEMM.Cache(id,true,0);
- }
- else PRINTF(L_CC_CAMDEXTR,"not send, already in cache");
- }
- else PRINTF(L_CC_EMM,"%s: EMM length %d > 255, not supported by UDP protocol",name,len+off);
- }
- else PRINTF(L_CC_CAMDEXTR,"dropped, updtype %d blocked",upd);
- }
- return true;
- }
- else PRINTF(L_CC_CAMDEXTR,"dropped, doesn't match card data");
- }
- else PRINTF(L_CC_CAMDEXTR,"dropped, doesn't want caSys %.4x",caSys);
- }
- return false;
-}
-
-bool cCardClientCamd35::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
-{
- bool res=false;
- const int length=SCT_LEN(data);
- if(length<=255) {
- Lock();
- while(exclusive) sleepCond.Wait(*this);
- unsigned char buff[300];
- memset(buff,0xff,sizeof(buff));
- struct CmdBlock *cb=(struct CmdBlock *)buff;
- const unsigned short pid=pinid++;
- int n;
- while((n=RecvBlock(cb,sizeof(buff),0))>0) {
- if(cb->udp_header.cmd==0x01 || cb->udp_header.cmd==0x44)
- PRINTF(L_CC_CAMD35,"unexpected CW answer on flush");
- else
- HandleEMMRequest(cb);
- }
- cb->udp_header.cmd=0x00;
- cb->service.srvID=bswap_16(ecm->prgId);
- cb->service.casID=bswap_16(ecm->caId);
- switch(ecm->caId>>8) {
- case 0x18: n=(data[5]*256)+data[6]; break;
- default: n=ecm->provId; break;
- }
- cb->service.prvID=bswap_32(n);
- cb->service.pinID=pid;
- memcpy(&cb->data[0],data,length);
- if(SendBlock(cb,length)) {
- exclusive=true;
- time.Set(CCTIMEOUT);
- do {
- sleepCond.TimedWait(*this,50);
- while((n=RecvBlock(cb,sizeof(buff),0))>0) {
- if(cb->udp_header.cmd==0x01) {
- if(cb->udp_header.len>=16 && cb->service.pinID==pid && !res) {
- memcpy(cw,cb->data,16);
- res=true;
- }
- else PRINTF(L_CC_CAMD35,"unexpected/bad CW packet");
- }
- else if(cb->udp_header.cmd==0x44) {
- if(cb->service.pinID==pid) {
- PRINTF(L_CC_ECM,"%s: server is unable to handle ECM",name);
- n=-1;
- break;
- }
- }
- else HandleEMMRequest(cb);
- }
- } while(!res && n>=0 && !time.TimedOut());
- if(!res && time.TimedOut()) PRINTF(L_CC_ECM,"%s: CW request timed out",name);
- exclusive=false;
- sleepCond.Broadcast();
- }
- Unlock();
- }
- else PRINTF(L_CC_ECM,"%s: ECM length %d > 255, not supported by UDP protocol",name,length);
- return res;
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <vdr/thread.h>
-#include <vdr/tools.h>
-
-#include "system.h"
-#include "cc.h"
-#include "network.h"
-#include "misc.h"
-#include "opts.h"
-#include "log-core.h"
-
-#define SYSTEM_NAME "Cardclient"
-#define SYSTEM_PRI -15
-
-#define CONF_FILE "cardclient.conf"
-
-static const struct LogModule lm_cc = {
- (LMOD_ENABLE|L_CC_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_CC_CORE|L_CC_LOGIN|L_CC_ECM|L_CC_EMM|L_CC_CAMD|L_CC_CAMD35|
- L_CC_RDGD|L_CC_NEWCAMD|L_CC_GBOX)&LOPT_MASK,
- "cardclient",
- { "core","login","ecm","emm","camd","camd35","camd35extra","radegast",
- "newcamd","gbox" }
- };
-ADD_MODULE(L_CC,lm_cc)
-
-static int immediate=true;
-
-// -- cCardClient --------------------------------------------------------------
-
-cCardClient::cCardClient(const char *Name)
-:msECM(32,16)
-,msEMM(32,0)
-{
- name=Name;
- emmAllowed=false; emmCaid[0]=0x1700; emmMask[0]=0xFF00; numCaid=1;
-}
-
-bool cCardClient::Immediate(void)
-{
- return immediate;
-}
-
-bool cCardClient::ParseStdConfig(const char *config, int *num)
-{
- int n, emm=0;
- if(!num) num=&n;
- if(sscanf(config,"%63[^:]:%d:%d%n",hostname,&port,&emm,num)<3) return false;
- if(emm>0) emmAllowed=true;
- if(config[*num]=='/') {
- numCaid=0;
- do {
- emmMask[numCaid]=0xFFFF;
- int start=(*num)+1;
- if(sscanf(&config[start],"%x%n/%x%n",&emmCaid[numCaid],num,&emmMask[numCaid],num)<1)
- return false;
- *num+=start;
- numCaid++;
- } while(numCaid<MAX_CC_CAID && config[*num]==',');
- }
- LBSTART(L_CC_CORE);
- LBPUT("hostname=%s port=%d emm=%d emmCaids",hostname,port,emmAllowed);
- for(int i=0; i<numCaid; i++) LBPUT(" %04x/%04x",emmCaid[i],emmMask[i]);
- LBEND();
- return true;
-}
-
-bool cCardClient::CanHandle(unsigned short SysId)
-{
- for(int i=0; i<numCaid; i++)
- if((SysId&emmMask[i])==emmCaid[i]) return true;
- return false;
-}
-
-bool cCardClient::SendMsg(cNetSocket *so, const unsigned char *data, int len)
-{
- if(!so->Connected() && !Login()) return false;
- if(so->Write(data,len)<0) {
- PRINTF(L_CC_CORE,"send error. reconnecting...");;
- so->Disconnect();
- return false;
- }
- return true;
-}
-
-int cCardClient::RecvMsg(cNetSocket *so, unsigned char *data, int len, int to)
-{
- if(!so->Connected() && !Login()) return -1;
- int n=so->Read(data,len,to);
- if(n<0 || (n==0 && to!=0)) {
- PRINTF(L_CC_CORE,"recv error. reconnecting...");;
- so->Disconnect();
- return -1;
- }
- return n;
-}
-
-// -- cCardClients -------------------------------------------------------------
-
-class cCardClients {
-friend class cCardClientLink;
-private:
- static cCardClientLink *first;
- //
- static void Register(cCardClientLink *ccl);
-public:
- cCardClientLink *FindByName(const char *name);
- };
-
-cCardClientLink *cCardClients::first=0;
-
-static cCardClients cardclients;
-
-void cCardClients::Register(cCardClientLink *ccl)
-{
- PRINTF(L_CORE_DYN,"cardclients: registering cardclient %s",ccl->name);
- ccl->next=first;
- first=ccl;
-}
-
-cCardClientLink *cCardClients::FindByName(const char *name)
-{
- cCardClientLink *ccl=first;
- while(ccl) {
- if(!strcasecmp(ccl->name,name)) break;
- ccl=ccl->next;
- }
- return ccl;
-}
-
-// -- cCardClientLink ----------------------------------------------------------
-
-cCardClientLink::cCardClientLink(const char *Name)
-{
- name=Name;
- cCardClients::Register(this);
-}
-
-// -- cSystemLinkCardClient -----------------------------------------------------------
-
-class cSystemLinkCardClient : public cSystemLink, public cStructListPlain<cCardClient> {
-protected:
- virtual bool ParseLinePlain(const char *line);
-public:
- cSystemLinkCardClient(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void);
- virtual void Clean(void);
- cCardClient *FindBySysId(unsigned short id, cCardClient *cc);
- };
-
-static cSystemLinkCardClient staticCcl;
-
-// -- cSystemCardClient ---------------------------------------------------------------
-
-class cSystemCardClient : public cSystem {
-private:
- cCardClient *cc;
-public:
- cSystemCardClient(void);
- virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *data);
- virtual void ProcessEMM(int pid, int caid, unsigned char *buffer);
- };
-
-cSystemCardClient::cSystemCardClient(void)
-:cSystem(SYSTEM_NAME,SYSTEM_PRI)
-{
- cc=0;
- local=false; hasLogger=true;
-}
-
-bool cSystemCardClient::ProcessECM(const cEcmInfo *ecm, unsigned char *data)
-{
- cCardClient *startCc=cc;
- do {
- if(cc) {
- cTimeMs start;
- int id=cc->msECM.Get(data,SCT_LEN(data),cw);
- if(id==0 || (id>0 && cc->ProcessECM(ecm,data,cw))) {
- int dur=start.Elapsed();
- if(dur>2000) {
- char bb[32];
- time_t now=time(0);
- ctime_r(&now,bb); stripspace(bb);
- PRINTF(L_CC_CORE,"%s: lagged cw %d ms (%s)",bb,dur,cc->Name());
- }
- char buff[32];
- snprintf(buff,sizeof(buff),"CC %s",cc->Name());
- KeyOK(buff);
- if(id>0) cc->msECM.Cache(id,true,cw);
- return true;
- }
- if(id>0) {
- PRINTF(L_CC_CORE,"client %s (%s:%d) ECM failed (%d ms)",cc->Name(),cc->hostname,cc->port,(int)start.Elapsed());
- cc->msECM.Cache(id,false,cw);
- }
- }
- if(!cc) PRINTF(L_CC_CORE,"cc-loop");
- cc=staticCcl.FindBySysId(ecm->caId,cc);
- if(cc && cc!=startCc) PRINTF(L_CC_CORE,"now trying client %s (%s:%d)",cc->Name(),cc->hostname,cc->port);
- } while(cc!=startCc);
- return false;
-}
-
-void cSystemCardClient::ProcessEMM(int pid, int caid, unsigned char *buffer)
-{
- cCardClient *cc=0;
- while((cc=staticCcl.FindBySysId(caid,cc)))
- cc->ProcessEMM(caid,buffer);
-}
-
-// -- cSystemLinkCardClient -----------------------------------------------------------
-
-cSystemLinkCardClient::cSystemLinkCardClient(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-,cStructListPlain<cCardClient>("cardclient config",CONF_FILE,SL_MISSINGOK|SL_VERBOSE|SL_NOPURGE)
-{
- opts=new cOpts(SYSTEM_NAME,1);
- opts->Add(new cOptBool("Immediate",trNOOP("Cardclient: connect immediately"),&immediate));
-}
-
-cCardClient *cSystemLinkCardClient::FindBySysId(unsigned short id, cCardClient *cc)
-{
- ListLock(false);
- for(cc=cc ? Next(cc):First(); cc; cc=Next(cc))
- if(cc->CanHandle(id)) break;
- ListUnlock();
- return cc;
-}
-
-bool cSystemLinkCardClient::CanHandle(unsigned short SysId)
-{
- return FindBySysId(SysId,0)!=0;
-}
-
-cSystem *cSystemLinkCardClient::Create(void)
-{
- return new cSystemCardClient();
-}
-
-bool cSystemLinkCardClient::ParseLinePlain(const char *line)
-{
- char name[32];
- int num;
- if(sscanf(line,"%31[^:]:%n",name,&num)==1) {
- cCardClientLink *ccl=cardclients.FindByName(name);
- if(ccl) {
- cCardClient *cc=ccl->Create();
- if(cc) {
- if(cc->Init(&line[num])) {
- Add(cc);
- PRINTF(L_CC_CORE,"client '%s' ready",cc->Name());
- return true;
- }
- else {
- delete cc;
- PRINTF(L_GEN_ERROR,"init of cardclient '%s' failed",name);
- }
- }
- else PRINTF(L_GEN_ERROR,"failed to create cardclient '%s'",name);
- }
- else PRINTF(L_GEN_ERROR,"no client found for card server type '%s'",name);
- }
- return false;
-}
-
-void cSystemLinkCardClient::Clean(void)
-{
- ListLock(true); Clear(); ListUnlock();
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___SYSTEM_CC_H
-#define ___SYSTEM_CC_H
-
-#include <vdr/thread.h>
-#include "system.h"
-#include "misc.h"
-#include "log.h"
-
-#define L_CC 6
-#define L_CC_CORE LCLASS(L_CC,0x2)
-#define L_CC_LOGIN LCLASS(L_CC,0x4)
-#define L_CC_ECM LCLASS(L_CC,0x8)
-#define L_CC_EMM LCLASS(L_CC,0x10)
-#define L_CC_CAMD LCLASS(L_CC,0x20)
-#define L_CC_CAMD35 LCLASS(L_CC,0x40)
-#define L_CC_CAMDEXTR LCLASS(L_CC,0x80)
-#define L_CC_RDGD LCLASS(L_CC,0x100)
-#define L_CC_NEWCAMD LCLASS(L_CC,0x200)
-#define L_CC_GBOX LCLASS(L_CC,0x400)
-
-#define L_CC_ALL LALL(L_CC_GBOX)
-
-// ----------------------------------------------------------------
-
-class cEcmInfo;
-class cNetSocket;
-class cCardClients;
-class cSystemCardClient;
-
-// ----------------------------------------------------------------
-
-#define MAX_CC_CAID 16
-
-class cCardClient : public cStructItem, protected cMutex {
-friend class cSystemCardClient;
-protected:
- const char *name;
- char hostname[64];
- int port;
- bool emmAllowed;
- int emmCaid[MAX_CC_CAID], emmMask[MAX_CC_CAID], numCaid;
- cMsgCache msECM, msEMM;
- //
- bool ParseStdConfig(const char *config, int *num=0);
- virtual bool SendMsg(cNetSocket *so, const unsigned char *data, int len);
- virtual int RecvMsg(cNetSocket *so, unsigned char *data, int len, int to=-1);
- virtual bool Login(void) { return false; }
- bool Immediate(void);
-public:
- cCardClient(const char *Name);
- virtual bool Init(const char *config)=0;
- virtual bool CanHandle(unsigned short SysId);
- virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)=0;
- virtual bool ProcessEMM(int caSys, const unsigned char *data) { return false; }
- const char *Name(void) { return name; }
- };
-
-// ----------------------------------------------------------------
-
-class cCardClientLink {
-friend class cCardClients;
-private:
- cCardClientLink *next;
-protected:
- const char *name;
-public:
- cCardClientLink(const char *Name);
- virtual ~cCardClientLink() {};
- virtual cCardClient *Create(void)=0;
- };
-
-// ----------------------------------------------------------------
-
-template<class CC> class cCardClientLinkReg : public cCardClientLink {
-public:
- cCardClientLinkReg(const char *Name):cCardClientLink(Name) {}
- virtual cCardClient *Create(void) { return new CC(name); }
- };
-
-#endif //___SYSTEM_CC_H
+++ /dev/null
-#
-# Cardclient
-#
-TARGET = cardclient
-OBJS = cc.o camd.o radegast.o aroureos.o newcamd.o gbox.o
-LIBS = -lcrypto -lcrypt
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- * This code is based on morfsta's version but has been rewritten nearly
- * from scratch.
- *
- * To get it working ensure that GBOX is running with no F: { 01 } line,
- * and no pmt.tmp file in /var/tmp.
- */
-
-#include <stdio.h>
-
-#include <vdr/pat.h>
-
-#include "cc.h"
-#include "network.h"
-#include "parse.h"
-
-// -- cGboxClient -----------------------------------------------------------
-
-class cCardClientGbox : public cCardClient {
-private:
- cNetSocket so;
- //
- int GetMsg(int cmd, unsigned char *buff, int len);
-protected:
- virtual bool Login(void);
-public:
- cCardClientGbox(const char *Name);
- virtual bool Init(const char *CfgDir);
- virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw);
- };
-
-static cCardClientLinkReg<cCardClientGbox> __ncd("gbox");
-
-cCardClientGbox::cCardClientGbox(const char *Name)
-:cCardClient(Name)
-,so(DEFAULT_CONNECT_TIMEOUT,2,DEFAULT_IDLE_TIMEOUT,true)
-{}
-
-bool cCardClientGbox::Init(const char *config)
-{
- cMutexLock lock(this);
- int num=0;
- if(!ParseStdConfig(config,&num)) return false;
- return Immediate() ? Login() : true;
-}
-
-bool cCardClientGbox::Login(void)
-{
- so.Disconnect();
- if(!so.Bind("127.0.0.1",8003)) return false;
- return true;
-}
-
-int cCardClientGbox::GetMsg(int cmd, unsigned char *buff, int len)
-{
- int n;
- do {
- n=so.Read(buff,len);
- if(n<=0) {
- if(n==0) PRINTF(L_CC_GBOX,"timeout on GetMsg.");
- break;
- }
- } while(buff[0]!=cmd);
- return n;
-}
-
-bool cCardClientGbox::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
-{
- cMutexLock lock(this);
- if((!so.Connected() && !Login()) || !CanHandle(ecm->caId)) return false;
- so.Flush();
-
- const int caid=ecm->caId;
- const int pid =ecm->ecm_pid;
-
- static const unsigned char pmt[] = {
- 0x87,
- 0x02,0xb0,0x25, // tid, sct len
- 0x17,0x74, // sid
- 0xc3,0x00,0x00, // vers, sctnr
- 0xff,0xec, // pcr pid
- 0xf0,0x00, // prg info len
- 0x02, 0xff,0xec, 0xf0,0x00
- };
- unsigned char buff[512];
- memcpy(buff,pmt,sizeof(pmt));
- buff[4]=ecm->prgId >> 8;
- buff[5]=ecm->prgId & 0xFF;
-#if APIVERSNUM >= 10500
- int casys[2];
-#else
- unsigned short casys[2];
-#endif
- casys[0]=caid;
- casys[1]=0;
- bool streamFlag;
- int n=GetCaDescriptors(ecm->source,ecm->transponder,ecm->prgId,casys,sizeof(buff)-sizeof(pmt),&buff[sizeof(pmt)],streamFlag);
- if(n<=0) {
- PRINTF(L_CC_GBOX,"no CA descriptor for caid %04x sid %d prov %04x",caid,ecm->prgId,ecm->provId);
- return false;
- }
- buff[16]=0xF0 | ((n>>8)&0x0F);
- buff[17]=n & 0xFF;
- SetSctLen(&buff[1],sizeof(pmt)-4+n+4);
- buff[2]=(buff[2]&0x0F)|0xB0;
-
- if(so.SendTo("127.0.0.1",8004,buff,sizeof(pmt)+n+4)<(int)sizeof(pmt)) {
- PRINTF(L_CC_GBOX,"failed to send PMT data. GBOX running?");
- return false;
- }
-
- if((n=GetMsg(0x8a,buff,sizeof(buff)))<=0) {
- PRINTF(L_CC_GBOX,"failed to get ECM port. GBOX running?");
- return false;
- }
- int pidnum=-1;
- if(n>=2) {
- for(int i=0 ; i<buff[1]; i++) {
- if(WORD(buff,2+i*2,0x1FFF)==pid) {
- pidnum=i;
- break;
- }
- }
- }
- if(pidnum<0) {
- PRINTF(L_CC_ECM,"%s: unable to decode for CAID %04X/PID %04X",name,caid,pid);
- return false;
- }
-
- n=SCT_LEN(data);
- if(n>=256) {
- PRINTF(L_CC_ECM,"%s: ECM section too long %d > 255",name,n);
- return false;
- }
- buff[0]=0x88;
- buff[1]=(pid>>8)&0x1F;
- buff[2]=pid & 0xFF;
- buff[3]=n;
- memcpy(&buff[4],data,n);
- n+=4;
- if(so.SendTo("127.0.0.1",8005+pidnum,buff,n)<n) {
- PRINTF(L_CC_GBOX,"failed to send ECM data. GBOX running?");
- return false;
- }
-
- if(GetMsg(0x89,buff,sizeof(buff))<=0) {
- PRINTF(L_CC_GBOX,"failed to get CW. GBOX running?");
- return false;
- }
- if(n<17) {
- PRINTF(L_CC_GBOX,"bad CW answer from GBOX");
- return false;
- }
- memcpy(cw,&buff[1],16);
- return true;
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <crypt.h>
-#include <byteswap.h>
-
-#include <vdr/thread.h>
-
-#include "cc.h"
-#include "network.h"
-#include "misc.h"
-#include "parse.h"
-
-#include <openssl/des.h>
-
-#define CWS_NETMSGSIZE 240
-
-// -- cTripleDes ---------------------------------------------------------------
-
-class cTripleDes {
-private:
- DES_key_schedule ks1,ks2;
- //
- void SetOddParity(unsigned char *key); // key must be 16 bytes!
-protected:
- unsigned char desKey[16];
- //
- void ScheduleKey(void);
- int PadMessage(unsigned char *data, int len);
- void Expand(unsigned char *expanded, const unsigned char *normal); // 14 byte key input, 16 byte expanded output
- void Decrypt(unsigned char *data, int len);
- const unsigned char *Encrypt(const unsigned char *data, int len, unsigned char *crypt);
- };
-
-void cTripleDes::SetOddParity(unsigned char *key)
-{
- DES_set_odd_parity((DES_cblock *)&key[0]); // set odd parity on both keys
- DES_set_odd_parity((DES_cblock *)&key[8]); //
-}
-
-void cTripleDes::ScheduleKey(void)
-{
- DES_key_sched((DES_cblock *)&desKey[0],&ks1);
- DES_key_sched((DES_cblock *)&desKey[8],&ks2);
-}
-
-void cTripleDes::Expand(unsigned char *expand, const unsigned char *normal)
-{
- expand[0] = normal[0] & 0xfe;
- expand[1] = ((normal[0] << 7) | (normal[1] >> 1)) & 0xfe;
- expand[2] = ((normal[1] << 6) | (normal[2] >> 2)) & 0xfe;
- expand[3] = ((normal[2] << 5) | (normal[3] >> 3)) & 0xfe;
- expand[4] = ((normal[3] << 4) | (normal[4] >> 4)) & 0xfe;
- expand[5] = ((normal[4] << 3) | (normal[5] >> 5)) & 0xfe;
- expand[6] = ((normal[5] << 2) | (normal[6] >> 6)) & 0xfe;
- expand[7] = normal[6] << 1;
- expand[8] = normal[7] & 0xfe;
- expand[9] = ((normal[7] << 7) | (normal[8] >> 1)) & 0xfe;
- expand[10] = ((normal[8] << 6) | (normal[9] >> 2)) & 0xfe;
- expand[11] = ((normal[9] << 5) | (normal[10] >> 3)) & 0xfe;
- expand[12] = ((normal[10] << 4) | (normal[11] >> 4)) & 0xfe;
- expand[13] = ((normal[11] << 3) | (normal[12] >> 5)) & 0xfe;
- expand[14] = ((normal[12] << 2) | (normal[13] >> 6)) & 0xfe;
- expand[15] = normal[13] << 1;
- SetOddParity(expand);
-}
-
-int cTripleDes::PadMessage(unsigned char *data, int len)
-{
- DES_cblock padBytes;
- unsigned char noPadBytes;
-
- noPadBytes = (8 - ((len - 1) % 8)) % 8;
- if(len+noPadBytes+1 >= CWS_NETMSGSIZE-8) {
- PRINTF(L_CC_NEWCAMD,"message overflow in cTripleDes::PadMessage");
- return -1;
- }
-
- srand(time(NULL)); // make sure the random generator is initialized
- DES_random_key((DES_cblock *)padBytes);
- memcpy(data+len,padBytes,noPadBytes); len+=noPadBytes;
- data[len]=XorSum(data+2,len-2);
- return len+1;
-}
-
-const unsigned char *cTripleDes::Encrypt(const unsigned char *data, int len, unsigned char *crypt)
-{
- DES_cblock ivec;
- DES_random_key((DES_cblock *)ivec);
- memcpy(crypt+len,ivec,sizeof(ivec));
- DES_ede2_cbc_encrypt(data+2,crypt+2,len-2,&ks1,&ks2,(DES_cblock *)ivec,DES_ENCRYPT);
- return crypt;
-}
-
-void cTripleDes::Decrypt(unsigned char *data, int len)
-{
- if((len-2) % 8 || (len-2)<16) {
- PRINTF(L_CC_NEWCAMD,"warning: encrypted data size mismatch");
- return;
- }
- DES_cblock ivec;
- len-=sizeof(ivec); memcpy(ivec, data+len, sizeof(ivec));
- DES_ede2_cbc_encrypt(data+2,data+2,len-2,&ks1,&ks2,(DES_cblock *)ivec,DES_DECRYPT);
-}
-
-// -- cNewCamdClient -----------------------------------------------------------
-
-#define USERLEN 32
-#define PASSWDLEN 32
-#define CWS_FIRSTCMDNO 0xe0
-
-typedef enum {
- MSG_CLIENT_2_SERVER_LOGIN = CWS_FIRSTCMDNO,
- MSG_CLIENT_2_SERVER_LOGIN_ACK,
- MSG_CLIENT_2_SERVER_LOGIN_NAK,
- MSG_CARD_DATA_REQ,
- MSG_CARD_DATA,
- MSG_SERVER_2_CLIENT_NAME,
- MSG_SERVER_2_CLIENT_NAME_ACK,
- MSG_SERVER_2_CLIENT_NAME_NAK,
- MSG_SERVER_2_CLIENT_LOGIN,
- MSG_SERVER_2_CLIENT_LOGIN_ACK,
- MSG_SERVER_2_CLIENT_LOGIN_NAK,
- MSG_ADMIN,
- MSG_ADMIN_ACK,
- MSG_ADMIN_LOGIN,
- MSG_ADMIN_LOGIN_ACK,
- MSG_ADMIN_LOGIN_NAK,
- MSG_ADMIN_COMMAND,
- MSG_ADMIN_COMMAND_ACK,
- MSG_ADMIN_COMMAND_NAK
- } net_msg_type_t;
-
-typedef enum {
- COMMTYPE_CLIENT,
- COMMTYPE_SERVER
- } comm_type_t;
-
-struct CustomData {
- union {
- struct {
- unsigned short prgId; // Big-Endian
- unsigned char data[6];
- } V525;
- struct {
- unsigned int prgId; // Big-Endian
- } V520;
- };
- };
-
-class cCardClientNewCamd : public cCardClient, private cTripleDes, private cIdSet {
-private:
- cNetSocket so;
- unsigned char configKey[14];
- unsigned short netMsgId;
- int caId, protoVers, cdLen;
- bool emmProcessing;
- char username[USERLEN], password[PASSWDLEN];
- //
- void InitVars(void);
- void InitProtoVers(int vers);
- bool NextProto(void);
- void InitCustomData(struct CustomData *cd, const unsigned short PrgId, const unsigned char *data);
- void PrepareLoginKey(unsigned char *deskey, const unsigned char *rkey, const unsigned char *ckey);
-protected:
- virtual bool Login(void);
-public:
- cCardClientNewCamd(const char *Name);
- // Client Helper functions
- bool SendMessage(cNetSocket *so, const unsigned char *data, int len, bool UseMsgId, const struct CustomData *cd=0, comm_type_t commType=COMMTYPE_CLIENT);
- int ReceiveMessage(cNetSocket *so, unsigned char *data, bool UseMsgId, struct CustomData *cd=0, comm_type_t commType=COMMTYPE_CLIENT);
- bool CmdSend(cNetSocket *so, net_msg_type_t cmd, comm_type_t commType=COMMTYPE_CLIENT);
- int CmdReceive(cNetSocket *so, comm_type_t commType=COMMTYPE_CLIENT);
- //
- virtual bool Init(const char *CfgDir);
- virtual bool CanHandle(unsigned short SysId);
- virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw);
- virtual bool ProcessEMM(int caSys, const unsigned char *data);
- };
-
-static cCardClientLinkReg<cCardClientNewCamd> __ncd("Newcamd");
-
-cCardClientNewCamd::cCardClientNewCamd(const char *Name)
-:cCardClient(Name)
-,so(DEFAULT_CONNECT_TIMEOUT,20,DEFAULT_IDLE_TIMEOUT)
-{
- memset(username,0,sizeof(username));
- memset(password,0,sizeof(password));
- InitVars();
- InitProtoVers(525);
-}
-
-void cCardClientNewCamd::InitVars(void)
-{
- netMsgId=0; caId=-1; emmProcessing=false;
- ResetIdSet();
-}
-
-void cCardClientNewCamd::InitProtoVers(int vers)
-{
- switch(vers) {
- case 525: protoVers=525; cdLen=8; break;
- default: protoVers=520; cdLen=4; break;
- }
- PRINTF(L_CC_NEWCAMD,"now using protocol version %d (cdLen=%d)",protoVers,cdLen);
-}
-
-bool cCardClientNewCamd::NextProto(void)
-{
- switch(protoVers) {
- case 525: InitProtoVers(520); break;
- default: return false;
- }
- return true;
-}
-
-void cCardClientNewCamd::InitCustomData(struct CustomData *cd, const unsigned short PrgId, const unsigned char *data)
-{
- if(cd) {
- switch(protoVers) {
- case 525:
- cd->V525.prgId=bswap_16(PrgId);
- if(data) memcpy(cd->V525.data,data,sizeof(cd->V525.data));
- else memset(cd->V525.data,0,sizeof(cd->V525.data));
- break;
- default:
- cd->V520.prgId=bswap_32((unsigned int)PrgId);
- break;
- }
- }
-}
-
-void cCardClientNewCamd::PrepareLoginKey(unsigned char *deskey, const unsigned char *rkey, const unsigned char *ckey)
-{
- unsigned char tmpkey[14];
- for (int i=0; i<(int)sizeof(tmpkey); i++) { tmpkey[i]=rkey[i]^ckey[i]; }
- Expand(deskey, tmpkey);
-}
-
-bool cCardClientNewCamd::SendMessage(cNetSocket *so, const unsigned char *data, int len, bool UseMsgId, const struct CustomData *cd, comm_type_t commType)
-{
- if(len<3||len+cdLen+4>CWS_NETMSGSIZE) {
- PRINTF(L_CC_NEWCAMD,"bad message size %d in SendMessage",len);
- return false;
- }
- unsigned char netbuf[CWS_NETMSGSIZE];
- memset(&netbuf[2],0,cdLen+2);
- memcpy(&netbuf[cdLen+4],data,len);
- netbuf[cdLen+4+1]=(data[1]&0xf0)|(((len-3)>>8)&0x0f);
- netbuf[cdLen+4+2]=(len-3)&0xff;
- len+=4;
- if(cd) memcpy(&netbuf[4],cd,cdLen);
- len+=cdLen;
- if(UseMsgId) {
- if(commType==COMMTYPE_CLIENT) netMsgId++;
- netbuf[2]=netMsgId>>8;
- netbuf[3]=netMsgId&0xff;
- }
- if((len=cTripleDes::PadMessage(netbuf,len))<0) {
- PRINTF(L_CC_NEWCAMD,"PadMessage failed");
- return false;
- }
- if((data=cTripleDes::Encrypt(netbuf,len,netbuf))==0) {
- PRINTF(L_CC_NEWCAMD,"Encrypt failed");
- return false;
- }
- len+=sizeof(DES_cblock);
- netbuf[0]=(len-2)>>8;
- netbuf[1]=(len-2)&0xff;
- return cCardClient::SendMsg(so,netbuf,len);
-}
-
-int cCardClientNewCamd::ReceiveMessage(cNetSocket *so, unsigned char *data, bool UseMsgId, struct CustomData *cd, comm_type_t commType)
-{
- unsigned char netbuf[CWS_NETMSGSIZE];
- int len=cCardClient::RecvMsg(so,netbuf,2);
- if(len!=2) {
- if(len>0) PRINTF(L_CC_NEWCAMD,"bad length %d != 2 on message length read",len);
- return 0;
- }
- const int mlen=WORD(netbuf,0,0xFFFF);
- if(mlen>CWS_NETMSGSIZE-2) {
- PRINTF(L_CC_NEWCAMD,"receive message buffer overflow");
- return 0;
- }
- len=cCardClient::RecvMsg(so,netbuf+2,mlen);
- if(len!=mlen) {
- PRINTF(L_CC_NEWCAMD,"bad length %d != %d on message read",len,mlen);
- return 0;
- }
- len+=2;
- cTripleDes::Decrypt(netbuf,len); len-=sizeof(DES_cblock);
- if(XorSum(netbuf+2, len-2)) {
- PRINTF(L_CC_NEWCAMD,"checksum error");
- return 0;
- }
-
- int returnLen=WORD(netbuf,5+cdLen,0x0FFF)+3;
- if(cd) memcpy(cd,&netbuf[4],cdLen);
- if(UseMsgId) {
- switch(commType) {
- case COMMTYPE_SERVER:
- netMsgId=WORD(netbuf,2,0xFFFF);
- break;
- case COMMTYPE_CLIENT:
- if(netMsgId!=WORD(netbuf,2,0xFFFF)) {
- PRINTF(L_CC_NEWCAMD,"bad msgid %04x != %04x ",netMsgId,WORD(netbuf,2,0xFFFF));
- return -1;
- }
- break;
- default:
- PRINTF(L_CC_NEWCAMD,"unknown commType %x",commType);
- return -1;
- }
- }
- memcpy(data,netbuf+4+cdLen,returnLen);
- return returnLen;
-}
-
-bool cCardClientNewCamd::CmdSend(cNetSocket *so, net_msg_type_t cmd, comm_type_t commType)
-{
- unsigned char buffer[3];
- buffer[0] = cmd; buffer[1] = buffer[2] = 0;
- return SendMessage(so,buffer,sizeof(buffer),false,0,commType);
-}
-
-int cCardClientNewCamd::CmdReceive(cNetSocket *so, comm_type_t commType)
-{
- unsigned char buffer[CWS_NETMSGSIZE];
- if(ReceiveMessage(so,buffer,false,0,commType)!=3) return -1;
- return buffer[0];
-}
-
-bool cCardClientNewCamd::CanHandle(unsigned short SysId)
-{
- return (caId>=0 && SysId==caId) || (caId==0x1234 && SysId == 0x1801) ||
- cCardClient::CanHandle(SysId);
-// return (caId>=0 && SysId==caId) || cCardClient::CanHandle(SysId);
-}
-
-bool cCardClientNewCamd::Init(const char *config)
-{
- cMutexLock lock(this);
- int num=0;
- char key[29];
- const char *tmp=key;
- if(!ParseStdConfig(config,&num)
- || sscanf(&config[num],":%31[^:]:%31[^:]:%28[^:]",username,password,key)!=3
- || GetHex(tmp,configKey,sizeof(configKey),false)!=14) return false;
- char str[32];
- PRINTF(L_CC_CORE,"%s: username=%s password=%s key=%s",name,username,password,HexStr(str,configKey,14));
- return Immediate() ? Login() : true;
-}
-
-bool cCardClientNewCamd::Login(void)
-{
- so.Disconnect();
- if(!so.Connect(hostname,port)) return false;
-
- InitVars();
- unsigned char randData[14];
- if(so.Read(randData,sizeof(randData))!=14) {
- PRINTF(L_CC_NEWCAMD,"no connect answer from %s:%d",hostname,port);
- so.Disconnect();
- return false;
- }
-
- char *crPasswd=crypt(password,"$1$abcdefgh$");
- unsigned char buffer[CWS_NETMSGSIZE];
- const int userLen=strlen(username)+1;
- const int passLen=strlen(crPasswd)+1;
-
- // prepare the initial login message
- buffer[0] = MSG_CLIENT_2_SERVER_LOGIN;
- buffer[1] = 0;
- buffer[2] = userLen+passLen;
- memcpy(&buffer[3],username,userLen);
- memcpy(&buffer[3]+userLen,crPasswd,passLen);
-
- // XOR configKey with randData and expand the 14 byte result -> 16 byte
- PrepareLoginKey(desKey,randData,configKey);
- cTripleDes::ScheduleKey();
-
- // set NewCS client identification
- struct CustomData cd;
- InitCustomData(&cd,0x5644,0);
-
- if(!SendMessage(&so,buffer,buffer[2]+3,true,&cd) || CmdReceive(&so)!=MSG_CLIENT_2_SERVER_LOGIN_ACK) {
- PRINTF(L_CC_NEWCAMD,"failed to login to cardserver for username %s (proto %d)",username,protoVers);
- if(NextProto()) return Login();
- return false;
- }
-
- // create the session key (for usage later)
- unsigned char tmpkey[14];
- memcpy(tmpkey, configKey, sizeof(tmpkey));
- const int passStrLen=strlen(crPasswd);
- for(int i=0; i<passStrLen; ++i) tmpkey[i%14]^=crPasswd[i];
-
- cTripleDes::Expand(desKey,tmpkey); // expand 14 byte key -> 16 byte
- cTripleDes::ScheduleKey();
-
- if(!CmdSend(&so,MSG_CARD_DATA_REQ) || ReceiveMessage(&so,buffer,false)<=0) return false;
- if(buffer[0] == MSG_CARD_DATA) {
- caId=(buffer[4]<<8)+buffer[5];
- LBSTARTF(L_CC_LOGIN);
- char str[32], str2[32];
- LBPUT("%s: CaID=%04x admin=%d srvUA=%s",name,caId,buffer[3]==1,HexStr(str,&buffer[6],8));
- if(!CheckNull(&buffer[6],8)) {
- emmProcessing=true;
- switch(caId>>8) {
- case 0x17:
- case 0x06: SetCard(new cCardIrdeto(buffer[6+4],&buffer[6+5])); break;
- case 0x01: SetCard(new cCardSeca(&buffer[6+2])); break;
- case 0x0b: SetCard(new cCardConax(&buffer[6+1])); break;
- case 0x09: SetCard(new cCardNDS(&buffer[6+4])); break;
- case 0x05: SetCard(new cCardViaccess(&buffer[6+3])); break;
- case 0x0d: SetCard(new cCardCryptoworks(&buffer[6+3])); break;
- case 0x12:
- case 0x18: if(caId==0x1801 || caId==0x1234 ) {
- SetCard(new cCardNagra2(&buffer[6+4]));
- break;
- }
- // fall through to default
- default:
- LBPUT(" (unhandled)");
- break;
- }
- }
- LBPUT(" provider");
- for(int i=(buffer[14]-1)*11; i>=0; i-=11) {
- LBPUT(" %s/%s",HexStr(str2,&buffer[15+i],3),HexStr(str,&buffer[18+i],8));
- if(!CheckNull(&buffer[18+i],8)) {
- switch(caId>>8) {
- case 0x17:
- case 0x06: AddProv(new cProviderIrdeto(buffer[18+i+4],&buffer[18+i+5])); break;
- case 0x01: AddProv(new cProviderSeca(&buffer[15+i+1],&buffer[18+i+4])); break;
- case 0x0b: AddProv(new cProviderConax(&buffer[18+i+1])); break;
- case 0x09: AddProv(new cProviderNDS(&buffer[18+i+4])); break;
- case 0x05: AddProv(new cProviderViaccess(&buffer[15+i],&buffer[18+i+4])); break;
- case 0x0d: AddProv(new cProviderCryptoworks(&buffer[18+i+3])); break;
- default:
- LBPUT(" <unhandled>");
- break;
- }
- }
- }
- LBEND();
- if(emmProcessing && !emmAllowed)
- PRINTF(L_CC_EMM,"%s: EMM disabled from config",name);
- }
- return true;
-}
-
-bool cCardClientNewCamd::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
-{
- cMutexLock lock(this);
- if((!so.Connected() && !Login()) || !CanHandle(ecm->caId)) return false;
- so.Flush();
-
- struct CustomData cd;
- InitCustomData(&cd,(unsigned short)ecm->prgId,0);
- if(!SendMessage(&so,data,SCT_LEN(data),true,&cd)) return false;
- unsigned char buffer[CWS_NETMSGSIZE];
- switch(ReceiveMessage(&so,buffer,true)) {
- case 19: // ecm was decoded
- // check for zero cw, as newcs doesn't send both cw's every time
- if(!CheckNull(buffer+3+0,8)) memcpy(cw+0,buffer+3+0,8);
- if(!CheckNull(buffer+3+8,8)) memcpy(cw+8,buffer+3+8,8);
- return true;
- case 3:
- PRINTF(L_CC_ECM,"%s: card was not able to decode the channel",name);
- break;
- default:
- PRINTF(L_CC_NEWCAMD,"warning an unexpected error occurred");
- break;
- }
- return false;
-}
-
-bool cCardClientNewCamd::ProcessEMM(int caSys, const unsigned char *data)
-{
- if(emmProcessing && emmAllowed) {
- cMutexLock lock(this);
- cAssembleData ad(data);
- if(MatchAndAssemble(&ad,0,0)) {
- while((data=ad.Assembled())) {
- int len=SCT_LEN(data);
- int id=msEMM.Get(data,len,0);
- if(id>0) {
- if(SendMessage(&so,data,len,true,0)) {
- unsigned char buffer[CWS_NETMSGSIZE];
- ReceiveMessage(&so,buffer,true);
- }
- msEMM.Cache(id,true,0);
- }
- }
- return true;
- }
- }
- return false;
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "cc.h"
-#include "parse.h"
-#include "network.h"
-#include "version.h"
-
-// -- cCardClientRadegast ------------------------------------------------------
-
-#define MAXCAIDS 16
-
-class cCardClientRadegast : public cCardClient, private cIdSet {
-private:
- cNetSocket so;
- bool emmProcessing;
- int caids[MAXCAIDS], numCaids;
- //
- void InitVars(void);
- void SetLength(unsigned char *buff, int len);
- int GetLength(const unsigned char *buff);
- int GetNanoStart(const unsigned char *buff);
- int GetMsgLength(const unsigned char *buff);
- int GetMaxLength(const unsigned char *buff);
- void StartMsg(unsigned char *buff, int cmd);
- bool CheckLength(const unsigned char *buff, int len);
- void AddNano(unsigned char *buff, int nano, int len, int value);
- void AddNano(unsigned char *buff, int nano, int len, const unsigned char *data);
- bool Send(const unsigned char *buff);
- int Recv(unsigned char *buff, int len);
-protected:
- virtual bool Login(void);
-public:
- cCardClientRadegast(const char *Name);
- virtual bool Init(const char *config);
- virtual bool CanHandle(unsigned short SysId);
- virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw);
- virtual bool ProcessEMM(int caSys, const unsigned char *data);
- };
-
-static cCardClientLinkReg<cCardClientRadegast> __rdg("Radegast");
-
-cCardClientRadegast::cCardClientRadegast(const char *Name)
-:cCardClient(Name)
-,so(DEFAULT_CONNECT_TIMEOUT,7,DEFAULT_IDLE_TIMEOUT)
-{
- InitVars();
-}
-
-void cCardClientRadegast::InitVars(void)
-{
- emmProcessing=false; numCaids=0;
-}
-
-bool cCardClientRadegast::CanHandle(unsigned short SysId)
-{
- cMutexLock lock(this);
- if(numCaids<=0) return cCardClient::CanHandle(SysId);
- for(int i=0; i<numCaids; i++) if(caids[i]==SysId) return true;
- return false;
-}
-
-bool cCardClientRadegast::Init(const char *config)
-{
- cMutexLock lock(this);
- so.Disconnect();
- return ParseStdConfig(config) && (Immediate() ? Login() : true);
-}
-
-void cCardClientRadegast::SetLength(unsigned char *buff, int len)
-{
- if(buff[0]<=0x90) buff[1]=min(255,len);
- else { buff[1]=len>>8; buff[2]=len&0xFF; }
-}
-
-int cCardClientRadegast::GetLength(const unsigned char *buff)
-{
- return (buff[0]<=0x90) ? buff[1] : ((buff[1]<<8)+buff[2]);
-}
-
-int cCardClientRadegast::GetNanoStart(const unsigned char *buff)
-{
- return (buff[0]<=0x90) ? 2 : 3;
-}
-
-int cCardClientRadegast::GetMsgLength(const unsigned char *buff)
-{
- return GetLength(buff)+GetNanoStart(buff);
-}
-
-int cCardClientRadegast::GetMaxLength(const unsigned char *buff)
-{
- return (buff[0]<=0x90) ? 0xFF : 0xFFFF;
-}
-
-void cCardClientRadegast::StartMsg(unsigned char *buff, int cmd)
-{
- buff[0]=cmd;
- SetLength(buff,0);
-}
-
-bool cCardClientRadegast::CheckLength(const unsigned char *buff, int len)
-{
- int l=GetLength(buff)+len+2;
- int max=GetMaxLength(buff);
- if(len>255) PRINTF(L_CC_RDGD,"cmd %02x: nano too long %d > 255",buff[0],len);
- else if(l>max) PRINTF(L_CC_RDGD,"cmd %02x: msg too long %d > %d",buff[0],l,max);
- return l<=max;
-}
-
-void cCardClientRadegast::AddNano(unsigned char *buff, int nano, int len, int value)
-{
- unsigned char hex[4];
- for(int i=0; i<len; i++) hex[i]=value >> ((len-i-1)*8);
- AddNano(buff,nano,len,hex);
-}
-
-void cCardClientRadegast::AddNano(unsigned char *buff, int nano, int len, const unsigned char *data)
-{
- int pos=GetLength(buff), off=GetNanoStart(buff);
- if(pos<GetMaxLength(buff)) {
- buff[off+pos]=nano;
- buff[off+pos+1]=len;
- memcpy(&buff[off+pos+2],data,len);
- pos+=len+2;
- }
- SetLength(buff,pos);
-}
-
-bool cCardClientRadegast::Send(const unsigned char *buff)
-{
- return SendMsg(&so,buff,GetMsgLength(buff));
-}
-
-int cCardClientRadegast::Recv(unsigned char *buff, int len)
-{
- int n=RecvMsg(&so,buff,len);
- if(n<1) return n;
- int k=GetNanoStart(buff);
- if(n<k) {
- PRINTF(L_CC_RDGD,"bad length %d < %d on cmd read",n,k);
- return -1;
- }
- k=GetMsgLength(buff);
- if(n<k) {
- PRINTF(L_CC_RDGD,"bad length %d < %d on nano read",n,k);
- return -1;
- }
- return n;
-}
-
-bool cCardClientRadegast::Login(void)
-{
- so.Disconnect();
- if(!so.Connect(hostname,port)) return false;
- PRINTF(L_CC_LOGIN,"%s: connected to %s:%d",name,hostname,port);
-
- InitVars();
- unsigned char buff[512];
- char hello[32];
- snprintf(hello,sizeof(hello),"rdgd/vdr-sc-%s",ScVersion);
- StartMsg(buff,0x90); // RDGD_MSG_CLIENT_HELLO
- AddNano(buff,1,strlen(hello),(unsigned char *)hello); // RDGD_NANO_DESCR
- int n;
- if(!Send(buff) || (n=Recv(buff,sizeof(buff)))<0) return false;
- if(n>0 && buff[0]==0x91) {
- PRINTF(L_CC_RDGD,"got server hello, assuming V4 mode");
- StartMsg(buff,0x94); // RDGD_MSG_CLIENT_CAP_REQ;
- if(!Send(buff) || (n=Recv(buff,sizeof(buff)))<0) return false;
- if(n>0 && buff[0]==0x95) {
- LBSTARTF(L_CC_LOGIN);
- LBPUT("radegast: got caps");
- int caid;
- for(int l=GetNanoStart(buff); l<n; l+=buff[l+1]+2) {
- switch(buff[l]) {
- case 0xE2:
- LBPUT(" VERS %s",(char *)&buff[l+2]);
- break;
- case 0xE4: // CAP_NANO_CAID
- if(numCaids>=MAXCAIDS) { l=n; break; } //stop processing
- caid=(buff[l+2]<<8)+buff[l+3];
- LBPUT(" CAID %04X",caid);
- caids[numCaids++]=caid;
- // XXX we should have EMM processing setup here, but as we don't
- // XXX get any ua/sa we cannot filter EMM anyways
- break;
- case 0xE5: // CAP_NANO_PROVID
- for(int i=0; i<buff[l+1]; i+=3)
- LBPUT("/%02X%02X%02X",buff[l+2+i],buff[l+2+i+1],buff[l+2+i+2]);
- break;
- }
- }
- LBEND();
- }
- }
- else PRINTF(L_CC_RDGD,"no server hello, assuming old mode");
- if(emmProcessing && !emmAllowed)
- PRINTF(L_CC_EMM,"%s: EMM disabled from config",name);
- return true;
-}
-
-bool cCardClientRadegast::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw)
-{
- cMutexLock lock(this);
- so.Flush();
- int len=SCT_LEN(source);
- int keynr=-1;
- switch(ecm->caId>>8) {
- case 0x01: // Seca
- keynr=source[7]&0x0F; break;
- case 0x05: // Viaccess
- keynr=source[4]&0x0F; break;
- }
- unsigned char buff[512], tmp[10];
- StartMsg(buff,1); // CMD_ECM_KEY_ASK
- AddNano(buff,2,1,ecm->caId>>8); // ECM_NANO_CAID_INDEX (old)
- AddNano(buff,10,2,ecm->caId); // ECM_NANO_CAID
- sprintf((char *)tmp,"%08X",ecm->provId);
- AddNano(buff,6,8,tmp); // ECM_NANO_PROVIDER
- if(keynr>=0) {
- sprintf((char *)tmp,"%04X",keynr);
- AddNano(buff,7,4,tmp); // ECM_NANO_KEYNO
- }
- if(!CheckLength(buff,len)) return false;
- AddNano(buff,3,len,source); // ECM_NANO_PACKET
-
- if(!Send(buff) || (len=Recv(buff,sizeof(buff)))<=0) return false;
- if(buff[0]==2) {
- for(int l=GetNanoStart(buff); l<len; l+=buff[l+1]+2) {
- switch(buff[l]) {
- case 0x05:
- if(buff[l+1]==16) {
- // check for zero cw, as someone may not send both cw's every time
- if(!CheckNull(buff+l+ 2,8)) memcpy(cw+0,buff+l+ 2,8);
- if(!CheckNull(buff+l+10,8)) memcpy(cw+8,buff+l+10,8);
- return true;
- }
- else PRINTF(L_CC_RDGD,"wrong cw length %d from server",buff[l+1]);
- break;
- case 0x04:
- PRINTF(L_CC_ECM,"%s: key not available from server",name);
- break;
- default:
- PRINTF(L_CC_RDGD,"unknown nano %02x in ECM response",buff[l]);
- break;
- }
- }
- }
- else PRINTF(L_CC_RDGD,"bad ECM response from server %02x != 02",buff[0]);
- return false;
-}
-
-bool cCardClientRadegast::ProcessEMM(int caSys, const unsigned char *data)
-{
- if(emmProcessing && emmAllowed) {
- cMutexLock lock(this);
- int upd;
- cProvider *p;
- cAssembleData ad(data);
- if(MatchAndAssemble(&ad,&upd,&p)) {
- while((data=ad.Assembled())) {
- int len=SCT_LEN(data);
- int id=msEMM.Get(data,len,0);
- if(id>0) {
- unsigned char buff[512];
- StartMsg(buff,0x41); //
- AddNano(buff,0x42,2,caSys); // EMM_CAID
- if(p) {
- unsigned char tmp[10];
- sprintf((char *)tmp,"%08X",(int)p->ProvId());
- AddNano(buff,0x46,8,tmp); // EMM_PROVID
- }
-/*
- if(upd==2 || upd==3) {
- AddNano(buff,0x44,2,(unsigned char *)"aa"); // EMM_ADDR_VAL
- }
-*/
- AddNano(buff,0x45,1,upd==3 ? 0x11 : (upd==2 ? 0x12 : 0x13)); // EMM_ADDR_TYPE
- if(CheckLength(buff,len)) {
- AddNano(buff,0x43,len,data); // EMM_CA_DATA
- Send(buff);
- }
- msEMM.Cache(id,true,0);
- }
- }
- return true;
- }
- }
- return false;
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "system-common.h"
-#include "crypto.h"
-#include "data.h"
-#include "misc.h"
-#include "log-sys.h"
-
-#define SYSTEM_CONAX 0x0B00
-
-#define SYSTEM_NAME "Conax"
-#define SYSTEM_PRI -10
-#define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_CONAX)
-
-#define L_SYS 3
-#define L_SYS_ALL LALL(L_SYS_LASTDEF)
-
-static const struct LogModule lm_sys = {
- (LMOD_ENABLE|L_SYS_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_SYS_DEFDEF)&LOPT_MASK,
- "conax",
- { L_SYS_DEFNAMES }
- };
-ADD_MODULE(L_SYS,lm_sys)
-
-// -- cSystemConax ---------------------------------------------------------------
-
-class cSystemConax : public cSystem {
-private:
- cRSA rsa;
- //
- void ParseECM(unsigned char *buf, int len);
-public:
- cSystemConax(void);
- virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *source);
- };
-
-cSystemConax::cSystemConax(void)
-:cSystem(SYSTEM_NAME,SYSTEM_PRI)
-{}
-
-void cSystemConax::ParseECM(unsigned char *buf, int len)
-{
- int i=0;
- while(i<len) {
- int nano=buf[i++];
- int nanolen=buf[i++];
-
- switch(nano) {
- case 0x80:
- case 0x82:
- ParseECM(buf+i+3,nanolen-3); break;
- case 0x81:
- ParseECM(buf+i+2,nanolen-2); break;
- case 0x30:
- memcpy(cw ,buf+i+10,8);
- memcpy(cw+8,buf+i+2 ,8);
- break;
- }
- i+=nanolen;
- }
-}
-
-bool cSystemConax::ProcessECM(const cEcmInfo *ecm, unsigned char *source)
-{
- int length=source[4]-2;
- const int keyid=source[6];
- const int nano=source[5];
- source+=7;
-
- cKeySnoop ks(this,'C',keyid,'M');
- cPlainKey *pk;
- cBN mod, exp;
- if(!(pk=keys.FindKey('C',keyid,'E',-1))) {
- if(doLog) PRINTF(L_SYS_KEY,"missing %02X E key",keyid);
- return false;
- }
- pk->Get(exp);
- if(!(pk=keys.FindKey('C',keyid,'M',-1))) {
- if(doLog) PRINTF(L_SYS_KEY,"missing %02X M key",keyid);
- return false;
- }
- pk->Get(mod);
-
- for(int i=length ; i>0 ;) {
- int index=i-64;
- if(index<0) index=0;
- if(rsa.RSA(source+index,source+index,64,exp,mod,false)<=0) {
- if(doLog) PRINTF(L_SYS_CRYPTO,"RSA failed");
- return false;
- }
- if(nano==0x63) {
- // nano 0x63 block only decodes to 63 bytes
- memmove(source+index,source+index+1,length-(index+1));
- length-=1;
- }
- i-=(i%60 && index) ? i%60 : 64;
- }
-
- static const unsigned char hash[] = { 0x05,0x00,0x05 };
- if(memcmp(hash,source+2,3) || memcmp(source+5,source+length-5,3)) {
- if(doLog) PRINTF(L_SYS_ECM,"signature check failed");
- return false;
- }
-
- ParseECM(source+10,length-10);
- ks.OK(pk);
- return true;
-}
-
-// -- cPlainKeyConax --------------------------------------------------------------
-
-#define PLAINLEN_CONAX 64
-
-class cPlainKeyConax : public cBNKey {
-protected:
- virtual cString PrintKeyNr(void);
-public:
- cPlainKeyConax(bool Super);
- virtual bool Parse(const char *line);
- };
-
-static cPlainKeyTypeReg<cPlainKeyConax,'C'> KeyReg;
-
-cPlainKeyConax::cPlainKeyConax(bool Super)
-:cBNKey(Super)
-{}
-
-bool cPlainKeyConax::Parse(const char *line)
-{
- unsigned char sid, skey[PLAINLEN_CONAX];
- if(GetChar(line,&type,1) && GetHex(line,&sid,1) &&
- GetChar(line,&keynr,1) && GetHex(line,skey,PLAINLEN_CONAX)) {
- type=toupper(type); keynr=toupper(keynr); id=sid;
- SetBinKey(skey,PLAINLEN_CONAX);
- return true;
- }
- return false;
-}
-
-cString cPlainKeyConax::PrintKeyNr(void)
-{
- return cString::sprintf("%c",keynr);
-}
-
-// -- cSystemLinkConax ---------------------------------------------------------
-
-class cSystemLinkConax : public cSystemLink {
-public:
- cSystemLinkConax(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemConax; }
- };
-
-static cSystemLinkConax staticInit;
-
-cSystemLinkConax::cSystemLinkConax(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- Feature.NeedsKeyFile();
-}
-
-bool cSystemLinkConax::CanHandle(unsigned short SysId)
-{
- SysId&=SYSTEM_MASK;
- return SYSTEM_CAN_HANDLE(SysId);
-}
+++ /dev/null
-#
-# Conax
-#
-TARGET = conax
-OBJS = conax.o
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <malloc.h>
-#include <ctype.h>
-#include <typeinfo>
-
-#include <vdr/channels.h>
-#include <vdr/sources.h>
-
-#include "system.h"
-#include "system-common.h"
-#include "data.h"
-#include "misc.h"
-
-#define SYSTEM_NAME "ConstCW"
-#define SYSTEM_PRI -20
-
-// -- cPlainKeyConstCw ----------------------------------------------------------------
-
-#define PLAINLEN_CW 16
-
-class cPlainKeyConstCw : public cHexKey {
-private:
- int prgId, source, transponder;
- int freq;
- char pol;
-protected:
- virtual int IdSize(void) { return 4; }
- virtual cString PrintKeyNr(void);
-public:
- cPlainKeyConstCw(bool Super);
- virtual bool Parse(const char *line);
- bool Matches(const cEcmInfo *ecm);
- };
-
-static cPlainKeyTypeReg<cPlainKeyConstCw,'X'> KeyReg;
-
-cPlainKeyConstCw::cPlainKeyConstCw(bool Super)
-:cHexKey(Super)
-{
- freq=-1;
-}
-
-bool cPlainKeyConstCw::Matches(const cEcmInfo *ecm)
-{
- return ecm->prgId==prgId && ecm->source==source && ecm->transponder==transponder;
-}
-
-bool cPlainKeyConstCw::Parse(const char *line)
-{
- unsigned char caid[2], skey[PLAINLEN_CW];
- if(GetChar(line,&type,1) && GetHex(line,caid,2)) {
- int num;
- char srcBuf[16];
- if(sscanf(line," %d:%c:%15[^:]:%d%n",&freq,&pol,srcBuf,&prgId,&num)==4) {
- source=cSource::FromString(srcBuf);
- transponder=freq;
- while(transponder>20000) transponder/=1000;
- if(cSource::IsSat(source)) transponder=cChannel::Transponder(transponder,pol);
- line+=num;
- if(GetHex(line,skey,PLAINLEN_CW)) {
- type=toupper(type);
- id=Bin2Int(caid,2);
- keynr=0;
- SetBinKey(skey,PLAINLEN_CW);
- return true;
- }
- }
- }
- return false;
-}
-
-cString cPlainKeyConstCw::PrintKeyNr(void)
-{
- return freq<0 ? "" : cString::sprintf("%d:%c:%s:%d",freq,pol,*cSource::ToString(source),prgId);
-}
-
-// -- cSystemConstCw ------------------------------------------------------------------
-
-class cSystemConstCw : public cSystem {
-public:
- cSystemConstCw(void);
- virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *source);
- };
-
-cSystemConstCw::cSystemConstCw(void)
-:cSystem(SYSTEM_NAME,SYSTEM_PRI)
-{
- constant=true;
-}
-
-bool cSystemConstCw::ProcessECM(const cEcmInfo *ecm, unsigned char *source)
-{
- cKeySnoop ks(this,'X',ecm->caId,0);
- cPlainKey *pk=0;
- while((pk=keys.FindKey('X',ecm->caId,0,16,pk))) {
- if(typeid(*pk)==typeid(cPlainKeyConstCw) && ((cPlainKeyConstCw *)pk)->Matches(ecm)) {
- pk->Get(cw);
- ks.OK(pk);
- return true;
- }
- }
- return false;
-}
-
-// -- cSystemLinkConstCw ------------------------------------------------------------
-
-class cSystemLinkConstCw : public cSystemLink {
-public:
- cSystemLinkConstCw(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemConstCw; }
- };
-
-static cSystemLinkConstCw staticInit;
-
-cSystemLinkConstCw::cSystemLinkConstCw(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- Feature.NeedsKeyFile();
-}
-
-bool cSystemLinkConstCw::CanHandle(unsigned short SysId)
-{
- return keys.FindKeyNoTrig('X',SysId,0,16)!=0;
-}
+++ /dev/null
-#
-# Const CW
-#
-TARGET = constcw
-OBJS = constcw.o
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <byteswap.h>
-
-#include "system-common.h"
-#include "data.h"
-#include "helper.h"
-#include "crypto.h"
-#include "misc.h"
-#include "log-sys.h"
-
-#define SYSTEM_CRYPTOWORKS 0x0D00
-
-#define SYSTEM_NAME "Cryptoworks"
-#define SYSTEM_PRI -10
-#define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_CRYPTOWORKS)
-
-#define L_SYS 4
-#define L_SYS_ALL LALL(L_SYS_LASTDEF)
-
-static const struct LogModule lm_sys = {
- (LMOD_ENABLE|L_SYS_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_SYS_DEFDEF)&LOPT_MASK,
- "cryptoworks",
- { L_SYS_DEFNAMES }
- };
-ADD_MODULE(L_SYS,lm_sys)
-
-#define DUMPNANO(t,p,n) \
- LBSTART(L_SYS_VERBOSE); \
- LBPUT("%s",(t)); \
- unsigned char *__p=(unsigned char *)(p); \
- int __n=(n); \
- for(int i=0; i<__n;) { \
- LBFLUSH(); \
- LBPUT("%02X %02X -",__p[i],__p[i+1]); \
- i+=2; \
- for(int l=__p[i-1]; l>0; l--) { LBPUT(" %02X",__p[i]); i++; }\
- if(i>__n) { LBFLUSH(); LBPUT("length exceeded %d != %d",i,__n); } \
- } \
- LBEND();
-
-// -- cCwDes -------------------------------------------------------------------
-
-static const unsigned char cryptoPC1[] = {
- 53,46,39,32,50,43,36,29,
- 22,15, 8, 1,51,44,37,30,
- 23,16, 9, 2,52,45,38,31,
- 24,17,10, 3,53,46,39,32,
- 25,18,11, 4,56,49,42,35,
- 28,21,14, 7,55,48,41,34,
- 27,20,13, 6,54,47,40,33,
- 26,19,12, 5,25,18,11, 4
- };
-
-static const unsigned char cryptoPC2[] = {
- 18,21,15,28, 5, 9, 7,32,19,10,25,14,
- 27,23,16, 8,30,12, 20,11,31,24,17, 6,
- 49,60,39,45,55,63, 38,48,59,53,41,56,
- 52,57,47,64,42,61, 54,50,58,44,37,40,
- };
-
-#define shiftin(V,R,n) ((V<<1)+(((R)>>(n))&1))
-#define rol28(V,n) (V<<(n) | ((V&0x0fffffffL)>>(28-(n))))
-#define ror28(V,n) (V>>(n) | ((V&0xfffffff0L)<<(28-(n))))
-
-#define DESROUND(C,D,T) { \
- unsigned int s=0; \
- for(int j=7, k=0; j>=0; j--) { \
- unsigned int v=0, K=0; \
- for(int t=5; t>=0; t--, k++) { \
- v=shiftin(v,T,E[k]); \
- if(PC2[k]<33) K=shiftin(K,C,32-PC2[k]); \
- else K=shiftin(K,D,64-PC2[k]); \
- } \
- s=(s<<4) + S[7-j][v^K]; \
- } \
- T=0; \
- for(int j=31; j>=0; j--) T=shiftin(T,s,P[j]); \
- }
-
-class cCwDes : public cDes {
-private:
- void PrepKey(unsigned char *out, const unsigned char *key) const;
- void PrepKey48(unsigned char *out, const unsigned char *key22, unsigned char algo) const;
-public:
- cCwDes(void);
- void CwDes(unsigned char *data, const unsigned char *key22, int mode) const;
- void CwL2Des(unsigned char *data, const unsigned char *key22, unsigned char algo) const;
- void CwR2Des(unsigned char *data, const unsigned char *key22, unsigned char algo) const;
- };
-
-cCwDes::cCwDes(void)
-:cDes(cryptoPC1,cryptoPC2)
-{}
-
-void cCwDes::PrepKey(unsigned char *out, const unsigned char *key) const
-{
- if(key!=out) memcpy(out,key,8);
- Permute(out,PC1,64);
-}
-
-void cCwDes::PrepKey48(unsigned char *out, const unsigned char *key22, unsigned char algo) const
-{
- memset(out,0,8);
- memcpy(out,&key22[16],6);
- int ctr=7-(algo&7);
- for(int i=8; i>=2 && i>ctr; i--) out[i-2]=key22[i];
-}
-
-void cCwDes::CwDes(unsigned char *data, const unsigned char *key22, int mode) const
-{
- unsigned char mkey[8];
- PrepKey(mkey,key22+9);
- LDUMP(L_SYS_VERBOSE,mkey,8,"prepped key DES:");
- unsigned int C=UINT32_BE(mkey );
- unsigned int D=UINT32_BE(mkey+4);
- unsigned int L=UINT32_BE(data );
- unsigned int R=UINT32_BE(data+4);
- if(!(mode&DES_RIGHT)) {
- for(int i=15; i>=0; i--) {
- C=rol28(C,LS[15-i]); D=rol28(D,LS[15-i]);
- unsigned int T=R;
- DESROUND(C,D,T);
- T^=L; L=R; R=T;
- }
- }
- else {
- for(int i=15; i>=0; i--) {
- unsigned int T=R;
- DESROUND(C,D,T);
- T^=L; L=R; R=T;
- C=ror28(C,LS[i]); D=ror28(D,LS[i]);
- }
- }
- BYTE4_BE(data ,L);
- BYTE4_BE(data+4,R);
-}
-
-void cCwDes::CwL2Des(unsigned char *data, const unsigned char *key22, unsigned char algo) const
-{
- unsigned char mkey[8];
- PrepKey48(mkey,key22,algo);
- PrepKey(mkey,mkey);
- LDUMP(L_SYS_VERBOSE,mkey,8,"prepped key L2:");
- unsigned int C=UINT32_BE(mkey );
- unsigned int D=UINT32_BE(mkey+4);
- unsigned int L=UINT32_BE(data );
- unsigned int R=UINT32_BE(data+4);
- for(int i=1; i>=0; i--) {
- C=rol28(C,1); D=rol28(D,1);
- unsigned int T=R;
- DESROUND(C,D,T);
- T^=L; L=R; R=T;
- PRINTF(L_SYS_VERBOSE,"round %d key L2: %08x %08x",i,C,D);
- }
- BYTE4_BE(data ,L);
- BYTE4_BE(data+4,R);
-}
-
-void cCwDes::CwR2Des(unsigned char *data, const unsigned char *key22, unsigned char algo) const
-{
- unsigned char mkey[8];
- PrepKey48(mkey,key22,algo);
- PrepKey(mkey,mkey);
- LDUMP(L_SYS_VERBOSE,mkey,8,"prepped key R2:");
- unsigned int C=UINT32_BE(mkey );
- unsigned int D=UINT32_BE(mkey+4);
- unsigned int L=UINT32_BE(data );
- unsigned int R=UINT32_BE(data+4);
- for(int i=1; i>=0; i--) {
- C=rol28(C,15); D=rol28(D,15);
- }
- for(int i=1; i>=0; i--) {
- unsigned int T=R;
- DESROUND(C,D,T);
- T^=L; L=R; R=T;
- C=ror28(C,1); D=ror28(D,1);
- }
- BYTE4_BE(data ,R);
- BYTE4_BE(data+4,L);
-}
-
-// -- cCryptoworks -------------------------------------------------------------
-
-class cCryptoworks {
-private:
- cCwDes des;
- cRSA rsa;
- cBN exp;
- //
- void EncDec(unsigned char *data, const unsigned char *key22, unsigned char algo, int mode);
-public:
- cCryptoworks(void);
- void Signature(const unsigned char *data, int len, const unsigned char *key22, unsigned char *sig);
- void DecryptDES(unsigned char *data, unsigned char algo, const unsigned char *key22);
- bool DecryptRSA(unsigned char *data, int len, unsigned char algo, const unsigned char *key22, BIGNUM *mod);
- };
-
-cCryptoworks::cCryptoworks(void)
-{
- BN_set_word(exp,2);
-}
-
-void cCryptoworks::EncDec(unsigned char *data, const unsigned char *key22, unsigned char algo, int mode)
-{
- LDUMP(L_SYS_VERBOSE,data,8,"encdec in :");
- PRINTF(L_SYS_VERBOSE,"algo %d",algo);
- LDUMP(L_SYS_VERBOSE,key22,22,"encdec key:");
- des.CwL2Des(data,key22,algo);
- des.CwDes(data,key22,mode);
- des.CwR2Des(data,key22,algo);
- LDUMP(L_SYS_VERBOSE,data,8,"encdec out:");
-}
-
-void cCryptoworks::Signature(const unsigned char *data, int len, const unsigned char *key22, unsigned char *sig)
-{
- PRINTF(L_SYS_VERBOSE,"sig start");
- int algo=data[0]&7;
- if(algo==7) algo=6;
- memset(sig,0,8);
- int j=0;
- bool first=true;
- for(int i=0; i<len; i++) {
- sig[j]^=data[i];
- if(++j>7) {
- LDUMP(L_SYS_VERBOSE,sig,8,"sig buf");
- if(first) {
- des.CwL2Des(sig,key22,algo);
- LDUMP(L_SYS_VERBOSE,sig,8,"sig -> ");
- }
- des.CwDes(sig,key22,DES_LEFT);
- j=0; first=false;
- LDUMP(L_SYS_VERBOSE,sig,8,"sig -> ");
- }
- }
- if(j>0) {
- LDUMP(L_SYS_VERBOSE,sig,8,"sig buf final ");
- des.CwDes(sig,key22,DES_LEFT);
- LDUMP(L_SYS_VERBOSE,sig,8,"sig -> ");
- }
- des.CwR2Des(sig,key22,algo);
- LDUMP(L_SYS_VERBOSE,sig,8,"sig calc ");
-}
-
-void cCryptoworks::DecryptDES(unsigned char *data, unsigned char algo, const unsigned char *key22)
-{
- algo&=7;
- if(algo<7) {
- EncDec(data,key22,algo,DES_RIGHT);
- }
- else {
- unsigned char k[22], t[8];
- memcpy(k,key22,22);
- for(int i=0; i<3; i++) {
- EncDec(data,k,algo,i&1);
- memcpy(t,k,8); memcpy(k,k+8,8); memcpy(k+8,t,8);
- }
- }
-}
-
-bool cCryptoworks::DecryptRSA(unsigned char *data, int len, unsigned char algo, const unsigned char *key22, BIGNUM *mod)
-{
- unsigned char buf[64], *mask=AUTOMEM(len);
-
- LDUMP(L_SYS_VERBOSE,data+len,8,"rsa in:");
- memcpy(buf,data+len,8);
- EncDec(buf,key22,algo,DES_LEFT);
- buf[0]|=0x80;
- if((algo&0x18)<0x18) buf[0]=0xFF;
- if(algo&8) buf[1]=0xFF;
- LDUMP(L_SYS_VERBOSE,buf,8,"rsa seed:");
-
- static const unsigned char t1[] = { 0xE,0x3,0x5,0x8,0x9,0x4,0x2,0xF,0x0,0xD,0xB,0x6,0x7,0xA,0xC,0x1 };
- for(int k=0; k<len; k+=32) {
- memcpy(buf+8,buf,8);
- for(int i=0; i<8; i++) {
- int n=i<<1;
- buf[n+1]=buf[i+8];
- buf[n ]=(t1[buf[n+1]>>4]<<4) | t1[buf[i+8]&0xF];
- LDUMP(L_SYS_VERBOSE,buf,16,"rsa buf:");
- }
- for(int i=16; i<64; i+=16) memcpy(&buf[i],buf,16);
- buf[31]=((buf[15]<<4)&0xFF) | 6;
- buf[16]=buf[0]^1;
- buf[32]&=0x7F;
- buf[32]|=0x40;
- RotateBytes(buf,32);
- RotateBytes(buf+32,32);
- LDUMP(L_SYS_VERBOSE,buf,64,"rsa data:");
-
- if(rsa.RSA(buf,buf,64,exp,mod,true)==0) {
- PRINTF(L_SYS_CRYPTO,"RSA failed");
- return false;
- }
- RotateBytes(buf,8);
- RotateBytes(mask+k,buf+8,min(32,len-k));
- }
- LDUMP(L_SYS_VERBOSE,mask,len,"rsa out:");
-
- xxor(data,len,data,mask);
- return true;
-}
-
-// -- cPlainKeyCryptoworks -----------------------------------------------------
-
-#define PLAINLEN_CW_D 16
-#define PLAINLEN_CW_CC 6
-#define PLAINLEN_CW_R 64
-
-#define CCTYP 0x00
-#define CCID 0xFF
-
-#define PROV(keynr) (((keynr)>>16)&0xFF)
-#define TYPE(keynr) (((keynr)>> 8)&0xFF)
-#define ID(keynr) (((keynr) )&0xFF)
-#define KEYSET(prov,typ,id) ((((prov)&0xFF)<<16)|(((typ)&0xFF)<<8)|((id)&0xFF))
-
-class cPlainKeyCryptoworks : public cDualKey {
-protected:
- virtual bool IsBNKey(void) const;
- virtual int IdSize(void) { return 4; }
- virtual cString PrintKeyNr(void);
-public:
- cPlainKeyCryptoworks(bool Super);
- virtual bool Parse(const char *line);
- };
-
-static cPlainKeyTypeReg<cPlainKeyCryptoworks,'W'> KeyReg;
-
-cPlainKeyCryptoworks::cPlainKeyCryptoworks(bool Super)
-:cDualKey(Super,true)
-{}
-
-bool cPlainKeyCryptoworks::IsBNKey(void) const
-{
- return TYPE(keynr)==0x10;
-}
-
-bool cPlainKeyCryptoworks::Parse(const char *line)
-{
- unsigned char sid[2], sprov;
- if(GetChar(line,&type,1) && GetHex(line,sid,2) && GetHex(line,&sprov,1)) {
- int keylen, prov;
- type=toupper(type); id=Bin2Int(sid,2); prov=sprov;
- line=skipspace(line);
- bool ok;
- if(!strncasecmp(line,"CC",2)) { // cardkey
- keynr=KEYSET(prov,CCTYP,CCID);
- keylen=PLAINLEN_CW_CC;
- line+=2;
- ok=true;
- }
- else {
- unsigned char sid, styp;
- ok=GetHex(line,&styp,1) && GetHex(line,&sid,1);
- keynr=KEYSET(prov,styp,sid);
- keylen=IsBNKey() ? PLAINLEN_CW_R : PLAINLEN_CW_D;
- }
- if(ok) {
- unsigned char *skey=AUTOMEM(keylen);
- if(GetHex(line,skey,keylen)) {
- SetBinKey(skey,keylen);
- return true;
- }
- }
- }
- return false;
-}
-
-cString cPlainKeyCryptoworks::PrintKeyNr(void)
-{
- int prov=PROV(keynr);
- int keytyp=TYPE(keynr);
- int keyid=ID(keynr);
- return cString::sprintf(keytyp==CCTYP && keyid==CCID ? "%02X CC":"%02X %02X %02X",prov,keytyp,keyid);
-}
-
-// -- cSystemCryptoworks -------------------------------------------------------
-
-#define ECM_ALGO_TYP 5
-#define ECM_DATA_START ECM_ALGO_TYP
-#define ECM_NANO_LEN 7
-#define ECM_NANO_START 8
-
-class cSystemCryptoworks : public cSystem, private cCryptoworks {
-private:
-public:
- cSystemCryptoworks(void);
- virtual bool ProcessECM(const cEcmInfo *ecmInfo, unsigned char *data);
-// virtual void ProcessEMM(int pid, int caid, unsigned char *data);
- };
-
-cSystemCryptoworks::cSystemCryptoworks(void)
-:cSystem(SYSTEM_NAME,SYSTEM_PRI)
-{
-// hasLogger=true;
-}
-
-bool cSystemCryptoworks::ProcessECM(const cEcmInfo *ecmInfo, unsigned char *data)
-{
- int len=SCT_LEN(data);
- if(data[ECM_NANO_LEN]!=len-ECM_NANO_START) {
- PRINTF(L_SYS_ECM,"invalid ECM structure");
- return false;
- }
-
- int prov=-1, keyid=0;
- for(int i=ECM_NANO_START; i<len; i+=data[i+1]+2) {
- if(data[i]==0x83) {
- prov =data[i+2]&0xFC;
- keyid=data[i+2]&0x03;
- break;
- }
- }
- if(prov<0) {
- PRINTF(L_SYS_ECM,"provider ID not located in ECM");
- return false;
- }
-
- unsigned char key[22];
- cPlainKey *pk;
- if(!(pk=keys.FindKey('W',ecmInfo->caId,KEYSET(prov,CCTYP,CCID),6))) {
- if(doLog) PRINTF(L_SYS_KEY,"missing %04X %02X CC key",ecmInfo->caId,prov);
- return false;
- }
- pk->Get(key+16);
-
- // RSA stage
- DUMPNANO("pre-RSA",&data[ECM_NANO_START],len-ECM_NANO_START);
- for(int i=ECM_NANO_START; i<len; i+=data[i+1]+2) {
- int l=data[i+1]+2;
- switch(data[i]) {
- case 0x85:
- {
- if(!(pk=keys.FindKey('W',ecmInfo->caId,KEYSET(prov,0x31,keyid),16))) {
- if(doLog) PRINTF(L_SYS_KEY,"missing %04X %02X 31 %02X key",ecmInfo->caId,prov,keyid);
- return false;
- }
- pk->Get(key);
- cBN mod;
- if(!(pk=keys.FindKey('W',ecmInfo->caId,KEYSET(prov,0x10,0x00),64))) {
- if(doLog) PRINTF(L_SYS_KEY,"missing %04X %02X 10 00 key",ecmInfo->caId,prov);
- return false;
- }
- pk->Get(mod);
-
- l-=10;
- if(!DecryptRSA(&data[i+2],l,data[ECM_ALGO_TYP],key,mod))
- return false;
- memmove(&data[i],&data[i+2],l);
- memmove(&data[i+l],&data[i+l+10],len-i-l);
- len-=10;
- break;
- }
- case 0x86:
- memmove(&data[i],&data[i+l],len-i-l);
- len-=l;
- continue;
- }
- }
- DUMPNANO("post-RSA",&data[ECM_NANO_START],len-ECM_NANO_START);
-
- cKeySnoop ks(this,'W',ecmInfo->caId,KEYSET(prov,0x20,keyid));
- if(!(pk=keys.FindKey('W',ecmInfo->caId,KEYSET(prov,0x20,keyid),16))) {
- if(doLog) PRINTF(L_SYS_KEY,"missing %04X %02X 20 %02X key",ecmInfo->caId,prov,keyid);
- return false;
- }
- pk->Get(key);
-
- // DES stage
- unsigned char sig[8];
- LDUMP(L_SYS_VERBOSE,&data[len-8],8,"sig org:");
- data[ECM_NANO_LEN]=len-ECM_NANO_START;
- Signature(&data[ECM_DATA_START],len-ECM_DATA_START-10,key,sig);
- for(int i=ECM_NANO_START; i<len; i+=data[i+1]+2) {
- switch(data[i]) {
- case 0xDA:
- case 0xDB:
- case 0xDC:
- for(int j=0; j<data[i+1]; j+=8)
- DecryptDES(&data[i+2+j],data[ECM_ALGO_TYP],key);
- break;
- case 0xDF:
- if(memcmp(&data[i+2],sig,8)) {
- PRINTF(L_SYS_ECM,"signature failed in ECM");
- return false;
- }
- break;
- }
- }
-
- // CW stage
- for(int i=ECM_NANO_START; i<len; i+=data[i+1]+2) {
- switch(data[i]) {
- case 0xDB:
- if(data[i+1]==0x10) {
- memcpy(cw,&data[i+2],16);
- LDUMP(L_SYS_VERBOSE,cw,16,"cw:");
- ks.OK(pk);
- return true;
- }
- break;
- }
- }
-
- return false;
-}
-
-/*
-void cSystemCryptoworks::ProcessEMM(int pid, int caid, unsigned char *data)
-{
-}
-*/
-
-// -- cSystemLinkCryptoworks ---------------------------------------------------
-
-class cSystemLinkCryptoworks : public cSystemLink {
-public:
- cSystemLinkCryptoworks(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemCryptoworks; }
- };
-
-static cSystemLinkCryptoworks staticInit;
-
-cSystemLinkCryptoworks::cSystemLinkCryptoworks(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- Feature.NeedsKeyFile();
-}
-
-bool cSystemLinkCryptoworks::CanHandle(unsigned short SysId)
-{
- SysId&=SYSTEM_MASK;
- return SYSTEM_CAN_HANDLE(SysId);
-}
+++ /dev/null
-#
-# Cryptoworks
-#
-TARGET = cryptoworks
-OBJS = cryptoworks.o
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "system-common.h"
-#include "data.h"
-#include "parse.h"
-#include "misc.h"
-#include "log-sys.h"
-
-#define SYSTEM_IRDETO 0x0600
-#define SYSTEM_BETA 0x1700
-
-#define SYSTEM_NAME "Irdeto"
-#define SYSTEM_PRI -10
-#define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_IRDETO || (x)==SYSTEM_BETA)
-
-#define L_SYS 5
-#define L_SYS_ALL LALL(L_SYS_LASTDEF)
-
-static const struct LogModule lm_sys = {
- (LMOD_ENABLE|L_SYS_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_SYS_DEFDEF)&LOPT_MASK,
- "irdeto",
- { L_SYS_DEFNAMES }
- };
-ADD_MODULE(L_SYS,lm_sys)
-
-static cPlainKeyTypeReg<cPlainKeyStd,'I',false> KeyReg;
-
-// -- cIrdCardInfo -------------------------------------------------------------
-
-class cIrdCardInfo : public cStructItem, public cProviderIrdeto, public cCardIrdeto {
-public:
- unsigned char PMK[8], HMK[10];
- bool haveHMK;
- //
- bool Parse(const char *line);
- virtual cString ToString(bool hide);
- };
-
-bool cIrdCardInfo::Parse(const char *line)
-{
- haveHMK=false;
- if(GetHex(line,hexSer,sizeof(hexSer)) && GetHex(line,HMK,sizeof(HMK))) haveHMK=true;
- return GetHex(line,&provBase,sizeof(provBase)) &&
- GetHex(line,provId,sizeof(provId)) &&
- GetHex(line,PMK,sizeof(PMK));
-}
-
-cString cIrdCardInfo::ToString(bool hide)
-{
- char s1[20], s2[20], s3[20], s4[20];
- return cString::sprintf("%s %s %02x %s %s",
- HexStr(s1,hexSer,sizeof(hexSer)),HexStr(s2,HMK,sizeof(HMK)),provBase,
- HexStr(s3,provId,sizeof(provId)),HexStr(s4,PMK,sizeof(PMK)));
-}
-
-// -- cIrdCardInfos ------------------------------------------------------------
-
-class cIrdCardInfos : public cCardInfos<cIrdCardInfo> {
-public:
- cIrdCardInfos(void);
- bool Update(cIrdCardInfo *ci, const unsigned char *pmk, const unsigned char *id);
- };
-
-static cIrdCardInfos Icards;
-
-cIrdCardInfos::cIrdCardInfos(void)
-:cCardInfos<cIrdCardInfo>("Irdeto cards","Ird-Beta.KID",SL_READWRITE)
-{}
-
-bool cIrdCardInfos::Update(cIrdCardInfo *ci, const unsigned char *pmk, const unsigned char *id)
-{
- bool res=false;
- char str[20], str2[12];
- if(memcmp(ci->PMK,pmk,sizeof(ci->PMK))) {
- PRINTF(L_GEN_INFO,"new PMK for I card %s: %s",HexStr(str2,ci->hexSer,sizeof(ci->hexSer)),KeyStr(str,pmk));
- memcpy(ci->PMK,pmk,sizeof(ci->PMK));
- res=true;
- }
- if(id && memcmp(ci->provId,id,sizeof(ci->provId))) {
- PRINTF(L_GEN_INFO,"new PrvID for I card %s: %s",HexStr(str2,ci->hexSer,sizeof(ci->hexSer)),HexStr(str,id,sizeof(ci->provId)));
- memcpy(ci->provId,id,sizeof(ci->provId));
- res=true;
- }
- if(res) Modified();
- return res;
-}
-
-// -- cIrdeto ------------------------------------------------------------------
-
-class cIrdeto {
-private:
- static const unsigned char T0[], T1[], T2[];
- unsigned char tempKey[10];
- //
- void Rotate(unsigned char *p);
- void MakeTempKey(const unsigned char *key, int date);
-protected:
- void SessionKeyCrypt(unsigned char *data, const unsigned char *key, int date);
- bool SignatureCheck(const unsigned char *data, int length, const unsigned char *key, int date, const unsigned char *signature, int keylen);
- void DecryptIrd(unsigned char *data, unsigned char *key, int rounds, int offset);
- };
-
-const unsigned char cIrdeto::T0[32] = {
- 0,1,2,3,4,5,6,7, 0,1,2,3,4,5,6,7,
- 0,1,2,3,4,5,6,7, 0,3,6,1,4,7,2,5
- };
-
-const unsigned char cIrdeto::T1[256] = {
- 0xDA,0x26,0xE8,0x72,0x11,0x52,0x3E,0x46, 0x32,0xFF,0x8C,0x1E,0xA7,0xBE,0x2C,0x29,
- 0x5F,0x86,0x7E,0x75,0x0A,0x08,0xA5,0x21, 0x61,0xFB,0x7A,0x58,0x60,0xF7,0x81,0x4F,
- 0xE4,0xFC,0xDF,0xB1,0xBB,0x6A,0x02,0xB3, 0x0B,0x6E,0x5D,0x5C,0xD5,0xCF,0xCA,0x2A,
- 0x14,0xB7,0x90,0xF3,0xD9,0x37,0x3A,0x59, 0x44,0x69,0xC9,0x78,0x30,0x16,0x39,0x9A,
- 0x0D,0x05,0x1F,0x8B,0x5E,0xEE,0x1B,0xC4, 0x76,0x43,0xBD,0xEB,0x42,0xEF,0xF9,0xD0,
- 0x4D,0xE3,0xF4,0x57,0x56,0xA3,0x0F,0xA6, 0x50,0xFD,0xDE,0xD2,0x80,0x4C,0xD3,0xCB,
- 0xF8,0x49,0x8F,0x22,0x71,0x84,0x33,0xE0, 0x47,0xC2,0x93,0xBC,0x7C,0x3B,0x9C,0x7D,
- 0xEC,0xC3,0xF1,0x89,0xCE,0x98,0xA2,0xE1, 0xC1,0xF2,0x27,0x12,0x01,0xEA,0xE5,0x9B,
- 0x25,0x87,0x96,0x7B,0x34,0x45,0xAD,0xD1, 0xB5,0xDB,0x83,0x55,0xB0,0x9E,0x19,0xD7,
- 0x17,0xC6,0x35,0xD8,0xF0,0xAE,0xD4,0x2B, 0x1D,0xA0,0x99,0x8A,0x15,0x00,0xAF,0x2D,
- 0x09,0xA8,0xF5,0x6C,0xA1,0x63,0x67,0x51, 0x3C,0xB2,0xC0,0xED,0x94,0x03,0x6F,0xBA,
- 0x3F,0x4E,0x62,0x92,0x85,0xDD,0xAB,0xFE, 0x10,0x2E,0x68,0x65,0xE7,0x04,0xF6,0x0C,
- 0x20,0x1C,0xA9,0x53,0x40,0x77,0x2F,0xA4, 0xFA,0x6D,0x73,0x28,0xE2,0xCD,0x79,0xC8,
- 0x97,0x66,0x8E,0x82,0x74,0x06,0xC7,0x88, 0x1A,0x4A,0x6B,0xCC,0x41,0xE9,0x9D,0xB8,
- 0x23,0x9F,0x3D,0xBF,0x8D,0x95,0xC5,0x13, 0xB9,0x24,0x5A,0xDC,0x64,0x18,0x38,0x91,
- 0x7F,0x5B,0x70,0x54,0x07,0xB6,0x4B,0x0E, 0x36,0xAC,0x31,0xE6,0xD6,0x48,0xAA,0xB4
- };
-
-const unsigned char cIrdeto::T2[256] = {
- 0x8E,0xD5,0x32,0x53,0x4B,0x18,0x7F,0x95, 0xBE,0x30,0xF3,0xE0,0x22,0xE1,0x68,0x90,
- 0x82,0xC8,0xA8,0x57,0x21,0xC5,0x38,0x73, 0x61,0x5D,0x5A,0xD6,0x60,0xB7,0x48,0x70,
- 0x2B,0x7A,0x1D,0xD1,0xB1,0xEC,0x7C,0xAA, 0x2F,0x1F,0x37,0x58,0x72,0x88,0xFF,0x87,
- 0x1C,0xCB,0x00,0xE6,0x4E,0xAB,0xEB,0xB3, 0xF7,0x59,0x71,0x6A,0x64,0x2A,0x55,0x4D,
- 0xFC,0xC0,0x51,0x01,0x2D,0xC4,0x54,0xE2, 0x9F,0x26,0x16,0x27,0xF2,0x9C,0x86,0x11,
- 0x05,0x29,0xA2,0x78,0x49,0xB2,0xA6,0xCA, 0x96,0xE5,0x33,0x3F,0x46,0xBA,0xD0,0xBB,
- 0x5F,0x84,0x98,0xE4,0xF9,0x0A,0x62,0xEE, 0xF6,0xCF,0x94,0xF0,0xEA,0x1E,0xBF,0x07,
- 0x9B,0xD9,0xE9,0x74,0xC6,0xA4,0xB9,0x56, 0x3E,0xDB,0xC7,0x15,0xE3,0x80,0xD7,0xED,
- 0xEF,0x13,0xAC,0xA1,0x91,0xC2,0x89,0x5B, 0x08,0x0B,0x4C,0x02,0x3A,0x5C,0xA9,0x3B,
- 0xCE,0x6B,0xA7,0xE7,0xCD,0x7B,0xA0,0x47, 0x09,0x6D,0xF8,0xF1,0x8B,0xB0,0x12,0x42,
- 0x4A,0x9A,0x17,0xB4,0x7E,0xAD,0xFE,0xFD, 0x2C,0xD3,0xF4,0xB6,0xA3,0xFA,0xDF,0xB8,
- 0xD4,0xDA,0x0F,0x50,0x93,0x66,0x6C,0x20, 0xD8,0x8A,0xDD,0x31,0x1A,0x8C,0x06,0xD2,
- 0x44,0xE8,0x23,0x43,0x6E,0x10,0x69,0x36, 0xBC,0x19,0x8D,0x24,0x81,0x14,0x40,0xC9,
- 0x6F,0x2E,0x45,0x52,0x41,0x92,0x34,0xFB, 0x5E,0x0D,0xF5,0x76,0x25,0x77,0x63,0x65,
- 0xAF,0x4F,0xCC,0x03,0x9D,0x0C,0x28,0x39, 0x85,0xDE,0xB5,0x7D,0x67,0x83,0xBD,0xC3,
- 0xDC,0x3C,0xAE,0x99,0x04,0x75,0x8F,0x97, 0xC1,0xA5,0x9E,0x35,0x0E,0x3D,0x1B,0x79
- };
-
-void cIrdeto::Rotate(unsigned char *p)
-{
- unsigned char c, t;
- c=p[9]<<7;
- t=*p; *p++=(t>>1) | c; c=t<<7;
- t=*p; *p++=(t>>1) | c; c=t<<7;
- t=*p; *p++=(t>>1) | c; c=t<<7;
- t=*p; *p++=(t>>1) | c; c=t<<7;
- t=*p; *p++=(t>>1) | c; c=t<<7;
- t=*p; *p++=(t>>1) | c; c=t<<7;
- t=*p; *p++=(t>>1) | c; c=t<<7;
- t=*p; *p++=(t>>1) | c; c=t<<7;
- t=*p; *p++=(t>>1) | c; c=t<<7;
- t=*p; *p++=(t>>1) | c; c=t<<7;
-}
-
-void cIrdeto::MakeTempKey(const unsigned char *key, int date)
-{
- memcpy(tempKey,key,8);
- tempKey[8]=(unsigned char)(date >> 8) ^ key[0];
- tempKey[9]=(unsigned char)date ^ key[1];
-}
-
-void cIrdeto::DecryptIrd(unsigned char *data, unsigned char *key, int rounds, int offset)
-{
- for(int count=0; count<rounds; count++) {
- int index=count % 10;
- if(index==0) Rotate(key);
- unsigned char k=key[index];
- unsigned char d=data[T0[(count & 0x0f) + offset]] ^ k;
- d=(k&1) ? T1[d] : T2[d];
- data[T0[((count+1) & 0x0f) + offset]] ^= d;
- }
-}
-
-void cIrdeto::SessionKeyCrypt(unsigned char *data, const unsigned char *key, int date)
-{
- MakeTempKey(key,date);
- DecryptIrd(data,tempKey,128,16);
-}
-
-bool cIrdeto::SignatureCheck(const unsigned char *data, int length, const unsigned char *key, int date, const unsigned char *signature, int keylen)
-{
- unsigned char buffer[256];
- memcpy(buffer,data,length);
- int rounds;
- if((length%8)==0) rounds=40;
- else {
- int i=0x61;
- while((length%8)!=0) buffer[length++]=i++;
- rounds=104;
- }
-
- if(keylen==10) memcpy(tempKey,key,10);
- else MakeTempKey(key,date);
-
- int i=0;
- while(i<length-8) {
- DecryptIrd(buffer,tempKey,40,0);
- i+=8;
- for(int j=0; j<8; j++) buffer[j] ^= buffer[i+j];
- Rotate(tempKey);
- }
- DecryptIrd(buffer,tempKey,rounds,0);
- return memcmp(buffer,signature,5)==0;
-}
-
-// -- cSystemIrd ---------------------------------------------------------------
-
-class cSystemIrd : public cSystem, private cIrdeto {
-private:
- unsigned char lastKey;
-public:
- cSystemIrd(void);
- virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *source);
- virtual void ProcessEMM(int pid, int caid, unsigned char *buffer);
- };
-
-cSystemIrd::cSystemIrd(void)
-:cSystem(SYSTEM_NAME,SYSTEM_PRI)
-{
- lastKey=0;
- hasLogger=true;
-}
-
-bool cSystemIrd::ProcessECM(const cEcmInfo *ecm, unsigned char *source)
-{
- unsigned char *data=0;
- int date=-1, keynr=0;
- source+=6;
- int length=source[5]+6-5; // 6 header bytes - 5 signature bytes
- for(int index=6 ; index<length && (data==0 || date==-1) ;) {
- int param=source[index++];
- int len =source[index++] & 0x3f;
-
- switch(param) {
- case 0x78:
- keynr = source[index];
- data = &source[index+2];
- break;
- case 0x00:
- case 0x40:
- date = (source[index]<<8) | source[index+1];
- break;
- }
- index+=len;
- }
- if(data==0 || date==-1) {
- PRINTF(L_SYS_ECM,"incomplete ECM structure");
- return false;
- }
-
- cKeySnoop ks(this,'I',source[2],keynr);
- cPlainKey *pk=0;
- unsigned char key[8];
- while((pk=keys.FindKey('I',source[2],keynr,sizeof(key),pk))) {
- unsigned char save[16];
- memcpy(save,data,16); // save the encrypted data
- pk->Get(key);
- SessionKeyCrypt(&data[0],key,date);
- SessionKeyCrypt(&data[8],key,date);
- if(SignatureCheck(source,length,key,date,&source[length],8)) {
- memcpy(cw,&data[0],16);
- ks.OK(pk);
- return true;
- }
- memcpy(data,save,16); // put back the encrypted data if it didn't works
- }
- return false;
-}
-
-void cSystemIrd::ProcessEMM(int pid, int caid, unsigned char *buffer)
-{
- int i, numKeys=0, date=0;
- unsigned char adr[10], id[4], *pk[4], prov, *mk=0, prvId[3]={0,0,0};
-
- int n=SCT_LEN(buffer);
- unsigned char savebuf[4096];
- if(n>(int)sizeof(savebuf)) {
- PRINTF(L_SYS_EMM,"%d: paket size %d to big for savebuffer in IrdetoLog",CardNum(),n);
- return;
- }
-
- int index=cParseIrdeto::AddrLen(buffer);
- memset(adr,0,sizeof(adr));
- memcpy(adr,&buffer[3],index+1);
- index+=4+4; // 3 header + adr type + 4 {0x01 0x00 0x00 len}
-
- int sindex=index; // save index for sig. check
- int slen=buffer[index-1]-5; // save packet length, 5 signature bytes
- int maxIndex=index+slen;
- if(maxIndex>n-5) {
- PRINTF(L_SYS_EMM,"%d: bad packet length (%d > %d)",CardNum(),maxIndex,n-5);
- maxIndex=n-5;
- }
- bool badnano=false;
- while(!badnano && index<maxIndex) {
- unsigned char nlen=buffer[index+1] & 0x3F;
- //unsigned char prio=buffer[index] & 0x40;
- unsigned char nano=buffer[index] & ~0x40;
- switch(nano) {
- case 0x10: // key update
- {
- int k=(buffer[index+1]>>6)+1; // key counter
- if(nlen!=k*9) { badnano=true; break; }
- for(i=0 ; i<k ; i++) {
- id[i]= buffer[index+2+0+i*9];
- pk[i]=&buffer[index+2+1+i*9];
- numKeys++;
- }
- }
- break;
- case 0x00: // date
- if(nlen<2) { badnano=true; break; }
- date=WORD(buffer,index+2,0xFFFF);
- break;
- case 0x28: // pmk & provid update
- if(nlen!=13) { badnano=true; break; }
- prov= buffer[index+2+0];
- mk= &buffer[index+2+2];
- prvId[0]=buffer[index+2+10];
- prvId[1]=buffer[index+2+11];
- prvId[2]=buffer[index+2+12];
- break;
- case 0x29: // pmk update
- if(nlen!=10) { badnano=true; break; }
- prov= buffer[index+2+0];
- mk= &buffer[index+2+2];
- break;
- case 0x11: // channel id
- if(nlen!=6) { badnano=true; break; }
- //chId[0]=buffer[index+2+0];
- //chId[1]=buffer[index+2+1];
- break;
- case 0x91: // erase channel id
- if(nlen!=6) { badnano=true; break; }
- //eraseChId[0]=buffer[index+2+0];
- //eraseChId[1]=buffer[index+2+1];
- break;
- case 0x8B: // CB20-matrix
- if(nlen!=0x20) { badnano=true; break; }
- //cb20ptr=&buffer[index+2];
- break;
- case 0x22: // set country code
- if(nlen!=3) { badnano=true; break; }
- //
- break;
- case 0x95: // unknown
- if(nlen!=2) { badnano=true; break; }
- //
- break;
- case 0x1E: // unknown
- if(nlen!=15) { badnano=true; break; }
- //
- break;
- case 0x1F: // unknown
- if(nlen!=3) { badnano=true; break; }
- //
- break;
- case 0x16: // unknown
- if(nlen!=2) { badnano=true; break; }
- //
- break;
- case 0x12: // unknown
- if(nlen!=6) { badnano=true; break; }
- //
- break;
-
- default:
- PRINTF(L_SYS_EMM,"%d: unhandled nano 0x%02x",CardNum(),nano);
- break;
- }
- index+=nlen+2;
- }
- if(badnano || index!=maxIndex) {
- PRINTF(L_SYS_EMM,"%d: bad nano/bad paket",CardNum());
- return;
- }
-
- // lastKey: save cpu time if we get bursts of the same key
- if((numKeys>0 && (id[0]!=lastKey || numKeys>1)) || mk) {
- memcpy(savebuf,buffer,n); // save the buffer
- cIrdCardInfo *ci=Icards.First();
- unsigned char *chkkey=AUTOMEM(max(sizeof(ci->PMK),sizeof(ci->HMK)));
- while(ci) {
- ci->hexBase=cParseIrdeto::AddrBase(buffer);
- if((numKeys>0 && (ci->cProviderIrdeto::MatchEMM(buffer) || CheckNull(ci->provId,sizeof(ci->provId)) )) ||
- (mk && ci->haveHMK && (ci->cCardIrdeto::MatchEMM(buffer)))) {
- LBSTARTF(L_SYS_EMM);
- LBPUT("%02x %02x%02x%02x",buffer[3],buffer[4],buffer[5],buffer[6]);
-
- for(i=0 ; i<numKeys ; i++) {
- lastKey=id[i];
- SessionKeyCrypt(pk[i],ci->PMK,date);
- }
- int keylen;
- if(mk) {
- memcpy(chkkey,ci->HMK,sizeof(ci->HMK)); // key is modified in decryptIrd()
- DecryptIrd(mk,chkkey,128,16);
- keylen=sizeof(ci->HMK);
- memcpy(chkkey,ci->HMK,sizeof(ci->HMK)); // signature check with HMK
- }
- else {
- keylen=sizeof(ci->PMK);
- memcpy(chkkey,ci->PMK,sizeof(ci->PMK)); // signature check with PMK
- }
-
- memcpy(&buffer[sindex-6],adr,5);
- if(SignatureCheck(&buffer[sindex-6],slen+6,chkkey,date,&buffer[sindex+slen],keylen))
- {
- char str[20];
- LBPUT(" - OK");
- for(i=0 ; i<numKeys ; i++) LBPUT(" - PK %02x %s",id[i],KeyStr(str,pk[i]));
- if(mk) LBPUT(" - PMK %s",KeyStr(str,mk));
-
- for(i=0 ; i<numKeys ; i++) {
- FoundKey();
- if(keys.NewKey('I',ci->provBase,id[i],pk[i],8)) NewKey();
- }
- if(mk) {
- FoundKey();
- if(Icards.Update(ci,mk,prvId[0]?prvId:0)) NewKey();
- }
- break;
- }
- else {
- LBPUT(" - FAIL");
- }
- LBEND();
-
- memcpy(buffer,savebuf,n); // restore the buffer
- }
- ci=Icards.Next(ci);
- }
- }
-}
-
-// -- cSystemLinkIrd -----------------------------------------------------------
-
-class cSystemLinkIrd : public cSystemLink {
-public:
- cSystemLinkIrd(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemIrd; }
- };
-
-static cSystemLinkIrd staticInit;
-
-cSystemLinkIrd::cSystemLinkIrd(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- Feature.NeedsKeyFile();
-}
-
-bool cSystemLinkIrd::CanHandle(unsigned short SysId)
-{
- SysId&=SYSTEM_MASK;
- return SYSTEM_CAN_HANDLE(SysId);
-}
+++ /dev/null
-#
-# Irdeto
-#
-TARGET = irdeto
-OBJS = irdeto.o
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "data.h"
-#include "cpu.h"
-#include "log-nagra.h"
-
-#define LOGLBPUT(...) loglb->Printf(__VA_ARGS__)
-#define CCLOGLBPUT(...) do { if(doDisAsm) loglb->Printf(__VA_ARGS__); } while(0)
-
-// -- cMapMem ------------------------------------------------------------------
-
-cMapMem::cMapMem(unsigned short Offset, int Size)
-{
- offset=Offset; size=Size;
- if((mem=(unsigned char *)malloc(size)))
- memset(mem,0,size);
-// PRINTF(L_SYS_EMU,"mapmem: new map off=%04x size=%04x",offset,size);
-}
-
-cMapMem::~cMapMem()
-{
- free(mem);
-}
-
-bool cMapMem::IsFine(void)
-{
- return (mem!=0);
-}
-
-unsigned char cMapMem::Get(unsigned short ea)
-{
- return (ea>=offset && ea<offset+size) ? mem[ea-offset] : 0;
-}
-
-void cMapMem::Set(unsigned short ea, unsigned char val)
-{
- if(ea>=offset && ea<offset+size)
- mem[ea-offset]=val;
-}
-
-// -- cMapRom ------------------------------------------------------------------
-
-cMapRom::cMapRom(unsigned short Offset, const char *Filename, int InFileOffset)
-{
- offset=Offset; addr=0;
- fm=filemaps.GetFileMap(Filename,FILEMAP_DOMAIN,false);
- if(fm && fm->Map()) {
- addr=fm->Addr()+InFileOffset;
- size=fm->Size()-InFileOffset;
- PRINTF(L_SYS_EMU,"maprom: new map off=%04x size=%04x",offset,size);
- }
-}
-
-cMapRom::~cMapRom()
-{
- if(fm) fm->Unmap();
-}
-
-bool cMapRom::IsFine(void)
-{
- return addr!=0 && size>0;
-}
-
-unsigned char cMapRom::Get(unsigned short ea)
-{
- return (ea>=offset && ea<offset+size) ? addr[ea-offset] : 0;
-}
-
-void cMapRom::Set(unsigned short ea, unsigned char val)
-{
- if(ea>=offset && ea<offset+size) LOGLBPUT("[ROM] ");
- // this is a ROM!
-}
-
-// -- cMapEeprom ---------------------------------------------------------------
-
-cMapEeprom::cMapEeprom(unsigned short Offset, const char *Filename, int OtpSize, int InFileOffset)
-{
- offset=Offset; otpSize=OtpSize; addr=0;
- fm=filemaps.GetFileMap(Filename,FILEMAP_DOMAIN,true);
- if(fm && fm->Map()) {
- addr=fm->Addr()+InFileOffset;
- size=fm->Size()-InFileOffset;
- PRINTF(L_SYS_EMU,"mapeeprom: new map off=%04x size=%04x otp=%04x",offset,size,otpSize);
- }
-}
-
-cMapEeprom::~cMapEeprom()
-{
- if(fm) fm->Unmap();
-}
-
-bool cMapEeprom::IsFine(void)
-{
- return (addr!=0);
-}
-
-unsigned char cMapEeprom::Get(unsigned short ea)
-{
- return (ea>=offset && ea<offset+size) ? addr[ea-offset] : 0;
-}
-
-void cMapEeprom::Set(unsigned short ea, unsigned char val)
-{
- if(ea>=offset && ea<offset+otpSize) {
- if(addr[ea-offset]==0) {
- addr[ea-offset]=val;
- LOGLBPUT("[OTP-SET] ");
- }
- LOGLBPUT("[OTP] ");
- }
- if(ea>=offset+otpSize && ea<offset+size) {
- addr[ea-offset]=val;
- LOGLBPUT("[EEP] ");
- }
-}
-
-// -- c6805 --------------------------------------------------------------------
-
-#define PAGEOFF(ea,s) (((ea)&0x8000) ? pageMap[s]:0)
-
-c6805::c6805(void) {
- cc.c=0; cc.z=0; cc.n=0; cc.i=0; cc.h=0; cc.v=1;
- pc=0; a=0; x=0; y=0; cr=dr=0; sp=spHi=0x100; spLow=0xC0;
- hasReadHandler=hasWriteHandler=false;
- exptBase=0x4000;
- ClearExceptions();
- ClearBreakpoints();
- InitMapper();
- ResetCycles();
- memset(stats,0,sizeof(stats));
- loglb=new cLineBuff(128);
-}
-
-c6805::~c6805()
-{
- if(LOG(L_SYS_CPUSTATS)) {
- int i, j, sort[256];
- for(i=0; i<256; i++) sort[i]=i;
- for(i=0; i<256; i++)
- for(j=0; j<255; j++)
- if(stats[sort[j]]<stats[sort[j+1]]) {
- int x=sort[j]; sort[j]=sort[j+1]; sort[j+1]=x;
- }
- PRINTF(L_SYS_CPUSTATS,"opcode statistics");
- for(i=0; i<256; i++)
- if((j=stats[sort[i]])) PRINTF(L_SYS_CPUSTATS,"opcode %02x: %d",sort[i],j);
- }
- ClearMapper();
- delete loglb;
-}
-
-bool c6805::AddMapper(cMap *map, unsigned short start, int size, unsigned char seg)
-{
- if(map && map->IsFine()) {
- if(nextMapper<MAX_MAPPER) {
- map->loglb=loglb;
- mapper[nextMapper]=map;
- memset(&mapMap[start+PAGEOFF(start,seg)],nextMapper,size);
- nextMapper++;
- return true;
- }
- else PRINTF(L_SYS_EMU,"6805: too many mappers");
- }
- else PRINTF(L_SYS_EMU,"6805: mapper not ready (start=%02x:%04x size=%04x)",seg,start,size);
- delete map;
- return false;
-}
-
-void c6805::ResetMapper(void)
-{
- ClearMapper(); InitMapper();
-}
-
-void c6805::InitMapper(void)
-{
- memset(mapMap,0,sizeof(mapMap));
- memset(mapper,0,sizeof(mapper));
- mapper[0]=new cMapMem(0,PAGE_SIZE*2);
- nextMapper=1;
- memset(pageMap,0,sizeof(pageMap));
- pageMap[0]=PAGE_SIZE*0;
- pageMap[1]=PAGE_SIZE*1;
- pageMap[2]=PAGE_SIZE*2;
- pageMap[0x80]=PAGE_SIZE*3;
- pageMap[0x40]=PAGE_SIZE*4;
-}
-
-void c6805::ClearMapper(void)
-{
- for(int i=0; i<MAX_MAPPER; i++) delete mapper[i];
-}
-
-unsigned char c6805::Get(unsigned short ea) const
-{
- return mapper[mapMap[ea+PAGEOFF(ea,cr)]&0x7f]->Get(ea);
-}
-
-unsigned char c6805::Get(unsigned char seg, unsigned short ea) const
-{
- return mapper[mapMap[ea+PAGEOFF(ea,seg)]&0x7f]->Get(ea);
-}
-
-void c6805::Set(unsigned short ea, unsigned char val)
-{
- if(hasWriteHandler) WriteHandler(cr,ea,val);
- unsigned char mapId=mapMap[ea+PAGEOFF(ea,cr)];
- if(!(mapId&0x80)) mapper[mapId&0x7f]->Set(ea,val);
-}
-
-void c6805::Set(unsigned char seg, unsigned short ea, unsigned char val)
-{
- if(hasWriteHandler) WriteHandler(seg,ea,val);
- unsigned char mapId=mapMap[ea+PAGEOFF(ea,seg)];
- if(!(mapId&0x80)) mapper[mapId&0x7f]->Set(ea,val);
-}
-
-void c6805::ForceSet(unsigned short ea, unsigned char val, bool ro)
-{
- mapMap[ea]=0; // reset to RAM map
- Set(0,ea,val); // set value
- if(ro) mapMap[ea]|=0x80; // protect byte
-}
-
-void c6805::SetMem(unsigned short addr, const unsigned char *data, int len, unsigned char seg)
-{
- while(len>0) { Set(seg,addr++,*data++); len--; }
-}
-
-void c6805::GetMem(unsigned short addr, unsigned char *data, int len, unsigned char seg) const
-{
- while(len>0) { *data++=Get(seg,addr++); len--; }
-}
-
-void c6805::SetSp(unsigned short SpHi, unsigned short SpLow)
-{
- spHi =sp=SpHi;
- spLow =SpLow;
-}
-
-void c6805::SetPc(unsigned short addr, unsigned char seg)
-{
- pc=addr; cr=seg;
- ResetCycles();
- ClearExceptions();
-}
-
-void c6805::PopPc(void)
-{
- poppc();
-}
-
-void c6805::PopCr(void)
-{
- cr=pop();
-}
-
-void c6805::Push(unsigned char c)
-{
- push(c);
-}
-
-void c6805::AddBreakpoint(unsigned short addr)
-{
- if(numBp<MAX_BREAKPOINTS) {
- bp[numBp++]=addr;
- PRINTF(L_SYS_EMU,"6805: setting breakpoint at 0x%04x",addr);
- }
- else PRINTF(L_SYS_EMU,"6805: too many breakpoints");
-}
-
-void c6805::ClearBreakpoints(void)
-{
- numBp=0;
- memset(bp,0,sizeof(bp));
-}
-
-void c6805::AddCycles(unsigned int num)
-{
- if(num>0) {
- clockcycles+=num;
- if(timerDisable>0) {
- timerDisable-=num;
- if(timerDisable<0) timerDisable=0;
- }
- if(!timerDisable)
- TimerHandler(num);
- }
-}
-
-void c6805::ResetCycles(void)
-{
- clockcycles=0;
-}
-
-void c6805::RaiseException(int num)
-{
- if(num<EXPT_MAX) {
- exptPending=true;
- expt[num]=true;
- }
-}
-
-void c6805::ClearExceptions(void)
-{
- timerDisable = delayTimerDisable = 0;
- exptPending = 0;
- exptReady = true;
- for(int i=0; i<EXPT_MAX; i++) expt[i]=false;
-}
-
-static const char * const ops[] = {
-// 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f
-/* 0x00 */ "BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR",
-/* 0x10 */ "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR",
-/* 0x20 */ "BRA", "BRN", "BHI", "BLS", "BCC", "BCS", "BNE", "BEQ", "BHCC", "BHCS", "BPL", "BMI", "BMC", "BMS", "BIL", "BIH",
-/* 0x30 */ "NEG", "pre31","pre32","COM", "LSR", "op35", "ROR", "ASR", "ASL", "ROL", "DEC", "op3b", "INC", "TST", "SWAP", "CLR",
-/* 0x40 */ "NEG", "op41", "MUL", "COM", "LSR", "op45", "ROR", "ASR", "ASL", "ROL", "DEC", "op4b", "INC", "TST", "SWAP", "CLR",
-/* 0x50 */ "NEG", "op51", "MUL", "COM", "LSR", "op55", "ROR", "ASR", "ASL", "ROL", "DEC", "op5b", "INC", "TST", "SWAP", "CLR",
-/* 0x60 */ "NEG", "op61", "op62", "COM", "LSR", "op65", "ROR", "ASR", "ASL", "ROL", "DEC", "op6b", "INC", "TST", "SWAP", "CLR",
-/* 0x70 */ "NEG", "LDD", "LDD", "COM", "LSR", "LDD", "ROR", "ASR", "ASL", "ROL", "DEC", "TAD", "INC", "TST", "SWAP", "CLR",
-/* 0x80 */ "RTI", "RTS", "op82", "SWI", "POPA", "POP%c","POPC", "PRTS", "PUSHA","PUSH%c","PUSHC","TDA", "TCA", "PJSR", "STOP", "WAIT",
-/* 0x90 */ "pre90","pre91","pre92","T%2$c%1$c","T%cS","TAS","TS%c","TA%c", "CLC", "SEC", "CLI", "SEI", "RSP", "NOP", "TSA", "T%cA",
-/* 0xa0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "opa7", "EOR", "ADC", "ORA", "ADD", "PUSHD","BSR", "LD%c", "POPD",
-/* 0xb0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c",
-/* 0xc0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c",
-/* 0xd0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c",
-/* 0xe0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c",
-/* 0xf0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c",
- };
-static const char * const vops[] = {
- "BVGT","BVLE","BVGE","BVLT","BVC","BVS"
- };
-
-// Flags:
-// 1 - read operant
-// 2 - write operant
-// 4 - use dr register
-// 8 - special address mode in high nibble
-static const char opFlags[] = {
-// 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
-/* 0x00 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-/* 0x10 */ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-/* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x30 */ 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02,
-/* 0x40 */ 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02,
-/* 0x50 */ 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02,
-/* 0x60 */ 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02,
-/* 0x70 */ 0x03, 0xA9, 0xB9, 0x03, 0x03, 0xC9, 0x03, 0x03, 0x03, 0x03, 0x03, 0x88, 0x03, 0x01, 0x03, 0x02,
-/* 0x80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa0 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x88, 0x88, 0x01, 0x88,
-/* 0xb0 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02,
-/* 0xc0 */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x06,
-/* 0xd0 */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x06,
-/* 0xe0 */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x06,
-/* 0xf0 */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x06,
- };
-
-static const unsigned char clock_cycles[] = {
-// 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
-/* 0x00 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-/* 0x10 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-/* 0x20 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-/* 0x30 */ 5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 4, 5, 5,
-/* 0x40 */ 3, 0, 11, 3, 3, 0, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3,
-/* 0x50 */ 3, 0, 0, 3, 3, 0, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3,
-/* 0x60 */ 6, 0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 0, 6, 5, 6, 6,
-/* 0x70 */ 5, 2, 3, 5, 5, 4, 5, 5, 5, 5, 5, 2, 5, 4, 5, 5,
-/* 0x80 */ 9, 6, 0, 10, 4, 4, 4, 6, 3, 3, 3, 2, 2, 7, 2, 2,
-/* 0x90 */ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* 0xa0 */ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 3, 6, 2, 4,
-/* 0xb0 */ 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 2, 5, 3, 4,
-/* 0xc0 */ 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 3, 6, 4, 5,
-/* 0xd0 */ 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 4, 7, 5, 6,
-/* 0xe0 */ 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 3, 6, 4, 5,
-/* 0xf0 */ 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 2, 5, 3, 4,
- };
-
-char * c6805::PADDR(unsigned char s, unsigned short ea)
-{
- snprintf(addrBuff,sizeof(addrBuff),((ea&0x8000) && s>0)?"%2$x:%1$04x":"%04x",ea,s);
- return addrBuff;
-}
-
-int c6805::Run(int max_count)
-{
-// returns:
-// 0 - breakpoint
-// 1 - stack overflow
-// 2 - instruction counter exeeded
-// 3 - unsupported instruction
-
- unsigned char cycles;
- unsigned short instrPc;
- bool disAsmHeader=false;
- disAsmLogClass=L_SYS_DISASM;
- if(LOG(L_SYS_DISASM)) doDisAsm=true;
- else {
- doDisAsm=false;
- if(LOG(L_SYS_DISASM80)) disAsmLogClass=L_SYS_DISASM80;
- }
-
- int count=0;
- while (1) {
- instrPc = pc;
- cycles = 0;
- if(exptPending && exptReady) {
- exptPending = false;
- for(int i=0; i<EXPT_MAX; ++i) {
- if(expt[i]) {
- exptPending = true; // to force check for another interrupt in next Run pass
- expt[i] = false;
- pushpc(); push(x); push(a); pushc(); cc.i = 1;
- pc = exptBase+4*i;
- timerDisable = delayTimerDisable;
- break;
- }
- }
- }
- delayTimerDisable = 0;
- exptReady = !cc.i;
-
- Stepper();
-
- if(sp<spLow) {
- PRINTF(L_SYS_EMU,"stack overflow (count=%d)",count);
- return 1;
- }
- if(spHi>spLow && sp>spHi) {
- PRINTF(L_SYS_EMU,"stack underflow (count=%d)",count);
- return 1;
- }
- if(pc>0x0400 && mapMap[pc+PAGEOFF(pc,cr)]==0) {
- PRINTF(L_SYS_EMU,"NX protection at %04x (count=%d)",pc,count);
- return 1;
- }
- count++;
-
- if(!LOG(L_SYS_DISASM) && LOG(L_SYS_DISASM80)) {
- bool flag=(pc>=0x80 && pc<0x200);
- if(doDisAsm && !flag) PRINTF(disAsmLogClass,"[...]");
- doDisAsm=flag;
- }
-
- if(doDisAsm && !disAsmHeader) {
- PRINTF(disAsmLogClass,"cr:-pc- aa xx yy dr -sp- VHINZC -mem@pc- -mem@sp- -cycles-");
- disAsmHeader=true;
- }
- CCLOGLBPUT("%02x:%04x %02x %02x %02x %02x %04x %c%c%c%c%c%c %02x%02x%02x%02x %02x%02x%02x%02x %08x ",
- cr,pc,a,x,y,dr,sp,
- cc.v?'V':'.',cc.h?'H':'.',cc.i?'I':'.',cc.n?'N':'.',cc.z?'Z':'.',cc.c?'C':'.',
- Get(pc),Get(pc+1),Get(pc+2),Get(pc+3),Get(sp+1),Get(sp+2),Get(sp+3),Get(sp+4),
- clockcycles);
-
- unsigned char *ex=&x;
- unsigned short idx=*ex;
- indirect=false;
- bool paged=false, vbra=false;
- unsigned char ins=Get(pc++);
- char xs='X', xi='X';
- int cycles=0;
-
- // check pre-bytes
- switch(ins) {
- case 0x31: // use SP indexed or indirect paged mode (ST19)
- cycles+=2;
- ins=Get(pc++);
- switch(ins) {
- case 0x22: case 0x23: case 0x24: case 0x25:
- case 0x26: case 0x27:
- vbra=true; break;
- case 0x75:
- case 0x8D:
- case 0xC0: case 0xC1: case 0xC2: case 0xC3:
- case 0xC4: case 0xC5: case 0xC6: case 0xC7:
- case 0xC8: case 0xC9: case 0xCA: case 0xCB:
- case 0xCE: case 0xCF:
- case 0xD0: case 0xD1: case 0xD2: case 0xD3:
- case 0xD4: case 0xD5: case 0xD6: case 0xD7:
- case 0xD8: case 0xD9: case 0xDA: case 0xDB:
- case 0xDE: case 0xDF:
- paged=true; indirect=true; break;
- case 0xE0: case 0xE1: case 0xE2: case 0xE3:
- case 0xE4: case 0xE5: case 0xE6: case 0xE7:
- case 0xE8: case 0xE9: case 0xEA: case 0xEB:
- case 0xEE: case 0xEF:
- idx=sp; xi='S'; break;
- }
- break;
- case 0x32: // use indirect SP indexed or indirect paged Y indexed mode (ST19)
- cycles+=2;
- ins=Get(pc++);
- switch(ins) {
- case 0x22: case 0x23: case 0x24: case 0x25:
- case 0x26: case 0x27:
- vbra=true; indirect=true; break;
- case 0xC3:
- case 0xCE: case 0xCF:
- case 0xD0: case 0xD1: case 0xD2: case 0xD3:
- case 0xD4: case 0xD5: case 0xD6: case 0xD7:
- case 0xD8: case 0xD9: case 0xDA: case 0xDB:
- case 0xDE: case 0xDF:
- paged=true; indirect=true; ex=&y; idx=*ex; xs='Y'; xi='Y'; break;
- case 0xE0: case 0xE1: case 0xE2: case 0xE3:
- case 0xE4: case 0xE5: case 0xE6: case 0xE7:
- case 0xE8: case 0xE9: case 0xEA: case 0xEB:
- case 0xEE: case 0xEF:
- indirect=true; idx=sp; xi='S'; break;
- }
- break;
- case 0x91: // use Y register with indirect addr mode (ST7)
- cycles++;
- indirect=true;
- // fall through
- case 0x90: // use Y register (ST7)
- cycles++;
- ex=&y; idx=*ex; xs='Y'; xi='Y';
- ins=Get(pc++);
- break;
- case 0x92: // use indirect addr mode (ST7)
- cycles+=2;
- indirect=true;
- ins=Get(pc++);
- break;
- }
- int postCycles=0;
-//XXX if(ins<=0x1F) postCycles=2; // btjt/btjf/bres/bset
- AddCycles(cycles+clock_cycles[ins]-postCycles);
-
- if(doDisAsm) {
- char str[8];
- if(!vbra) snprintf(str,sizeof(str),ops[ins],xs,xs^1);
- else snprintf(str,sizeof(str),"%s",vops[ins-0x22]);
- LOGLBPUT("%-5s ",str);
- }
-
- // address decoding
- unsigned short ea=0;
- unsigned char flags=opFlags[ins];
- unsigned char pr=(flags&4) ? dr:cr;
- switch(((flags&8) ? flags:ins)>>4) {
- case 0x2: // no or special address mode
- case 0x8:
- case 0x9:
- break;
- case 0xA: // immediate
- CCLOGLBPUT("#%02x ",Get(pc));
- ea=pc++; break;
- case 0x3: // short
- case 0xB:
- ea=Get(pc++);
- if(!indirect) { // short direct
- }
- else { // short indirect
- CCLOGLBPUT("[%02x] -> ",ea);
- ea=Get(ea);
- }
- CCLOGLBPUT("%02x ",ea);
- break;
- case 0xC: // long
- if(!indirect) { // long direct
- ea=HILO(pc); pc+=2;
- }
- else { // long indirect
- if(paged) {
- ea=HILO(pc); pc+=2;
- CCLOGLBPUT("[%s] -> ",PADDR(pr,ea));
- unsigned char s=Get(pr,ea);
- ea=HILOS(pr,ea+1);
- pr=s;
- }
- else {
- ea=Get(pc++);
- CCLOGLBPUT("[%02x] -> ",ea);
- ea=HILO(ea);
- }
- }
- CCLOGLBPUT("%s ",PADDR(pr,ea));
- break;
- case 0xD: // long indexed
- if(!indirect) { // long direct indexed
- ea=HILO(pc); pc+=2;
- CCLOGLBPUT("(%s",PADDR(cr,ea));
- }
- else { // long indirect indexed
- if(paged) {
- ea=HILO(pc); pc+=2;
- CCLOGLBPUT("([%s]",PADDR(pr,ea));
- unsigned char s=Get(pr,ea++);
- ea=HILOS(pr,ea);
- pr=s;
- }
- else {
- ea=Get(pc++);
- CCLOGLBPUT("([%02x]",ea);
- ea=HILO(ea);
- }
- CCLOGLBPUT(",%c) -> (%s",xi,PADDR(pr,ea));
- }
- ea+=idx;
- CCLOGLBPUT(",%c) -> %s ",xi,PADDR(pr,ea));
- break;
- case 0x6: // short indexed
- case 0xE:
- ea=Get(pc++);
- if(!indirect) { // short direct indexed
- CCLOGLBPUT("(%02x",ea);
- }
- else { // short indirect indexed
- CCLOGLBPUT("([%02x]",ea);
- ea=Get(ea);
- CCLOGLBPUT(",%c) -> (%02x",xi,ea);
- }
- ea+=idx;
- CCLOGLBPUT(",%c) -> %s ",xi,PADDR(pr,ea));
- break;
- case 0x7: // indexed
- case 0xF:
- ea=idx;
- CCLOGLBPUT("(%c) -> %s ",xi,PADDR(pr,ea));
- break;
- case 0x4: // inherent A
- CCLOGLBPUT("A ");
- break;
- case 0x5: // inherent X/Y
- CCLOGLBPUT("%c ",xs);
- break;
- case 0x0: // bit
- case 0x1:
- ea=Get(pc++);
- if(!indirect) {
- }
- else {
- CCLOGLBPUT("[%02x] -> ",ea);
- ea=Get(ea);
- indirect=false; // don't use indirect mode in case this is a bit branch
- }
- CCLOGLBPUT("%02x ",ea);
- break;
- }
-
- // read operant
- unsigned char op=0;
- if(flags & 1) {
- switch(((flags&8) ? flags:ins)>>4) {
- case 0x2: // no or special address mode
- case 0x8:
- case 0x9:
- break;
- case 0x3: // short
- case 0xB:
- case 0xC: // long
- case 0xD: // long indexed
- case 0x6: // short indexed
- case 0xE:
- case 0x7: // indexed
- case 0xF:
- case 0x0: // bit
- case 0x1:
- op=Get(pr,ea);
- if(hasReadHandler) ReadHandler(pr,ea,op);
- CCLOGLBPUT("{%02x} ",op);
- break;
- case 0xA: // immediate
- op=Get(pr,ea);
- break;
- case 0x4: // inherent A
- op=a; break;
- case 0x5: // inherent X/Y
- op=*ex; break;
- }
- }
-
- if(postCycles) AddCycles(postCycles);
-
- // command decoding
- stats[ins]++;
- switch(ins) {
- case 0xA6: // LDA
- case 0xB6:
- case 0xC6:
- case 0xD6:
- case 0xE6:
- case 0xF6:
- a=op; tst(op); break;
- case 0xAE: // LDX
- case 0xBE:
- case 0xCE:
- case 0xDE:
- case 0xEE:
- case 0xFE:
- *ex=op; tst(op); break;
- case 0xB7: // STA
- case 0xC7:
- case 0xD7:
- case 0xE7:
- case 0xF7:
- op=a; tst(op); break;
- case 0xBF: // STX
- case 0xCF:
- case 0xDF:
- case 0xEF:
- case 0xFF:
- op=*ex; tst(op); break;
- case 0x97: // TAX
- *ex=a; break;
- case 0x9F: // TXA
- a=*ex; break;
- case 0x93: // TYX (ST7)
- if(ex==&x) *ex=y; else *ex=x; break;
- case 0x3D: // TST
- case 0x4D:
- case 0x5D:
- case 0x6D:
- case 0x7D:
- tst(op); break;
- case 0x3F: // CLR
- case 0x4F:
- case 0x5F:
- case 0x6F:
- case 0x7F:
- op=0; tst(0); break;
- case 0x3C: // INC
- case 0x4C:
- case 0x5C:
- case 0x6C:
- case 0x7C:
- op++; cc.v=(op==0x80); tst(op); break;
- case 0x3A: // DEC
- case 0x4A:
- case 0x5A:
- case 0x6A:
- case 0x7A:
- op--; cc.v=(op==0x7f); tst(op); break;
- case 0x33: // COM
- case 0x43:
- case 0x53:
- case 0x63:
- case 0x73:
- op=~op; cc.c=1; tst(op); break;
- case 0x30: // NEG
- case 0x40:
- case 0x50:
- case 0x60:
- case 0x70:
- op=~op+1; cc.c=(op!=0); cc.v=(op==0x80); tst(op); break;
- case 0x42: // MUL
- case 0x52:
- {
- unsigned short res=*ex * a;
- *ex=(res>>8); a=res&0xff; cc.c=0; cc.h=0;
- break;
- }
- case 0xA9: // ADC
- case 0xB9:
- case 0xC9:
- case 0xD9:
- case 0xE9:
- case 0xF9:
- a=add(op,cc.c); break;
- case 0xAB: // ADD
- case 0xBB:
- case 0xCB:
- case 0xDB:
- case 0xEB:
- case 0xFB:
- a=add(op,0); break;
- case 0xA2: // SBC
- case 0xB2:
- case 0xC2:
- case 0xD2:
- case 0xE2:
- case 0xF2:
- a=sub(a,op,cc.c); break;
- case 0xA0: // SUB
- case 0xB0:
- case 0xC0:
- case 0xD0:
- case 0xE0:
- case 0xF0:
- a=sub(a,op,0); break;
- case 0xA1: // CMP
- case 0xB1:
- case 0xC1:
- case 0xD1:
- case 0xE1:
- case 0xF1:
- sub(a,op,0); break;
- case 0xA3: // CPX
- case 0xB3:
- case 0xC3:
- case 0xD3:
- case 0xE3:
- case 0xF3:
- sub(*ex,op,0); break;
- case 0xA4: // AND
- case 0xB4:
- case 0xC4:
- case 0xD4:
- case 0xE4:
- case 0xF4:
- a &= op; tst(a); break;
- case 0xAA: // ORA
- case 0xBA:
- case 0xCA:
- case 0xDA:
- case 0xEA:
- case 0xFA:
- a |= op; tst(a); break;
- case 0xA8: // EOR
- case 0xB8:
- case 0xC8:
- case 0xD8:
- case 0xE8:
- case 0xF8:
- a ^= op; tst(a); break;
- case 0xA5: // BIT
- case 0xB5:
- case 0xC5:
- case 0xD5:
- case 0xE5:
- case 0xF5:
- tst(a & op); break;
- case 0x38: // ASL
- case 0x48:
- case 0x58:
- case 0x68:
- case 0x78:
- op=rollL(op,0); break;
- case 0x39: // ROL
- case 0x49:
- case 0x59:
- case 0x69:
- case 0x79:
- op=rollL(op,cc.c); break;
- case 0x37: // ASR
- case 0x47:
- case 0x57:
- case 0x67:
- case 0x77:
- op=rollR(op,bitset(op,7)); break;
- case 0x34: // LSR
- case 0x44:
- case 0x54:
- case 0x64:
- case 0x74:
- op=rollR(op,0); break;
- case 0x36: // ROR
- case 0x46:
- case 0x56:
- case 0x66:
- case 0x76:
- op=rollR(op,cc.c); break;
- case 0x3E: // SWAP (ST7)
- case 0x4E:
- case 0x5E:
- case 0x6E:
- case 0x7E:
- op=(op<<4)|(op>>4); tst(op); break;
- //case 0x00 ... 0x0F: // BRSET BRCLR
- case 0x00: case 0x01: case 0x02: case 0x03:
- case 0x04: case 0x05: case 0x06: case 0x07:
- case 0x08: case 0x09: case 0x0A: case 0x0B:
- case 0x0C: case 0x0D: case 0x0E: case 0x0F:
- {
- int bit=(ins&0x0F)>>1;
- CCLOGLBPUT(",#%x,",bit);
- cc.c=bitset(op,bit);
- branch((ins&0x01) ? !cc.c:cc.c);
- break;
- }
- //case 0x10 ... 0x1F: // BSET BCLR
- case 0x10: case 0x11: case 0x12: case 0x13:
- case 0x14: case 0x15: case 0x16: case 0x17:
- case 0x18: case 0x19: case 0x1A: case 0x1B:
- case 0x1C: case 0x1D: case 0x1E: case 0x1F:
- {
- int bit=(ins&0x0F)>>1;
- CCLOGLBPUT(",#%x",bit);
- if(ins&0x01) op &= ~(1<<bit);
- else op |= (1<<bit);
- break;
- }
- case 0x20: // BRA
- branch(true); break;
- case 0x21: // BRN
- branch(false); break;
- case 0x22: // BHI
- if(vbra) branch(!cc.z && ((cc.n && cc.v) || (!cc.n && !cc.v)));
- else branch(!cc.c && !cc.z);
- break;
- case 0x23: // BLS
- if(vbra) branch(cc.z || (cc.n && !cc.v) || (!cc.n && cc.v));
- else branch( cc.c || cc.z);
- break;
- case 0x24: // BCC BHS
- if(vbra) branch((cc.n && cc.v) || (!cc.n && !cc.v));
- else branch(!cc.c);
- break;
- case 0x25: // BCS BLO
- if(vbra) branch((cc.n && !cc.v) || (!cc.n && cc.v));
- else branch( cc.c);
- break;
- case 0x26: // BNE
- if(vbra) branch(!cc.v);
- else branch(!cc.z);
- break;
- case 0x27: // BEQ
- if(vbra) branch(cc.v);
- else branch( cc.z); break;
- case 0x28: // BHCC
- branch(!cc.h); break;
- case 0x29: // BHCS
- branch( cc.h); break;
- case 0x2A: // BPL
- branch(!cc.n); break;
- case 0x2B: // BMI
- branch( cc.n); break;
- case 0x2C: // BMC
- branch(!cc.i); break;
- case 0x2D: // BMS
- branch( cc.i); break;
- case 0xBC: // JMP
- case 0xCC:
- case 0xDC:
- case 0xEC:
- case 0xFC:
- pc=ea; break;
- case 0xAD: // BSR
- pc++; pushpc(); pc--; branch(true); break;
- case 0xBD: // JSR
- case 0xCD:
- case 0xDD:
- case 0xED:
- case 0xFD:
- pushpc(); pc=ea; break;
- case 0x81: // RTS
- poppc(); break;
- case 0x83: // SWI
- pushpc(); push(x); push(a); pushc();
- cc.i=1; pc=HILO(0x1ffc); break;
- case 0x80: // RTI
- popc(); a=pop(); x=pop(); poppc(); break;
- case 0x9C: // RSP
- sp=spHi; break;
- case 0x96: // TSX
- *ex=sp&0xFF; break;
- case 0x94: // TXS (ST7)
- sp=(sp&0xFF00)|*ex; break;
- case 0x9E: // TSA
- a=sp&0xFF; break;
- case 0x95: // TAS (ST7)
- sp=(sp&0xFF00)|a; break;
- case 0x84: // POPA (ST7)
- a=pop(); break;
- case 0x85: // POPX (ST7)
- *ex=pop(); break;
- case 0x86: // POPC (ST7)
- popc(); break;
- case 0x88: // PUSHA (ST7)
- push(a); break;
- case 0x89: // PUSHX (ST7)
- push(*ex); break;
- case 0x8A: // PUSHC (ST7)
- pushc(); break;
- case 0x98: // CLC
- cc.c=0; break;
- case 0x99: // SEC
- cc.c=1; break;
- case 0x9A: // CLI
- cc.i=0; break;
- case 0x9B: // SEI
- cc.i=1; break;
- case 0x9D: // NOP
- break;
-
- case 0x71: // LDD (ST19)
- case 0x72:
- case 0x75:
- dr=op; break;
- case 0x7B: // TAD (ST19)
- dr=a; break;
- case 0x8B: // TDA (ST19)
- a=dr; break;
- case 0x8C: // TCA (ST19)
- a=cr; break;
- case 0xAC: // PUSHD (ST19)
- push(dr); break;
- case 0xAF: // POPD (ST19)
- dr=pop(); break;
- case 0x87: // PRTS (ST19)
- cr=pop(); poppc(); break;
- case 0x8D: // PJSR (ST19)
- if(paged) {
- ea=HILO(pc); pc+=2;
- CCLOGLBPUT("[%s] -> ",PADDR(cr,ea));
- }
- else {
- ea=pc; pc+=3;
- }
- pr=Get(ea++);
- ea=HILO(ea);
- CCLOGLBPUT("%s ",PADDR(pr,ea));
- pushpc(); push(cr); cr=pr; pc=ea; break;
-
- case 0x90: // pre-bytes
- case 0x91:
- case 0x92:
- case 0x31:
- case 0x32:
- PRINTF(L_SYS_EMU,"pre-byte %02x in command decoding (count=%d)",ins,count);
- loglb->cLineBuff::Flush();
- return 3;
- default:
- PRINTF(L_SYS_EMU,"unsupported instruction 0x%02x (count=%d)",ins,count);
- loglb->cLineBuff::Flush();
- return 3;
- }
-
- // write operant
- if(flags & 2) {
- switch(((flags&8) ? flags:ins)>>4) {
- case 0x2: // no or special address mode
- case 0x8:
- case 0x9:
- break;
- case 0xA: // immediate
- case 0x3: // short
- case 0xB:
- case 0xC: // long
- case 0xD: // long indexed
- case 0x6: // short indexed
- case 0xE:
- case 0x7: // indexed
- case 0xF:
- case 0x0: // bit
- case 0x1:
- Set(ea,op); break;
- case 0x4: // inherent A
- a=op; break;
- case 0x5: // inherent X/Y
- *ex=op; break;
- }
- }
- if(doDisAsm) PUTLB(disAsmLogClass,loglb);
- else loglb->cLineBuff::Flush();
-
- for(int i=numBp-1 ; i>=0 ; i--) {
- if(bp[i]==pc) {
- PRINTF(L_SYS_EMU,"6805: breakpoint at %04x (count=%d)",pc,count);
- return 0;
- }
- }
- if(count>=max_count) {
- PRINTF(L_SYS_EMU,"max. instruction counter exceeded (count=%d)",count);
- return 2;
- }
- }
-}
-
-void c6805::branch(bool branch)
-{
- if(doDisAsm) {
- unsigned char off=Get(pc);
- if(indirect) {
- LOGLBPUT("[%02x] -> ",off);
- off=Get(off);
- }
- unsigned short npc=pc+off+1;
- if(off&0x80) npc-=0x100; // gcc fixup. take care of sign
- LOGLBPUT("%s ",PADDR(cr,npc));
- if(branch) LOGLBPUT("(taken) ");
- }
- pc++;
- if(branch) {
- unsigned char offset=Get(pc-1);
- if(indirect) offset=Get(offset);
- pc+=offset;
- if(offset&0x80) pc-=0x100; // gcc fixup. take care of sign
- }
-}
-
-void c6805::push(unsigned char c)
-{
- Set(sp--,c);
-}
-
-unsigned char c6805::pop(void)
-{
- return Get(++sp);
-}
-
-void c6805::pushpc(void)
-{
- push(pc & 0xff);
- push(pc >> 8);
-}
-
-void c6805::poppc(void)
-{
- pc=(pop()<<8) | pop();
-}
-
-void c6805::pushc(void)
-{
- unsigned char c=0xC0+(cc.v?32:0)+(cc.h?16:0)+(cc.i?8:0)+(cc.n?4:0)+(cc.z?2:0)+(cc.c?1:0);
- push(c);
-}
-
-void c6805::popc(void)
-{
- unsigned char c=pop();
- cc.v=(c&32) ? 1:0;
- cc.h=(c&16) ? 1:0;
- cc.i=(c& 8) ? 1:0;
- cc.n=(c& 4) ? 1:0;
- cc.z=(c& 2) ? 1:0;
- cc.c=(c& 1) ? 1:0;
-}
-
-void c6805::tst(unsigned char c)
-{
- cc.z=!c;
- cc.n=bitset(c,7);
-}
-
-unsigned char c6805::add(unsigned char op, unsigned char c)
-{
- unsigned short res_half=(a&0x0f) + (op&0x0f) + c;
- unsigned short res=(unsigned short)a + (unsigned short)op + (unsigned short)c;
- cc.h=res_half > 0x0f;
- cc.c=res > 0xff;
- res&=0xff;
- cc.v=((op+c)&0x80) ? ((a&0x80) && !(res&0x80)) : (!(a&0x80) && (res&0x80));
- tst(res);
- return res;
-}
-
-unsigned char c6805::sub(unsigned char op1, unsigned char op2, unsigned char c)
-{
- short res=(short)op1 - (short)op2 - (short)c;
- cc.c=res < 0;
- res&=0xff;
- cc.v=((op2+c)&0x80) ? (!(op1&0x80) && (res&0x80)) : ((op1&0x80) && !(res&0x80));
- tst(res);
- return res;
-}
-
-unsigned char c6805::rollR(unsigned char op, unsigned char c)
-{
- cc.c=bitset(op,0);
- op >>= 1;
- op |= c << 7;
- tst(op);
- return op;
-}
-
-unsigned char c6805::rollL(unsigned char op, unsigned char c)
-{
- cc.c=bitset(op,7);
- op <<= 1;
- op |= c;
- tst(op);
- return op;
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __NAGRA_CPU_H
-#define __NAGRA_CPU_H
-
-#define FILEMAP_DOMAIN "nagra"
-
-class cFileMap;
-class cLineBuff;
-class c6805;
-
-// ----------------------------------------------------------------
-
-class cMap {
-friend class c6805;
-protected:
- cLineBuff *loglb;
-public:
- virtual ~cMap() {};
- virtual unsigned char Get(unsigned short ea)=0;
- virtual void Set(unsigned short ea, unsigned char val)=0;
- virtual bool IsFine(void)=0;
-};
-
-// ----------------------------------------------------------------
-
-class cMapMem : public cMap {
-protected:
- unsigned short offset;
- unsigned char *mem;
- int size;
-public:
- cMapMem(unsigned short Offset, int Size);
- virtual ~cMapMem();
- virtual unsigned char Get(unsigned short ea);
- virtual void Set(unsigned short ea, unsigned char val);
- virtual bool IsFine(void);
- };
-
-// ----------------------------------------------------------------
-
-class cMapRom : public cMap {
-private:
- unsigned short offset;
- cFileMap *fm;
- unsigned char *addr;
- int size;
-public:
- cMapRom(unsigned short Offset, const char *Filename, int InFileOffset=0);
- virtual ~cMapRom();
- virtual unsigned char Get(unsigned short ea);
- virtual void Set(unsigned short ea, unsigned char val);
- virtual bool IsFine(void);
- };
-
-// ----------------------------------------------------------------
-
-class cMapEeprom : public cMap {
-private:
- unsigned short offset;
- cFileMap *fm;
- unsigned char *addr;
- int size, otpSize;
-public:
- cMapEeprom(unsigned short Offset, const char *Filename, int OtpSize, int InFileOffset=0);
- virtual ~cMapEeprom();
- virtual unsigned char Get(unsigned short ea);
- virtual void Set(unsigned short ea, unsigned char val);
- virtual bool IsFine(void);
- };
-
-// ----------------------------------------------------------------
-
-#define MAX_BREAKPOINTS 24
-#define MAX_MAPPER 10
-#define MAX_PAGES 5
-#define PAGE_SIZE 32*1024
-#define EXPT_MAX 16
-
-#define bitset(d,bit) (((d)>>(bit))&1)
-
-#define HILO(ea) ((Get(ea)<<8)+Get((ea)+1))
-#define HILOS(s,ea) ((Get((s),(ea))<<8)+Get((s),(ea)+1))
-
-class c6805 {
-private:
- unsigned short pc, sp, spHi, spLow, exptBase;
- unsigned short bp[MAX_BREAKPOINTS], numBp;
- unsigned char mapMap[(MAX_PAGES+1)*PAGE_SIZE];
- cMap *mapper[MAX_MAPPER];
- int nextMapper;
- int pageMap[256];
- bool indirect;
- unsigned int clockcycles;
- bool exptPending, exptReady, expt[EXPT_MAX];
- int timerDisable, delayTimerDisable;
- int instruction;
- //
- void InitMapper(void);
- void ClearMapper(void);
- void branch(bool branch);
- inline void tst(unsigned char c);
- inline void push(unsigned char c);
- inline unsigned char pop(void);
- void pushpc(void);
- void poppc(void);
- void pushc(void);
- void popc(void);
- unsigned char add(unsigned char op, unsigned char c);
- unsigned char sub(unsigned char op1, unsigned char op2, unsigned char c);
- unsigned char rollR(unsigned char op, unsigned char c);
- unsigned char rollL(unsigned char op, unsigned char c);
-protected:
- unsigned char a, x, y, cr, dr;
- struct CC { unsigned char c, z, n, i, h, v; } cc;
- bool hasReadHandler, hasWriteHandler;
- //
- int Run(int max_count);
- void AddBreakpoint(unsigned short addr);
- void ClearBreakpoints(void);
- void ClearExceptions(void);
- bool AddMapper(cMap *map, unsigned short start, int size, unsigned char seg=0);
- cMap* FindMapper(unsigned char seg, unsigned short ea);
- void ResetMapper(void);
- void Set(unsigned short ea, unsigned char val);
- void Set(unsigned char seg, unsigned short ea, unsigned char val);
- void GetMem(unsigned short addr, unsigned char *data, int len, unsigned char seg=0) const;
- void SetMem(unsigned short addr, const unsigned char *data, int len, unsigned char seg=0);
- void ForceSet(unsigned short ea, unsigned char val, bool ro);
- void SetSp(unsigned short SpHi, unsigned short SpLow);
- void SetPc(unsigned short addr, unsigned char seg=0);
- void ResetCycles();
- void PopPc(void);
- void PopCr(void);
- void Push(unsigned char c);
- virtual void Stepper(void)=0;
- virtual void WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op) {}
- virtual void ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op) {}
- virtual void TimerHandler(unsigned int num) {}
-private:
- unsigned int stats[256];
- char addrBuff[32];
- bool doDisAsm;
- int disAsmLogClass;
-protected:
- cLineBuff *loglb;
- char * PADDR(unsigned char s, unsigned short ea);
-public:
- c6805(void);
- virtual ~c6805();
- unsigned char Get(unsigned short ea) const;
- unsigned char Get(unsigned char seg, unsigned short ea) const;
- unsigned short GetPc(void) const { return pc; }
- unsigned short GetCr(void) const { return cr; }
- unsigned short GetSp(void) const { return sp; }
- unsigned int Cycles() const { return clockcycles; }
- void AddCycles(unsigned int num);
- void RaiseException(int num);
- void SetExptBase(unsigned short base) { exptBase=base; }
- void DisableTimers(int num) { delayTimerDisable = num; }
- int Show_Diss;
- int LoopCount;
- char displaystr1[80];
- char displaystr2[80];
- char txt[80];
-};
-
-#endif
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __NAGRA_DEBUG_H
-#define __NAGRA_DEBUG_H
-
-#define DEBUG_EMU // debug CardEmu (very verbose!)
-#define DEBUG_EMU_0x80 // if the above is enabled, limit output to range x080-0xc0
-//#define DEBUG_STAT // give some statistics on CardEmu
-//#define DEBUG_MAP // debug file mapping code
-//#define DEBUG_NAGRA // debug Nagra crypt code
-//#define DEBUG_LOG // debug Nagra logger code
-
-#ifdef DEBUG_EMU
-#define dee(x) { (x); }
-#ifdef DEBUG_EMU_0x80
-#define de(x) { if(pc80flag) { (x); } }
-#else
-#define de(x) { (x); }
-#endif
-#else
-#define de(x) ;
-#define dee(x) ;
-#endif
-
-#ifdef DEBUG_NAGRA
-#define dn(a) { a; }
-#else
-#define dn(a) ;
-#endif
-
-#ifdef DEBUG_LOG
-#define dl(x) { (x); }
-#else
-#define dl(x) ;
-#endif
-
-#endif
-
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __LOG_NAGRA_H
-#define __LOG_NAGRA_H
-
-#include "log-sys.h"
-
-#define L_SYS 7
-#define L_SYS_EMU LCLASS(L_SYS,L_SYS_LASTDEF<<1)
-#define L_SYS_DISASM LCLASS(L_SYS,L_SYS_LASTDEF<<2)
-#define L_SYS_DISASM80 LCLASS(L_SYS,L_SYS_LASTDEF<<3)
-#define L_SYS_CPUSTATS LCLASS(L_SYS,L_SYS_LASTDEF<<4)
-#define L_SYS_MAP LCLASS(L_SYS,L_SYS_LASTDEF<<5)
-#define L_SYS_RAWEMM LCLASS(L_SYS,L_SYS_LASTDEF<<6)
-#define L_SYS_RAWECM LCLASS(L_SYS,L_SYS_LASTDEF<<7)
-#define L_SYS_ALL LALL(L_SYS_RAWECM)
-
-#define bprint(a) {fprintf(stdout, #a "="); BN_print_fp(stdout,a); fprintf(stdout,"\n");}
-
-#endif
-
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __NAGRA_NAGRA_DEF_H
-#define __NAGRA_NAGRA_DEF_H
-
-// ----------------------------------------------------------------
-
-#define SYSTEM_NAGRA 0x1800
-#define SYSTEM_NAGRA2 0x1801
-#define SYSTEM_NAGRA_BEV 0x1234
-
-// ----------------------------------------------------------------
-
-// Nagra1 defines
-#define DEF_TYPE 0
-#define DEF_PK 2
-#define DEF_ROM 0
-
-#define TYPE(keynr) (((keynr)>>16)&1)
-#define PK(keynr) (((keynr)>>17)&3)
-#define ROM(keynr) (((keynr)>>19)&15)
-#define KEYSET(rom,pk,type) ((((rom)&15)<<3)|(((pk)&3)<<1)|((type)&1))
-
-// Nagra2 defines
-#define N2_MAGIC 0x80
-#define N2_EMM_G_I 0x02
-#define N2_EMM_G_R 0x12
-#define N2_EMM_S_I 0x01
-#define N2_EMM_S_R 0x11
-#define N2_EMM_SEL 0x40
-#define N2_EMM_V 0x03
-
-#endif
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "nagra.h"
-#include "nagra-def.h"
-#include "log-nagra.h"
-#include "log-core.h"
-
-static const struct LogModule lm_sys = {
- (LMOD_ENABLE|L_SYS_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_SYS_DEFDEF|L_SYS_EMU|L_SYS_DISASM80|L_SYS_MAP)&LOPT_MASK,
- "nagra",
- { L_SYS_DEFNAMES,"emu","disasm","disasm80","cpuStats","map","rawemm","rawecm" }
- };
-ADD_MODULE(L_SYS,lm_sys)
-
-int minEcmTime=400; // ms
-
-// -- cPlainKeyNagra -----------------------------------------------------------
-
-#define PLAINLEN_NAGRA_H 8
-#define PLAINLEN_NAGRA_I 16
-#define PLAINLEN_NAGRA_B 64
-#define PLAINLEN_NAGRA_IE 24
-#define PLAINLEN_NAGRA_BE 96
-
-static cPlainKeyTypeReg<cPlainKeyNagra,'N'> KeyReg;
-
-cPlainKeyNagra::cPlainKeyNagra(bool Super)
-:cDualKey(Super,true)
-{}
-
-bool cPlainKeyNagra::IsBNKey(int kn)
-{
- switch(kn & C2MASK) {
- // Nagra1
- case MBC('M','1'):
- case MBC('E','1'):
- case MBC('N','1'):
- case MBC('N','2'):
- // Nagra2
- case MBC(N2_MAGIC,N2_EMM_G_R):
- case MBC(N2_MAGIC,N2_EMM_S_R):
- case MBC(N2_MAGIC,N2_EMM_G_R|N2_EMM_SEL):
- case MBC(N2_MAGIC,N2_EMM_S_R|N2_EMM_SEL):
- return true;
- }
- return false;
-}
-
-bool cPlainKeyNagra::IsBNKey(void) const
-{
- return IsBNKey(keynr);
-}
-
-int cPlainKeyNagra::ParseTag(const char *tag, const char * &line)
-{
- int r=-1;
- const int l=strlen(tag);
- if(!strncasecmp(line,tag,l)) {
- line+=l; r=0;
- while(*line!=0 && isdigit(*line)) {
- r=r*10 + *line-'0';
- line++;
- }
- line=skipspace(line);
- }
- return r;
-}
-
-void cPlainKeyNagra::GetTagDef(int nr, int &romnr, int &pk, int &keytype)
-{
- romnr =DEF_ROM;
- pk =DEF_PK;
- keytype=DEF_TYPE;
- nr&=C2MASK;
- if(nr=='V' || nr==MBC('N','2') || nr==MBC('M','1'))
- pk=0; // different default
-}
-
-bool cPlainKeyNagra::Parse(const char *line)
-{
- unsigned char sid[2];
- int len;
- if(GetChar(line,&type,1) && (len=GetHex(line,sid,2,false))) {
- type=toupper(type); id=Bin2Int(sid,len);
- line=skipspace(line);
- bool ok;
- if(!strncasecmp(line,"NN",2)) {
- line=skipspace(line+2);
- unsigned char skeynr;
- if((ok=GetHex(line,&skeynr,1)))
- keynr=MBC(N2_MAGIC,skeynr);
- }
- else {
- bool tags;
- switch(toupper(*line)) {
- case 'E':
- case 'N': ok=GetChar(line,&keynr,2); tags=true; break;
- case 'M': ok=GetChar(line,&keynr,2); tags=false; break;
- case 'V': ok=GetChar(line,&keynr,1); tags=true; break;
- default: {
- unsigned char skeynr;
- ok=GetHex(line,&skeynr,1); keynr=skeynr; tags=false; break;
- }
- }
- if(ok) {
- int romnr, pk, keytype;
- GetTagDef(keynr,romnr,pk,keytype);
- line=skipspace(line);
- while(tags) {
- int r;
- if((r=ParseTag("ROM",line))>=0) {
- if(r>0 && r<=15) romnr=r;
- else PRINTF(L_CORE_LOAD,"nagrakey: ignoring bad ROM number %d",r);
- }
- else if((r=ParseTag("TYP",line))>=0) {
- if(r>=0 && r<=1) keytype=r;
- else PRINTF(L_CORE_LOAD,"nagrakey: ignoring bad key type %d",r);
- }
- else if((r=ParseTag("PK",line))>=0) {
- if(r>=0 && r<=2) pk=r;
- else PRINTF(L_CORE_LOAD,"nagrakey: ignoring bad PK key number %d",pk);
- }
- else {
- tags=false;
- if(pk!=0 && (keynr=='V' || keynr==MBC('N','2'))) {
- pk=0;
- PRINTF(L_CORE_LOAD,"nagrakey: auto-adjusting to PK0 for N2/V key");
- }
- if(romnr!=0 && keytype!=1) {
- keytype=1;
- PRINTF(L_CORE_LOAD,"nagrakey: auto-adjusting to TYP1 for ROM key");
- }
- }
- }
- if(IsBNKey() || keynr=='V') keynr=ADDC3(keynr,KEYSET(romnr,pk,keytype));
- }
- }
-
- unsigned char skey[PLAINLEN_NAGRA_BE];
- int keylen=PLAINLEN_NAGRA_BE;
- len=GetHex(line,skey,keylen,false);
- if( (!IsBNKey() && (len==PLAINLEN_NAGRA_H || len==PLAINLEN_NAGRA_I || len==PLAINLEN_NAGRA_IE))
- || ( IsBNKey() && (len==PLAINLEN_NAGRA_B || len==PLAINLEN_NAGRA_BE)))
- keylen=len;
- if(len==keylen) {
- if((keynr=='V' || keynr==MBC(N2_MAGIC,0x03) || keynr==MBC(N2_MAGIC,(0x03|N2_EMM_SEL))) && CheckNull(skey,len))
- PRINTF(L_GEN_WARN,"nagrakey: FAKE verify keys will cause problems. Please remove them!");
- SetBinKey(skey,len);
- return true;
- }
- }
- return false;
-}
-
-cString cPlainKeyNagra::PrintKeyNr(void)
-{
- if(C2(keynr)==N2_MAGIC)
- return cString::sprintf("NN %.2X",keynr&0xFF);
- int k=keynr & C2MASK;
- if(!IsBNKey() && k!='V')
- return cString::sprintf("%.2X",keynr);
- char nr[32];
- int q=0;
- if(IsBNKey()) nr[q++]=(keynr>>8) & 0xff;
- nr[q++]=keynr & 0xff;
- nr[q]=0;
- int romnr, pk, keytype;
- GetTagDef(keynr,romnr,pk,keytype);
- if(ROM(keynr) !=romnr ) q+=snprintf(nr+q,sizeof(nr)-q," ROM%d",ROM(keynr));
- if(PK(keynr) !=pk ) q+=snprintf(nr+q,sizeof(nr)-q," PK%d",PK(keynr));
- if(TYPE(keynr)!=keytype) q+=snprintf(nr+q,sizeof(nr)-q," TYP%d",TYPE(keynr));
- return nr;
-}
-
-// -- cNagra -------------------------------------------------------------------
-
-cNagra::cNagra(void)
-{
- BN_set_word(pubExp,3);
-}
-
-void cNagra::CreateRSAPair(const unsigned char *key, const unsigned char *data, BIGNUM *e, BIGNUM *m)
-{
- // Calculate P and Q from data
- cBN p,q;
- CreatePQ(key,p,q);
- ExpandPQ(p,q,data,e,m);
-}
-
-void cNagra::ExpandPQ(BIGNUM *p, BIGNUM *q, const unsigned char *data, BIGNUM *e, BIGNUM *m)
-{
- // Calculate N=P*Q (modulus)
- cBNctx ctx;
- BN_mul(m,p,q,ctx);
- if(data) BN_bin2bn(data,64,e); // set provided data as E1
- else { // else calculate the 'official' one
- // E = ( ( ( (P-1) * (Q-1) * 2) + 1) / 3)
- BN_sub_word(p,1);
- BN_sub_word(q,1);
- BN_mul(e,p,q,ctx);
- BN_mul_word(e,2);
- BN_add_word(e,1);
- BN_div_word(e,3);
- }
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __NAGRA_NAGRA_H
-#define __NAGRA_NAGRA_H
-
-#include "system-common.h"
-#include "crypto.h"
-
-// ----------------------------------------------------------------
-
-extern int minEcmTime;
-
-// ----------------------------------------------------------------
-
-class cPlainKeyNagra : public cDualKey {
-private:
- int ParseTag(const char *tag, const char * &line);
- void GetTagDef(int nr, int &romnr, int &pk, int &keytype);
-protected:
- virtual bool IsBNKey(void) const;
- virtual int IdSize(void) { return 4; }
- virtual cString PrintKeyNr(void);
-public:
- cPlainKeyNagra(bool Super);
- virtual bool Parse(const char *line);
- static bool IsBNKey(int kn);
- };
-
-// ----------------------------------------------------------------
-
-class cNagra {
-protected:
- cRSA rsa;
- cBN pubExp;
- //
- virtual void CreatePQ(const unsigned char *pk, BIGNUM *p, BIGNUM *q)=0;
- void ExpandPQ(BIGNUM *p, BIGNUM *q, const unsigned char *data, BIGNUM *e, BIGNUM *m);
- void CreateRSAPair(const unsigned char *key, const unsigned char *data, BIGNUM *e, BIGNUM *m);
-public:
- cNagra(void);
- virtual ~cNagra() {};
- };
-
-#endif
+++ /dev/null
-#
-# Nagra
-#
-TARGET = nagra
-OBJS = nagra.o nagra1.o nagra2.o cpu.o \
- $(patsubst %.c,%.o,$(wildcard nagra2-[0-9][0-9][0-9][0-9].c))
-LIBS = -lcrypto
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "system.h"
-#include "misc.h"
-#include "opts.h"
-#include "helper.h"
-
-#include "nagra.h"
-#include "nagra-def.h"
-#include "cpu.h"
-#include "log-nagra.h"
-
-#define SYSTEM_NAME "Nagra"
-#define SYSTEM_PRI -10
-
-// -- cEmu ---------------------------------------------------------------------
-
-#define MAX_COUNT 200000
-
-class cEmu : public c6805 {
-protected:
- int romNr, id;
- char *romName, *romExtName, *eepromName;
- //
- int InitStart, InitEnd;
- int EmmStart, EmmEnd, EmmKey0, EmmKey1;
- int FindKeyStart, FindKeyEnd;
- int MapAddr;
- int Rc1H, Rc1L;
- int EnsIrdChk, Cmd83Chk;
- int SoftInt, StackHigh;
- //
- bool AddRom(unsigned short addr, unsigned short size, const char *name);
- bool AddEeprom(unsigned short addr, unsigned short size, unsigned short otpSize, const char *name);
- //
- virtual bool InitSetup(void) { return true; }
- virtual bool UpdateSetup(const unsigned char *emm) { return true; }
- virtual bool MathMapHandler(void);
-public:
- cEmu(void);
- virtual ~cEmu();
- bool Init(int RomNr, int Id);
- bool GetOpKeys(const unsigned char *Emm, unsigned char *id, unsigned char *key0, unsigned char *key1);
- bool GetPkKeys(const unsigned char *select, unsigned char *pkset);
- bool Matches(int RomNr, int Id);
- };
-
-cEmu::cEmu(void)
-{
- romName=romExtName=eepromName=0;
-}
-
-cEmu::~cEmu()
-{
- free(romName);
- free(romExtName);
- free(eepromName);
-}
-
-bool cEmu::AddRom(unsigned short addr, unsigned short size, const char *name)
-{
- cMap *map=new cMapRom(addr,name);
- return AddMapper(map,addr,size);
-}
-
-bool cEmu::AddEeprom(unsigned short addr, unsigned short size, unsigned short otpSize, const char *name)
-{
- cMap *map=new cMapEeprom(addr,name,otpSize);
- return AddMapper(map,addr,size);
-}
-
-bool cEmu::Matches(int RomNr, int Id)
-{
- return (romNr==RomNr && id==Id);
-}
-
-bool cEmu::Init(int RomNr, int Id)
-{
- romNr=RomNr; id=Id;
- asprintf(&romName,"ROM%d.bin",romNr);
- asprintf(&romExtName,"ROM%dext.bin",romNr);
- asprintf(&eepromName,"eep%i_%02x.bin",romNr,(id&0xff00)>>8);
- if(InitSetup()) {
- ForceSet(EnsIrdChk, 0x81,true);
- ForceSet(Cmd83Chk+0,0x98,true);
- ForceSet(Cmd83Chk+1,0x9d,true);
- if(SoftInt) {
- Set(0x1ffc,SoftInt>>8);
- Set(0x1ffd,SoftInt&0xff);
- }
- SetSp(StackHigh,0);
- SetPc(InitStart);
- ClearBreakpoints();
- AddBreakpoint(InitEnd);
- if(!Run(MAX_COUNT)) return true;
- }
- return false;
-}
-
-bool cEmu::GetOpKeys(const unsigned char *Emm, unsigned char *id, unsigned char *key0, unsigned char *key1)
-{
- int keys=0;
- if(UpdateSetup(Emm)) {
- SetMem(0x0080,&Emm[0],64);
- SetMem(0x00F8,&Emm[1],2);
- SetPc(EmmStart);
- ClearBreakpoints();
- AddBreakpoint(EmmEnd);
- AddBreakpoint(MapAddr);
- AddBreakpoint(EmmKey0);
- AddBreakpoint(EmmKey1);
- while(!Run(MAX_COUNT)) {
- unsigned short pc=GetPc();
- if(pc==EmmKey0) {
- GetMem(0x82,key0,8);
- keys++;
- }
- if(pc==EmmKey1) {
- GetMem(0x82,key1,8);
- keys++;
- }
- if(pc==MapAddr) {
- if(!MathMapHandler()) break;
- PopPc(); // remove return address from stack
- }
- if(pc==EmmEnd) {
- GetMem(0x00F8,id,2);
- break;
- }
- }
- }
- return (keys==2);
-}
-
-bool cEmu::GetPkKeys(const unsigned char *select, unsigned char *pkset)
-{
- Set(0x0081,select[2]<<7);
- SetMem(0x00F8,select,3);
- SetPc(FindKeyStart);
- ClearBreakpoints();
- AddBreakpoint(FindKeyEnd);
- while(!Run(MAX_COUNT)) {
- unsigned short pc=GetPc();
- if(pc==FindKeyEnd) {
- if(!cc.c) {
- PRINTF(L_SYS_EMU,"Updating PK keys");
- unsigned short loc=(Get(Rc1H)<<8)+Get(Rc1L);
- for(int i=0; i<45; i+=15) GetMem(loc+4+i,pkset+i,15);
- return true;
- }
- else {
- PRINTF(L_SYS_EMU,"Updating PK keys failed. Used a correct EEPROM image for provider %04x ?",((select[0]<<8)|select[1]));
- break;
- }
- }
- }
- return false;
-}
-
-bool cEmu::MathMapHandler(void)
-{
- PRINTF(L_SYS_EMU,"Unsupported math call $%02x in ROM %d, please report",a,romNr);
- return false;
-}
-
-// -- cEmuRom3Core -------------------------------------------------------------
-
-class cEmuRom3Core : public cEmu {
-private:
- bool special05;
-protected:
- virtual void Stepper(void);
- virtual void WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op);
- virtual void ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op);
- bool CoreInitSetup(void);
- bool DoMaps(bool hasExt);
-public:
- cEmuRom3Core(void);
- };
-
-cEmuRom3Core::cEmuRom3Core(void)
-{
- special05=false;
-}
-
-void cEmuRom3Core::WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op)
-{
- if(ea==0x05) special05=(op&0x40)!=0;
-}
-
-void cEmuRom3Core::ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op)
-{
- if(special05) {
- special05=false; // prevent loop
- unsigned short start=Get(0x30C0);
- unsigned short end=Get(0x30C1);
- if(((ea>>8)>=start) && ((ea>>8)<=end)) op=0x00; // dataspace
- else op=0x01; // codespace
- special05=true;
- }
- else
- switch(ea) {
- case 0x06:
- case 0x07:
- if(!(Get(0x04)&4)) op=random()&0xFF;
- break;
- }
-}
-
-void cEmuRom3Core::Stepper(void)
-{}
-
-bool cEmuRom3Core::CoreInitSetup(void)
-{
- ForceSet(0x0001,1<<3,true);
- Set(0x0002,0x03);
- Set(0x004e,0x4B);
- return true;
-}
-
-bool cEmuRom3Core::DoMaps(bool hasExt)
-{
- // Eeprom & ROMext are non-fatal also they are required for some providers
- if(hasExt) AddRom(0x2000,0x2000,romExtName);
- AddEeprom(0xE000,0x1000,0x20,eepromName);
- return AddRom(0x4000,0x4000,romName);
-}
-
-// -- cEmuRom3 -----------------------------------------------------------------
-
-class cEmuRom3 : public cEmuRom3Core {
-protected:
- virtual bool InitSetup(void);
- virtual bool UpdateSetup(const unsigned char *emm);
-public:
- cEmuRom3(void);
- };
-
-cEmuRom3::cEmuRom3(void)
-{
- InitStart=0x4000;
- InitEnd =0x734b;
- EmmStart =0x5a82;
- EmmEnd =0x67db;
- EmmKey0 =0x617c;
- EmmKey1 =0x6184;
- FindKeyStart=0x6133;
- FindKeyEnd =0x6147;
- MapAddr =0x2800;
- Rc1H =0x0024;
- Rc1L =0x0025;
- EnsIrdChk=0x6437;
- Cmd83Chk =0x6431;
- SoftInt =0x0000;
- StackHigh=0x7f;
-}
-
-bool cEmuRom3::InitSetup(void)
-{
- return DoMaps(true) && CoreInitSetup();
-}
-
-bool cEmuRom3::UpdateSetup(const unsigned char *emm)
-{
- return CoreInitSetup();
-}
-
-// -- cEmuRom7 -----------------------------------------------------------------
-
-class cEmuRom7 : public cEmuRom3Core {
-protected:
- virtual bool InitSetup(void);
- virtual bool UpdateSetup(const unsigned char *emm);
-public:
- cEmuRom7(void);
- };
-
-cEmuRom7::cEmuRom7(void)
-{
- InitStart=0x4000;
- InitEnd =0x7b68;
- EmmStart =0x482b;
- EmmEnd =0x6146;
- EmmKey0 =0x4f2a;
- EmmKey1 =0x4f32;
- FindKeyStart=0x4ee4;
- FindKeyEnd =0x4ef5;
- MapAddr =0x200f;
- Rc1H =0x0028;
- Rc1L =0x0029;
- EnsIrdChk=0x51df;
- Cmd83Chk =0x51d9;
- SoftInt =0x4008;
- StackHigh=0x7f;
-}
-
-bool cEmuRom7::InitSetup(void)
-{
- return DoMaps(false) && CoreInitSetup();
-}
-
-bool cEmuRom7::UpdateSetup(const unsigned char *emm)
-{
- SetMem(0x01A2,&emm[1],2);
- return true;
-}
-
-// -- cEmuRom10Core ------------------------------------------------------------
-
-class cEmuRom10Core : public cEmu {
-protected:
- struct Map { unsigned char A[64], B[64], C[64], D[4], opSize; } map;
- //
- virtual void Stepper(void);
- bool DoMaps(bool hasExt, int romSize);
- bool CoreInitSetup(void);
- bool CoreUpdateSetup(const unsigned char *emm);
- };
-
-void cEmuRom10Core::Stepper(void)
-{
- int rnd=random();
- unsigned char mem7=Get(0x07);
- if(cc.i) mem7&=0xFD; else mem7|=0x02;
- Set(0x07,mem7);
- if(bitset(mem7,1) && bitset(mem7,7)) {
- Set(0x05,(rnd&0xFF00)>>8);
- Set(0x06,rnd&0xFF);
- }
-}
-
-bool cEmuRom10Core::DoMaps(bool hasExt, int romSize)
-{
- // Eeprom & ROMext are non-fatal also they are required for some providers
- if(hasExt) AddRom(0x2000,0x2000,romExtName);
- AddEeprom(0xC000,0x2000,0x40,eepromName);
- return AddRom(0x4000,romSize,romName);
-}
-
-bool cEmuRom10Core::CoreInitSetup(void)
-{
- ForceSet(0x01,0x13,true);
- Set(0x02,0x3);
- Set(0x07,0xFF);
- return true;
-}
-
-bool cEmuRom10Core::CoreUpdateSetup(const unsigned char *emm)
-{
- SetMem(0x01A2,&emm[1],2);
- SetMem(0x0307,&emm[1],2);
- Set(0x0300,emm[5]);
- Set(0x0301,emm[2]);
- return true;
-}
-
-// -- cEmuRom10 ----------------------------------------------------------------
-
-class cEmuRom10 : public cEmuRom10Core {
-protected:
- virtual bool InitSetup(void);
- virtual bool UpdateSetup(const unsigned char *emm);
- virtual bool MathMapHandler(void);
-public:
- cEmuRom10(void);
- };
-
-cEmuRom10::cEmuRom10(void)
-{
- InitStart=0x4000;
- InitEnd =0x81ca;
- EmmStart =0x6a71;
- EmmEnd =0x81f7;
- EmmKey0 =0x7172;
- EmmKey1 =0x717a;
- FindKeyStart=0x712c;
- FindKeyEnd =0x713d;
- MapAddr =0x2020;
- Rc1H =0x004a;
- Rc1L =0x004b;
- EnsIrdChk=0x7427;
- Cmd83Chk =0x7421;
- SoftInt =0x4004;
- StackHigh=0x3ff;
-}
-
-bool cEmuRom10::InitSetup(void)
-{
- return DoMaps(false,0x5A00) && CoreInitSetup();
-}
-
-bool cEmuRom10::UpdateSetup(const unsigned char *emm)
-{
- Set(0x006e,0x4B);
- return CoreUpdateSetup(emm);
-}
-
-bool cEmuRom10::MathMapHandler(void)
-{
- PRINTF(L_SYS_EMU,"math call: $%02x",a);
- switch(a) {
- case 0x02:
- switch(Get(0x41)) {
- case 0: map.opSize=0x04; break;
- case 1: map.opSize=0x20; break;
- case 2: map.opSize=0x24; break;
- case 3: map.opSize=0x30; break;
- case 4: map.opSize=0x34; break;
- case 5:
- default: map.opSize=0x40; break;
- }
- return true;
-
- case 0x0e:
- case 0x0F:
- case 0x10:
- {
- const unsigned short addr=(Get(0x4d)<<8)|Get(0x4e);
- unsigned char tmp[64];
- GetMem(addr,tmp,map.opSize);
- unsigned char *reg;
- switch(a) {
- case 0x0e: reg=map.A; break;
- case 0x0f: reg=map.B; break;
- case 0x10: reg=map.C; break;
- default: return false;
- }
- SetMem(addr,reg,map.opSize);
- memcpy(reg,tmp,map.opSize);
- Set(0x41,map.opSize);
- return true;
- }
-
- case 0x29:
- Set(0x120,1);
- return true;
- }
- return cEmu::MathMapHandler();
-}
-
-// -- cEmuRom11 ----------------------------------------------------------------
-
-class cEmuRom11 : public cEmuRom10Core {
-protected:
- virtual bool InitSetup(void);
- virtual bool UpdateSetup(const unsigned char *emm);
-public:
- cEmuRom11(void);
- };
-
-cEmuRom11::cEmuRom11(void)
-{
- InitStart=0x4000;
- InitEnd =0x405b;
- EmmStart =0x5865;
- EmmEnd =0x9990;
- EmmKey0 =0x5f66;
- EmmKey1 =0x5f6e;
- FindKeyStart=0x5f20;
- FindKeyEnd =0x5f31;
- MapAddr =0x2020;
- Rc1H =0x004a;
- Rc1L =0x004b;
- EnsIrdChk=0x621b;
- Cmd83Chk =0x6215;
- SoftInt =0x4004;
- StackHigh=0x3ff;
-}
-
-bool cEmuRom11::InitSetup(void)
-{
- return DoMaps(false,0x8000) && CoreInitSetup();
-}
-
-bool cEmuRom11::UpdateSetup(const unsigned char *emm)
-{
- Set(0x0068,0x4B);
- return CoreUpdateSetup(emm);
-}
-
-// -- cNagraDES ----------------------------------------------------------------
-
-class cNagraDES {
-private:
- cDes des;
-protected:
- void Decrypt(const unsigned char *data, const unsigned char *key, unsigned char *out, bool desmod=false);
- void Crypt(const unsigned char *data, const unsigned char *key, unsigned char *out);
- bool SigCheck(const unsigned char *block, const unsigned char *sig, const unsigned char *vkey, const int rounds);
-};
-
-void cNagraDES::Decrypt(const unsigned char *data, const unsigned char *key, unsigned char *out, bool desmod)
-{
- unsigned char cardkey[8];
- memcpy(cardkey,key,8);
- RotateBytes(cardkey,8);
- memcpy(out,data,8);
- if(!desmod) RotateBytes(out,8);
- des.Des(out,cardkey,NAGRA_DES_DECR);
- if(!desmod) RotateBytes(out,8);
-}
-
-void cNagraDES::Crypt(const unsigned char *data, const unsigned char *key, unsigned char *out)
-{
- unsigned char cardkey[8];
- memcpy(cardkey,key,8);
- RotateBytes(cardkey,8);
- memcpy(out,data,8);
- RotateBytes(out,8);
- des.Des(out,cardkey,NAGRA_DES_ENCR);
- RotateBytes(out,8);
-}
-
-bool cNagraDES::SigCheck(const unsigned char *block, const unsigned char *sig, const unsigned char *vkey, const int rounds)
-{
- unsigned char hash[8];
- memcpy(hash,vkey,8);
- for(int j=0; j<rounds; j++) {
- unsigned char cr[8];
- Crypt(block+j*8,hash,cr);
- xxor(hash,8,cr,&block[j*8]);
- }
- return (0==memcmp(hash,sig,8));
-}
-
-// -- cNagra1 ------------------------------------------------------------------
-
-class cNagra1 : public cNagra, public cNagraDES {
-protected:
- virtual void CreatePQ(const unsigned char *key, BIGNUM *p, BIGNUM *q);
- bool DecryptECM(const unsigned char *in, unsigned char *out, const unsigned char *vkey, int len, BIGNUM *e1, BIGNUM *n1, BIGNUM *n2);
- bool DecryptEMM(const unsigned char *in, unsigned char *out, const unsigned char *vkey, int len, BIGNUM *e1, BIGNUM *n1, BIGNUM *n2);
- };
-
-bool cNagra1::DecryptECM(const unsigned char *in, unsigned char *out, const unsigned char *vkey, int len, BIGNUM *e1, BIGNUM *n1, BIGNUM *n2)
-{
- cBN result;
- if(rsa.RSA(result,&in[2],len,pubExp,n2)<=0) {
- PRINTF(L_SYS_CRYPTO,"error decrypting ECM (round 1)");
- return false;;
- }
- cBN mod;
- BN_set_word(mod,in[0]>>4);
- BN_lshift(mod,mod,508);
- BN_add(result,result,mod);
- if(rsa.RSA(out,64,result,e1,n1,false)!=64) {
- PRINTF(L_SYS_CRYPTO,"error: result of ECM decryption is not 64 bytes");
- return false;
- }
- if(vkey && !SigCheck(out,&out[56],vkey,7)) {
- PRINTF(L_SYS_CRYPTO,"ECM decryption failed");
- return false;
- }
- return true;
-}
-
-bool cNagra1::DecryptEMM(const unsigned char *in, unsigned char *out, const unsigned char *vkey, int len, BIGNUM *e1, BIGNUM *n1, BIGNUM *n2)
-{
- cBN result;
- if(rsa.RSA(result,&in[9],len,pubExp,n2)<=0) {
- PRINTF(L_SYS_CRYPTO,"error decrypting EMM (round 1)");
- return false;;
- }
- cBN mod;
- BN_set_word(mod,in[0]>>6);
- BN_lshift(mod,mod,510);
- BN_add(result,result,mod);
- if(rsa.RSA(out,64,result,e1,n1,false)!=64) {
- PRINTF(L_SYS_CRYPTO,"error: result of EMM decryption is not 64 bytes");
- return false;
- }
- if(!vkey || SigCheck(out,&in[1],vkey,8))
- return true;
-
- // We need to use signature exchange method (7blocks emm,1 block signature)
- PRINTF(L_SYS_CRYPTO,"warning: signature failed,trying signature exchange method");
- unsigned char buf[8];
- RotateBytes(buf,&in[1],sizeof(buf));
- cBN newdata, newsig;
- BN_bin2bn(buf,sizeof(buf),newdata);
- BN_copy(newsig,result);
- BN_mask_bits(newsig,64);
- BN_bn2bin(newsig,buf);
- RotateBytes(buf,sizeof(buf));
-
- BN_rshift(result,result,64); // delete the lower 64 bits,we saved it
- BN_lshift(result,result,64); // before as the new 64 bit signature
- BN_add(result,result,newdata);
-
- if(rsa.RSA(out,64,result,e1,n1)!=64) {
- PRINTF(L_SYS_CRYPTO,"error: result of EMM decryption is not 64 bytes");
- return false;
- }
- if(vkey && !SigCheck(out,buf,vkey,8)) {
- PRINTF(L_SYS_CRYPTO,"fatal: signature failed in signature exchange method");
- return false;
- }
- return true;
-}
-
-void cNagra1::CreatePQ(const unsigned char *key, BIGNUM *p, BIGNUM *q)
-{
- // Make des_key
- unsigned char des_data[32];
- unsigned char des_key[8], des_tmp[8];
- memcpy(des_data,key,8);
- RotateBytes(des_tmp,key,8);
- des_tmp[7]=0x00;
- Decrypt(des_data,des_tmp,des_key,true);
- RotateBytes(des_key,8);
- des_key[7]=0x00;
-
- // Calculate P
- for(int i=0; i<4; i++) {
- const int off=i*8;
- memcpy(&des_data[off],&key[4],8);
- des_data[off]^=i;
- Decrypt(&des_data[off],des_key,des_tmp,true);
- memcpy(&des_data[off],des_tmp,8);
- }
- BN_bin2bn(des_data,32,p);
- BN_add_word(p,(key[12]<<4)|((key[13]>>4)&0x0f));
- BN_set_bit(p,(BN_num_bytes(p)*8)-1);
-
- // Calculate Q
- for(int i=0; i<4; i++) {
- const int off=i*8;
- memcpy(&des_data[off],&key[4],8);
- des_data[off]^=(i+4);
- Decrypt(&des_data[off],des_key,des_tmp,true);
- memcpy(&des_data[off],des_tmp,8);
- }
- BN_bin2bn(des_data,32,q);
- BN_add_word(q,((key[13]&0x0f)<<8)|key[14]);
- BN_set_bit(q,(BN_num_bytes(q)*8)-1);
-}
-
-#ifndef TESTER
-
-// -- cSystemNagra -------------------------------------------------------------
-
-class cSystemNagra : public cSystem, public cNagra1 {
-private:
- unsigned char mecmTable[256];
- cEmu *emu;
- //
- void WriteTable(unsigned char *from, int off);
-public:
- cSystemNagra(void);
- virtual ~cSystemNagra();
- virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *data);
- virtual void ProcessEMM(int pid, int caid, unsigned char *buffer);
- };
-
-cSystemNagra::cSystemNagra(void)
-:cSystem(SYSTEM_NAME,SYSTEM_PRI)
-{
- emu=0;
- memset(mecmTable,0,sizeof(mecmTable));
- hasLogger=true;
-}
-
-cSystemNagra::~cSystemNagra()
-{
- delete emu;
-}
-
-void cSystemNagra::WriteTable(unsigned char *from, int off)
-{
- off&=0xFF;
- if(off+16<256) memcpy(mecmTable+off,from,16);
- else {
- int l=256-off;
- memcpy(mecmTable+off,from,l);
- memcpy(mecmTable,from+l,16-l);
- }
-}
-
-bool cSystemNagra::ProcessECM(const cEcmInfo *ecm, unsigned char *data)
-{
- int cmdLen=data[4];
- int id=(data[5]*256)+data[6];
- cTimeMs minTime;
- if(data[3]!=0x03) {
- PRINTF(L_SYS_ECM,"invalid ECM");
- return false;
- }
- data+=7;
- if(data[0]!=0x10) {
- PRINTF(L_SYS_ECM,"no ECM data available");
- return false;
- }
- const int ecmLen=data[1];
- const int verType=(data[2]>>3)&1;
- const int keynr=(data[2]>>4)&1;
- const int ecmParm=data[2]&7;
- bool decrypt;
- if(ecmParm==7) decrypt=false;
- else if(ecmParm==5) decrypt=true;
- else {
- PRINTF(L_SYS_ECM,"unknown ecmParm, ignoring ECM");
- return false;
- }
-
- cKeySnoop ks(this,'N',id,keynr);
- unsigned char sessionKey[8], verifyKey[8];
- bool hasVerifyKey=false;
- cPlainKey *pk;
- if((pk=keys.FindKey('N',id,ADDC3('V',KEYSET(0,0,verType)),sizeof(verifyKey)))) {
- pk->Get(verifyKey);
- hasVerifyKey=true;
- }
- else if(doLog) PRINTF(L_SYS_KEY,"missing %04X V TYP%d key (non-fatal)",id,verType);
- if(!(pk=keys.FindKey('N',id,keynr,sizeof(sessionKey)))) return false;
- pk->Get(sessionKey);
-
- const int desLen=(ecmLen-9) & ~7; // datalen - signature - ks byte
- unsigned char *decrypted=AUTOMEM(desLen);
- for(int i=(desLen/8)-1; decrypt && i>=0; i--) {
- const int off=i*8;
- Decrypt(data+11+off,sessionKey,decrypted+off);
- }
- if(decrypt && hasVerifyKey && !SigCheck(decrypted,data+3,verifyKey,desLen/8)) {
- PRINTF(L_SYS_ECM,"signature check failed in DES decrypt");
- return false;
- }
- int cwEvenMecmIndex=-1, cwOddMecmIndex=-1;
- switch(decrypted[0]) {
- case 0x10: // Whole CW
- cwOddMecmIndex=decrypted[1];
- memcpy(cw+8,&decrypted[2],8);
- cwEvenMecmIndex=decrypted[10];
- memcpy(cw,&decrypted[11],8);
- break;
- case 0x11: // Odd CW
- cwOddMecmIndex=decrypted[1];
- memcpy(cw+8, &decrypted[2],8);
- break;
- case 0x12: // Even CW
- cwEvenMecmIndex=decrypted[1];
- memcpy(cw,&decrypted[2],8);
- break;
- default: PRINTF(L_SYS_ECM,"failed to get CW"); return false;
- }
-
- const unsigned char * const mecmData=data+(ecmLen+2);
- const int mecmRSALen=mecmData[1]-4;
- if((cmdLen-(ecmLen+2))>64 && (*mecmData==0x20 || *mecmData==0x39)) {
- if(mecmRSALen!=64) {
- if(mecmRSALen>64 && doLog)
- PRINTF(L_SYS_ECM,"ECM too big (len: %d)",mecmRSALen);
- return false;
- }
-
- const int mecmProvId=mecmData[2]*256+mecmData[3];
- const int keyType=(mecmData[4]>>3)&1;
- const int pkey=mecmData[4]&3;
-
- cBN e1, n1, n2;
- cPlainKey *pk;
- if(!(pk=keys.FindKey('N',mecmProvId,MBC3('E','1',KEYSET(0,pkey,keyType)),-1))) {
- if(doLog) PRINTF(L_SYS_KEY,"missing %04x E1 PK%d TYP%d key",mecmProvId,pkey,keyType);
- return false;
- }
- pk->Get(e1);
- if(!(pk=keys.FindKey('N',mecmProvId,MBC3('N','1',KEYSET(0,pkey,keyType)),-1))) {
- if(doLog) PRINTF(L_SYS_KEY,"missing %04x N1 PK%d TYP%d key",mecmProvId,pkey,keyType);
- return false;
- }
- pk->Get(n1);
- if(!(pk=keys.FindKey('N',mecmProvId,MBC3('N','2',KEYSET(0,0,keyType)),-1))) {
- if(doLog) PRINTF(L_SYS_KEY,"missing %04x N2 TYP%d key",mecmProvId,keyType);
- return false;
- }
- pk->Get(n2);
- hasVerifyKey=false;
- if((pk=keys.FindKey('N',mecmProvId,ADDC3('V',KEYSET(0,0,keyType)),sizeof(verifyKey)))) {
- pk->Get(verifyKey);
- hasVerifyKey=true;
- }
- else if(doLog) PRINTF(L_SYS_KEY,"missing %04x V TYP%d key (non-fatal)",mecmProvId,keyType);
- unsigned char *decrMecmData=AUTOMEM(mecmRSALen);
- if(!DecryptECM(&mecmData[4],decrMecmData,hasVerifyKey?verifyKey:0,mecmRSALen,e1,n1,n2))
- return false;
-
- if(*mecmData==0x39 || (*mecmData==0x20 && (mecmProvId&0xFE00)==0x4800)) {
- unsigned char xor_table[64];
- for(int i=sizeof(xor_table)-1; i>=0; i--) xor_table[i]=63-i;
- CreateRSAPair(&decrMecmData[24],xor_table,e1,n1);
-
- // new XOR table for MECM data
- cBNctx ctx;
- cBN x;
- BN_mod_exp(x,e1,pubExp,n1,ctx);
- int l=sizeof(xor_table)-BN_num_bytes(x);
- memset(xor_table,0,l);
- BN_bn2bin(x,xor_table+l);
- RotateBytes(xor_table,sizeof(xor_table));
-
- // And finally, new MECM table
- for(int i=39; i<mecmRSALen; i++) decrMecmData[i]^=xor_table[i-39];
- memcpy(&decrMecmData[3],&decrMecmData[39],mecmRSALen-39);
- }
-
- if(decrMecmData[0]==0x2F && decrMecmData[1]==mecmData[2] && decrMecmData[2]==mecmData[3])
- WriteTable(decrMecmData+4,decrMecmData[3]*2);
- }
-
- if(cwOddMecmIndex>=0 && cwOddMecmIndex<0x80) {
- const int d=cwOddMecmIndex*2;
- for(int i=0 ; i<8 ; i++) cw[i+8]^=mecmTable[(d+i)&0xFF]; // odd
- }
- if(cwEvenMecmIndex>=0 && cwEvenMecmIndex<0x80) {
- const int d=cwEvenMecmIndex*2;
- for(int i=0 ; i<8 ; i++) cw[i]^=mecmTable[(d+i)&0xFF]; // even
- }
- ks.OK(pk);
- int i=minEcmTime-minTime.Elapsed();
- if(i>0) cCondWait::SleepMs(i);
-
- return true;
-}
-
-void cSystemNagra::ProcessEMM(int pid, int caid, unsigned char *buffer)
-{
- const int id=buffer[10]*256+buffer[11];
- static const unsigned char tester[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x4B };
- if(memcmp(&buffer[3],tester,sizeof(tester)) || SCT_LEN(buffer)<(12+9+64)) {
- PRINTF(L_SYS_EMM,"%d: not a valid EMM structure",CardNum());
- return;
- }
- const int pkey=(buffer[12]&3);
- cPlainKey *pk;
- cBN e1, n1, n2;
- if(!(pk=keys.FindKey('N',id,MBC3('E','1',KEYSET(0,pkey,0)),-1))) return;
- pk->Get(e1);
- if(!(pk=keys.FindKey('N',id,MBC3('N','1',KEYSET(0,pkey,0)),-1))) return;
- pk->Get(n1);
- unsigned char v[8];
- bool hasVerifyKey=false;
- if((pk=keys.FindKey('N',id,ADDC3('V',KEYSET(0,0,0)),sizeof(v)))) {
- pk->Get(v);
- hasVerifyKey=true;
- }
- int mode=(buffer[12]&8) ? 0:2;
- unsigned char emmdata[64];
- bool r;
- do {
- switch(mode) {
- case 0: // get the ROM10 specific management key
- if(!(pk=keys.FindKey('N',id,MBC3('N','2',KEYSET(10,0,1)),-1))) return;
- pk->Get(n2);
- mode=1; break;
- case 1: // get the ROM11 specific management keys
- if(!(pk=keys.FindKey('N',id,MBC3('E','1',KEYSET(11,pkey,1)),-1))) return;
- pk->Get(e1);
- if(!(pk=keys.FindKey('N',id,MBC3('N','1',KEYSET(11,pkey,1)),-1))) return;
- pk->Get(n1);
- if(!(pk=keys.FindKey('N',id,MBC3('N','2',KEYSET(11,0,1)),-1))) return;
- pk->Get(n2);
- hasVerifyKey=false;
- if((pk=keys.FindKey('N',id,ADDC3('V',KEYSET(11,0,1)),sizeof(v)))) {
- pk->Get(v);
- hasVerifyKey=true;
- }
- mode=-1; break;
- case 2: // get the universal management key
- if(!(pk=keys.FindKey('N',id,MBC3('N','2',KEYSET(0,0,0)),-1))) return;
- pk->Get(n2);
- mode=-1; break;
- }
- r=DecryptEMM(&buffer[12],emmdata,hasVerifyKey?v:0,64,e1,n1,n2);
- } while(!r && mode>=0);
- if(r) {
- HEXDUMP(L_SYS_RAWEMM,emmdata,sizeof(emmdata),"Nagra1 RAWEMM");
- unsigned int i=0;
- bool gotKeys=false;
- unsigned char key0[8], key1[8];
- int keyId=(emmdata[i+1]<<8)+emmdata[i+2];
- switch(emmdata[i]) { // Check filter type
- case 0x00: // One card
- i+=7; break;
- case 0x01: case 0x02: case 0x03: case 0x04: // Group of cards
- case 0x05: case 0x06: case 0x07: case 0x08:
- case 0x09: case 0x0A: case 0x0B: case 0x0C:
- case 0x0D: case 0x0E: case 0x0F: case 0x10:
- case 0x11: case 0x12: case 0x13: case 0x14:
- case 0x15: case 0x16: case 0x17: case 0x18:
- case 0x19: case 0x1A: case 0x1B: case 0x1C:
- case 0x1D: case 0x1E: case 0x1F: case 0x20:
- i+=emmdata[i]+0x7; break;
- case 0x3e:
- i+=6; break;
- case 0x3d: // All cards with same system ID
- case 0x3f:
- i+=3; break;
- }
- int nrKeys=0;
- while(i<sizeof(emmdata)) {
- if((emmdata[i]&0xF0)==0xF0) { // Update with CPU code
- const int romNr=emmdata[i]&0x0F;
- if(!emu || !emu->Matches(romNr,id)) {
- delete emu; emu=0;
- PRINTF(L_SYS_EMM,"%d: setting defaults for ROM %d",CardNum(),romNr);
- switch(romNr) {
- case 3: emu=new cEmuRom3; break;
- case 7: emu=new cEmuRom7; break;
- case 10: emu=new cEmuRom10; break;
- case 11: emu=new cEmuRom11; break;
- default: PRINTF(L_SYS_EMM,"%d: unsupported ROM",CardNum()); return;
- }
- if(!emu || !emu->Init(romNr,id)) {
- delete emu; emu=0;
- PRINTF(L_SYS_EMM,"%d: initialization failed for ROM %d",CardNum(),romNr);
- return;
- }
- }
- unsigned char ki[2];
- if((gotKeys=emu->GetOpKeys(emmdata,ki,key0,key1))) {
- keyId=(ki[0]<<8)+ki[1];
- PRINTF(L_SYS_EMM,"%d: got keys for %04X (ROM %d)",CardNum(),keyId,romNr);
- }
- unsigned char select[3], pkset[3][15];
- select[0]=(keyId>>8)|0x01; // always high id for ECM RSA keys
- select[1]=keyId&0xFF;
- select[2]=0; // type 0
- if(emu->GetPkKeys(&select[0],&pkset[0][0])) {
- int pkKeyId=((select[0]<<8)+select[1]);
- PRINTF(L_SYS_EMM,"%d: got PK keys for %04X (ROM %d)",CardNum(),pkKeyId,romNr);
- for(int i=0; i<3; i++) {
- CreateRSAPair(pkset[i],0,e1,n1);
- FoundKey();
- if(keys.NewKey('N',pkKeyId,ADDC3(MBC('N','1'),KEYSET(0,i,0)),n1,64)) NewKey();
- FoundKey();
- if(keys.NewKey('N',pkKeyId,ADDC3(MBC('E','1'),KEYSET(0,i,0)),e1,64)) NewKey();
- }
- }
- break; // don't process other nanos
- }
- else if(emmdata[i]==0x60) { // NULL nano
- i+=2;
- }
- else if(emmdata[i]==0x00) {
- i++;
- }
- else if(emmdata[i]==0x81) {
- i++;
- }
- else if(emmdata[i]==0x83) {
- keyId=(emmdata[i+1]<<8)+emmdata[i+2];
- i+=3;
- }
- else if(emmdata[i]==0x42) { // plain Key
- if(emmdata[i+1]==0x05) memcpy(key0,&emmdata[i+2],sizeof(key0));
- else memcpy(key1,&emmdata[i+2],sizeof(key1));
- i+=10;
- if(++nrKeys==2) {
- gotKeys=true;
- PRINTF(L_SYS_EMM,"%d: got keys for %04X (plain)",CardNum(),keyId);
- break;
- }
- }
- else {
- PRINTF(L_SYS_EMM,"%d: ignored nano %02x",CardNum(),emmdata[i]);
- break;
- }
- }
- if(gotKeys) {
- FoundKey();
- if(keys.NewKey('N',keyId,00,key0,8)) NewKey();
- FoundKey();
- if(keys.NewKey('N',keyId,01,key1,8)) NewKey();
- }
- }
-}
-
-// -- cSystemLinkNagra ---------------------------------------------------------
-
-class cSystemLinkNagra : public cSystemLink {
-public:
- cSystemLinkNagra(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemNagra; }
- };
-
-static cSystemLinkNagra staticInitN1;
-
-cSystemLinkNagra::cSystemLinkNagra(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- opts=new cOpts(SYSTEM_NAME,1);
- opts->Add(new cOptInt("MinEcmTime",trNOOP("Nagra: min. ECM processing time"),&minEcmTime,0,5000));
- Feature.NeedsKeyFile();
-}
-
-bool cSystemLinkNagra::CanHandle(unsigned short SysId)
-{
- return SysId==SYSTEM_NAGRA; // || SysId==SYSTEM_NAGRA_BEV;
-}
-
-#endif //TESTER
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "nagra2.h"
-
-// -- cAuxSrv ------------------------------------------------------------------
-
-#ifdef HAS_AUXSRV
-#include "network.h"
-#define AUX_PROTOCOL_VERSION 2
-int auxEnabled=0;
-int auxPort=7777;
-char auxAddr[80]="localhost";
-char auxPassword[250]="auxserver";
-
-class cAuxSrv : public cMutex {
-private:
- cNetSocket so;
- //
- bool Login(void);
-public:
- cAuxSrv(void);
- int Map(int map, unsigned char *data, int len, int outlen);
- };
-
-cAuxSrv::cAuxSrv(void)
-:so(DEFAULT_CONNECT_TIMEOUT,7,DEFAULT_IDLE_TIMEOUT)
-{}
-
-bool cAuxSrv::Login()
-{
- unsigned char buff[256];
- PRINTF(L_SYS_MAP,"auxsrv: connecting to %s:%d",auxAddr,auxPort);
- if(so.Connect(auxAddr,auxPort)) {
- buff[0]=0xA7;
- buff[1]=0x7A;
- buff[2]=0;
- int l=strlen(auxPassword);
- buff[3]=l;
- memcpy(&buff[4],auxPassword,l);
- buff[4+l]=0xFF;
- if(so.Write(buff,l+5)==l+5 &&
- so.Read(buff,sizeof(buff))>=9 &&
- buff[0]==0x7A && buff[1]==0xA7 && buff[2]==0x00 && buff[3]==0x04 && buff[8]==0xff &&
- ((buff[4]<<8)|buff[5])==AUX_PROTOCOL_VERSION) return true;
- PRINTF(L_SYS_MAP,"auxsrv: login write failed");
- }
- so.Disconnect();
- return false;
-}
-
-int cAuxSrv::Map(int map, unsigned char *data, int len, int outlen)
-{
- if(!auxEnabled) {
- PRINTF(L_SYS_MAP,"auxsrv: AUXserver is disabled!");
- return -1;
- }
- if(len>500 || outlen>500) return -1;
- cMutexLock lock(this);
- if(!so.Connected() && !Login()) return false;
- PRINTF(L_SYS_MAP,"auxsrv: calling map%02x",map);
- unsigned char buff[512];
- buff[0]=0xA7;
- buff[1]=0x7A;
- buff[2]=((len+1)>>8) & 0xff;
- buff[3]=(len+1)&0xff;
- buff[4]=map;
- memcpy(&buff[5],data,len);
- buff[len+5]=0xFF;
- if(so.Write(buff,len+6)==len+6) {
- if((len=so.Read(buff,sizeof(buff)))>0) {
- if(buff[0]==0x7A && buff[1]==0xA7) {
- if(buff[4]==0x00) {
- int cycles=(buff[5]<<16)|(buff[6]<<8)|buff[7];
- int l=buff[2]*256+buff[3];
- if(len>=l+5 && l==outlen+4) {
- if(buff[l+4]==0xFF) {
- memcpy(data,buff+8,outlen);
- return cycles;
- }
- else PRINTF(L_SYS_MAP,"auxsrv: bad footer in map%02x response",map);
- }
- else PRINTF(L_SYS_MAP,"auxsrv: bad length in map%02x response (got=%d,%d want=%d,%d)",map,l-4,len,outlen,l+8);
- }
- else PRINTF(L_SYS_MAP,"auxsrv: map%02x not successfull (unsupported?)",map);
- }
- else PRINTF(L_SYS_MAP,"auxsrv: bad response to map%02x",map);
- }
- else PRINTF(L_SYS_MAP,"auxsrv: map%02x read failed",map);
- }
- else PRINTF(L_SYS_MAP,"auxsrv: map%02x write failed",map);
- so.Disconnect();
- return -1;
-}
-#endif //HAS_AUXSRV
-
-// -- cMap0101 ----------------------------------------------------------------
-
-class cMap0101 : public cMapCore {
-private:
- static const unsigned char primes[];
- static const unsigned short coef22[][32];
-#ifdef HAS_AUXSRV
- cAuxSrv aux;
-#endif
- //
- void MakePrime(BIGNUM *n, unsigned char *residues);
-protected:
- unsigned char residues[53];
-
- void Map22(int pow);
- void Map3b(unsigned char *data, unsigned char size);
- void Map3c(unsigned char *data, unsigned char size);
- void Map3e(unsigned char *data, unsigned char size);
- void Map57(unsigned char *data, unsigned char size);
-
- void IMakeJ();
- void IMonInit0(int bits=0);
- void IMonInit(int bits=0);
-public:
- cMap0101(void);
- virtual bool Map(int f, unsigned char *data, int l);
- };
-
-cMap0101::cMap0101(void)
-{
-}
-const unsigned char cMap0101::primes[] = {
- 0x03,0x05,0x07,0x0B,0x0D,0x11,0x13,0x17,0x1D,0x1F,0x25,0x29,0x2B,0x2F,0x35,0x3B,
- 0x3D,0x43,0x47,0x49,0x4F,0x53,0x59,0x61,0x65,0x67,0x6B,0x6D,0x71,0x7F,0x83,0x89,
- 0x8B,0x95,0x97,0x9D,0xA3,0xA7,0xAD,0xB3,0xB5,0xBF,0xC1,0xC5,0xC7,0xD3,0xDF,0xE3,
- 0xE5,0xE9,0xEF,0xF1,0xFB
- };
-
-void cMap0101::MakePrime(BIGNUM *n, unsigned char *residues)
-{
- bool isPrime;
- unsigned int counts[3] = { 0 };
- do {
- ++counts[0];
- BN_add_word(n,2);
- isPrime=true;
- for(int i=0; i<sizeof(primes); i++) {
- residues[i]+=2;
-
- unsigned char num, denom, r;
- num = residues[i];
- denom = primes[i];
- r = 0;
-
- if(num>denom) {
- while(denom>=r) {
- ++counts[1];
- r = (r<<1)|((num&0x80)>>7);
- num <<= 1;
- }
- }
-
- residues[i]%=primes[i];
- if(residues[i]==0) {
- ++counts[2];
- isPrime=false;
- }
- }
- } while(!isPrime);
-
- cycles = 1290 + 1465 * counts[0] + counts[1] + 13 * counts[2];
-}
-
-void cMap0101::Map57(unsigned char *data, unsigned char size) {
- cBN a, b, x, y, scalar;
- int owordsize = wordsize;
- if(size<=0) size = wordsize;
-
- if(size<2 || size>4) {
- size = 4;
- }
- wordsize = size;
- size *= 8;
-
- D.GetLE(data+0*size,size);
- x.GetLE(data+1*size,size);
- y.GetLE(data+2*size,size);
- b.GetLE(data+3*size,size);
- a.GetLE(data+4*size,size);
- scalar.GetLE(data+5*size,size);
-
- bool doz = false;
- int scalarbits = BN_num_bits(scalar);
- if(scalarbits>=2) {
- if(BN_is_zero(x) && (BN_is_zero(y) || (BN_is_zero(b) && BN_num_bits(y)==1))) {
- BN_zero(Px);
- BN_copy(Py,y);
- BN_zero(Qz);
- MakeJ0(J, D);
- } else {
- CurveInit(a);
- ToProjective(0,x,y);
- BN_copy(Qx,Px);
- BN_copy(Qy,Py);
- for(int i=scalarbits-2; i>=0; i--) {
- DoubleP(0);
- if(BN_is_bit_set(scalar,i)) {
- BN_copy(A,Pz);
- if(BN_is_zero(Pz) || BN_is_zero(D)) {
- BN_copy(Px,Qx);
- BN_copy(Py,Qy);
- BN_copy(Pz,Qz);
- AddP(1);
- }
- else {
- doz = true;
- if(wordsize==4) {
- BN_rshift(Py,Py,32);
- BN_lshift(Py,Py,32);
- BN_rshift(b,Qz,224);
- BN_add(Py,Py,b);
- }
- BN_mask_bits(Px,32);
- BN_lshift(b,Qz,32);
- BN_add(Px,Px,b);
- BN_mask_bits(Px,8*size);
- AddP(0);
- }
- }
- }
- ToAffine();
- }
- } else {
- BN_copy(Px,x);
- BN_copy(Py,y);
- BN_zero(Qz);
- MakeJ0(J, D);
- }
-
- memset(data,0,0x40);
- Px.PutLE(data+0x00,size);
- if(size<0x20 && doz) {
- unsigned char tmp[0x20];
- Qz.PutLE(tmp,size);
- memcpy(data+0x00+size,tmp+(size-4),4);
- }
- Py.PutLE(data+0x20,size);
- BN_zero(A);
- BN_zero(B);
- BN_zero(C);
- wordsize = owordsize;
-}
-
-void cMap0101::Map22(int pow)
-{
- BN_zero(B);
- BN_set_bit(B,80);
- AddMapCycles(644);
- BN_zero(B);
- BN_set_bit(B,96);
- AddMapCycles(76);
-
- cBN v;
-
- if(BN_is_zero(D)) {
- cycles = 639 - 6;
- return;
- }
-
- pow &= 0x1fff;
- BN_one(B);
- BN_mod_lshift(B, B, pow, D, ctx);
-
- if(pow<64)
- cycles = 927 + (pow&7)*9;
- else {
- div_t val = div(pow-64, 2046);
- int j = 16*((val.rem+1)/2) + (val.rem>4?val.rem-7:val.rem-12)/4;
- cycles = 1086 + j - ((j-2)%5) + 16923*val.quot - ((4*val.quot-2)%5);
- }
-}
-
-void cMap0101::Map3b(unsigned char *data, unsigned char size)
-{
-static int tbl[][17] = {
- { 2666, 2804, 2957, 3105, 3258, 3406, 3554, 3707, 3855, 4008, 4156, 4304, 4457, 4605, 4758, 4906, 5054 },
- { 3163, 3316, 3484, 3652, 3815, 3983, 4146, 4314, 4482, 4645, 4813, 4976, 5144, 5312, 5475, 5643, 5806 },
- { 3715, 3888, 4071, 4254, 4432, 4615, 4798, 4981, 5164, 5342, 5525, 5708, 5891, 6074, 6252, 6435, 6618 },
- { 4302, 4490, 4688, 4886, 5084, 5282, 5480, 5678, 5876, 6074, 6272, 6470, 6668, 6866, 7064, 7262, 7460 },
- { 4899, 5107, 5320, 5533, 5751, 5964, 6177, 6390, 6603, 6821, 7034, 7247, 7460, 7673, 7891, 8104, 8317 },
- { 5541, 5759, 5992, 6220, 6453, 6681, 6909, 7142, 7370, 7603, 7831, 8059, 8292, 8520, 8753, 8981, 9209 },
- { 6198, 6431, 6679, 6927, 7170, 7418, 7661, 7909, 8157, 8400, 8648, 8891, 9139, 9387, 9630, 9878, 10121 },
- { 6910, 7163, 7426, 7689, 7947, 8210, 8473, 8736, 8999, 9257, 9520, 9783, 10046, 10309, 10567, 10830, 11093 },
- { 7637, 7905, 8183, 8461, 8739, 9017, 9295, 9573, 9851, 10129, 10407, 10685, 10963, 11241, 11519, 11797, 12075 },
- { 8394, 8682, 8975, 9268, 9566, 9859, 10152, 10445, 10738, 11036, 11329, 11622, 11915, 12208, 12506, 12799, 13092 },
- { 9196, 9494, 9807, 10115, 10428, 10736, 11044, 11357, 11665, 11978, 12286, 12594, 12907, 13215, 13528, 13836, 14144 },
- { 10003, 10346, 10674, 11002, 11325, 11653, 11976, 12304, 12632, 12955, 13283, 13606, 13934, 14262, 14585, 14913, 15236 },
- { 10885, 11218, 11561, 11904, 12242, 12585, 12928, 13271, 13614, 13952, 14295, 14638, 14981, 15324, 15662, 16005, 16348 },
- { 11792, 12145, 12498, 12856, 13214, 13572, 13930, 14288, 14646, 15004, 15362, 15720, 16078, 16436, 16794, 17152, 17510 },
- { 12709, 13087, 13465, 13843, 14226, 14604, 14982, 15360, 15738, 16121, 16499, 16877, 17255, 17633, 18016, 18394, 18772 },
- { 13671, 14069, 14477, 14880, 15283, 15686, 16084, 16492, 16890, 17298, 17696, 18099, 18507, 18905, 19313, 19711, 20114 },
- { 14668, 15091, 15519, 15947, 16370, 16798, 17221, 17654, 18082, 18505, 18933, 19356, 19784, 20212, 20640, 21068, 21491 },
- };
- cBN scalar;
- AddMapCycles(441);
- IMakeJ();
- AddMapCycles(327);
- BN_zero(B);
- BN_set_bit(B,104);
- AddMapCycles(46-373);
- IMonInit0(wordsize*0x3c + 4*size);
- scalar.GetLE(data, size*8);
- MonMul(B, scalar, B, size);
- cycles = tbl[wordsize-1][size-1] - 6;
-}
-
-void cMap0101::Map3c(unsigned char *data, unsigned char size)
-{
-
- cBN scalar;
-
- cycles = 0;
-
- if(size<=0) {
- cycles += 4;
- size = wordsize;
- } else if(size>wordsize) {
- cycles += size>17?9:4;
- size = wordsize;
- }
-
- scalar.GetLE(data, size*8);
-
- int sbits = BN_num_bits(scalar);
-
- int i, msb;
- msb = data[(sbits-1)/8];
- cycles += 2714 + ((sbits-1)/8)*650 - 11;
- for(i=7; i>=1; --i) if((msb&(1<<i))) { cycles += i*75 - 15; break; }
- for(i=0; i<sbits; ++i) if(BN_is_bit_set(scalar, i)) cycles += 88;
-
- AddMapCycles(441);
-
- if(BN_is_zero(scalar) || BN_num_bits(D)<=1) {
- IMakeJ();
-
- if(BN_num_bits(D)==1 || !BN_is_zero(scalar))
- BN_zero(B);
- else
- BN_one(B);
- BN_one(A);
- } else {
- IMonInit();
- AddMapCycles(60);
- MonMul(B,A,B);
- AddMapCycles(121);
- MonExp(scalar);
- }
- BN_zero(C);
-}
-
-
-void cMap0101::Map3e(unsigned char *data, unsigned char size)
-{
- cBN scalar;
-
- cycles = 0;
-
- if(size<=0) {
- cycles += 4;
- size = wordsize;
- } else if(size>wordsize) {
- cycles += size>17?9:4;
- size = wordsize;
- }
-
- scalar.GetLE(data, size*8);
-
- int sbits = BN_num_bits(scalar);
-
- int i, msb;
- msb = data[(sbits-1)/8];
- cycles += 3848 + ((sbits-1)/8)*650 - 11;
- for(i=7; i>=1; --i) if((msb&(1<<i))) { cycles += i*75 - 15; break; }
- for(i=0; i<sbits; ++i) if(BN_is_bit_set(scalar, i)) cycles += 88;
-
- AddMapCycles(441);
- if(BN_is_zero(scalar) || BN_num_bits(D)<=1) {
- IMakeJ();
- if(BN_num_bits(D)==1 || !BN_is_zero(scalar))
- BN_zero(B);
- else
- BN_one(B);
- BN_one(A);
- } else {
- IMonInit();
- MonMul(B,A,B);
- MonExp(scalar);
- }
- BN_zero(C);
-}
-
-void cMap0101::IMakeJ()
-{
- int owordsize = wordsize;
- AddMapCycles(19);
- wordsize = 1;
- AddMapCycles(102);
- MakeJ0(J, D, C);
- AddMapCycles(303);
- BN_zero(C);
- AddMapCycles(34);
- wordsize = owordsize;
- AddMapCycles(10);
-}
-
-void cMap0101::IMonInit0(int bits)
-{
- AddMapCycles(132+(wordsize*8+3)/5*5);
- if(BN_num_bits(D)>1) AddMapCycles(54);
- if(!BN_is_zero(D)) {
- AddMapCycles(54);
- BN_zero(I);
- BN_set_bit(I,68*wordsize);
- BN_zero(B);
- AddMapCycles(141+(wordsize*8+3)/5*5);
- BN_set_bit(B,64*(wordsize-1)+bits);
- AddMapCycles(92+72*wordsize);
- BN_mod(B,I,D,ctx);
- AddMapCycles(639);
- }
-
- AddMapCycles(52);
- for(int i=0; i<4; i++) {
- MonMul0(B,B,B,C,D,J);
- AddMapCycles(96+6*(i>0));
- MonMulFin(B,D);
- }
-}
-
-void cMap0101::IMonInit(int bits)
-{
- IMakeJ();
- IMonInit0(bits);
-}
-
-bool cMap0101::Map(int f, unsigned char *data, int l)
-{
- switch(f) {
- case 0x21:
- AddMapCycles(169-6);
- IMakeJ();
- cycles = 898;
- break;
- case 0x22:
- Map22(l<0?-l:l);
- break;
- case 0x23:
-/* AddMapCycles(169);
- IMonInit0(24);*/
- {
- cBN s,x,y;
- BN_copy(s,D);
- BN_rshift(s,s,64+ 1 *8);
- BN_lshift(s,s,64);
- BN_copy(x,D);
- BN_mask_bits(x,64);
- BN_copy(y,D);
- BN_rshift(y,y,64);
- BN_mask_bits(y,1*8);
- BN_lshift(y,y,128-1*8);
- BN_copy(D,s);
- BN_add(D,D,x);
- BN_add(D,D,y);
- }
- BN_zero(B);
- BN_set_bit(B,88);
- break;
- case 0x25:
- {
- AddMapCycles(254);
- MakeJ0(B, D, C, wordsize*64);
- // valid for wordsize 1 and 2
- AddMapCycles(795*wordsize-492);
- BN_zero(C);
- cycles = 49 + 800*wordsize;
- }
- break;
- case 0x29:
- {
- BN_add(B, B, C);
- bool b = BN_is_bit_set(B, wordsize<<6);
- if(b) BN_mask_bits(B, wordsize<<6);
- if(data) data[0] = b;
- cycles = 501+(8*wordsize+3)/5*5-6;
- }
- break;
- case 0x2a:
- {
- bool b = ModSub(B, B, D);
- if(data) data[0] = b;
- BN_zero(C);
- }
- break;
- case 0x2e:
- {
- int ti=1;
- H.GetLE(data,16);
- BN_rshift(H,H,64);
- BN_lshift(H,H,64);
- BN_add(H,J,H);
- BN_rshift(H,H,ti<<3);
- BN_copy(J,H);
- BN_mask_bits(J,64);
- cycles = 864;
- }
- break;
- case 0x2F:
- H.GetLE(data,16);
- BN_rshift(H,H,64);
- BN_lshift(H,H,64);
- BN_add(H,H,J);
- BN_rshift(J,H,8);
- BN_mask_bits(J,64);
- cycles = 808;
- break;
- case 0x30:
- case 0x31:
- {
- BN_mul(D, B, B, ctx);
- if((f&1)) BN_add(D, D, C);
- BN_rshift(C, D, wordsize*64);
- ++wordsize;
- BN_rshift(J, B, (wordsize/2)*128-64);
- BN_mask_bits(J, 64);
- --wordsize;
- }
- break;
- case 0x32:
- {
- if(l<=0) l = wordsize;
- else if(l>34) l = 34;
- cBN scalar;
- if(!BN_is_zero(D)) {
- scalar.GetLE(data, l*8);
- BN_div(C, B, scalar, D, ctx);
- BN_rshift(A, C, 17*8*8);
- A.Commit(17);
- C.Commit(17);
- }
- BN_zero(J);
- }
- break;
- case 0x36:
- case 0x38:
- {
- AddMapCycles(230);
- MonMul0(B, f==0x36?A:B, B, C, D, J);
- AddMapCycles(102);
- MonMulFin(B, D);
- }
- break;
- case 0x39:
- case 0x3a:
- {
-
- cBN scalar;
-
- AddMapCycles(f==0x39?433:192);
- IMonInit();
-
- if(f==0x39) scalar.GetLE(data, wordsize*8);
- MonMul(B, (f==0x39?(BIGNUM*)scalar:A), B);
- MonMul(B, A, B);
-/* {
- cBN tmp1,tmp2,tmp3;
- BN_rshift(tmp1,D,64);
- BN_mask_bits(tmp1,64);
- BN_lshift(tmp1,tmp1,64);
- BN_copy(tmp2,D);
- BN_mask_bits(tmp2,64);
- BN_rshift(tmp2,tmp2,16);
- BN_copy(tmp3,D);
- BN_mask_bits(tmp3,16);
- BN_lshift(tmp3,tmp3,48);
- BN_copy(D,tmp1);
- BN_add(D,D,tmp2);
- BN_add(D,D,tmp3);
- }
-*/
- MakeJ();
- BN_zero(R);
- BN_set_bit(R,136); //27:26
- BN_mod(B,R,D,ctx);
- for (int i=0; i<4; i++)
- {
- MonMul(B,B,B);
- }
- MonMul(B,A,B);
- BN_zero(B);
- }
- break;
- case 0x3b:
- Map3b(data, l);
- break;
- case 0x3c:
- Map3c(data, l);
- break;
- case 0x3d:
- D.GetLE(data,16);
- {
- cBN v;
- BN_zero(v);
- BN_sub(J,v,D);
- BN_set_bit(J,0);
- BN_set_bit(v,64);
- BN_mod_inverse(J,J,v,ctx);
- BN_mask_bits(J,64);
- BN_mod(D,D,v,ctx);
- BN_mul(C,J,D,ctx);
- BN_rshift(C,C,64);
- BN_mask_bits(C,64);
- BN_rshift(A,A,64);
- BN_mask_bits(A,64);
- BN_lshift(A,A,64);
- BN_add(C,A,C);
- BN_free(v);
- }
-/* {
- D.GetLE(data,(l<=0? l:wordsize)<<3);
- MakeJ();
- MonMul0(C,B,B,B,D,J);
- }*/
- break;
- case 0x3e:
- Map3e(data, l);
- break;
- case 0x46:
- AddMapCycles(328);
- IMonInit();
- break;
- case 0x4d:
- if(-0x018000==l) {
- BN_mask_bits(B,64);
- } else {
- BN_set_bit(B,(wordsize<<6)-1);
- if(-0x028000==l) {
- BN_set_bit(B,(wordsize<<6)-2);
- }
- }
- BN_set_bit(B,0);
- for(int i=0; i<sizeof(primes); ++i) residues[i]=BN_mod_word(B,primes[i]);
- break;
- case 0x4e:
-// MakePrime(B,residues);
- BN_copy(D,B);
- break;
- case 0x4f:
-/* BN_copy(D,B);
- BN_zero(A);
-// BN_set_bit(A,56);//cycles=752
- BN_set_bit(A,40);//cycles=808
- BN_add(A,A,A);*/
- BN_set_word(A,2);
- BN_add(B,B,A);
- break;
- case 0x57:
- Map57(data, l);
- break;
-
- default:
- return false;
- }
- return true;
-}
-
-// -- cMECM ----------------------------------------------------------------
-
-class cMECM: public cMap0101 {
-private:
- unsigned char sig[12];
- cIDEA idea;
-public:
- cMECM(const unsigned char* sig);
- virtual bool CompareSig(const unsigned char *sig) const;
- void ComputeCW(unsigned char *digest, unsigned char *cw);
- virtual int Algo(int hdsize, const unsigned char *hd, const unsigned char *lhd, const unsigned char *cw, const unsigned char *lcw, const unsigned char *pcw, unsigned char *hw) { return MARV_NOT_PROCESSED; }
- virtual int PostAlgo(int hdsize, const unsigned char *hd, const unsigned char *lhd, const unsigned char *cw, const unsigned char *lcw, const unsigned char *pcw, unsigned char *hw) { return MARV_NOT_PROCESSED; }
-};
-
-cMECM::cMECM(const unsigned char* sig)
-{
- memcpy(this->sig, sig, sizeof(this->sig));
-}
-
-bool cMECM::CompareSig(const unsigned char *sig) const
-{
- return memcmp(this->sig, sig, sizeof(this->sig))==0;
-}
-
-void cMECM::ComputeCW(unsigned char *digest, unsigned char *cw)
-{
- memcpy(digest+8,digest,8);
- IdeaKS ks;
- idea.SetEncKey(digest,&ks);
- memcpy(digest+0,cw+8,6);
- memcpy(digest+6,cw+0,6);
- idea.Encrypt(digest+4,8,digest+4,&ks,0);
- idea.Encrypt(digest+0,8,digest+0,&ks,0);
-
- memcpy(cw+ 0,digest+6,3);
- memcpy(cw+ 4,digest+9,3);
- memcpy(cw+ 8,digest+0,3);
- memcpy(cw+12,digest+3,3);
- for(int i=0; i<16; i+=4) cw[i+3]=cw[i]+cw[i+1]+cw[i+2];
-}
-
-class cMECM_Map57_071227: public cMECM {
-private:
- static unsigned char sig[12];
- int lasttm;
-public:
- cMECM_Map57_071227(): cMECM(sig),lasttm(0) {}
- virtual int Algo(int hdsize, const unsigned char *hd, const unsigned char *lhd, const unsigned char *cw, const unsigned char *lcw, const unsigned char *pcw, unsigned char *hw);
- virtual int PostAlgo(int hdsize, const unsigned char *hd, const unsigned char *lhd, const unsigned char *cw, const unsigned char *lcw, const unsigned char *pcw, unsigned char *hw);
- virtual bool Brute(const unsigned char* cw, const unsigned char* lcw, unsigned char* hw, bool first);
-};
-
-unsigned char cMECM_Map57_071227::sig[12] = { 0x32, 0x03, 0xaa, 0x03, 0xf0, 0x09, 0x50, 0xa9, 0x99, 0x8a, 0x9b, 0xb6 };
-
-int cMECM_Map57_071227::Algo(int hdsize, const unsigned char *hd, const unsigned char *lhd, const unsigned char *cw, const unsigned char *lcw, const unsigned char *pcw, unsigned char *hw)
-{
-#if 0
- unsigned char tmp[0x60];
-
- DoMap(SETSIZE, 0, 2);
- memcpy(tmp, hw, sizeof(tmp));
- DoMap(0x57, tmp, 2);
- memcpy(hw+8, tmp, 0x40);
- hw[0x08] = 4;
- hw[0x10] = 16;
- return MARV_SUCCESS;
-#else
- return MARV_NOT_PROCESSED;
-#endif
-}
-
-int cMECM_Map57_071227::PostAlgo(int hdsize, const unsigned char *hd, const unsigned char *lhd, const unsigned char *cw, const unsigned char *lcw, const unsigned char *pcw, unsigned char *hw)
-{
- int ret = MARV_NOT_PROCESSED;
- if(!lcw[16]) {
- ret = MARV_SYNCING;
- if(CheckNull(lhd, hdsize)) {
- PRINTF(L_SYS_ECM,"Syncing to stream");
- } else {
- if(memcmp(lhd, hd, hdsize)==0 && memcmp(cw, pcw, 16)) {
- if(Brute(cw, pcw, hw, true)) {
- PRINTF(L_SYS_ECM,"Stream synced");
- ret = MARV_SUCCESS;
- }
- }
- if(ret!=MARV_SUCCESS && !CheckNull(lcw, 16) && Brute(cw, lcw, hw, false)) {
- PRINTF(L_SYS_ECM,"Stream synced");
- ret = MARV_SUCCESS;
- }
- if(ret!=MARV_SUCCESS) {
- PRINTF(L_SYS_ECM,"Syncing to stream");
- ret = MARV_MAYBE_SUCCESS;
- }
- }
- if(ret!=MARV_SUCCESS && lasttm) {
- hw[0x08] = 0xff - (((lasttm-1+4-0x101*4)/4)&0xff);
- hw[0x10] = 0xff - (((lasttm-1+16-0x101*16)/16)&0xff);
- }
- } else {
- if(Brute(cw, lcw, hw, false))
- ret = MARV_SUCCESS;
- else {
- PRINTF(L_SYS_ECM,"Stream desynced");
- ret = MARV_DESYNCED;
- }
- }
-
- return ret;
-}
-
-bool cMECM_Map57_071227::Brute(const unsigned char* cw, const unsigned char* lcw, unsigned char* hw, bool first)
-{
- bool ret = false;
- unsigned char digest[20], digest2[20];
- unsigned char tcw[2][16];
- const unsigned char* ccw = first ? tcw[1] : lcw;
-
- memcpy(hw+128,hw,64);
- RotateBytes(hw+64,128);
-
- for(int tm=4096+4; tm<8192+4; tm+=4) {
- hw[127-0x08] = 0xff - (((tm-1+4-0x101*4)/4)&0xff);
- hw[127-0x10] = 0xff - (((tm-1+16-0x101*16)/16)&0xff);
- SHA1(hw+64,128,digest);
- RotateBytes(digest,20);
- memcpy(tcw[0], cw, 16);
- if(first) {
- memcpy(digest2, digest, sizeof(digest2));
- memcpy(tcw[1], lcw, 16);
- ComputeCW(digest2, tcw[1]);
- }
- ComputeCW(digest, tcw[0]);
- if(memcmp(tcw[0], ccw, 8)==0 || memcmp(tcw[0]+8, ccw+8, 8)==0) {
- lasttm = tm;
- ret = true;
- break;
- }
- }
-
- RotateBytes(hw+64,128);
- if(ret)
- memcpy(hw,hw+128,64);
- else if(lasttm) {
- hw[0x08] = 0xff - (((lasttm-1+4-0x101*4)/4)&0xff);
- hw[0x10] = 0xff - (((lasttm-1+16-0x101*16)/16)&0xff);
- }
- return ret;
-}
-
-static cMECM_Map57_071227 MECM_Map57;
-static cMECM* vMECM0101[] = { &MECM_Map57 };
-
-// -- cN2Prov0101 --------------------------------------------------------------
-
-class cN2Prov0101 : public cMutex, public cN2Prov, public cN2Emu, private cMap0101 {
-private:
- int desSize;
- DES_key_schedule desks1, desks2;
- unsigned char desblock[8];
- IdeaKS ks;
- cMapMemHW *hwMapper;
- bool special05;
- //
-protected:
- int mecmAddr[2];
- int mecmKeyId;
- int bfValue;
- //
- virtual int Algo(int algo, const unsigned char *hd, const unsigned char *ed, unsigned char *hw, const unsigned char *cw);
- virtual void DynamicHD(unsigned char *hd, const unsigned char *ed);
- virtual bool RomInit(void);
- virtual void Stepper(void);
- virtual void TimerHandler(unsigned int num);
- virtual void AddMapCycles(unsigned int num);
- virtual void WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op);
- virtual void ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op);
- virtual unsigned int CpuCycles(void) { return Cycles(); }
- void AddRomCallbacks(void);
- bool RomCallbacks(void);
- bool ProcessMap(int f);
- bool ProcessDESMap(int f);
-public:
- cN2Prov0101(int Id, int Flags);
- virtual bool PostProcAU(int id, unsigned char *data);
- virtual int ProcessBx(unsigned char *data, int len, int pos);
- virtual int ProcessEx(unsigned char *data, int len, int pos);
- virtual int RunEmu(unsigned char *data, int len, unsigned short load, unsigned short run, unsigned short stop, unsigned short fetch, int fetch_len, int maxinstr=100000);
- virtual bool BFReset() { bfValue=0; return true; }
- virtual bool BFNext() { return (++bfValue<1024); }
- };
-
-static cN2ProvLinkReg<cN2Prov0101,0x0101,(N2FLAG_MECM|N2FLAG_POSTAU|N2FLAG_Bx|N2FLAG_Ex)> staticPL0101;
-
-cN2Prov0101::cN2Prov0101(int Id, int Flags)
-:cN2Prov(Id,Flags)
-{
- special05 = false;
- hasWriteHandler = hasReadHandler = true;
- mecmAddr[0]=0x91d7; mecmAddr[1]=0x92d7; mecmKeyId=0x106;
- seedSize=10;
- desSize=16; hwMapper=0;
- SetMapIdent(Id);
-}
-
-void cN2Prov0101::DynamicHD(unsigned char *hd, const unsigned char *ed)
-{
- hd[5]=ed[5];
- hd[6]=(ed[7]&0xEF) | ((ed[6]&0x40)>>2);
- hd[7]=ed[8];
- hd[8]=(ed[9]&0x7F) | ((ed[6]&0x20)<<2);
- hd[9]=ed[6]&0x80;
-}
-
-int cN2Prov0101::Algo(int algo, const unsigned char *hd, const unsigned char *ed, unsigned char *hw, const unsigned char *cw)
-{
- if(algo!=0x40 && algo!=0x60) {
- PRINTF(L_SYS_ECM,"%04X: unknown MECM algo %02x",id,algo);
- return MARV_ERROR;
- }
- if(!Init(id,102)) {
- PRINTF(L_SYS_ECM,"%04X: failed to initialize ROM",id);
- return MARV_ERROR;
- }
-
- unsigned char keyNr=(algo>>5)&0x01;
- unsigned char mecmCode[256];
- GetMem(mecmAddr[keyNr],mecmCode,256,0x80);
- cPlainKey *pk;
- unsigned char ideaKey[16];
- if(!(pk=keys.FindKey('N',mecmKeyId,keyNr,sizeof(ideaKey)))) {
- PRINTF(L_SYS_KEY,"missing %04x %02x MECM key",mecmKeyId,keyNr);
- return false;
- }
- pk->Get(ideaKey);
- idea.SetEncKey(ideaKey,&ks);
- for(int i=0x100-8; i>=8; i-=8) {
- idea.Encrypt(mecmCode+i,8,mecmCode+i,&ks,0);
- xxor(mecmCode+i,8,mecmCode+i,mecmCode+i-8);
- }
- idea.Encrypt(mecmCode,8,mecmCode,&ks,0);
- HEXDUMP(L_SYS_RAWECM,mecmCode,sizeof(mecmCode),"decrypted MECM code");
- // check signature
- unsigned char data[256];
- memcpy(data,mecmCode,sizeof(data));
- RotateBytes(data,sizeof(data));
- SHA1(data,sizeof(data)-8,data);
- RotateBytes(data,20);
- if(memcmp(data,mecmCode,8)) {
- PRINTF(L_SYS_ECM,"%04X: MECM %02x decrypt signature failed",id,keyNr);
- return false;
- }
-
- memcpy(hw,hd,seedSize);
- ExpandInput(hw);
-
- cMECM *mecm = NULL;
- int i;
- for(i=0; i<sizeof(vMECM0101)/sizeof(*vMECM0101); ++i) {
- if(vMECM0101[i]->CompareSig(mecmCode)) {
- mecm = vMECM0101[i];
- break;
- }
- }
-
- i = MARV_NOT_PROCESSED;
- if(mecm) {
- if((i=mecm->Algo(seedSize, hd, lasthd, cw, lastcw, prevcw, hw))==MARV_ERROR)
- return i;
- }
-
- if(i==MARV_NOT_PROCESSED) {
- SetMem(0xa00,hd,seedSize);
- SetMem(0x0ba2,hw,0x80);
- i = MARV_ERROR;
- if(RunEmu(mecmCode+8, sizeof(mecmCode)-8, 0x100, 0x100, 0, 0, 0, 200000)>0) {
- GetMem(0x0ba2,hw,0x80);
- i = MARV_SUCCESS;
- }
- if(i==MARV_ERROR) return i;
- }
-
- if(mecm && (i=mecm->PostAlgo(seedSize, hd, lasthd, cw, lastcw, prevcw, hw))!=MARV_NOT_PROCESSED)
- return i;
-
- return MARV_SUCCESS;
-
-/*
- if(algo==0x40) {
- const int hwCount=2;
- memcpy(hw,hd,hwCount+1);
- ExpandInput(hw);
- hw[0x18]|=1; hw[0x40]|=1;
- DoMap(SETSIZE,0,2);
- DoMap(IMPORT_A,hw,3);
- DoMap(IMPORT_D,hw+24);
- DoMap(0x3b);
- DoMap(EXPORT_C,hw);
- DoMap(IMPORT_A,hw+40,3);
- DoMap(IMPORT_D,hw+64);
- DoMap(0x3b);
- DoMap(EXPORT_C,hw+40);
- DoMap(0x43);
- DoMap(0x44,hw);
- DoMap(0x44,hw+64);
- memcpy(&hw[0],&hw[64+4],hwCount);
- memset(&hw[hwCount],0,128-hwCount);
- return true;
- }
- else if(algo==0x60) { // map 4D/4E/57
- hw[127]|=0x80; hw[0]|=0x01;
- DoMap(SETSIZE,0,16);
- DoMap(IMPORT_A,hw);
- DoMap(0x4d);
- DoMap(0x4e);
- DoMap(EXPORT_A,hw);
- RotateBytes(hw,16);
- DoMap(IMPORT_A,hw);
- DoMap(0x4e);
- DoMap(EXPORT_A,hw);
- DoMap(0x57,hw);
- return true;
- }
-
- PRINTF(L_SYS_ECM,"%04X: unknown MECM algo %02x",id,algo);
-*/
- return MARV_ERROR;
-}
-
-bool cN2Prov0101::PostProcAU(int id, unsigned char *data)
-{
- if(data[1]&0x5f) return false;
- return true;
-}
-
-bool cN2Prov0101::RomInit(void)
-{
- cMutexLock lock(this);
- if(!AddMapper(hwMapper=new cMapMemHW(*this),HW_OFFSET,HW_REGS,0x00)) return false;
- SetPc(0x4000);
- SetSp(0x0FFF,0x0FE0);
- ClearBreakpoints();
- AddBreakpoint(0x537d);
- AddBreakpoint(0x8992);
- AddBreakpoint(0xA822);
- while(!Run(5000)) {
- switch(GetPc()) {
- case 0x537d:
- PRINTF(L_SYS_EMU,"%04x: ROM init successfull",id);
- return true;
- default:
- PRINTF(L_SYS_EMU,"%04x: ROM init failed: unexpected breakpoint",id);
- break;
- }
- }
- return false;
-}
-
-void cN2Prov0101::AddMapCycles(unsigned int num)
-{
- AddCycles(num);
-}
-
-bool cN2Prov0101::ProcessMap(int f)
-{
- unsigned short addr;
- unsigned char tmp[512];
- int l=GetOpSize(Get(0x48));
- int dl=l<<3;
-
- switch(f) {
- case SETSIZE:
- DoMap(f,0,Get(0x48));
- break;
- case IMPORT_J:
- l=8; dl=8<<3;
- // fall throught
- case IMPORT_A:
- case IMPORT_B:
- case IMPORT_C:
- case IMPORT_D:
- case IMPORT_LAST:
- addr=HILO(0x44);
- GetMem(addr,tmp,dl,0); DoMap(f,tmp,l);
- break;
- case EXPORT_J:
- l=8; dl=8<<3;
- // fall throught
- case EXPORT_A:
- case EXPORT_B:
- case EXPORT_C:
- case EXPORT_D:
- case EXPORT_LAST:
- addr=HILO(0x44);
- DoMap(f,tmp,l); SetMem(addr,tmp,(f == EXPORT_J ? 8 : dl),0);
- break;
- case SWAP_A:
- case SWAP_B:
- case SWAP_C:
- case SWAP_D:
- addr=HILO(0x44);
- GetMem(addr,tmp,dl,0); DoMap(f,tmp,l); SetMem(addr,tmp,dl,0);
- break;
- case CLEAR_A:
- case CLEAR_B:
- case CLEAR_C:
- case CLEAR_D:
- case COPY_A_B:
- case COPY_B_A:
- case COPY_A_C:
- case COPY_C_A:
- case COPY_C_D:
- case COPY_D_C:
- DoMap(f);
- break;
- case 0x22:
- DoMap(f,tmp,(Get(0x48)<<16)|(Get(0x4a)<<8)|Get(0x49));
- break;
- case 0x23:
- case 0x25:
- DoMap(f);
- break;
- case 0x29:
- case 0x2a:
- DoMap(f,tmp);
- Set(0x4b,tmp[0]);
- break;
- case 0x3c:
- case 0x3e:
- if(l>wordsize) { l=wordsize; dl=l<<3; }
- // fall through
- case 0x32:
- case 0x39:
- if(l>34) { l=34; dl=34<<3; }
- case 0x2e:
- case 0x2F:
- case 0x3b:
- case 0x3d:
- GetMem(HILO(0x44),tmp,dl,0);
- DoMap(f,tmp,l);
- break;
- case 0x21:
- case 0x30:
- case 0x31:
- case 0x36:
- case 0x38:
- case 0x3a:
- case 0x43:
- case 0x4f:
- DoMap(f);
- break;
- case 0x44:
- case 0x45:
- GetMem(0x400,tmp,64,0);
- DoMap(f,tmp,l);
- SetMem(0x440,tmp,20,0);
- break;
- case 0x46:
- GetMem(HILO(0x44),tmp,8,0);
- DoMap(f,tmp,l);
- break;
- case 0x4d:
- DoMap(f,tmp,-((Get(0x48)<<16)|(Get(0x49)<<8)|Get(0x4a)));
- SetMem(0x400,tmp,53,0);
- break;
- case 0x4e:
- GetMem(0x400,tmp,53,0);
- DoMap(f,tmp);
- SetMem(0x400,tmp,53,0);
- break;
- case 0x57:
- addr=HILO(0x46);
- l=wordsize; if(l<2 || l>4) l=4;
- dl=l<<3;
- for(int i=0; i<6; i++) GetMem(HILO(addr+i*2),tmp+i*dl,dl,0);
- DoMap(f,tmp);
- SetMem(0x400,tmp,0x40,0);
- //memset(tmp,0,11*32);
- //SetMem(0x440,tmp,11*32,0);
- //AddCycles(MapCycles());
- AddCycles((int)MapCycles()>0 ? MapCycles() : 4*bfValue);
- break;
- default:
- PRINTF(L_SYS_MAP,"%04x: map call %02x not emulated",id,f);
- return false;
- }
- c6805::a=0; c6805::x=0; c6805::y=0;
- return true;
-}
-
-bool cN2Prov0101::ProcessDESMap(int f)
-{
- unsigned char data[16];
- switch(f) {
- case 0x05: // 3DES encrypt
- DES_ecb2_encrypt(DES_CAST(desblock),DES_CAST(desblock),&desks1,&desks2,DES_ENCRYPT);
- break;
- case 0x06: // 3DES decrypt
- DES_ecb2_encrypt(DES_CAST(desblock),DES_CAST(desblock),&desks1,&desks2,DES_DECRYPT);
- break;
- case 0x07: // 3DES decrypt
- Set(0x00, 0x2d, 0x02);
- break;
- case 0x0b: // load DES data block from memory
- GetMem(HILO(0x25),desblock,8,Get(0x24));
- break;
- case 0x0c: // store DES data block to memory
- SetMem(HILO(0x2b),desblock,8,Get(0x2a));
- break;
- case 0x0e: // get DES key1 and key2
- GetMem(HILO(0x25),data,8,Get(0x24));
- DES_key_sched((DES_cblock *)data,&desks1);
- GetMem(HILO(0x28),data,8,Get(0x27));
- DES_key_sched((DES_cblock *)data,&desks2);
- break;
- case 0x0f: // set DES size
- desSize=Get(0x2d);
- if(desSize!=0x10 && desSize!=0x18) {
- PRINTF(L_SYS_EMU,"%04x: invalid DES key size %02x",id,desSize);
- return false;
- }
- break;
- default:
- PRINTF(L_SYS_MAP,"%04x: DES map call %02x not emulated",id,f);
- return false;
- }
- return true;
-}
-
-bool cN2Prov0101::RomCallbacks(void)
-{
- bool dopop=true;
- unsigned int ea=GetPc();
- if(ea&0x8000) ea|=(cr<<16);
- switch(ea) {
- case 0x3840: //MAP Handler
- case 0x00A822:
- if(!ProcessMap(a)) return false;
- if(Interrupted()) dopop=false;
- break;
- case 0x3844: //DES Handler
- if(!ProcessDESMap(a)) return false;
- break;
- case 0x5F23: //Erase_RAM_and_Hang
- case 0x5F27: //Erase_RAM_and_Hang_Lp
- case 0x5F5E: //BrainDead
- PRINTF(L_SYS_EMU,"%04x: emu hung at %04x",id,ea);
- return false;
- case 0x70A6: //Write_Row_EEP_RC2_Len_A_To_RC1
- {
- unsigned short rc1=HILO(0x47);
- unsigned short rc2=HILO(0x4a);
- for(int i=0; i<a; i++) Set(0x80,rc1++,Get(dr,rc2++));
- Set(0x4a,rc2>>8);
- Set(0x4b,rc2&0xff);
- break;
- }
- case 0x7BFE: //Write_Row_EEPROM_A_from_X_to_RC1
- {
- unsigned short rc1=HILO(0x47);
- unsigned short rc2=c6805::x;
- for(int i=0; i<a; i++) Set(0x80,rc1++,Get(rc2++));
- break;
- }
- case 0x7CFF: //UPDATE_USW_03DD_03DE
- Set(0x30E8,Get(0x03DD));
- Set(0x30E9,Get(0x03DE));
- break;
- case 0x00A23C: //IDEA_Generate_Expanded_Key
- {
- unsigned char key[16];
- GetMem(0x0a20,key,16);
- idea.SetEncKey(key,&ks);
- break;
- }
- case 0x00A2E9: //IDEA_Cypher
- {
- unsigned char data[8];
- GetMem(0x070,data,8);
- idea.Encrypt(data,8,data,&ks,0);
- SetMem(0x070,data,8);
- break;
- }
- default:
- PRINTF(L_SYS_EMU,"%04X: unknown ROM breakpoint %04x",id,ea);
- return false;
- }
- if(dopop) {
- if(ea>=0x8000) PopCr();
- PopPc();
- }
- return true;
-}
-
-void cN2Prov0101::AddRomCallbacks(void)
-{
- AddBreakpoint(0xA822); // map handler
- AddBreakpoint(0x3840);
- AddBreakpoint(0x3844);
- AddBreakpoint(0xA23C); //IDEA
- AddBreakpoint(0xA2E9);
- AddBreakpoint(0x70A6);
- AddBreakpoint(0x7BFE);
- AddBreakpoint(0x7CFF);
- AddBreakpoint(0x5F23);
- AddBreakpoint(0x5F27);
- AddBreakpoint(0x5F5E);
-}
-
-int cN2Prov0101::ProcessBx(unsigned char *data, int len, int pos)
-{
- if(Init(id,102)) {
- SetMem(0x92,data+pos-1,len-pos+1);
- SetPc(0x93);
- SetSp(0x0FFF,0x0EF8);
- ClearBreakpoints();
- AddBreakpoint(0x9569);
- AddBreakpoint(0x0000);
- AddRomCallbacks();
- while(!Run(1000)) {
- if(GetPc()==0x9569) {
- GetMem(0x80,data,len);
- return a;
- }
- else if(GetPc()==0x0000) break;
- else if(!RomCallbacks()) break;
- }
- }
- return -1;
-}
-
-int cN2Prov0101::ProcessEx(unsigned char *data, int len, int pos)
-{
- if(Init(id,102)) {
- SetMem(0x80,data,len);
- SetPc(0x9591);
- SetSp(0x0FFF,0x0EF8);
- Push(0x99); //push the bug-table return onto the stack
- Push(0x95);
- Push(0x00);
- Set(0x00,0x62,0x26);
- Set(0x00,0x63,0x02);
- Set(0x00,0x03d3,len-0x12);
- ClearBreakpoints();
- AddBreakpoint(0x9569);
- AddBreakpoint(0x9599);
- AddRomCallbacks();
- while(!Run(10000)) {
- if(GetPc()==0x9569) {
- GetMem(0x80,data,len);
- return max((int)a,6);
- }
- else if(GetPc()==0x9599) break;
- else if(!RomCallbacks()) break;
- }
- }
- return -1;
-}
-
-int cN2Prov0101::RunEmu(unsigned char *data, int len, unsigned short load, unsigned short run, unsigned short stop, unsigned short fetch, int fetch_len, int maxinstr)
-{
- if(Init(id,102)) {
- SetSp(0x0FFF,0x0EF8);
- SetMem(load,data,len);
- SetPc(run);
- ClearBreakpoints();
- AddBreakpoint(stop);
- if(stop!=0x0000) AddBreakpoint(0x0000);
- AddRomCallbacks();
- while(!Run(maxinstr)) {
- if(GetPc()==0x0000 || GetPc()==stop) {
- GetMem(fetch,data,fetch_len);
- return 1;
- }
- else if(!RomCallbacks()) break;
- }
- }
- return -1;
-}
-
-void cN2Prov0101::TimerHandler(unsigned int num)
-{
- if(hwMapper) {
- int mask=hwMapper->AddCycles(num);
- for(int t=0; mask; mask>>=1,t++)
- if(mask&1) {
- DisableTimers(11);
- if(t==2) {
- PRINTF(L_SYS_MAP,"Timer interrupt %u @ %04x",t,GetPc());
- RaiseException(9);
- if(Interruptible()) throw(t);
- }
- }
- }
-}
-
-void cN2Prov0101::Stepper(void)
-{
- unsigned short pc=GetPc();
- if(pc>=0x93 && pc<=0xE0) { // pc in EMM data
- unsigned char op=Get(pc);
- if((op&0xF0)==0x00) { // current opcode BRCLR/BRSET
- int fake=0; // 1=branch -1=non-branch
- if(Get(pc+3)==0x81) // next opcode == RTS
- fake=1; // fake branch
- else {
- unsigned char off=Get(pc+2);
- unsigned short target=pc+3+off;
- if(off&0x80) target-=0x100;
- if(Get(target)==0x81) // branch target == RTS
- fake=-1; // fake non-branch
- }
- if(fake) {
- unsigned short ea=Get(pc+1);
- unsigned char val=Get(dr,ea);
- int bit=1<<((op&0xF)>>1);
- // set/clr bit according to fake-mode and opcode
- if((fake>0 && (op&0x01)) || (fake<0 && !(op&0x01))) {
- if(val&bit) loglb->Printf("*");
- val&=~bit;
- }
- else {
- if(!(val&bit)) loglb->Printf("*");
- val|=bit;
- }
- Set(dr,ea,val);
- }
- }
- }
-}
-void cN2Prov0101::WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op)
-{
- switch(ea) {
- case cMapMemHW::HW_SECURITY:
- if(cr==0x00) op = Get(ea);
- break;
- case 0x05:
- if(cr==0x00) special05=(op&0x40)!=0;
- break;
- }
-}
-
-void cN2Prov0101::ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op)
-{
- if(special05) {
- special05=false; // prevent loop
- unsigned short start=Get(0x00,0x30C0);
- unsigned short end=Get(0x00,0x30C1);
- if(((ea>>8)>=start) && ((ea>>8)<=end)) op=0x00; // dataspace
- else op=0x01; // codespace
- special05=true;
- }
-
- switch(ea) {
- case 0x2f71:
-// op = (rand()&0xeb)^((op&2)<<3)^((op&0x40)>>4);
- op = (rand()&0xe3)^((op&2)<<3)^((op&0x40)>>4)^((op&1)<<3)^((op&0x80)>>4);
- Set(seg, ea, op);
- break;
- }
-}
-
-
-
-// -- cN2Prov0901 --------------------------------------------------------------
-
-class cN2Prov0901 : public cN2Prov0101 {
-public:
- cN2Prov0901(int Id, int Flags);
- };
-
-static cN2ProvLinkReg<cN2Prov0901,0x0901,(N2FLAG_MECM|N2FLAG_POSTAU|N2FLAG_Bx|N2FLAG_Ex)> staticPL0901;
-
-cN2Prov0901::cN2Prov0901(int Id, int Flags)
-:cN2Prov0101(Id,Flags)
-{
- mecmAddr[0]=0x91f5; mecmAddr[1]=0x92f5; mecmKeyId=0x907;
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "nagra2.h"
-
-// -- cMap0501 -----------------------------------------------------------------
-
-class cMap0501 : public cMapCore {
-private:
-protected:
- virtual bool Map(int f, unsigned char *data, int l);
-public:
- cMap0501(void);
- };
-
-cMap0501::cMap0501(void)
-{
-}
-
-bool cMap0501::Map(int f, unsigned char *data, int l)
-{
- switch(f) {
- case 0x37:
- l=(l?l:wordsize)<<3;
- H.GetLE(data,l);
- MonMul(B,H,A);
- break;
- case 0x3a:
- MakeJ();
- BN_zero(R);
- BN_set_bit(R,68*wordsize);
- BN_mod(H,R,D,ctx);
- for(int i=0; i<4; i++) MonMul(H,H,H);
- MonMul(B,A,H);
- MonMul(B,A,B);
- break;
- default:
- return false;
- }
- return true;
-}
-
-// -- cN2Prov0501 --------------------------------------------------------------
-
-class cN2Prov0501 : public cN2Prov, private cMap0501 {
-protected:
- virtual int Algo(int algo, const unsigned char *hd, const unsigned char *ed, unsigned char *hw, const unsigned char *cw);
- virtual bool NeedsCwSwap(void) { return true; }
-public:
- cN2Prov0501(int Id, int Flags):cN2Prov(Id,Flags) { seedSize=3; SetMapIdent(Id); }
- };
-
-static cN2ProvLinkReg<cN2Prov0501,0x0501,N2FLAG_MECM|N2FLAG_INV> staticPL0501;
-
-int cN2Prov0501::Algo(int algo, const unsigned char *hd, const unsigned char *ed, unsigned char *hw, const unsigned char *cw)
-{
- if(algo==0x60) {
- hw[0]=hd[0];
- hw[1]=hd[1];
- hw[2]=hd[2]&0xF8;
- ExpandInput(hw);
- hw[63]|=0x80;
- hw[95]=hw[127]=hw[95]&0x7F;
- SetWordSize(4);
- ImportReg(IMPORT_J,hw+0x18);
- ImportReg(IMPORT_D,hw+0x20);
- ImportReg(IMPORT_A,hw+0x60);
- DoMap(0x37,hw+0x40);
- ExportReg(EXPORT_C,hw);
- DoMap(0x3a);
- ExportReg(EXPORT_C,hw+0x20);
- DoMap(0x43);
- DoMap(0x44,hw);
- hw[0]&=7;
- ExportReg(EXPORT_B,hw+3);
- memset(hw+3+0x20,0,128-(3+0x20));
- return MARV_SUCCESS;
- }
-
- PRINTF(L_SYS_MAP,"0501: unknown MECM algo %02x",algo);
- return MARV_ERROR;
-}
-
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "nagra2.h"
-
-// -- cMap4101 -----------------------------------------------------------------
-
-class cMap4101 : public cMapCore {
-protected:
- virtual bool Map(int f, unsigned char *data, int l);
- };
-
-bool cMap4101::Map(int f, unsigned char *data, int l)
-{
- switch(f) {
- case 0x58:
- {
- cBN a, b, x, y, scalar;
- D.GetLE(data+0x00,16);
- x.GetLE(data+0x10,16);
- y.GetLE(data+0x20,16);
- b.GetLE(data+0x30,16);
- a.GetLE(data+0x40,16);
- scalar.GetLE(data+0x50,16);
- int scalarbits=BN_num_bits(scalar);
- if(scalarbits>=2 && !BN_is_zero(x) && !BN_is_zero(y) && !BN_is_zero(b)) {
- CurveInit(a);
- ToProjective(0,x,y);
- BN_copy(Qx,Px);
- BN_copy(Qy,Py);
- for(int i=scalarbits-2; i>=0; i--) {
- DoubleP(0);
- if(BN_is_bit_set(scalar,i)) AddP(0);
- }
- ToAffine();
- }
- memset(data,0,64);
- Px.PutLE(&data[0],16);
- Py.PutLE(&data[32],16);
- break;
- }
- case 0x44:
- sctx.h4=UINT32_LE(data);
- sctx.h3=UINT32_LE(data+4);
- sctx.h2=UINT32_LE(data+8);
- sctx.h1=UINT32_LE(data+12);
- sctx.h0=UINT32_LE(data+16);
- cMapCore::DoMap(0x44,data);
- break;
- default:
- return false;
- }
- return true;
-}
-
-// -- cN2Prov4101 ----------------------------------------------------------------
-
-class cN2Prov4101 : public cN2Prov, public cMap4101, public cN2Emu {
-protected:
- virtual void WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op);
-public:
- cN2Prov4101(int Id, int Flags);
- virtual bool PostProcAU(int id, unsigned char *data);
- virtual int ProcessBx(unsigned char *data, int len, int pos);
- };
-
-static cN2ProvLinkReg<cN2Prov4101,0x4101,(N2FLAG_POSTAU|N2FLAG_Bx)> staticPL4101;
-
-cN2Prov4101::cN2Prov4101(int Id, int Flags)
-:cN2Prov(Id,Flags)
-{
- hasWriteHandler=true;
- SetMapIdent(Id);
-}
-
-bool cN2Prov4101::PostProcAU(int id, unsigned char *data)
-{
- if(data[1]==0x01) {
- cPlainKey *pk;
- if(!(pk=keys.FindKeyNoTrig('N',id,MBC(N2_MAGIC,0x30),16))) {
- PRINTF(L_SYS_EMM,"missing %04x NN 30 3DES key (16 bytes)",id);
- return false;
- }
- unsigned char dkey[16];
- pk->Get(dkey);
- DES_key_schedule ks1, ks2;
- DES_key_sched((DES_cblock *)&dkey[0],&ks1);
- DES_key_sched((DES_cblock *)&dkey[8],&ks2);
- DES_ecb2_encrypt(DES_CAST(&data[7]),DES_CAST(&data[7]),&ks1,&ks2,DES_DECRYPT);
- DES_ecb2_encrypt(DES_CAST(&data[7+8]),DES_CAST(&data[7+8]),&ks1,&ks2,DES_DECRYPT);
- }
- return true;
-}
-
-int cN2Prov4101::ProcessBx(unsigned char *data, int len, int pos)
-{
- if(Init(id,110)) {
- SetMem(0x80,data,len);
- SetPc(0x80+pos);
- SetSp(0x0FFF,0x0FE0);
- ClearBreakpoints();
- AddBreakpoint(0xACDD);
- AddBreakpoint(0x9BDD);
- AddBreakpoint(0x7EC5);
- while(!Run(5000)) {
- switch(GetPc()) {
- case 0xACDD:
- return -1;
- case 0x9BDD:
- GetMem(0x80,data,len);
- return a;
- case 0x7EC5:
- {
- PopPc();
- unsigned short args=GetPc();
- int clen=Get(args+4);
- unsigned short ptr=(Get(args)<<8)+Get(args+1);
- if(clen+pos-1>len) return -1; // sanity
- GetMem(ptr,&data[pos-1],clen);
- ptr=(Get(args+2)<<8)+Get(args+3)-0x0CED+0x00B4-0x0080; // wild hack
- if(ptr<7 || ptr+8>len || data[ptr-1]!=0x10 || data[ptr-7]!=0x42) // sanity
- return -1;
- unsigned char tmp[96];
- memcpy(&tmp[0],&data[ptr],8);
- ptr=(((data[ptr]&0x3F)|0x40)<<8)+(data[ptr+1]&0x7F);
- GetMem(ptr,&tmp[8],sizeof(tmp)-8);
- DoMap(0x02,0,2);
- DoMap(0x58,tmp);
- DoMap(0x43);
- DoMap(0x44,tmp);
- SetMem(0x0440,tmp,20);
- SetMem(0x80,data,len);
- SetPc(0x80+pos);
- break;
- }
- }
- }
- }
- return -1;
-}
-
-void cN2Prov4101::WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op)
-{
- if(cr==0x00) {
- if(ea==0x0a || ea==0x12 || ea==0x16) {
- unsigned char old=Get(ea);
- if(old&2) op=(old&~0x02) | (op&0x02);
- }
- }
-}
-
-// -- cN2Prov7101 ----------------------------------------------------------------
-
-static cN2ProvLinkReg<cN2Prov4101,0x7101,(N2FLAG_POSTAU)> staticPL7101;
-
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-// -- cN2Map57 ----------------------------------------------------------------
-
-class cN2Map57 {
-private:
- void mod_add(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4);
- void bn_cmplx1(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4, BIGNUM *arg5);
- void bn_cmplx1a(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4, BIGNUM *arg5);
- void mod_sub(void);
- void bn_func1(BIGNUM *arg0);
- void bn_func2(int arg0);
- void bn_func3(int arg0);
- void bn_cmplx7(void);
- void bn_cmplx2(BIGNUM *var1, BIGNUM *var2, BIGNUM *var3, BIGNUM *var4, BIGNUM *var5, BIGNUM *var6);
- BIGNUM *bn_glb0, *bn_glb1, *bn_glb3, *bn_glb5, *bn_glb6, *bn_glb7;
- BIGNUM *bn_glb_a, *bn_glb_b, *bn_glb_c, *bn_glb_d, *bn_glb_e, *bn_glb_f, *bn_glb_g;
- BIGNUM *bn_glb_h, *bn_glb_i, *bn_glb_j, *bn_glb_k, *bn_glb_l, *bn_glb_m;
- BIGNUM *glb2pow128, *mask128, *glb2pow64, *mask64;
- BN_CTX *t1;
-public:
- void Map57(unsigned char *data);
- };
-
-void cN2Map57::mod_add(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4)
-{
- BN_add(arg1, arg2, arg3);
- if(BN_cmp(arg1, arg4) >= 0) {
- BN_sub(arg1, arg1, arg4);
- }
- BN_mask_bits(arg1, 128);
-}
-
-void cN2Map57::bn_cmplx1(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4, BIGNUM *arg5)
-{
- int j;
- BIGNUM *var44, *var64, *var84, *vara4;
- var44 = BN_new();
- var64 = BN_new();
- var84 = BN_new();
- vara4 = BN_new();
- BN_copy(var44, arg2);
- BN_copy(var64, arg3);
- BN_clear(vara4);
- for(j=0; j<2; j++) {
- BN_copy(var84, var64);
- BN_mask_bits(var84, 64);
- BN_rshift(var64, var64, 64);
- BN_mul(var84, var84, var44, t1);
- BN_add(vara4, vara4, var84);
- BN_copy(var84, vara4);
- BN_mask_bits(var84, 128);
- BN_mul(var84, vara4, arg4, t1);
- BN_mask_bits(var84, 64);
- BN_mul(var84, var84, arg5, t1);
- BN_add(vara4, vara4, var84);
- BN_rshift(vara4, vara4, 64);
- if(BN_cmp(vara4, arg5) >= 0) {
- BN_sub(vara4, vara4, arg5);
- }
- BN_mask_bits(vara4, 128);
- }
- BN_copy(arg1, vara4);
- BN_free(var44);
- BN_free(var64);
- BN_free(var84);
- BN_free(vara4);
-}
-
-void cN2Map57::bn_cmplx1a(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4, BIGNUM *arg5)
-{
- int j;
- BIGNUM *var44, *var64, *var84, *vara4;
- var44 = BN_new();
- var64 = BN_new();
- var84 = BN_new();
- vara4 = BN_new();
- BN_copy(var44, arg2);
- BN_copy(var64, arg3);
- BN_clear(vara4);
- for(j=0; j<2; j++) {
- BN_copy(var84, var64);
- BN_mask_bits(var84, 64);
- BN_rshift(var64, var64, 64);
- BN_mul(var84, var84, var44, t1);
- BN_add(vara4, vara4, var84);
- BN_copy(var84, vara4);
- BN_mask_bits(var84, 128);
- BN_mul(var84, vara4, arg4, t1);
- BN_mask_bits(var84, 64);
- BN_mul(var84, var84, arg5, t1);
- BN_add(vara4, vara4, var84);
- BN_rshift(vara4, vara4, 64);
- if(j==0 && BN_cmp(vara4, arg5) >= 0) {
- BN_sub(vara4, vara4, arg5);
- }
- BN_mask_bits(vara4, 128);
- }
- BN_copy(arg1, vara4);
- BN_free(var44);
- BN_free(var64);
- BN_free(var84);
- BN_free(vara4);
-}
-
-//uses 3, 1, glb2pow128
-//sets 1, 0 (unused)
-void cN2Map57::mod_sub()
-{
- BN_copy(bn_glb0, bn_glb3);
- BN_mod_sub(bn_glb1, bn_glb3, bn_glb1, glb2pow128, t1);
- BN_mask_bits(bn_glb1, 128);
-}
-
-//uses 1, 3, 6
-//sets 1, 0 (unused), 7(unused)
-void cN2Map57::bn_func1(BIGNUM *arg0)
-{
- BIGNUM *var30 = BN_new();
- BIGNUM *var50 = BN_new();
- BN_copy(var30,arg0);
- BN_mask_bits(var30, 8);
- unsigned int x = BN_get_word(var30);
- BN_copy(var30,arg0);
- if( x != 0) {
- BN_clear(var50);
- BN_set_word(var50, 2);
- BN_sub(var30, var30, var50);
- } else {
- BN_clear(var50);
- BN_set_word(var50, 0xfe);
- BN_add(var30, var30, var50);
- }
- BN_copy(bn_glb7, bn_glb1);
- if(BN_is_zero(arg0)) {
- BN_clear(bn_glb7);
- BN_set_word(bn_glb7, 1);
- BN_clear(bn_glb0);
-
- mod_add(bn_glb1, bn_glb7, bn_glb0, bn_glb3);
- BN_free(var30);
- BN_free(var50);
- return;
- } else {
- int msb = BN_num_bits(var30) -1;
- while (msb > 0) {
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
- msb--;
- if(BN_is_bit_set(var30, msb)) {
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
- }
- }
- BN_clear(bn_glb7);
- BN_set_word(bn_glb7, 1);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
- BN_clear(bn_glb0);
- }
- BN_free(var30);
- BN_free(var50);
-}
-
-//uses 3, 6, a, b, c, l, glb2pow128
-//sets 0, 1, 5, 7, a, b, c, f, g
-void cN2Map57::bn_func2(int arg0)
-{
- BN_copy(bn_glb1, bn_glb_b);
-
- mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3);
- BN_copy(bn_glb7, bn_glb1);
- BN_copy(bn_glb5, bn_glb_c);
- BN_mask_bits(bn_glb1, 128);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
- BN_copy(bn_glb_g, bn_glb1);
- BN_copy(bn_glb1, bn_glb7);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
- BN_copy(bn_glb7, bn_glb_a);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
- mod_sub();
- BN_copy(bn_glb_f, bn_glb1);
- BN_copy(bn_glb1, bn_glb7);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
- BN_copy(bn_glb7, bn_glb1);
-
- mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3);
-
- mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3);
- BN_copy(bn_glb7, bn_glb1);
- BN_copy(bn_glb1, bn_glb_c);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
- BN_copy(bn_glb5, bn_glb_l);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-
- mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3);
- BN_copy(bn_glb7, bn_glb1);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
- BN_copy(bn_glb0, bn_glb_f);
-
- mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3);
- mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3);
- if(arg0 == 0) {
- BN_copy(bn_glb_a, bn_glb1);
- } else {
- BN_copy(bn_glb_f, bn_glb1);
- }
-
- mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
- BN_copy(bn_glb7, bn_glb1);
- BN_copy(bn_glb1, bn_glb_b);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-
- mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-
- mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3);
-
- mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3);
- mod_sub();
- if(arg0 == 0) {
- BN_copy(bn_glb_b, bn_glb1);
- BN_copy(bn_glb_c, bn_glb_g);
- } else {
- BN_copy(bn_glb_f, bn_glb1);
- BN_copy(bn_glb_f, bn_glb_g);
- }
-}
-
-//uses 3, 6, a, b, c, d, e, k
-//sets 0, 1, 5, 7, a, b, c, f, g, h, i, j
-void cN2Map57::bn_func3(int arg0)
-{
- BN_copy(bn_glb1, bn_glb_c);
- BN_copy(bn_glb7, bn_glb1);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-
- bn_cmplx1(bn_glb0, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
- BN_copy(bn_glb_f, bn_glb0);
- BN_copy(bn_glb5, bn_glb_d);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
- BN_copy(bn_glb7, bn_glb1);
- mod_sub();
- BN_copy(bn_glb0, bn_glb_a);
-
- mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3);
- BN_copy(bn_glb_g, bn_glb1);
- BN_copy(bn_glb5, bn_glb_c);
-
- bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
- if(arg0 == 0) {
- BN_copy(bn_glb_c, bn_glb0);
- } else {
- BN_copy(bn_glb_g, bn_glb0);
- }
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
- BN_copy(bn_glb_h, bn_glb1);
- BN_copy(bn_glb0, bn_glb_a);
-
- mod_add(bn_glb0, bn_glb0, bn_glb7, bn_glb3);
- BN_copy(bn_glb7, bn_glb0);
-
- //NOTE: don't 'mod' bn_glb1, but DO 'mod' glb_i
- bn_cmplx1(bn_glb7, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
- bn_cmplx1a(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
- BN_copy(bn_glb_i, bn_glb7);
- BN_copy(bn_glb1, bn_glb_e);
- BN_copy(bn_glb5, bn_glb_f);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
- BN_copy(bn_glb_f, bn_glb1);
- mod_sub();
- BN_copy(bn_glb0, bn_glb_b);
-
- mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3);
- BN_copy(bn_glb_j, bn_glb1);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
- BN_copy(bn_glb0, bn_glb1);
- BN_copy(bn_glb1, bn_glb7);
- BN_copy(bn_glb7, bn_glb0);
- mod_sub();
-
- mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3);
- if(arg0 == 0) {
- BN_copy(bn_glb_a, bn_glb1);
- } else {
- BN_copy(bn_glb_f, bn_glb1);
- }
-
- mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3);
- mod_sub();
- BN_copy(bn_glb7, bn_glb_i);
-
- mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3);
- BN_copy(bn_glb5, bn_glb_j);
-
- bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
- BN_copy(bn_glb1, bn_glb_f);
- BN_copy(bn_glb_f, bn_glb0);
- BN_copy(bn_glb7, bn_glb_b);
-
- mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3);
- BN_copy(bn_glb7, bn_glb1);
- BN_copy(bn_glb1, bn_glb_g);
- BN_copy(bn_glb5, bn_glb_h);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
- mod_sub();
- BN_copy(bn_glb7, bn_glb_f);
-
- mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3);
- BN_copy(bn_glb5, bn_glb_k);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
- if(arg0 == 0) {
- BN_copy(bn_glb_b, bn_glb1);
- } else {
- BN_copy(bn_glb_f, bn_glb1);
- }
-}
-
-//uses c, d, e, m
-//sets 0, a, b, c
-void cN2Map57::bn_cmplx7()
-{
- BIGNUM *var1;
- var1 = BN_new();
- BN_copy(bn_glb0, bn_glb_c);
- if(BN_is_zero(bn_glb_c)) {
- BN_copy(bn_glb_a, bn_glb_d);
- BN_copy(bn_glb_b, bn_glb_e);
- BN_copy(bn_glb_c, bn_glb_m);
- bn_func3(1);
- } else {
- BN_clear(var1);
- BN_set_word(var1, 0xFFFFFFFF);
- BN_mask_bits(bn_glb_a, 32);
- BN_lshift(var1, bn_glb_m, 0x20);
- BN_add(bn_glb_a, bn_glb_a, var1);
- BN_mask_bits(bn_glb_a, 128);
- bn_func3(0);
- }
- BN_free(var1);
-}
-
-void cN2Map57::bn_cmplx2(BIGNUM *var1, BIGNUM *var2, BIGNUM *var3, BIGNUM *var4, BIGNUM *var5, BIGNUM *var6)
-{
- BIGNUM *var48;
- int len = BN_num_bits(var6);
- int i;
- if(len < 2)
- return;
-
- if(BN_is_zero(var2) && BN_is_zero(var3) && BN_is_zero(var4))
- return;
- var48 = BN_new();
- BN_copy(bn_glb3, var1);
-
- BN_copy(bn_glb6, bn_glb3);
- BN_set_bit(bn_glb6, 0);
- BN_sub(bn_glb6, glb2pow128, bn_glb6);
- BN_mod_inverse(bn_glb6, bn_glb6, glb2pow64, t1);
- BN_clear(bn_glb0);
- //
- if(! BN_is_zero(bn_glb3)) {
- BN_clear(bn_glb1);
- BN_set_word(bn_glb1, 2);
- BN_clear(bn_glb_k);
- BN_set_word(bn_glb_k, 0x88);
- BN_mod_exp(bn_glb1, bn_glb1, bn_glb_k, bn_glb3, t1);
- }
- //
- for(i=0; i < 4; i++) {
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
- }
- //
- BN_clear(bn_glb7);
- BN_set_word(bn_glb7, 1);
- BN_add(bn_glb0, bn_glb3, bn_glb7);
- BN_copy(bn_glb_k, bn_glb0);
- BN_rshift(bn_glb_k, bn_glb_k, 1);
- BN_copy(bn_glb7, bn_glb1);
- BN_copy(bn_glb5, bn_glb_k);
- BN_mask_bits(bn_glb5, 128);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
- BN_copy(bn_glb_k, bn_glb1);
-
- BN_copy(bn_glb1, var5);
- BN_mask_bits(bn_glb1, 128);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
- BN_copy(bn_glb_l, bn_glb1);
- BN_copy(bn_glb1, bn_glb7);
- BN_clear(bn_glb5);
- BN_set_word(bn_glb5, 1);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
- BN_copy(bn_glb_c, bn_glb1);
- BN_copy(bn_glb_m, bn_glb1);
- BN_copy(bn_glb1, bn_glb7);
-
- BN_copy(bn_glb5, var2);
- BN_mask_bits(bn_glb5, 128);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
- BN_copy(bn_glb_a, bn_glb1);
- BN_copy(bn_glb1, bn_glb7);
-
- BN_copy(bn_glb5, var3);
- BN_mask_bits(bn_glb5, 128);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
- BN_copy(bn_glb_b, bn_glb1);
- BN_copy(bn_glb_d, bn_glb_a);
- BN_copy(bn_glb_e, bn_glb_b);
-
- int x = len -1;
- while(x > 0) {
- x--;
- bn_func2(0);
- if(BN_is_bit_set(var6, x)) {
- bn_cmplx7();
- }
- }
-
- BN_copy(bn_glb1, bn_glb_c);
- BN_mask_bits(bn_glb1, 128);
- BN_copy(bn_glb7, bn_glb1);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
- BN_clear(bn_glb7);
- BN_set_word(bn_glb7, 1);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
- BN_copy(bn_glb0, bn_glb1);
- BN_clear(bn_glb7);
- BN_set_word(bn_glb7, 1);
- BN_copy(bn_glb1, bn_glb0);
- BN_clear(bn_glb0);
- bn_func1(var1);
- BN_copy(bn_glb5, bn_glb_b);
- BN_mask_bits(bn_glb5, 128);
-
- bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-
- BN_copy(bn_glb7, bn_glb0);
- BN_copy(bn_glb5, bn_glb_c);
- BN_mask_bits(bn_glb5, 128);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-
- BN_copy(bn_glb5, bn_glb_a);
- BN_mask_bits(bn_glb5, 128);
-
- bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-
- BN_clear(bn_glb5);
- BN_set_word(bn_glb5, 1);
-
- bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
- BN_copy(bn_glb_a, bn_glb0);
- BN_copy(bn_glb1, bn_glb7);
-
- BN_clear(bn_glb5);
- BN_set_word(bn_glb5, 1);
-
- bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
- BN_copy(bn_glb_b, bn_glb0);
- BN_free(var48);
-}
-
-void cN2Map57::Map57(unsigned char *data)
-{
- BIGNUM *var38, *var58, *var78, *var98, *varb8, *vard8;
- BN_CTX *t;
- unsigned char tmpdata[256];
- unsigned char res[256];
-
- t = BN_CTX_new();
- t1 = BN_CTX_new();
- BN_CTX_init(t);
-
- glb2pow128 = BN_new();
- BN_clear(glb2pow128);
- BN_set_bit(glb2pow128, 128);
- mask128 = BN_new();
- BN_hex2bn(&mask128, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
-
- glb2pow64 = BN_new();
- BN_clear(glb2pow64);
- BN_set_bit(glb2pow64, 64);
- mask64 = BN_new();
- BN_hex2bn(&mask64, "FFFFFFFFFFFFFFFF");
-
- bn_glb0=BN_new(); BN_clear(bn_glb0);
- bn_glb1=BN_new(); BN_clear(bn_glb1);
- bn_glb3=BN_new(); BN_clear(bn_glb3);
- bn_glb5=BN_new(); BN_clear(bn_glb5);
- bn_glb6=BN_new(); BN_clear(bn_glb6);
- bn_glb7=BN_new(); BN_clear(bn_glb7);
-
- bn_glb_a=BN_new(); BN_clear(bn_glb_a);
- bn_glb_b=BN_new(); BN_clear(bn_glb_b);
- bn_glb_c=BN_new(); BN_clear(bn_glb_c);
- bn_glb_d=BN_new(); BN_clear(bn_glb_d);
- bn_glb_e=BN_new(); BN_clear(bn_glb_e);
- bn_glb_f=BN_new(); BN_clear(bn_glb_f);
- bn_glb_g=BN_new(); BN_clear(bn_glb_g);
- bn_glb_h=BN_new(); BN_clear(bn_glb_h);
- bn_glb_i=BN_new(); BN_clear(bn_glb_i);
- bn_glb_j=BN_new(); BN_clear(bn_glb_j);
- bn_glb_k=BN_new(); BN_clear(bn_glb_k);
- bn_glb_l=BN_new(); BN_clear(bn_glb_l);
- bn_glb_m=BN_new(); BN_clear(bn_glb_m);
-
- var38=BN_new(); BN_clear(var38);
- var58=BN_new(); BN_clear(var58);
- var78=BN_new(); BN_clear(var78);
- var98=BN_new(); BN_clear(var98);
- varb8=BN_new(); BN_clear(varb8);
- vard8=BN_new(); BN_clear(vard8);
-
- memcpy(tmpdata, data, 0x60);
- RotateBytes(tmpdata, 0x60);
- BN_bin2bn(tmpdata, 16, var98);
- BN_bin2bn(tmpdata+0x10, 16, var78);
- BN_bin2bn(tmpdata+0x20, 16, var38);
- BN_bin2bn(tmpdata+0x30, 16, vard8);
- BN_bin2bn(tmpdata+0x40, 16, var58);
- BN_bin2bn(tmpdata+0x50, 16, varb8);
-
- bn_cmplx2(varb8, var58, vard8, var38, var78, var98);
-
- memset(res, 0, 0x80);
- unsigned int *dest = (unsigned int *)res, *src = (unsigned int *)data;
- *dest++ = src[0x03];
- *dest++ = src[0x02];
- *dest++ = src[0x01];
- *dest++ = src[0x00];
- *dest++ = src[0x07];
- *dest++ = src[0x06];
- *dest++ = src[0x05];
- *dest++ = src[0x04];
-
- memset(tmpdata, 0, 0x20);
- int len = BN_bn2bin(bn_glb_a, tmpdata);
- if(len) {
- RotateBytes(tmpdata, len);
- }
- src = (unsigned int *)tmpdata;
- *dest++ = src[0x03];
- *dest++ = src[0x02];
- *dest++ = src[0x01];
- *dest++ = src[0x00];
-
- memset(tmpdata, 0, 0x20);
- len = BN_bn2bin(bn_glb_m, tmpdata);
- if(len) {
- RotateBytes(tmpdata, len);
- }
- *dest = src[0x03];
- dest+=4;
-
- memset(tmpdata, 0, 0x20);
- len = BN_bn2bin(bn_glb_b, tmpdata);
- if(len) {
- RotateBytes(tmpdata, len);
- }
- *dest++ = src[0x03];
- *dest++ = src[0x02];
- *dest++ = src[0x01];
- *dest++ = src[0x00];
-
- dest+=4;
- src = (unsigned int *)(data+0x60);
- *dest++ = src[0x03];
- *dest++ = src[0x02];
- *dest++ = src[0x01];
- *dest++ = src[0x00];
- *dest++ = src[0x07];
- *dest++ = src[0x06];
- *dest++ = src[0x05];
- *dest++ = src[0x04];
-
- *(unsigned int *)(data + (0<<2))= *(unsigned int *)(res + (11<<2));
- *(unsigned int *)(data + (1<<2))= *(unsigned int *)(res + (10<<2));
- *(unsigned int *)(data + (2<<2))= *(unsigned int *)(res + (9<<2));
- *(unsigned int *)(data + (3<<2))= *(unsigned int *)(res + (8<<2));
- *(unsigned int *)(data + (4<<2))= *(unsigned int *)(res + (12<<2));
- *(unsigned int *)(data + (5<<2))= *(unsigned int *)(res + (13<<2));
- *(unsigned int *)(data + (6<<2))= *(unsigned int *)(res + (14<<2));
- *(unsigned int *)(data + (7<<2))= *(unsigned int *)(res + (15<<2));
- *(unsigned int *)(data + (8<<2))= *(unsigned int *)(res + (19<<2));
- *(unsigned int *)(data + (9<<2))= *(unsigned int *)(res + (18<<2));
- *(unsigned int *)(data + (10<<2))= *(unsigned int *)(res + (17<<2));
- *(unsigned int *)(data + (11<<2))= *(unsigned int *)(res + (16<<2));
- *(unsigned int *)(data + (12<<2))= *(unsigned int *)(res + (20<<2));
- *(unsigned int *)(data + (13<<2))= *(unsigned int *)(res + (21<<2));
- *(unsigned int *)(data + (14<<2))= *(unsigned int *)(res + (22<<2));
- *(unsigned int *)(data + (15<<2))= *(unsigned int *)(res + (23<<2));
-
- BN_free(glb2pow128);
- BN_free(mask128);
- BN_free(glb2pow64);
- BN_free(mask64);
-
- BN_free(bn_glb0);
- BN_free(bn_glb1);
- BN_free(bn_glb3);
- BN_free(bn_glb5);
- BN_free(bn_glb6);
- BN_free(bn_glb7);
-
- BN_free(bn_glb_a);
- BN_free(bn_glb_b);
- BN_free(bn_glb_c);
- BN_free(bn_glb_d);
- BN_free(bn_glb_e);
- BN_free(bn_glb_f);
- BN_free(bn_glb_g);
- BN_free(bn_glb_h);
- BN_free(bn_glb_i);
- BN_free(bn_glb_j);
- BN_free(bn_glb_k);
- BN_free(bn_glb_l);
- BN_free(bn_glb_m);
-
- BN_free(var38);
- BN_free(var58);
- BN_free(var78);
- BN_free(var98);
- BN_free(varb8);
- BN_free(vard8);
-
- BN_CTX_free(t);
- BN_CTX_free(t1);
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "system.h"
-#include "opts.h"
-#include "log-core.h"
-#include "debug.h"
-#include "cpu.h"
-#include "stdio.h"
-#include "math.h"
-
-#include "nagra.h"
-#include "nagra2.h"
-
-#define SYSTEM_NAME "Nagra2"
-#define SYSTEM_PRI -10
-
-// -- cN2Timer -----------------------------------------------------------------
-
-cN2Timer::cN2Timer(): cpu(0)
-{
- cycles=intrCycles=0; ctrl=0; val=0; divisor=0; invDivisor=0; timerBugged = false; latch=0xFF;
- delayInterrupt = 0;
-}
-
-double cN2Timer::GetDivisor()
-{
- int prescalar = ((ctrl&0x38)>>3)+1;
- double divisor = pow(4.0, prescalar);
- double multiplier;
-
- // multipliers for 0 and 2 aren't correct yet
- switch((ctrl&0xc0)>>6) {
- case 0: multiplier = 10.3f; break;
- case 1: multiplier = 1.0f; break;
- case 2: multiplier = 6.375f; break;
- default:multiplier = 0;
- }
-
- return divisor * multiplier;
-}
-
-void cN2Timer::Update()
-{
- int rlatch = latch;
-
- if(divisor) {
- if(timerBugged && cycles>=0x100 * divisor) {
- timerBugged = false;
- cycles -= 0x101 * divisor;
- }
- if(timerBugged) rlatch = 0x100;
-
- unsigned int v = cycles * invDivisor;
- if(ctrl&tmCONTINUOUS) {
- val = rlatch - (v % (rlatch+1));
- if(InterruptSet() && val==0) {
- intrCycles = cycles + (unsigned int)((val?val:latch)*divisor);
- }
- } else {
- // one-shot
- if(v>=rlatch) {
- val = 0;
- if(Running() && ((cycles - 2) * invDivisor)>=rlatch)
- Stop();
- } else
- val = rlatch - v;
- }
- } else
- val = 0;
-}
-
-bool cN2Timer::AddCycles(unsigned int count)
-{
- bool irq = false;
- if(Running()) {
- cycles += count;
- if(!delayInterrupt && InterruptSet() && cycles>=intrCycles) {
- delayInterrupt = intrCycles-cycles;
- if(delayInterrupt < 0)
- delayInterrupt = count;
- else
- delayInterrupt += count;
- intrCycles = 0;
- if((ctrl&tmCONTINUOUS)) Update();
- }
- }
-
- if(delayInterrupt) {
- delayInterrupt -= count;
- if(delayInterrupt < 0)
- delayInterrupt = 0;
- if(!delayInterrupt) {
- Update();
- irq = true;
- }
- }
- return irq;
-}
-
-unsigned int cN2Timer::Cycles()
-{
- if(Running()) Update();
- PRINTF(L_SYS_EMU,"n2timer read %u @ %02x:%04x: %u %02x %02x = %02x", id, cpu?cpu->GetCr():0, cpu?cpu->GetPc():0, cycles, ctrl&0xff, latch&0xff, val);
- return val;
-}
-
-unsigned char cN2Timer::Ctrl()
-{
- if(Running()) Update();
- return ctrl;
-}
-
-void cN2Timer::Latch(unsigned char val)
-{
- if(!Running()) {
- latch=val; if(latch==0) latch=0x100;
- cycles=0;
- ctrl|=tmLATCHED;
- timerBugged = false;
- }
-}
-
-void cN2Timer::Ctrl(unsigned char val)
-{
- if(Running()) {
- ctrl=(ctrl&~tmRUNNING) | (val&tmRUNNING);
- if(!Running()) {
- Stop();
- --cycles;
- Update();
- PRINTF(L_SYS_EMU,"n2timer %u: stopped cycles=%d (%02x) ctrl=%02x latch=%02x",id,cycles,val,ctrl,latch&0xff);
- }
- }
- else {
- ctrl=(ctrl&~tmMASK) | (val&tmMASK);
- divisor = GetDivisor();
- if(divisor) invDivisor = 1.0 / divisor;
- if(Running()) {
- if(!(ctrl&tmLATCHED) && divisor>0) {
- if(this->val==0) {
- timerBugged = true;
- cycles = (unsigned int)divisor;
- } else {
- cycles = (unsigned int)(((timerBugged?0x100:latch)-this->val+1) * divisor);
- }
- }
- if((ctrl&tmINTERRUPT)) {
- intrCycles = cycles + (unsigned int)((timerBugged?0x101:this->val?this->val:latch)*divisor);
- if(id==2) PRINTF(L_SYS_MAP,"Timer %d set for %u cycles (%02x %02x)", id, intrCycles-cycles, Latch(), ctrl&0xff);
- }
- ctrl &= ~tmLATCHED;
- }
- }
-}
-
-void cN2Timer::Stop(void)
-{
- ctrl&=~(tmRUNNING|tmLATCHED);
- if(delayInterrupt>=3)
- delayInterrupt = 0;
-}
-
-// -- cMapMemHW ----------------------------------------------------------------
-
-//#define CRC_POLY 0x8408 // ccitt poly
-
-
-cMapMemHW::cMapMemHW(c6805& _cpu)
-:cMapMem(HW_OFFSET,HW_REGS),cpu(_cpu)
-{
- CRCvalue=0xffff; CRCit=CRCCALC_DELAY+1; CRCpos=0; CRCtime=0;
- GenCRC16Table();
- for(int i=0; i<MAX_TIMERS; ++i)
- timer[i].SetId((i+1)%3, &cpu);
- PRINTF(L_SYS_EMU,"mapmemhw: new HW map off=%04x size=%04x",offset,size);
-
- Set(HW_IO, 0xfe); // IO
- Set(HW_CRC_CONTROL, CRC_DISABLED); // CRC disabled
- Set(HW_TIMER0_LATCH, 0x00); // initialize timer0 latch
- Set(HW_TIMER1_LATCH, 0x00); // initialize timer1 latch
- Set(HW_TIMER2_LATCH, 0x00); // initialize timer2 latch
- Set(HW_TIMER0_CONTROL, 0x00); // disable timer0
- Set(HW_TIMER1_CONTROL, 0x00); // disable timer1
- Set(HW_TIMER2_CONTROL, 0x00); // disable timer2
-}
-
-void cMapMemHW::GenCRC16Table()
-{
- for(int i=0; i<256; ++i) {
- unsigned short c = i;
- for(int j=0; j<8; ++j)
- c = (c>>1) ^ ((c&1) ? CRC_POLY : 0);
- CRC16table[i] = c;
- }
-}
-
-unsigned short cMapMemHW::CRCcalculate(unsigned short crc, unsigned char val, int bits)
-{
- if(bits>=8) return (crc>>8)^CRC16table[(crc^val)&0xff];
- if(bits>0) crc ^= (val&(0xff>>(8-bits)));
- for(int i=0; i<bits; ++i)
- crc = (crc>>1) ^ ((crc&1) ? CRC_POLY : 0);
- return crc;
-}
-
-void cMapMemHW::CRCupdate(unsigned int cycles)
-{
- if(!(mem[HW_CRC_CONTROL-offset]&CRC_DISABLED) && CRCit<=CRCCALC_DELAY) {
- int elapsed = cycles-CRCtime;
- CRCtime = cycles;
- int it = CRCit;
- unsigned char val = mem[HW_CRC_DATA-offset];
- if((CRCit+=elapsed)>CRCCALC_DELAY) // > instead of >= because of CRC_BUSY lockout
- CRCit = CRCCALC_DELAY+1;
- if(it==0 && CRCit>=CRCCALC_DELAY)
- CRCvalue = (CRCvalue>>8)^CRC16table[(CRCvalue^val)&0xff];
- else
- for(int i=it; i<CRCit && i<CRCCALC_DELAY; ++i)
- CRCvalue = (CRCvalue>>1) ^ (((CRCvalue^(val>>i))&1) ? CRC_POLY : 0);
- }
-}
-
-int cMapMemHW::AddCycles(unsigned int num)
-{
- int mask=0;
- for(int i=0; i<MAX_TIMERS; i++)
- if(timer[i].AddCycles(num)) mask |= 1<<timer[i].Id();
- return mask;
-}
-
-unsigned char cMapMemHW::Get(unsigned short ea)
-{
- if(ea<offset || ea>=offset+size) return 0;
- ea-=offset;
- switch(ea) {
- case HW_SECURITY:
- return (mem[ea]&0x70)|0x0f;
- case HW_TIMER0_CONTROL:
- case HW_TIMER1_CONTROL:
- case HW_TIMER2_CONTROL:
- return timer[TIMER_NUM(ea)].Ctrl();
- case HW_TIMER0_DATA:
- case HW_TIMER1_DATA:
- case HW_TIMER2_DATA:
- return timer[TIMER_NUM(ea)].Cycles();
- case HW_TIMER0_LATCH:
- case HW_TIMER1_LATCH:
- case HW_TIMER2_LATCH:
- return timer[TIMER_NUM(ea)].Latch();
- case HW_CRC_CONTROL:
- {
- unsigned char r=mem[ea];
- CRCupdate(cpu.Cycles());
- if(CRCit<CRCCALC_DELAY) r |= CRC_BUSY;
- else r &= ~CRC_BUSY;
- return r|0x80;
- }
- case HW_CRC_DATA:
- {
- CRCupdate(cpu.Cycles());
- unsigned char r=(CRCvalue^0xffff)>>((CRCpos&1)<<3);
- CRCpos^=1;
- return r;
- }
- default:
- return mem[ea];
- }
-}
-
-void cMapMemHW::Set(unsigned short ea, unsigned char val)
-{
- if(ea<offset || ea>=offset+size) return;
- ea-=offset;
- switch(ea) {
- case HW_TIMER0_CONTROL:
- case HW_TIMER1_CONTROL:
- case HW_TIMER2_CONTROL:
- timer[TIMER_NUM(ea)].Ctrl(val);
- break;
- case HW_TIMER0_LATCH:
- case HW_TIMER1_LATCH:
- case HW_TIMER2_LATCH:
- timer[TIMER_NUM(ea)].Latch(val);
- break;
- case HW_CRC_CONTROL:
- if((mem[ea]&CRC_DISABLED)) {
- if(!(val&CRC_DISABLED)) {
- CRCvalue=0xffff; CRCpos=0; CRCtime=cpu.Cycles();
- if(CRCit<=CRCCALC_DELAY) {
- ++CRCtime;
- ++CRCit;
- }
- }
- } else if((val&CRC_DISABLED)) {
- CRCupdate(cpu.Cycles());
- }
- mem[ea]=val;
- break;
- case HW_CRC_DATA:
- CRCupdate(cpu.Cycles());
- if(CRCit>CRCCALC_DELAY) {
- if(!(mem[HW_CRC_CONTROL-offset]&CRC_DISABLED)) {
- mem[ea] = val;
- CRCit = 0;
- CRCtime=cpu.Cycles();
- }
- }
- break;
- default:
- mem[ea]=val;
- break;
- }
-}
-
-// -- cN2Emu -------------------------------------------------------------------
-
-cN2Emu::cN2Emu(void)
-{
- initDone=false;
-}
-
-bool cN2Emu::Init(int id, int romv)
-{
- if(!initDone) {
- ResetMapper();
- char buff[256];
- snprintf(buff,sizeof(buff),"ROM%d.bin",romv);
- // UROM 0x00:0x4000-0x7fff
- if(!AddMapper(new cMapRom(0x4000,buff,0x00000),0x4000,0x4000,0x00)) return false;
- // ROM00 0x00:0x8000-0xffff
- if(!AddMapper(new cMapRom(0x8000,buff,0x04000),0x8000,0x8000,0x00)) return false;
- // ROM01 0x01:0x8000-0xffff
- if(!AddMapper(new cMapRom(0x8000,buff,0x0C000),0x8000,0x8000,0x01)) return false;
- // ROM02 0x02:0x8000-0xbfff
- if(!AddMapper(new cMapRom(0x8000,buff,0x14000),0x8000,romv>=110?0x8000:0x4000,0x02)) return false;
-
- snprintf(buff,sizeof(buff),"EEP%02X_%d.bin",(id>>8)&0xFF|0x01,romv);
- // Eeprom00 0x00:0x3000-0x37ff OTP 0x80
- //XXX if(!AddMapper(new cMapRom(0x3000,buff,0x0000),0x3000,0x0800,0x00)) return false;
- if(!AddMapper(new cMapEeprom(0x3000,buff,128,0x0000),0x3000,0x0800,0x00)) return false;
- // Eeprom80 0x80:0x8000-0xbfff
- //XXX if(!AddMapper(new cMapRom(0x8000,buff,0x0800),0x8000,0x4000,0x80)) return false;
- if(!AddMapper(new cMapEeprom(0x8000,buff, 0,0x0800),0x8000,0x4000,0x80)) return false;
- initDone=RomInit();
- }
- return initDone;
-}
-
-// -- cMapReg ------------------------------------------------------------------
-
-cMapReg::cMapReg(int *_defwordsize, int _maxwordsize): wordsize(DEF_WORDSIZE),maxwordsize(_maxwordsize),
- defwordsize(_defwordsize)
-{
-}
-
-BIGNUM* cMapReg::Value(int wsize, bool mask)
-{
- wsize = OpWordSize(wsize);
- if(wordsize!=wsize) {
- Commit();
- Reload();
- } else if(mask) {
- BN_mask_bits(reg, wsize*64);
- }
- return reg;
-}
-
-void cMapReg::ClearReg(int wsize)
-{
- BN_rshift(reg,reg,wsize*64);
- BN_lshift(reg,reg,wsize*64);
-}
-
-void cMapReg::ClearFullReg(int wsize)
-{
- BN_rshift(fullreg,fullreg,wsize*64);
- BN_lshift(fullreg,fullreg,wsize*64);
-}
-
-void cMapReg::SetTmp(BIGNUM* val, int wsize)
-{
- if(val->neg) {
- BN_clear(tmp);
- BN_set_bit(tmp,wsize*64);
- BN_add(tmp,tmp,val);
- } else
- BN_copy(tmp,val);
- BN_mask_bits(tmp,wsize*64);
-}
-
-void cMapReg::Commit(int wsize, int resync)
-{
- if(resync<0 && wsize<0) resync = 1;
- wsize = OpWordSize(wsize>=0?wsize:wordsize);
- ClearFullReg(wsize);
- SetTmp(reg,wsize);
- BN_add(fullreg, fullreg, tmp);
- if(resync) {
- if(wordsize==wsize) BN_mask_bits(reg, wsize*64);
- else wordsize = wsize;
- }
-}
-
-void cMapReg::Reload(int wsize)
-{
- wsize = OpWordSize(wsize>=0?wsize:wordsize);
- wordsize = wsize;
- BN_copy(reg, fullreg);
- BN_mask_bits(reg, 64*wsize);
-}
-
-void cMapReg::GetLE(const unsigned char *in, int n)
-{
- int wsize = OpWordSize(n<=0?n:(n+7)/8);
- if(wordsize>wsize) Commit();
- reg.GetLE(in, 8*wsize);
- Commit(wsize);
-}
-
-void cMapReg::PutLE(unsigned char* out, int n)
-{
- int wsize = OpWordSize(n<=0?n:(n+7)/8);
- Commit();
- fullreg.PutLE(out, 8*wsize);
-}
-
-void cMapReg::Set(BIGNUM* val, int wsize)
-{
- wsize = OpWordSize(wsize);
- if(wordsize!=wsize) Commit();
- ClearReg(wsize);
- SetTmp(val,wsize);
- if(wordsize!=wsize) {
- ClearFullReg(wsize);
- BN_add(fullreg, fullreg, tmp);
- }
- BN_add(reg, reg, tmp);
-}
-
-void cMapReg::Clear(int wsize)
-{
- wsize = OpWordSize(wsize);
- if(wordsize!=wsize) {
- Commit();
- ClearFullReg(wsize);
- }
- ClearReg(wsize);
-}
-
-// -- cMapMath -----------------------------------------------------------------
-
-cMapMath::cMapMath(): A(&wordsize),B(&wordsize),C(&wordsize),D(&wordsize),J(NULL,1),I(&wordsize)
-{
- wordsize = 4;
-}
-bool cMapMath::ModAdd(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *d)
-{
- bool ret = false;
- BN_add(r,a,b);
- if(BN_cmp(r,d)>=0) {
- BN_sub(r,r,d);
- ret = true;
- }
- BN_mask_bits(r,wordsize<<6);
- return ret;
-}
-
-bool cMapMath::ModSub(BIGNUM *r, BIGNUM *d, BIGNUM *b)
-{
- cBN p;
- bool ret = BN_cmp(d, b)<0;
- BN_set_bit(p,wordsize<<6);
- BN_mod_sub(r,d,b,p,ctx);
- BN_mask_bits(r,wordsize<<6);
- return ret;
-}
-
-void cMapMath::MakeJ0(BIGNUM *j, BIGNUM *d, BIGNUM* c, int bits)
-{
-#if OPENSSL_VERSION_NUMBER < 0x0090700fL
-#error BN_mod_inverse is probably buggy in your openssl version
-#endif
- BN_zero(x);
- BN_sub(j,x,d);
- j->neg = 1;
- BN_set_bit(j,0);
- BN_set_bit(x,bits);
- BN_mod_inverse(j,j,x,ctx);
- if(c) {
- BN_copy(c,d);
- BN_mask_bits(c,bits);
- BN_mul(c,j,c,ctx);
- BN_rshift(c,c,bits);
- BN_mask_bits(c,bits);
- }
-}
-
-void cMapMath::MonMul0(BIGNUM *o, BIGNUM *a, BIGNUM *b, BIGNUM *c, BIGNUM *d, BIGNUM *j, int words)
-{
- if(words<=0) words = wordsize;
- BN_zero(s);
- for(int i=0; --words>=0; ) {
- BN_rshift(x,a,(i++)<<6);
- BN_mask_bits(x,64);
- BN_mul(x,x,b,ctx);
- BN_add(s,s,x);
-
- BN_copy(x,s);
- BN_mask_bits(x,64);
- BN_mul(x,x,j,ctx);
- if(!words) {
- BN_lshift(y,x,64);
- BN_add(y,y,x);
- // Low
- BN_rshift(c,y,2);
- BN_add(c,c,s);
- BN_rshift(c,c,52);
- BN_mask_bits(c,12);
- }
-
- BN_mask_bits(x,64);
- BN_mul(x,x,d,ctx);
- BN_add(s,s,x);
- if(!words) {
- // High
- BN_lshift(y,s,12);
- BN_add(c,c,y);
- BN_mask_bits(c,wordsize<<6);
- }
-
- BN_rshift(s,s,64);
- if(words && BN_cmp(s,d)>=0) {
- BN_copy(x,s);
- BN_sub(s,x,d);
- }
- }
- BN_copy(o,s);
-}
-
-void cMapMath::MonMulFin(BIGNUM *o, BIGNUM *d)
-{
- if(BN_cmp(o,d)>=0)
- BN_sub(o,o,d);
-}
-
-void cMapMath::MonMul(BIGNUM *o, BIGNUM *a, BIGNUM *b, BIGNUM *c, BIGNUM *d, BIGNUM *j, int words)
-{
- MonMul0(o, a, b, c, d, j, words);
- MonMulFin(o, d);
-}
-
-
-// -- cMapCore -----------------------------------------------------------------
-
-cMapCore::cMapCore(void)
-{
- last=1; mapid=0;
- regs[0]=&J; regs[1]=&A; regs[2]=&B; regs[3]=&C; regs[4]=&D;
- interruptible=false;
-}
-
-void cMapCore::ImportReg(unsigned char reg, const unsigned char *in, int l)
-{
- int dl=(l>0?l:wordsize)<<3;
- cBN tmp;
- switch(reg) {
- case IMPORT_J:
- case IMPORT_A:
- case IMPORT_B:
- case IMPORT_C:
- case IMPORT_D:
- last = reg-IMPORT_J;
- // fall through
- case IMPORT_LAST:
- regs[last]->GetLE(in+(last>0?0:dl-8),last>0?dl:8);
- break;
- default: PRINTF(L_SYS_MAP,"internal: nagramap import register not supported"); return;
- }
-}
-
-void cMapCore::ExportReg(unsigned char reg, unsigned char *out, int l)
-{
- int dl=(l>0?l:wordsize)<<3;
- switch(reg) {
- case EXPORT_J:
- case EXPORT_A:
- case EXPORT_B:
- case EXPORT_C:
- case EXPORT_D:
- last = reg-EXPORT_J;
- // fall through
- case EXPORT_LAST:
- regs[last]->PutLE(out,last>0?dl:8);
- if(reg==EXPORT_LAST && last==0)
- for(int i=8; i<dl; i+=8) memcpy(out+i,out,8);
- break;
- default: PRINTF(L_SYS_MAP,"internal: nagramap export register not supported"); return;
- }
-}
- void cMapCore::MonInit(int bits)
-{
- // Calculate J0 & H montgomery elements in J and B
- MakeJ0(J,D);
- BN_zero(I);
- BN_set_bit(I,bits ? bits : 68*wordsize);
- BN_mod(B,I,D,ctx);
- for(int i=0; i<4; i++) MonMul(B,B,B);
-}
-
-void cMapCore::MonExp(BIGNUM *scalar)
-{
- if(BN_is_zero(D)) { BN_one(A); return; }
- BN_copy(A,B);
- for(int i=BN_num_bits(scalar)-2; i>-1; i--) {
- MonMul(B,B,B);
- if(BN_is_bit_set(scalar,i)) MonMul(B,A,B);
- }
- BN_one(A);
- MonMul(B,A,B);
-}
-
-void cMapCore::MonExpNeg(void)
-{
- if(BN_is_zero(D)) { BN_set_word(A,1); return; }
- BN_copy(e,D);
- BN_mask_bits(e,8); // check LSB
- unsigned int n=BN_get_word(e);
- BN_copy(e,D);
- if(n) BN_sub_word(e,0x02); // N -2
- else BN_add_word(e,0xFE); // N + 254 ('carryless' -2)
- BN_copy(A,B);
- for(int i=BN_num_bits(e)-2; i>-1; i--) {
- MonMul(B,B,B);
- if(BN_is_bit_set(e,i)) MonMul(B,A,B);
- }
- if(BN_is_bit_set(D,0)) {
- int i;
- for(i=BN_num_bits(D)-2; i>0; i--) if(BN_is_bit_set(D,i)) break;
- if(i<=0) {
- MonMul(B,B,B);
- MonMul(B,A,B);
- }
- }
- BN_set_word(A,1);
- MonMul(B,A,B);
-}
-
-void cMapCore::DoubleP(int temp)
-{
- ModAdd(B,Py,Py,D);
- MonMul(sC0,Pz,B);
- MonMul(B,B,B);
- MonMul(B,Px,B);
- ModSub(sA0,D,B);
- MonMul(B,Px,Px);
- BN_copy(A,B);
- ModAdd(B,B,B,D);
- ModAdd(A,B,A,D);
- MonMul(B,Pz,Pz);
- MonMul(B,B,B);
- MonMul(B,s160,B);
- ModAdd(B,B,A,D);
- BN_copy(A,B);
- MonMul(B,B,B);
- BN_copy(C,sA0);
- ModAdd(B,C,B,D);
- ModAdd(B,C,B,D);
- if(temp==0) BN_copy(Px,B); else BN_copy(sA0,B);
- ModAdd(B,C,B,D);
- MonMul(B,A,B);
- BN_copy(A,B);
- MonMul(B,Py,Py);
- ModAdd(B,B,B,D);
- MonMul(B,B,B);
- ModAdd(B,B,B,D);
- ModAdd(B,B,A,D);
- ModSub(B,D,B);
- if(temp==0) { BN_copy(Py,B); BN_copy(Pz,sC0); }
- else BN_copy(sA0,sC0);
-}
-
-void cMapCore::AddP(int temp)
-{
- MonMul(B,Pz,Pz);
- MonMul(sA0,Pz,B);
- MonMul(B,Qx,B);
- BN_copy(A,B);
- ModSub(B,D,B);
- ModAdd(B,Px,B,D);
- BN_copy(sC0,B);
- MonMul(I,Pz,B);
- if(temp==0) BN_copy(Pz,I); else BN_copy(sA0,I);
- MonMul(B,B,B);
- BN_copy(sE0,B);
- ModAdd(A,Px,A,D);
- MonMul(A,A,B);
- BN_copy(s100,A);
- MonMul(B,sA0,Qy);
- BN_copy(sA0,B);
- ModSub(B,D,B);
- ModAdd(B,Py,B,D);
- BN_copy(s120,B);
- MonMul(B,B,B);
- BN_swap(A,B);
- ModSub(B,D,B);
- ModAdd(B,A,B,D);
- if(temp==0) BN_copy(Px,B); else BN_copy(sA0,B);
- ModAdd(B,B,B,D);
- ModSub(B,D,B);
- ModAdd(B,B,s100,D);
- ModAdd(A,sA0,Py,D);
- MonMul(sA0,s120,B);
- MonMul(B,sE0,sC0);
- MonMul(B,A,B);
- ModSub(B,D,B);
- ModAdd(B,B,sA0,D);
- MonMul(B,s140,B);
- if(temp==0) BN_copy(Py,B); else BN_copy(sA0,B);
-}
-
-void cMapCore::ToProjective(int set, BIGNUM *x, BIGNUM *y)
-{
- if(set==0) {
- BN_set_word(I,1); MonMul(Pz,I,B);
- BN_copy(Qz,Pz);
- MonMul(Px,x,B);
- MonMul(Py,y,B);
- }
- else {
- MonMul(Qx,x,B);
- MonMul(Qy,y,B);
- }
-}
-
-void cMapCore::ToAffine(void)
-{
- BN_set_word(I,1);
- MonMul(B,Pz,Pz); MonMul(B,Pz,B); MonMul(B,I,B);
- MonExpNeg();
- BN_set_word(I,1);
- MonMul(A,Py,B); MonMul(Py,I,A);
- MonMul(B,Pz,B); MonMul(B,Px,B); MonMul(Px,I,B);
-}
-
-void cMapCore::CurveInit(BIGNUM *a)
-{
- BN_zero(Px); BN_zero(Py); BN_zero(Pz); BN_zero(Qx); BN_zero(Qy); BN_zero(Qz);
- BN_zero(sA0); BN_zero(sC0); BN_zero(sE0); BN_zero(s100);
- BN_zero(s120); BN_zero(s140); BN_zero(s160);
- MonInit();
- BN_copy(A,B);
- BN_copy(I,D);
- BN_add_word(I,1);
- BN_mask_bits(I,wordsize<<6);
- BN_rshift(I,I,1);
- MonMul(s140,I,B);
- MonMul(s160,B,a);
-}
-
-int cMapCore::GetOpSize(int l)
-{
- return l!=0 ? l : wordsize;
-}
-
-void cMapCore::DoMap(int f, unsigned char *data, int l)
-{
- PRINTF(L_SYS_MAP,"%04x: calling function %02X",mapid,f);
- cycles=0;
- unsigned int startcycles=CpuCycles();
- interrupted=false; interruptible=true;
- try {
- if(!Map(f,data,l) && !MapGeneric(f,data,l))
- PRINTF(L_SYS_MAP,"%04x: unsupported call %02x",mapid,f);
- if(cycles) {
- unsigned int elapsed=CpuCycles()-startcycles;
- if(cycles>elapsed) AddMapCycles(cycles-elapsed);
- }
- } catch(int) { interrupted=true; }
- interruptible=false;
- cycles=CpuCycles()-startcycles;
-}
-
-bool cMapCore::MapGeneric(int f, unsigned char *data, int l)
-{
- const int l1=GetOpSize(l);
- const int dl=l1<<3;
- switch(f) {
- case SETSIZE:
- cycles=(l>17 ? 459 : (l ? 475 : 454))-6;
- if(l>=1 && l<=17) wordsize=l;
- break;
-
- case IMPORT_J:
- cycles=890-6;
- last=0;
- regs[0]->GetLE(data,8);
- break;
- case IMPORT_A:
- case IMPORT_B:
- case IMPORT_C:
- case IMPORT_D:
- if(l>17) { l=17; cycles+=5; }
- else if(l<=0) { l=wordsize; cycles+=4; }
- cycles+=771+160*l-6;
- last=f-IMPORT_J;
- regs[last]->GetLE(data,l<<3);
- break;
- case IMPORT_LAST:
- if(l>16) { l=1; cycles+=5; }
- else if(l<=0) l=1;
- cycles=656+160*l-6;
- regs[last]->GetLE(data,(last==0?1:l)<<3);
- break;
-
- case EXPORT_J:
- cycles=897-6;
- last=0;
- regs[0]->PutLE(data,8);
- break;
- case EXPORT_A:
- case EXPORT_B:
- case EXPORT_C:
- case EXPORT_D:
- if(l>17) { l=17; cycles+=5; }
- else if(l<=0) { l=wordsize; cycles+=4; }
- cycles=778+160*l-6;
- last=f-EXPORT_J;
- regs[last]->PutLE(data,l<<3);
- break;
- case EXPORT_LAST:
- if(l>16) { l=1; cycles+=5; }
- else if(l<=0) l=1;
- cycles=668+160*l-6;
- regs[last]->PutLE(data,(last==0?1:l)<<3);
- break;
-
- case SWAP_A:
- case SWAP_B:
- case SWAP_C:
- case SWAP_D:
- cycles=776+248*l1-6;
- last=f-SWAP_A+1;
- e.GetLE(data,dl);
- regs[last]->PutLE(data,dl);
- regs[last]->Set(e,l1);
- break;
-
- case CLEAR_A:
- case CLEAR_B:
- case CLEAR_C:
- case CLEAR_D:
- cycles=462+(8*l1+3)/5*5-6;
- last=f-CLEAR_A+1;
- regs[last]->Clear(l1);
- break;
-
- case COPY_A_B:
- last=2; B.Set(A,l1); cycles=462+(8*l1+3)/5*5-6; break;
- case COPY_B_A:
- last=1; A.Set(B,l1); cycles=462+(8*l1+3)/5*5-6; break;
- case COPY_A_C:
- last=3; C.Set(A,l1); cycles=462+(8*l1+3)/5*5-6; break;
- case COPY_C_A:
- last=1; A.Set(C,l1); cycles=462+(8*l1+3)/5*5-6; break;
- case COPY_C_D:
- last=4; D.Set(C,l1); cycles=462+(8*l1+3)/5*5-6; break;
- case COPY_D_C:
- last=3; C.Set(D,l1); cycles=462+(8*l1+3)/5*5-6; break;
-
- case 0x39:
- case 0x3a:
- AddMapCycles(512);
- WS_START(1);
- MakeJ0(J,D);
- AddMapCycles(256);
- WS_END();
- AddMapCycles(340);
- if(!BN_is_zero(D)) {
- BN_zero(I);
- BN_set_bit(I,68*wordsize);
- BN_mod(B,I,D,ctx);
- }
- AddMapCycles(320);
- for(int i=0; i<4; i++) MonMul(B,B,B);
-
- if(f==0x39) I.GetLE(data,wordsize<<3);
- MonMul(B,(f==0x39?I:A),B);
- MonMul(B,A,B);
- break;
- case 0x43: // init SHA1
- SHA1_Init(&sctx);
- break;
- case 0x44: // add 64 bytes to SHA1 buffer
- RotateBytes(data,64);
- SHA1_Update(&sctx,data,64);
- BYTE4_LE(data ,sctx.h4);
- BYTE4_LE(data+4 ,sctx.h3);
- BYTE4_LE(data+8 ,sctx.h2);
- BYTE4_LE(data+12,sctx.h1);
- BYTE4_LE(data+16,sctx.h0);
- break;
- case 0x45: // add wordsize bytes to SHA1 buffer and finalize SHA result
- if(dl) {
- if(dl>1) RotateBytes(data,dl);
- SHA1_Update(&sctx,data,dl);
- }
- SHA1_Final(data,&sctx);
- RotateBytes(data,20);
- break;
- default:
- return false;
- }
- return true;
-}
-
-// -- cN2Prov ------------------------------------------------------------------
-
-cN2Prov::cN2Prov(int Id, int Flags)
-{
-// keyValid=false; id=Id|0x100; flags=Flags; seedSize=5;
- id=Id|0x100; flags=Flags;
- memset(lastcw, 0, sizeof(lastcw));
- memset(prevcw, 0, sizeof(prevcw));
- memset(lasthd, 0, sizeof(lasthd));
-}
-
-void cN2Prov::PrintCaps(int c)
-{
- PRINTF(c,"provider %04x capabilities%s%s%s%s%s",id,
- HasFlags(N2FLAG_MECM) ?" MECM":"",
- HasFlags(N2FLAG_Bx) ?" Bx":"",
- HasFlags(N2FLAG_Ex) ?" Ex":"",
- HasFlags(N2FLAG_POSTAU) ?" POSTPROCAU":"",
- HasFlags(N2FLAG_INV) ?" INVCW":"");
-}
-
-void cN2Prov::ExpandInput(unsigned char *hw)
-{
- hw[0]^=(0xDE +(0xDE<<1)) & 0xFF;
- hw[1]^=(hw[0]+(0xDE<<1)) & 0xFF;
- for(int i=2; i<128; i++) hw[i]^=hw[i-2]+hw[i-1];
- IdeaKS ks;
- idea.SetEncKey((unsigned char *)"NagraVision S.A.",&ks);
- unsigned char buf[8];
- memset(buf,0,8);
- for(int i=0; i<128; i+=8) {
- xxor(buf,8,buf,&hw[i]);
- idea.Encrypt(buf,8,buf,&ks,0);
- xxor(buf,8,buf,&hw[i]);
- memcpy(&hw[i],buf,8);
- }
-}
-
-bool cN2Prov::MECM(unsigned char in15, int algo, const unsigned char *ed, unsigned char *cw)
-{
- unsigned char hd[32], hw[128+64], buf[20];
- int rv;
- hd[0]=in15&0x7F;
- hd[1]=cw[14];
- hd[2]=cw[15];
- hd[3]=cw[6];
- hd[4]=cw[7];
-
- DynamicHD(hd,ed);
- hd[seedSize] = algo;
-
- if(keyValid && !memcmp(seed,hd,seedSize+1)) { // key cached
- memcpy(buf,cwkey,8);
- rv = MARV_SUCCESS;
- }
- else { // key not cached
- memset(hw,0,sizeof(hw));
- if((rv=Algo(algo,hd,ed,hw,cw))==MARV_ERROR) return false;
- memcpy(&hw[128],hw,64);
- RotateBytes(&hw[64],128);
- SHA1(&hw[64],128,buf);
- RotateBytes(buf,20);
-
- if(rv==MARV_SUCCESS) {
- memcpy(seed,hd,seedSize+1);
- memcpy(cwkey,buf,8);
- keyValid=true;
- }
- }
-
- memcpy(prevcw, cw, sizeof(prevcw));
- memcpy(lasthd, hd, seedSize+1);
-
- memcpy(&buf[8],buf,8);
- IdeaKS ks;
- idea.SetEncKey(buf,&ks);
- memcpy(&buf[0],&cw[8],6);
- memcpy(&buf[6],&cw[0],6);
- idea.Encrypt(&buf[4],8,&buf[4],&ks,0);
- idea.Encrypt(buf,8,buf,&ks,0);
-
- memcpy(&cw[ 0],&buf[6],3);
- memcpy(&cw[ 4],&buf[9],3);
- memcpy(&cw[ 8],&buf[0],3);
- memcpy(&cw[12],&buf[3],3);
- for(int i=0; i<16; i+=4) cw[i+3]=cw[i]+cw[i+1]+cw[i+2];
-
- if(rv==MARV_DESYNCED)
- lastcw[16] = 0;
- else if(rv>=MARV_SUCCESS) {
- if(rv==MARV_SUCCESS) lastcw[16] = 1;
- memcpy(lastcw, cw, 16);
- }
-
- return true;
-}
-
-void cN2Prov::SwapCW(unsigned char *cw)
-{
- if(NeedsCwSwap()) {
- unsigned char tt[8];
- memcpy(&tt[0],&cw[0],8);
- memcpy(&cw[0],&cw[8],8);
- memcpy(&cw[8],&tt[0],8);
- }
-}
-
-// -- cN2Providers -------------------------------------------------------------
-
-cN2ProvLink *cN2Providers::first=0;
-
-void cN2Providers::Register(cN2ProvLink *plink)
-{
- PRINTF(L_CORE_DYN,"n2providers: registering prov %04X with flags %d",plink->id,plink->flags);
- plink->next=first;
- first=plink;
-}
-
-cN2Prov *cN2Providers::GetProv(int Id, int Flags)
-{
- cN2ProvLink *pl=first;
- while(pl) {
- if(pl->CanHandle(Id) && pl->HasFlags(Flags)) return pl->Create();
- pl=pl->next;
- }
- return 0;
-}
-
-// -- cN2ProvLink --------------------------------------------------------------
-
-cN2ProvLink::cN2ProvLink(int Id, int Flags)
-{
- id=Id; flags=Flags;
- cN2Providers::Register(this);
-}
-
-// -- cNagra2 ------------------------------------------------------------------
-
-class cNagra2 : public cNagra {
-private:
- bool Signature(const unsigned char *vkey, const unsigned char *sig, const unsigned char *msg, int len);
-protected:
- cIDEA idea;
- //
- virtual void CreatePQ(const unsigned char *key, BIGNUM *p, BIGNUM *q);
- bool DecryptECM(const unsigned char *in, unsigned char *out, const unsigned char *key, int len, const unsigned char *vkey, BIGNUM *m);
- bool DecryptEMM(const unsigned char *in, unsigned char *out, const unsigned char *key, int len, const unsigned char *vkey, BIGNUM *m);
- };
-
-void cNagra2::CreatePQ(const unsigned char *key, BIGNUM *p, BIGNUM *q)
-{
- // Calculate P and Q from PK
- IdeaKS ks;
- idea.SetEncKey(key,&ks);
- // expand IDEA-G key
- unsigned char idata[96];
- for(int i=11; i>=0; i--) {
- unsigned char *d=&idata[i*8];
- memcpy(d,&key[13],8);
- *d^=i;
- idea.Decrypt(d,8,&ks,0);
- xxor(d,8,d,&key[13]);
- *d^=i;
- }
- // Calculate P
- idata[0] |= 0x80;
- idata[47] |= 1;
- BN_bin2bn(idata,48,p);
- BN_add_word(p,(key[21] << 5 ) | ((key[22] & 0xf0) >> 3));
- // Calculate Q
- idata[48] |= 0x80;
- idata[95] |= 1;
- BN_bin2bn(idata+48,48,q);
- BN_add_word(q,((key[22]&0xf)<<9) | (key[23]<<1));
-}
-
-bool cNagra2::Signature(const unsigned char *vkey, const unsigned char *sig, const unsigned char *msg, int len)
-{
- unsigned char buff[16];
- memcpy(buff,vkey,sizeof(buff));
- for(int i=0; i<len; i+=8) {
- IdeaKS ks;
- idea.SetEncKey(buff,&ks);
- memcpy(buff,buff+8,8);
- idea.Encrypt(msg+i,8,buff+8,&ks,0);
- xxor(&buff[8],8,&buff[8],msg+i);
- }
- buff[8]&=0x7F;
- return (memcmp(sig,buff+8,8)==0);
-}
-
-bool cNagra2::DecryptECM(const unsigned char *in, unsigned char *out, const unsigned char *key, int len, const unsigned char *vkey, BIGNUM *m)
-{
- int sign=in[0] & 0x80;
- if(rsa.RSA(out,in+1,64,pubExp,m)<=0) {
- PRINTF(L_SYS_CRYPTO,"first RSA failed (ECM)");
- return false;
- }
- out[63]|=sign; // sign adjustment
- if(len>64) memcpy(out+64,in+65,len-64);
-
- if(in[0]&0x04) {
- unsigned char tmp[8];
- DES_key_schedule ks1, ks2;
- RotateBytes(tmp,&key[0],8);
- DES_key_sched((DES_cblock *)tmp,&ks1);
- RotateBytes(tmp,&key[8],8);
- DES_key_sched((DES_cblock *)tmp,&ks2);
- memset(tmp,0,sizeof(tmp));
- for(int i=7; i>=0; i--) RotateBytes(out+8*i,8);
- DES_ede2_cbc_encrypt(out,out,len,&ks1,&ks2,(DES_cblock *)tmp,DES_DECRYPT);
- for(int i=7; i>=0; i--) RotateBytes(out+8*i,8);
- }
- else idea.Decrypt(out,len,key,0);
-
- RotateBytes(out,64);
- if(rsa.RSA(out,out,64,pubExp,m,false)<=0) {
- PRINTF(L_SYS_CRYPTO,"second RSA failed (ECM)");
- return false;
- }
- if(vkey && !Signature(vkey,out,out+8,len-8)) {
- PRINTF(L_SYS_CRYPTO,"signature failed (ECM)");
- return false;
- }
- return true;
-}
-
-bool cNagra2::DecryptEMM(const unsigned char *in, unsigned char *out, const unsigned char *key, int len, const unsigned char *vkey, BIGNUM *m)
-{
- int sign=in[0]&0x80;
- if(rsa.RSA(out,in+1,96,pubExp,m)<=0) {
- PRINTF(L_SYS_CRYPTO,"first RSA failed (EMM)");
- return false;
- }
- out[95]|=sign; // sign adjustment
- cBN exp;
- if(in[0]&0x08) {
- // standard IDEA decrypt
- if(len>96) memcpy(out+96,in+97,len-96);
- idea.Decrypt(out,len,key,0);
- BN_set_word(exp,3);
- }
- else {
- // private RSA key expansion
- CreateRSAPair(key,0,exp,m);
- }
- RotateBytes(out,96);
- if(rsa.RSA(out,out,96,exp,m,false)<=0) {
- PRINTF(L_SYS_CRYPTO,"second RSA failed (EMM)");
- return false;
- }
- if(vkey && !Signature(vkey,out,out+8,len-8)) {
- PRINTF(L_SYS_CRYPTO,"signature failed (EMM)");
- return false;
- }
- return true;
-}
-
-// -- cSystemNagra2 ------------------------------------------------------------
-
-static int dropEMMs=1;
-
-class cSystemNagra2 : public cSystem, protected cNagra2 {
-private:
- int lastEcmId, lastEmmId;
- cN2Prov *ecmP, *emmP;
-public:
- cSystemNagra2(void);
- ~cSystemNagra2();
- virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *data);
- virtual void ProcessEMM(int pid, int caid, unsigned char *buffer);
- };
-
-cSystemNagra2::cSystemNagra2(void)
-:cSystem(SYSTEM_NAME,SYSTEM_PRI)
-{
- hasLogger=true;
- lastEcmId=lastEmmId=0; ecmP=emmP=0;
-}
-
-cSystemNagra2::~cSystemNagra2()
-{
- delete ecmP;
- delete emmP;
-}
-
-bool cSystemNagra2::ProcessECM(const cEcmInfo *ecm, unsigned char *data)
-{
-#define NA_SOURCE_START 0x8267 // cSource::FromString("S61.5W");
-#define NA_SOURCE_END 0x85c8 // cSource::FromString("S148W");
- unsigned char odata[15];
- memcpy(odata,data,sizeof(odata));
- if(ecm->source>=NA_SOURCE_START && ecm->source<=NA_SOURCE_END) {
- switch(ecm->source) {
- case 0x8267: // S61.5W
- case 0x82d0: // S72.0W
- case 0x8302: // S77.0W
- case 0x844c: // S110.0W
- case 0x849c: // S118.0W
- case 0x84a6: // S119.0W
- case 0x841a: // S105.0W
- case 0x84ba: // S121.0W
- case 0x850a: // S129.0W
- case 0x85c8: // S148.0W
- data[5]=0x01;
- break;
- case 0x8334: // S82.0W
- case 0x838e: // S91.0W
- data[5]=0x09;
- break;
- case 0x83ca: // S97.0W
- data[5]=0xc1;
- break;
- default:
- if (ecm->caId==0x1234)
- data[5]=0x09;
- else
- data[5]=0x01;
- }
-
- data[6]&=0x1F;
- data[7]=data[7]&0x10|0x86;
- data[8]=0;
- data[9]=data[9]&0x80|0x08;
- }
- int cmdLen=data[4]-5;
- int id=(data[5]*256)+data[6];
- cTimeMs minTime;
- int provider=id;
- if(id==0x4101) StartLog(ecm,0x1881); // D+ AU
- if(id==0x0505 || id==0x0503 || id==0x0511) id=0x0501; // PremStar ugly again :(
- if (id >= 0x0101 && id <= 0x01FF) {
- provider = 0x0101;
- } else if (id >= 0x0901 && id <= 0x09FF) {
- provider = 0x0901;
- } else {
- provider = id;
- }
-
- if(cmdLen<64 || SCT_LEN(data)<cmdLen+10) {
- if(doLog) PRINTF(L_SYS_ECM,"bad ECM message msgLen=%d sctLen=%d",cmdLen,SCT_LEN(data));
- return false;
- }
-
- int keyNr=(data[7]&0x10)>>4;
- cKeySnoop ks(this,'N',provider,keyNr);
- cPlainKey *pk;
-
- cBN m1;
- unsigned char ideaKey[16], vKey[16];
- bool hasVerifyKey=false;
- if(!(pk=keys.FindKey('N',provider,MBC('M','1'),-1))) {
- if(doLog) PRINTF(L_SYS_KEY,"missing %04x M1 key",id);
- return false;
- }
- pk->Get(m1);
- if((pk=keys.FindKeyNoTrig('N',provider,'V',sizeof(vKey)))) {
- pk->Get(vKey);
- hasVerifyKey=true;
- }
- else if(doLog && id!=lastEcmId) PRINTF(L_SYS_KEY,"missing %04x V key (non-fatal)",id);
- if(!(pk=keys.FindKey('N',provider,keyNr,sizeof(ideaKey)))) return false;
- pk->Get(ideaKey);
-
- unsigned char buff[256];
- if(!DecryptECM(data+9,buff,ideaKey,cmdLen,hasVerifyKey?vKey:0,m1)) {
- if(doLog) PRINTF(L_SYS_ECM,"decrypt of ECM failed (%04x)",id);
- return false;
- }
-
- if((!ecmP && id!=lastEcmId) || (ecmP && !ecmP->CanHandle(id))) {
- delete ecmP;
- ecmP=cN2Providers::GetProv(id,N2FLAG_NONE);
- if(ecmP) ecmP->PrintCaps(L_SYS_ECM);
- }
- lastEcmId=id;
-
- HEXDUMP(L_SYS_RAWECM,buff,cmdLen,"Nagra2 RAWECM");
- int l=0, mecmAlgo=0;
- LBSTARTF(L_SYS_ECM);
- bool contFail=false;
- for(int i=(buff[14]&0x10)?16:20; i<cmdLen-10 && l!=3; ) {
- switch(buff[i]) {
- case 0x10:
- case 0x11:
- if(buff[i+1]==0x09) {
- int s=(~buff[i])&1;
- mecmAlgo=buff[i+2]&0x60;
- memcpy(cw+(s<<3),&buff[i+3],8);
- i+=11; l|=(s+1);
- }
- else {
- PRINTF(L_SYS_ECM,"bad length %d in CW nano %02x",buff[i+1],buff[i]);
- i++;
- }
- break;
- case 0x00:
- i+=2; break;
- case 0x30:
- case 0x31:
- case 0x32:
- case 0x33:
- case 0x34:
- case 0x35:
- case 0x36:
- case 0xB0:
- i+=buff[i+1]+2;
- break;
- default:
- if(!contFail) LBPUT("unknown ECM nano");
- LBPUT(" %02x",buff[i]);
- contFail=true;
- i++;
- continue;
- }
- LBFLUSH(); contFail=false;
- }
- LBEND();
- if(l!=3) return false;
- if(mecmAlgo>0) {
- if(ecmP && ecmP->HasFlags(N2FLAG_MECM)) {
- if(!ecmP->MECM(buff[15],mecmAlgo,odata,cw)) return false;
- }
- else { PRINTF(L_SYS_ECM,"MECM for provider %04x not supported",id); return false; }
- }
- if(ecmP) ecmP->SwapCW(cw);
- ks.OK(pk);
-
- int i=minEcmTime-minTime.Elapsed();
- if(i>0) cCondWait::SleepMs(i);
- return true;
-}
-
-void cSystemNagra2::ProcessEMM(int pid, int caid, unsigned char *buffer)
-{
- int cmdLen=buffer[9]-5;
- int id=buffer[10]*256+buffer[11];
- char txt[150];
-
- if(buffer[0]==0x83 && dropEMMs) return; // skip EMM-S if disabled
- if(cmdLen<96 || SCT_LEN(buffer)<cmdLen+15) {
- PRINTF(L_SYS_EMM,"Bad EMM message msgLen=%d sctLen=%d",cmdLen,SCT_LEN(buffer));
- return;
- }
- char time_str[20];
- char text[100];
- int keyset=(buffer[12]&0x03);
- int sel=(buffer[12]&0x10)<<2;
- int sigsel=(buffer[13]&0x80)>>1;
- int CamID = 0;
- int provider=id;
- if (id >= 0x0101 && id <= 0x010F) {
- provider = 0x0101;
- } else if (id >= 0x0901 && id <= 0x090F) {
- provider = 0x0901;
- } else {
- provider = id;
- }
- if((!emmP && id!=lastEmmId) || (emmP && !emmP->CanHandle(id))) {
- delete emmP;
- emmP=cN2Providers::GetProv(id,N2FLAG_NONE);
-// if(emmP) emmP->PrintCaps(L_SYS_EMM);
- }
- lastEmmId=id;
-
- //HEXDUMP(L_SYS_RAWEMM,buffer+14,cmdLen,"Nagra2 Encrypted EMM");
- //id=(emmdata[8]<<8)+emmdata[9];
- //LBSTARTF(L_SYS_EMM);
- int keyPTR = N2_MAGIC;
- if (buffer[0] == 0x83) {
- keyPTR = 0;
- for (int it=5; it>2; it--) {
- CamID = MBC(CamID,buffer[it]);
- }
- //keyPTR=CID(N2_EMM_S,buffer[5],buffer[4],buffer[3]);
- }
-
-
- cPlainKey *pk;
- cBN n;
- unsigned char ideaKey[24], vKey[16];
- bool hasVerifyKey=false;
- if(!(pk=keys.FindKey('N',provider,MBC(keyPTR,keyset+0x10+sel),96,0)))
- {
- PRINTF(L_SYS_EMM,"You are missing %04x NN %.02X RSA key (96 bytes)",id,keyset+0x10+sel);
- return;
- }
- pk->Get(n);
- if (buffer[0] != 0x83) {
- if((pk=keys.FindKey('N',provider,MBC(keyPTR,0x03+sigsel),sizeof(vKey)))) {
- pk->Get(vKey);
- hasVerifyKey=true;
- }
- else if(id!=lastEmmId) {
- PRINTF(L_SYS_EMM,"You are missing %04x NN %.02X signature key (non-fatal)",id,0x03+sigsel);
- }
- }
- if(!(pk=keys.FindKey('N',provider,MBC(keyPTR,keyset),24,0))) {
- if(!(pk=keys.FindKey('N',provider,MBC(keyPTR,keyset+sel),16))) {
- PRINTF(L_SYS_EMM,"You are missing %04x NN %.02x IDEA key (24 or 16 bytes)",id,keyset);
- return;
- }
- memset(ideaKey+16,0,8);
- }
- pk->Get(ideaKey);
-
- unsigned char emmdata[256];
- if(!DecryptEMM(buffer+14,emmdata,ideaKey,cmdLen,hasVerifyKey?vKey:0,n)) {
- sprintf(txt,"[%s] nagra2: decrypt of EMM failed (%04x)", time_str, id);
- if (buffer[0] == 0x82) {
- PRINTF(L_SYS_EMM,"Bad EMM-G Packet (Idea Hash failed! -> RSA decryption failed!): %04x", id);
- } else if (buffer[0] == 0x83) {
- PRINTF(L_SYS_EMM,"EMM-S {%06X%02X} (Idea Hash failed! -> RSA decryption failed!)",CamID,buffer[6]);
- }
- return;
- } else {
- if (buffer[0] == 0x82) {
- PRINTF(L_SYS_EMM,"Decrypt of EMM-G Succeeded (%04x)", id);
- char str2[51]; // 4AFFB6B0C6C52F7C0801144F8C9F18717787E3
- sprintf(&str2[0],"%02X ",emmdata[18]);
- for(int it=1; it<20; it++) sprintf(&str2[(it*2)+1],"%02X",emmdata[it+18]);
- PRINTF(L_SYS_EMM,"Decrypt of EMM-S Succeeded (%04x)", id);
- }
- }
- lastEmmId=id;
- if((!emmP && id!=lastEmmId) || (emmP && !emmP->CanHandle(id))) {
- delete emmP;
- emmP=cN2Providers::GetProv(id,N2FLAG_NONE);
- if(emmP) emmP->PrintCaps(L_SYS_EMM);
- }
- lastEmmId=id;
-
- HEXDUMP(L_SYS_RAWEMM,buffer+14,cmdLen,"Nagra2 Encrypted EMM");
- id=(emmdata[8]<<8)+emmdata[9];
- LBSTARTF(L_SYS_EMM);
- bool contFail=false;
-
- if (buffer[0] == 0x82) {
- id=(emmdata[8]<<8)+emmdata[9];
- }
-
- for(int i=8+2+4+4; i<cmdLen-22; ) {
- switch(emmdata[i]) {
- case 0x42: // plain Key update
- if((((emmdata[i+3]|0xF3)+1)&0xFF) != 0) {
- int len=emmdata[i+2];
- int off=emmdata[i+5];
- int ulen=emmdata[i+6];
- if(len>0 && ulen>0 && off+ulen<=len) {
- int ks=emmdata[i+3], kn;
- if(ks==0x06 || ks==0x46) kn=(ks>>6)&1; else kn=MBC(N2_MAGIC,ks);
- unsigned char key[256];
- memset(key,0,sizeof(key));
- if((pk=keys.FindKeyNoTrig('N',id,kn,len))) {
- if(cPlainKeyNagra::IsBNKey(kn)) { pk->Get(n); n.PutLE(key,len); }
- else pk->Get(key);
- }
- bool ok=false;
- if((emmdata[i+1]&0x7F)==0) ok=true;
- else {
- if(emmP && emmP->HasFlags(N2FLAG_POSTAU)) {
- if(emmP->PostProcAU(id,&emmdata[i])) ok=true;
- }
- else PRINTF(L_SYS_EMM,"POSTAU for provider %04x not supported",id);
- }
- if(ok) {
- memcpy(&key[off],&emmdata[i+7],ulen);
- FoundKey();
- for(int it=7 ; it<23 ; it++) sprintf(&text[(it-7)*2],"%02X",emmdata[i+it]);
- PRINTF(L_SYS_EMM,"Key %02X: %s (%04X)",(emmdata[i+3]&0x40)>>6,text,id);
- if(cPlainKeyNagra::IsBNKey(kn)) {
- n.GetLE(key,len);
- if(keys.NewKey('N',id,kn,n,len)) NewKey();
- }
- else {
- if(keys.NewKey('N',id,kn,key,len)) {
- NewKey();
- }
- }
- }
- i+=ulen;
- }
- else PRINTF(L_SYS_EMM,"nano42 key size mismatch len=%d off=%d ulen=%d",len,off,ulen);
- }
- else PRINTF(L_SYS_EMM,"nano42 0xf3 status exceeded");
- i+=7;
- break;
- case 0xE0: // DN key update
- if(emmdata[i+1]==0x25) {
- FoundKey();
- PRINTF(L_SYS_EMM,"Key packet for %04x",id);
- if(keys.NewKey('N',id,(emmdata[i+16]&0x40)>>6,&emmdata[i+23],16)) NewKey();
- }
- i+=emmdata[i+1]+2;
- break;
- case 0x83: // change data prov. id
- id=(emmdata[i+1]<<8)|emmdata[i+2];
- i+=3;
- break;
- //CamID target update
- case 0xA0:
- PRINTF(L_SYS_EMM, "EMM-S CAM Id Update");
- i+=5;
- break;
- case 0xB0: case 0xB1: case 0xB2: case 0xB3: // Update with ROM CPU code
- case 0xB4: case 0xB5: case 0xB6: case 0xB7:
- case 0xB8: case 0xB9: case 0xBA: case 0xBB:
- case 0xBC: case 0xBD: case 0xBE: case 0xBF:
- {
- int bx=emmdata[i]&15;
- if(!emmP || !emmP->HasFlags(N2FLAG_Bx)) {
- PRINTF(L_SYS_EMM,"B%X for provider %04x not supported",bx,id);
- i=cmdLen;
- break;
- }
- int r;
- if((r=emmP->ProcessBx(emmdata,cmdLen,i+1))>0 || (r==0 && emmdata[i]!=0xb1)){
- PRINTF(L_SYS_EMM,"B%X executing succeeded for %04x",bx,id);
- i+=r;
- }
- else {
- PRINTF(L_SYS_EMM,"B%X executing failed for %04x",bx,id);
- i=cmdLen;
- }
- break;
- }
- case 0xA4: i+=emmdata[i+1]+2+4; break; // conditional (always no match assumed for now)
- case 0xA6: i+=15; break;
- case 0xAA: i+=emmdata[i+1]+5; break;
- case 0xAD: i+=emmdata[i+1]+2; break;
- case 0xA2:
- case 0xAE: i+=11;break;
- case 0x12: i+=emmdata[i+1]+2; PRINTF(L_SYS_EMM,"Create tier packet"); break; // create tier
- case 0x20: i+=19; PRINTF(L_SYS_EMM,"Modify tier packet"); break; // modify tier
- case 0x9F: i+=6; break;
- case 0xE3: // Eeprom update
- {
- int ex=emmdata[i]&15;
- if(!emmP || !emmP->HasFlags(N2FLAG_Ex)) {
- i+=emmdata[i+4]+5;
- PRINTF(L_SYS_EMM,"E%X for provider %04x not supported",ex,id);
- break;
- }
- int r;
- if((r=emmP->ProcessEx(emmdata,cmdLen,i+1))>0){
- PRINTF(L_SYS_EMM,"E%X for provider %04x succeeded",ex,id);
- i+=r;
- }
- else {
- PRINTF(L_SYS_EMM,"E%X executing failed for %04x",ex,id);
- i=cmdLen;
- }
- break;
- }
- case 0xE1:
- case 0xE2:
- case 0x00: i=cmdLen; break; // end of processing
- default:
- if(!contFail) LBPUT("unknown EMM nano");
- LBPUT(" %02x",emmdata[i]);
- contFail=true;
- i++;
- continue;
- }
- LBFLUSH(); contFail=false;
- }
- LBEND();
-}
-// -- cSystemLinkNagra2 --------------------------------------------------------
-
-class cSystemLinkNagra2 : public cSystemLink {
-public:
- cSystemLinkNagra2(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemNagra2; }
- };
-
-static cSystemLinkNagra2 staticInitN2;
-
-cSystemLinkNagra2::cSystemLinkNagra2(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- opts=new cOpts(SYSTEM_NAME,5);
- opts->Add(new cOptBool("DropEMMS",trNOOP("Nagra2: drop EMM-S packets"),&dropEMMs));
-#ifdef HAS_AUXSRV
- static const char allowed_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz-.";
- opts->Add(new cOptBool("AuxServerEnable",trNOOP("Nagra2: Enable AUXserver"),&auxEnabled));
- opts->Add(new cOptStr("AuxServerAddr",trNOOP("Nagra2: AUXserver hostname"),auxAddr,sizeof(auxAddr),allowed_chars));
- opts->Add(new cOptInt("AuxServerPort",trNOOP("Nagra2: AUXserver port"),&auxPort,0,65535));
- opts->Add(new cOptStr("AuxServerPass",trNOOP("Nagra2: AUXserver password"),auxPassword,sizeof(auxPassword),allowed_chars));
-#endif
- Feature.NeedsKeyFile();
-}
-
-bool cSystemLinkNagra2::CanHandle(unsigned short SysId)
-{
- return ((SysId&SYSTEM_MASK)==SYSTEM_NAGRA && (SysId&0xFF)>0) ||
- SysId==SYSTEM_NAGRA_BEV;
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __NAGRA_NAGRA2_H
-#define __NAGRA_NAGRA2_H
-
-#include "data.h"
-#include "crypto.h"
-#include "misc.h"
-#include "helper.h"
-
-#include <openssl/des.h>
-#include <openssl/sha.h>
-#include "openssl-compat.h"
-
-#include "nagra-def.h"
-#include "cpu.h"
-#include "log-nagra.h"
-
-// ----------------------------------------------------------------
-
-#define MATCH_ID(x,y) ((((x)^(y))&~0x107)==0)
-
-// ----------------------------------------------------------------
-
-#define HAS_AUXSRV
-
-#ifdef HAS_AUXSRV
-extern int auxEnabled;
-extern int auxPort;
-extern char auxAddr[80];
-extern char auxPassword[250];
-#endif
-
-// ----------------------------------------------------------------
-
-class cMapReg {
-protected:
- enum { DEF_WORDSIZE = 4, DEF_MAXWORDSIZE = 17 };
- cBN fullreg, reg, tmp;
- int wordsize, maxwordsize, *defwordsize;
- int DefWordSize() const { return defwordsize ? *defwordsize : DEF_WORDSIZE; }
- int OpWordSize(int wsize) const { int sz = wsize>0 ? wsize : DefWordSize(); return sz>maxwordsize ? maxwordsize : sz; }
- void ClearReg(int wsize);
- void ClearFullReg(int wsize);
- void SetTmp(BIGNUM* val, int wsize);
-protected:
- void SetMaxWordSize(int max) { maxwordsize = max; }
- void SetDefWordSize(int* _defwordsize) { defwordsize = _defwordsize; }
-public:
- cMapReg(int* defwordsize=NULL, int maxwordsize=DEF_MAXWORDSIZE);
- operator BIGNUM* () { return Value(); }
- BIGNUM *operator->() { return Value(); }
- BIGNUM* Value(int wsize=0, bool mask=false);
- int OpWordSize() const { return wordsize; }
-
- void Commit(int wsize=-1, int resync=-1);
- void Reload(int wsize=0);
- void GetLE(const unsigned char *in, int n=0);
- void PutLE(unsigned char *out, int n=0);
- void Set(BIGNUM* val, int wsize);
- void Clear(int wsize);
-};
-
-
-
-// ----------------------------------------------------------------
-
-#define WS_START(x) { int __oldws=wordsize; wordsize=(x);
-#define WS_END() wordsize=__oldws; }
-
-class cMapMath {
-private:
- cBN x, y, s;
-protected:
- int wordsize;
- cMapReg A, B, C, D, J, I;
- cBNctx ctx;
- SHA_CTX sctx;
- // stateless
-#if 0
- void ClearReg(BIGNUM* reg, int size=0);
- void SetReg(BIGNUM* reg, BIGNUM* in, int size=0);
- void SetReg(BIGNUM* reg, unsigned int val, int size=0);
- void SetRestoreReg(BIGNUM* reg, BIGNUM* restorereg, int size=0);
- void LoadReg(BIGNUM* out, BIGNUM* reg, int size=0);
- void LoadSaveReg(BIGNUM* reg, BIGNUM* savereg, int size=0);
-#endif
-
- void MakeJ0(BIGNUM *j, BIGNUM *d, BIGNUM *c=NULL, int bits=64);
- void MakeJ() { MakeJ0(J, D, C); }
- bool ModAdd(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *d);
- bool ModSub(BIGNUM *r, BIGNUM *d, BIGNUM *b);
- void MonMul0(BIGNUM *o, BIGNUM *a, BIGNUM *b, BIGNUM *c, BIGNUM *d, BIGNUM *j, int words=0);
- void MonMulFin(BIGNUM *o, BIGNUM *d);
- void MonMul(BIGNUM *o, BIGNUM *a, BIGNUM *b, BIGNUM *c, BIGNUM *d, BIGNUM *j, int words=0);
- // statefull
- void MonMul(BIGNUM *o, BIGNUM *a, BIGNUM *b, int words=0) { MonMul(o, a, b, C, D, J, words); }
-public:
- cMapMath(void);
- };
-
-// ----------------------------------------------------------------
-
-#define SETSIZE 0x02
-#define IMPORT_J 0x03
-#define IMPORT_A 0x04
-#define IMPORT_B 0x05
-#define IMPORT_C 0x06
-#define IMPORT_D 0x07
-#define IMPORT_LAST 0x08
-#define EXPORT_J 0x09
-#define EXPORT_A 0x0A
-#define EXPORT_B 0x0B
-#define EXPORT_C 0x0C
-#define EXPORT_D 0x0D
-#define EXPORT_LAST 0x0E
-#define SWAP_A 0x0F
-#define SWAP_B 0x10
-#define SWAP_C 0x11
-#define SWAP_D 0x12
-#define CLEAR_A 0x13
-#define CLEAR_B 0x14
-#define CLEAR_C 0x15
-#define CLEAR_D 0x16
-#define COPY_A_B 0x17
-#define COPY_B_A 0x18
-#define COPY_A_C 0x19
-#define COPY_C_A 0x1A
-#define COPY_C_D 0x1B
-#define COPY_D_C 0x1C
-
-class cMapCore : public cMapMath {
-private:
- int mapid, last;
- cBN x, y, s, j;
- cBN e;
- cMapReg *regs[5];
- c6805* cpu;
- bool interruptible, interrupted;
- //
- bool MapGeneric(int f, unsigned char *data, int l);
-protected:
- unsigned int cycles;
- cBN Px, Py, Pz,Qx, Qy, Qz; // 0x00,0x20,0x40,0x60,0x80,0x180
- cBN sA0, sC0, sE0, s100, s120, s140, s160;
- cBN H, R;
- void ImportReg(unsigned char reg, const unsigned char *data, int l=0);
- void ExportReg(unsigned char reg, unsigned char *data, int l=0);
- void SetWordSize(int l) { wordsize=l; }
- // statefull
- void MonInit(int bits=0);
- void MonExp(BIGNUM *scalar);
- void MonExpNeg(void);
- // ECC
- void DoubleP(int temp);
- void AddP(int temp);
- void ToProjective(int set, BIGNUM *x, BIGNUM *y);
- void ToAffine(void);
- void CurveInit(BIGNUM *a);
- //
- int GetOpSize(int l);
- void DoMap(int f, unsigned char *data=0, int l=0);
- virtual bool Map(int f, unsigned char *data, int l) { return false; }
- void SetMapIdent(int Mapid) { mapid=Mapid; }
- bool Interruptible(void) { return interruptible; }
- bool Interrupted(void) { return interrupted; }
- virtual void AddMapCycles(unsigned int num) {}
- unsigned int MapCycles(void) { return cycles; }
- virtual unsigned int CpuCycles(void) { return 0; }
-public:
- cMapCore(void);
- virtual ~cMapCore() {}
- };
-
-// ----------------------------------------------------------------
-
-class cN2Timer {
-private:
- int ctrl, latch, id, delayInterrupt;
- unsigned char val;
- unsigned int cycles, intrCycles;
- double divisor, invDivisor;
- bool timerBugged;
- enum { tmCONTINUOUS=0x01, tmRUNNING=0x02, tmINTERRUPT=0x04, tmMASK=0xFF, tmLATCHED=0x100 };
- //
- void Stop(void);
- double GetDivisor();
- void Update();
- c6805* cpu;
-public:
- cN2Timer();
- int Id() const { return id; }
- void SetId(unsigned char num, c6805* _cpu=NULL) { id = num; cpu = _cpu; }
- bool AddCycles(unsigned int count);
- unsigned int Cycles();
- unsigned char Ctrl();
- void Ctrl(unsigned char c);
- unsigned char Latch(void) { return latch&0xFF; }
- void Latch(unsigned char val);
- bool Running(void) { return ctrl&tmRUNNING; }
- bool InterruptSet(void) { return ctrl&tmINTERRUPT; }
-};
-
-// ----------------------------------------------------------------
-#define HW_REGS 0x20
-#define HW_OFFSET 0x0000
-
-#define MAX_TIMERS 3
-#define TIMER_NUM(x) (((x)>>2)&3) // timer order doesn't match HW order
-
-// $00 = I/O Reg
-// 0 = stop bit
-// $01 = Security
-// $06 = UART Clock control
-// $08 = timer 0 value
-// $09 = timer 0 latch
-// $0a = timer 0 config
-// $0d = PIC IMR
-// 3 = timer 0
-// $0e = CRC control
-// 0 = busy
-// 1 = disabled
-// $0f = CRC data
-// $10 = timer 1 value
-// $11 = timer 1 latch
-// $12 = timer 1 control
-// $14 = timer 2 value
-// $15 = timer 2 latch
-// $16 = timer 2 control
-// 0 = one-shot/periodic
-// 1 = enabled
-// 3-5 = prescalar
-// 6-7 = multiplier
-
-class cMapMemHW : public cMapMem {
-public:
- // memory mapped HW
- enum {
- HW_IO=0x00, HW_SECURITY,
- HW_TIMER0_DATA=0x08, HW_TIMER0_LATCH, HW_TIMER0_CONTROL,
- HW_CRC_CONTROL=0x0e, HW_CRC_DATA,
- HW_TIMER1_DATA=0x10, HW_TIMER1_LATCH, HW_TIMER1_CONTROL,
- HW_TIMER2_DATA=0x14, HW_TIMER2_LATCH, HW_TIMER2_CONTROL
- };
-private:
- c6805& cpu;
- // timer hardware
- cN2Timer timer[MAX_TIMERS];
- // CRC hardware
- enum { CRCCALC_DELAY=8, CRC_BUSY=1, CRC_DISABLED=2, CRC_POLY=0x8408 /* ccitt*/};
- unsigned short CRCvalue;
- unsigned char CRCpos:1;
- unsigned int CRCtime, CRCit;
- unsigned short CRC16table[256];
- void GenCRC16Table();
- unsigned short CRCcalculate(unsigned short crc, unsigned char val, int bits);
- void CRCupdate(unsigned int cycles);
- //
-public:
- cMapMemHW(c6805& cpu);
- virtual unsigned char Get(unsigned short ea);
- virtual void Set(unsigned short ea, unsigned char val);
- int AddCycles(unsigned int num);
-};
-
-// ----------------------------------------------------------------
-
-class cN2Emu : protected c6805 {
-private:
- bool initDone;
-protected:
- bool Init(int id, int romv);
- virtual bool RomInit(void) { return true; }
- virtual void Stepper(void) {}
-public:
- cN2Emu(void);
- virtual ~cN2Emu() {}
- };
-
-// ----------------------------------------------------------------
-#define N2FLAG_NONE 0
-#define N2FLAG_MECM 1
-#define N2FLAG_Bx 2
-#define N2FLAG_POSTAU 4
-#define N2FLAG_Ex 8
-#define N2FLAG_INV 128
-
-// MECM Algo return values
-enum {
- MARV_SYNCING = -3, MARV_DESYNCED, MARV_NOT_PROCESSED,
- MARV_ERROR = 0, MARV_SUCCESS, MARV_MAYBE_SUCCESS
-};
-
-class cN2Prov {
-private:
- unsigned char seed[32], cwkey[8];
- bool keyValid;
-protected:
- int id, flags, seedSize;
- unsigned char lastcw[17]; // last byte used to indicate confirmed cw
- unsigned char prevcw[16], lasthd[32];
- cIDEA idea;
- //
- virtual int Algo(int algo, const unsigned char *hd, const unsigned char *ed, unsigned char *hw, const unsigned char* cw) { return false; }
- virtual void DynamicHD(unsigned char *hd, const unsigned char *ed) {}
- virtual bool NeedsCwSwap(void) { return false; }
- void ExpandInput(unsigned char *hw);
-public:
- cN2Prov(int Id, int Flags);
- virtual ~cN2Prov() {}
- bool MECM(unsigned char in15, int algo, const unsigned char *ed, unsigned char *cw);
- void SwapCW(unsigned char *cw);
- virtual int ProcessBx(unsigned char *data, int len, int pos) { return -1; }
- virtual int ProcessEx(unsigned char *data, int len, int pos) { return -1; }
- virtual bool PostProcAU(int id, unsigned char *data) { return true; }
- virtual int RunEmu(unsigned char *data, int len, unsigned short load, unsigned short run, unsigned short stop, unsigned short fetch, int fetch_len, int maxinstr=100000) { return -1; }
- bool CanHandle(int Id) { return MATCH_ID(Id,id); }
- bool HasFlags(int Flags) { return (flags&Flags)==Flags; }
- void PrintCaps(int c);
- virtual bool BFReset() { return false;}
- virtual bool BFNext() { return false; }
- };
-
-// ----------------------------------------------------------------
-
-class cN2Providers;
-
-class cN2ProvLink {
-friend class cN2Providers;
-private:
- cN2ProvLink *next;
-protected:
- int id, flags;
- //
- virtual cN2Prov *Create(void)=0;
- bool CanHandle(int Id) { return MATCH_ID(Id,id); }
- bool HasFlags(int Flags) { return (flags&Flags)==Flags; }
-public:
- cN2ProvLink(int Id, int Flags);
- virtual ~cN2ProvLink() {}
- };
-
-template<class PROV, int ID, int FLAGS> class cN2ProvLinkReg : public cN2ProvLink {
-public:
- cN2ProvLinkReg(void):cN2ProvLink(ID,FLAGS) {}
- virtual cN2Prov *Create(void) { return new PROV(id,flags); }
- };
-
-// ----------------------------------------------------------------
-
-class cN2Providers {
-friend class cN2ProvLink;
-private:
- static cN2ProvLink *first;
- //
- static void Register(cN2ProvLink *plink);
-public:
- static cN2Prov *GetProv(int Id, int Flags);
- };
-
-#endif
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "system-common.h"
-#include "smartcard.h"
-#include "parse.h"
-#include "misc.h"
-#include "log-sc.h"
-
-#define SYSTEM_CONAX 0x0B00
-
-#define SYSTEM_NAME "SC-Conax"
-#define SYSTEM_PRI -5
-#define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_CONAX)
-
-#define SC_NAME "Conax"
-#define SC_ID MAKE_SC_ID('C','o','n','x')
-
-#define L_SC 9
-#define L_SC_ALL LALL(L_SC_LASTDEF)
-
-static const struct LogModule lm_sc = {
- (LMOD_ENABLE|L_SC_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_SC_DEFDEF)&LOPT_MASK,
- "sc-conax",
- { L_SC_DEFNAMES }
- };
-ADD_MODULE(L_SC,lm_sc)
-
-// -- cSystemScConax ------------------------------------------------------------------
-
-class cSystemScConax : public cSystemScCore {
-public:
- cSystemScConax(void);
- };
-
-cSystemScConax::cSystemScConax(void)
-:cSystemScCore(SYSTEM_NAME,SYSTEM_PRI,SC_ID,"SC Conax")
-{
- hasLogger=true;
-}
-
-// -- cSystemLinkScConax --------------------------------------------------------------
-
-class cSystemLinkScConax : public cSystemLink {
-public:
- cSystemLinkScConax(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemScConax; }
- };
-
-static cSystemLinkScConax staticInit;
-
-cSystemLinkScConax::cSystemLinkScConax(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- Feature.NeedsSmartCard();
-}
-
-bool cSystemLinkScConax::CanHandle(unsigned short SysId)
-{
- bool res=false;
- cSmartCard *card=smartcards.LockCard(SC_ID);
- if(card) {
- res=card->CanHandle(SysId);
- smartcards.ReleaseCard(card);
- }
- return res;
-}
-
-// -- cSmartCardConax -----------------------------------------------------------------
-
-#define STDENTTAG 0x32
-#define PPVENTTAG 0x39
-#define ADDR_SIZE 7
-
-struct stdent {
- unsigned short id;
- char name[16], date[4][16];
- unsigned int pbm[2];
- };
-
-class cSmartCardConax : public cSmartCard, private cProviders {
-private:
- int sysId, cardVer, currency;
- bool emmInitDone;
- //
- int GetLen(void);
-public:
- cSmartCardConax(void);
- virtual bool Init(void);
- virtual bool Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw);
- virtual bool Update(int pid, int caid, const unsigned char *data);
- virtual bool CanHandle(unsigned short SysId);
- };
-
-static const struct StatusMsg msgs[] = {
- { { 0x90,0x00 }, "Instruction executed without errors", true },
- { { 0x90,0x11 }, "Bad instruction", false },
- { { 0x90,0x12 }, "Access denied, check your subscription", false },
- { { 0x90,0x13 }, "Bit error detected", false },
- { { 0x90,0x16 }, "Insuficient info", false },
- { { 0x94,0x00 }, "Instruction executed without errors, waiting for user interaction", true },
- { { 0x98,0xFF }, "Instruction accepted, data to be read", true },
- { { 0x9c,0xFF }, "Instruction accepted, data to be read", true },
- { { 0xFF,0xFF }, 0, false }
- };
-
-static const struct CardConfig cardCfg = {
- SM_8E2,1000,100
- };
-
-cSmartCardConax::cSmartCardConax(void)
-:cSmartCard(&cardCfg,msgs)
-{
- sysId=0; cardVer=0; currency=0;
- emmInitDone=false;
-}
-
-bool cSmartCardConax::CanHandle(unsigned short SysId)
-{
- return (SysId==sysId);
-}
-
-int cSmartCardConax::GetLen(void)
-{
- return (sb[0]==0x98 || sb[0]==0x9C || (sb[0]==0x90 && sb[1]==0x00)) ? sb[1] : -1;
-}
-
-bool cSmartCardConax::Init(void)
-{
- static const unsigned char cnxHist[] = { '0','B','0','0' }; // XXX is this always true ?
-
- sysId=0; cardVer=0; currency=0;
- if(atr->histLen<4 || memcmp(atr->hist, cnxHist, atr->histLen)) {
- PRINTF(L_SC_INIT,"doesn't look like a Conax card");
- return false;
- }
-
- infoStr.Begin();
- infoStr.Strcat("Conax smartcard\n");
- static unsigned char ins26[] = { 0xdd, 0x26, 0x00, 0x00, 0x03 };
- static unsigned char insc6[] = { 0xdd, 0xc6, 0x00, 0x00, 0x03 };
- static unsigned char insca[] = { 0xdd, 0xca, 0x00, 0x00, 0x00 };
- static const unsigned char hostVer[] = { 0x10,0x01,0x01 }; // host version
- unsigned char buff[MAX_LEN];
- int l;
- if(!IsoWrite(ins26,hostVer) || !Status() || (l=GetLen())<=0) {
- PRINTF(L_SC_ERROR,"card init failed (1)");
- return false;
- }
- insca[4]=l;
- if(!IsoRead(insca,buff) || !Status()) {
- PRINTF(L_SC_ERROR,"card init failed (2)");
- return false;
- }
- for(int i=0; i<l; i+=buff[i+1]+2) {
- switch(buff[i]) {
- case 0x20: cardVer=buff[i+2]; break;
- case 0x28: sysId=(buff[i+2]<<8)+buff[i+3]; break;
- case 0x2f: currency=(buff[i+2]<<8)+buff[i+3]; break;
- }
- }
- infoStr.Printf("Card v.%d Caid %04x\n",cardVer,sysId);
- PRINTF(L_SC_INIT,"card v.%d",cardVer);
- snprintf(idStr,sizeof(idStr),"%s (V.%d)",SC_NAME,cardVer);
-
- static const unsigned char stdEntits[] = { 0x1C,0x01,0x00 };
- if(IsoWrite(insc6,stdEntits) && Status() && (l=GetLen())>0) {
- infoStr.Printf("Subscriptions:\n");
- infoStr.Printf("|id |name |date |\n");
- infoStr.Printf("+----+------------+-----------------+\n");
-
- do {
- insca[4]=l;
- if(!IsoRead(insca,buff) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to read entitlements");
- break;
- }
- for(int i=0; i<l; i+=buff[i+1]+2) {
- if(buff[i]!=STDENTTAG) {
- PRINTF(L_SC_ERROR,"bad entitlement format %02x != %02x",buff[i],STDENTTAG);
- break;
- }
-
- struct stdent ent;
- memset(&ent,0,sizeof(ent));
- ent.id=(buff[i+2]<<8)|buff[i+3];
-
- int date=0, pbm=0;
- int max=i+buff[i+1]+2;
- for(int j=i+4; j<max; j+=buff[j+1]+2) {
- switch(buff[j]) {
- case 0x01: // prov. name
- snprintf(ent.name,sizeof(ent.name),"%.12s",&buff[j+2]);
- break;
- case 0x30: // date
- if(date<=3) {
- snprintf(ent.date[date],sizeof(ent.date[0]),"%02d.%02d.%02d",buff[j+2]&0x1F,buff[j+3]&0xF,(1990+((buff[j+3]>>4)+((buff[j+2]>>5)&0x7)*10))%100);
- date++;
- }
- break;
- case 0x20:
- if(pbm<=1) {
- ent.pbm[pbm]=(buff[j+2]<<24)|(buff[j+3]<<16)|(buff[j+4]<<8)|buff[j+5];
- pbm++;
- }
- break;
- }
- }
- infoStr.Printf("|%04X|%s|%s-%s|\n",ent.id,ent.name,ent.date[0],ent.date[1]);
- infoStr.Printf("| | |%s-%s|\n",ent.date[2],ent.date[3]);
- }
- } while((l=GetLen())>0);
- }
- else
- PRINTF(L_SC_ERROR,"requesting entitlements failed");
-
-/*
- static const unsigned char ppvEntits[] = { 0x1C,0x01,0x01 };
- if(IsoWrite(ins26,ppvEntits) && Status()) {
- while((l=GetLen())>0) {
- insca[4]=l;
- if(!IsoRead(insca,buff) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to read PPV entitlements");
- break;
- }
-
-
- }
- }
- else
- PRINTF(L_SC_ERROR,"getting PPV entitlements failed");
-*/
-
- emmInitDone=false;
- infoStr.Finish();
- return true;
-}
-
-bool cSmartCardConax::Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
-{
- static unsigned char insa2[] = { 0xDD,0xA2,0x00,0x00,0x00 };
- static unsigned char insca[] = { 0xDD,0xCA,0x00,0x00,0x00 };
-
- int l;
- if((l=CheckSctLen(data,3))<=0) return false;
- unsigned char buff[MAX_LEN];
- buff[0]=0x14;
- buff[1]=l+1;
- buff[2]=0;
- memcpy(buff+3,data,l);
-
- insa2[4]=l+3;
- if(!IsoWrite(insa2,buff) || !Status() || (l=GetLen())<=0) return false;
- int gotIdx=0;
- do {
- insca[4]=l;
- if(!IsoRead(insca,buff) || !Status()) return false;
- for(int i=0; i<l; i+=buff[i+1]+2) {
- switch(buff[i]) {
- case 0x25:
- if(buff[i+1]>=13) {
- int idx=buff[i+4];
- if(idx<=1) {
- gotIdx|=(1<<idx);
- memcpy(cw+idx*8,&buff[i+7],8);
- }
- }
- break;
- }
- }
- } while((l=GetLen())>0);
- if(gotIdx!=3) PRINTF(L_SC_ERROR,"strange, only got index %d cw. Failing... (this may be a bug)",gotIdx==1?0:1);
- return gotIdx==3;
-}
-
-bool cSmartCardConax::Update(int pid, int caid, const unsigned char *data)
-{
- static unsigned char ins82[] = { 0xdd,0x82,0x00,0x00,0x10 };
- static unsigned char ins84[] = { 0xdd,0x84,0x00,0x00,0x00 };
- static unsigned char insca[] = { 0xdd,0xca,0x00,0x00,0x00 };
- static unsigned char ins82Data[] = { 0x11,0x0e,0x01,0xb0,0x0f,0xff,0xff,0xdd,0x00,0x00,0x09,0x04,0x0b,0x00,0x00,0x00 };
- unsigned char buff[MAX_LEN];
-
- if(!emmInitDone) {
- ins82Data[14]=(pid>>8)&0xFF;
- ins82Data[15]=pid&0xFF;
- int l;
- if(!IsoWrite(ins82,ins82Data) || !Status() || (l=GetLen())<=0) return false;
- insca[4]=l;
- if(!IsoRead(insca,buff) || !Status()) return false;
- if(buff[0]!=0x22 || buff[1]+2!=l) {
- PRINTF(L_SC_ERROR,"bad card reply on EMM init");
- return false;
- }
-
- LBSTARTF(L_SC_INIT);
- LBPUT("set filter");
- Clear();
- for(int i=2; i<l; i+=buff[i+1]+2) {
- if(buff[i]==0x23) { // Card Address
- if(buff[i+1]==ADDR_SIZE) {
- AddProv(new cProviderConax(&buff[i+2]));
- char str[ADDR_SIZE*2+4];
- LBPUT(" addr %s",HexStr(str,&buff[i+2],ADDR_SIZE));
- }
- else {
- LBPUT(" bad addr cmd (size=%d)",buff[i+1]);
- return false;
- }
- }
- }
- LBEND();
- emmInitDone=true;
- }
-
- if(MatchProv(data)) {
- int l;
- if((l=CheckSctLen(data,2))>0) {
- buff[0]=0x12; buff[1]=l;
- memcpy(&buff[2],data,l);
- ins84[4]=l+2;
- if(IsoWrite(ins84,buff) && !Status()) return true;
- }
- }
- return false;
-}
-
-// -- cSmartCardLinkConax -------------------------------------------------------------
-
-class cSmartCardLinkConax : public cSmartCardLink {
-public:
- cSmartCardLinkConax(void):cSmartCardLink(SC_NAME,SC_ID) {}
- virtual cSmartCard *Create(void) { return new cSmartCardConax(); }
- };
-
-static cSmartCardLinkConax staticScInit;
+++ /dev/null
-#
-# Smartcard Conax
-#
-TARGET = sc_conax
-OBJS = sc-conax.o
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "system-common.h"
-#include "smartcard.h"
-#include "data.h"
-#include "parse.h"
-#include "crypto.h"
-#include "opts.h"
-#include "misc.h"
-#include "log-sc.h"
-#include "log-core.h"
-
-#define SYSTEM_NAME "SC-Cryptoworks"
-#define SYSTEM_PRI -5
-
-#define SC_NAME "Cryptoworks"
-#define SC_ID MAKE_SC_ID('C','r','W','o')
-
-#define L_SC 10
-#define L_SC_EXTRA LCLASS(L_SC,L_SC_LASTDEF<<1)
-#define L_SC_ALL LALL(L_SC_EXTRA)
-
-static const struct LogModule lm_sc = {
- (LMOD_ENABLE|L_SC_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_SC_DEFDEF)&LOPT_MASK,
- "sc-cryptoworks",
- { L_SC_DEFNAMES,"extra" }
- };
-ADD_MODULE(L_SC,lm_sc)
-
-static int disableParental=0;
-
-// -- cSystemScCryptoworks ---------------------------------------------------------------
-
-class cSystemScCryptoworks : public cSystemScCore {
-public:
- cSystemScCryptoworks(void);
- };
-
-cSystemScCryptoworks::cSystemScCryptoworks(void)
-:cSystemScCore(SYSTEM_NAME,SYSTEM_PRI,SC_ID,"SC Cryptoworks")
-{
- hasLogger=true;
-}
-
-// -- cSystemLinkScCryptoworks --------------------------------------------------------
-
-class cSystemLinkScCryptoworks : public cSystemLink {
-public:
- cSystemLinkScCryptoworks(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemScCryptoworks; }
- };
-
-static cSystemLinkScCryptoworks staticInit;
-
-cSystemLinkScCryptoworks::cSystemLinkScCryptoworks(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- static const char *rat[] = {
- trNOOP("don't touch"),
- trNOOP("disable")
- };
-
- opts=new cOpts(SYSTEM_NAME,1);
- opts->Add(new cOptSel("DisableParental",trNOOP("SC-Cryptoworks: Parental rating"),&disableParental,sizeof(rat)/sizeof(char *),rat));
- Feature.NeedsSmartCard();
-}
-
-bool cSystemLinkScCryptoworks::CanHandle(unsigned short SysId)
-{
- bool res=false;
- cSmartCard *card=smartcards.LockCard(SC_ID);
- if(card) {
- res=card->CanHandle(SysId);
- smartcards.ReleaseCard(card);
- }
- return res;
-}
-
-// -- cSmartCardDataCryptoworks -----------------------------------------------------
-
-enum eDataType { dtIPK, dtUCPK, dtPIN };
-
-class cSmartCardDataCryptoworks : public cSmartCardData {
-private:
- int IdLen(void) const { return type==dtIPK ? 2:5; }
-public:
- eDataType type;
- unsigned char id[5], pin[4];
- cBN key;
- //
- cSmartCardDataCryptoworks(void);
- cSmartCardDataCryptoworks(eDataType Type, unsigned char *Id);
- virtual bool Parse(const char *line);
- virtual bool Matches(cSmartCardData *param);
- };
-
-cSmartCardDataCryptoworks::cSmartCardDataCryptoworks(void)
-:cSmartCardData(SC_ID)
-{}
-
-cSmartCardDataCryptoworks::cSmartCardDataCryptoworks(eDataType Type, unsigned char *Id)
-:cSmartCardData(SC_ID)
-{
- type=Type;
- memset(id,0,sizeof(id));
- memcpy(id,Id,IdLen());
-}
-
-bool cSmartCardDataCryptoworks::Matches(cSmartCardData *param)
-{
- cSmartCardDataCryptoworks *cd=(cSmartCardDataCryptoworks *)param;
- return cd->type==type && !memcmp(cd->id,id,IdLen());
-}
-
-bool cSmartCardDataCryptoworks::Parse(const char *line)
-{
- line=skipspace(line);
- if(!strncasecmp(line,"IPK",3)) { type=dtIPK; line+=3; }
- else if(!strncasecmp(line,"UCPK",4)) { type=dtUCPK; line+=4; }
- else if(!strncasecmp(line,"PIN",3)) { type=dtPIN; line+=3; }
- else {
- PRINTF(L_CORE_LOAD,"smartcarddatacryptoworks: format error: datatype");
- return false;
- }
- line=skipspace(line);
- if(GetHex(line,id,IdLen())!=IdLen()) {
- PRINTF(L_CORE_LOAD,"smartcarddatacryptoworks: format error: caid/serial");
- return false;
- }
- line=skipspace(line);
- if(type==dtPIN) {
- for(int i=0; i<4; i++) {
- if(!isdigit(*line)) {
- PRINTF(L_CORE_LOAD,"smartcarddatacryptoworks: format error: pin");
- return false;
- }
- pin[i]=*line++;
- }
- }
- else {
- unsigned char buff[64];
- if(GetHex(line,buff,64,true)!=64) {
- PRINTF(L_CORE_LOAD,"smartcarddatacryptoworks: format error: ipk/ucpk");
- return false;
- }
- BN_bin2bn(buff,64,key);
- }
- return true;
-}
-
-// -- cSmartCardCryptoworks -----------------------------------------------------------
-
-class cSmartCardCryptoworks : public cSmartCard, public cIdSet {
-private:
- int caid;
- cRSA rsa;
- cBN ucpk, exp;
- bool ucpkValid;
- //
- int GetLen(void);
- bool EndOfData(void);
- bool SelectFile(int file);
- int ReadRecord(unsigned char *buff, int num);
- int ReadData(unsigned char *buff, int len);
-public:
- cSmartCardCryptoworks(void);
- virtual bool Init(void);
- virtual bool Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw);
- virtual bool Update(int pid, int caid, const unsigned char *data);
- virtual bool CanHandle(unsigned short CaId);
- };
-
-static const struct StatusMsg msgs[] = {
- { { 0x90,0x00 }, "Instruction executed without errors", true },
- { { 0x92,0x40 }, "Memory problem", false },
- { { 0x94,0x02 }, "Out of range", false },
- { { 0x94,0x04 }, "File not found", false },
- { { 0x98,0x04 }, "Verification failed (wrong PIN)", false },
- { { 0x98,0x05 }, "Wrong signature", false },
- { { 0x98,0x40 }, "Verification failed, card blocked (deblocking by uplink required)", false },
- { { 0x9F,0xFF }, "Instruction accepted, data to be read", true },
- { { 0xFF,0xFF }, 0, false }
- };
-
-static const struct CardConfig cardCfg = {
- SM_8E2,1000,100
- };
-
-struct chid_dat {
- unsigned int chid, version;
- unsigned char id, status;
- char from[16], to[16], name[16];
- };
-
-cSmartCardCryptoworks::cSmartCardCryptoworks(void)
-:cSmartCard(&cardCfg,msgs)
-{
- static const unsigned char cwexp[] = { 0x01,0x00,0x01 };
- BN_bin2bn(cwexp,sizeof(cwexp),exp);
- ucpkValid=false;
-}
-
-int cSmartCardCryptoworks::GetLen(void)
-{
- return (sb[0]==0x9F) ? sb[1] : -1;
-}
-
-bool cSmartCardCryptoworks::EndOfData(void)
-{
- return sb[0]==0x94 && sb[1]==0x02;
-}
-
-bool cSmartCardCryptoworks::SelectFile(int file)
-{
- static unsigned char insa4[] = { 0xA4,0xA4,0x00,0x00,0x02,0x00,0x00 };
- insa4[5]=file>>8;
- insa4[6]=file&0xFF;
- return IsoWrite(insa4,&insa4[5]) && Status();
-}
-
-int cSmartCardCryptoworks::ReadRecord(unsigned char *buff, int num)
-{
- static unsigned char insa2[] = { 0xA4,0xA2,0x00,0x00,0x01,0x00 };
- static unsigned char insb2[] = { 0xA4,0xB2,0x00,0x00,0x00 };
- insa2[5]=num;
- if(IsoWrite(insa2,&insa2[5]) && Status() && (num=GetLen())>0) {
- insb2[4]=num;
- if(IsoRead(insb2,buff) && Status()) return num;
- }
- return -1;
-}
-
-int cSmartCardCryptoworks::ReadData(unsigned char *buff, int len)
-{
- static unsigned char insc0[] = { 0xA4,0xC0,0x00,0x00,0x00 };
- insc0[4]=len;
- if(IsoRead(insc0,buff) && Status()) return len;
- return -1;
-}
-
-bool cSmartCardCryptoworks::Init(void)
-{
- if(atr->histLen<6 || atr->hist[1]!=0xC4 || atr->hist[4]!=0x8F || atr->hist[5]!=0xF1) {
- PRINTF(L_SC_INIT,"doesn't look like a Cryptoworks card");
- return false;
- }
- infoStr.Begin();
- infoStr.Strcat("Cryptoworks smartcard\n");
- ucpkValid=false;
- unsigned char buff[MAX_LEN];
- int mfid=0x3F20;
- if(ReadData(buff,0x11)>0 && buff[0]==0xDF && buff[1]>=6)
- mfid=buff[6]*256+buff[7];
- else PRINTF(L_SC_ERROR,"reading MF-ID failed, using default 3F20");
-
- unsigned char Caid[2], serial[5];
- if(!SelectFile(0x2F01) || ReadRecord(buff,0xD1)<4) {
- PRINTF(L_SC_ERROR,"reading record 2f01/d1 failed");
- return false;
- }
- memcpy(Caid,&buff[2],2);
- caid=buff[2]*256+buff[3];
- if(ReadRecord(buff,0x80)<7) {
- PRINTF(L_SC_ERROR,"reading record 2f01/80 failed");
- return false;
- }
- SetCard(new cCardCryptoworks(&buff[2]));
- memcpy(serial,&buff[2],5);
- snprintf(idStr,sizeof(idStr),"%s (V.%d)",SC_NAME,atr->hist[2]);
- char str[20];
- infoStr.Printf("Card v.%d (PINcount=%d)\n"
- "Caid %04x Serial %s\n",
- atr->hist[2],atr->hist[3],caid,HexStr(str,&buff[2],5));
- PRINTF(L_SC_INIT,"card v.%d (pindown=%d) caid %04x serial %s MF %04X",atr->hist[2],atr->hist[3],caid,HexStr(str,&buff[2],5),mfid);
- if(ReadRecord(buff,0x9F)>=3) {
- const char *n="(unknown)";
- if(ReadRecord(buff+10,0xC0)>=18) n=(char *)buff+10+2;
- infoStr.Printf("Issuer: 0x%02x (%.16s)\n",buff[2],n);
- PRINTF(L_SC_INIT,"card issuer: 0x%02x %.16s",buff[2],n);
- }
- if(ReadRecord(buff,0x9E)>=66) {
- HEXDUMP(L_SC_EXTRA,&buff[2],64,"card ISK");
- cSmartCardDataCryptoworks cd(dtIPK,Caid);
- cSmartCardDataCryptoworks *entry=(cSmartCardDataCryptoworks *)smartcards.FindCardData(&cd);
- if(entry) {
- PRINTF(L_SC_EXTRA,"got IPK from smartcard.conf");
- if(rsa.RSA(&buff[2],&buff[2],64,exp,entry->key,false)>0) {
- HEXDUMP(L_SC_EXTRA,&buff[2],64,"decrypted ISK");
- if(buff[2] == ((mfid&0xFF)>>1)) {
- buff[2]|=0x80;
- BN_bin2bn(&buff[2],64,ucpk);
- ucpkValid=true;
- PRINTF(L_SC_INIT,"got UCPK from IPK/ISK");
- }
- else PRINTF(L_SC_ERROR,"UCPK check failed %02x != %02x",buff[2],(mfid&0xFF)>>1);
- }
- else PRINTF(L_SC_ERROR,"RSA failed for UCPK");
- }
- }
- if(!ucpkValid) {
- cSmartCardDataCryptoworks cd(dtUCPK,serial);
- cSmartCardDataCryptoworks *entry=(cSmartCardDataCryptoworks *)smartcards.FindCardData(&cd);
- if(entry) {
- BN_copy(ucpk,entry->key);
- ucpkValid=true;
- PRINTF(L_SC_INIT,"got UCPK from smartcard.conf");
- }
- }
- if(!ucpkValid) PRINTF(L_GEN_WARN,"no valid UCPK for cryptoworks smartcard");
-
- // read entitlements
- static unsigned char insb8[] = { 0xA4,0xB8,0x00,0x00,0x0C };
- unsigned char provId[16];
- unsigned int count=0;
- insb8[2]=insb8[3]=0x00;
- while(IsoRead(insb8,buff) && !EndOfData() && Status()) {
- if(buff[0]==0xDF && buff[1]==0x0A) {
- int fileno=(buff[4]&0x3F)*256+buff[5];
- if((fileno&0xFF00)==0x1F00) {
- provId[count++]=fileno&0xFF;
- if(count>=sizeof(provId)) break;
- }
- }
- insb8[2]=insb8[3]=0xFF;
- }
- for(unsigned int i=0; i<count ; i++) {
- if(SelectFile(0x1F00+provId[i])) {
- const char *n="(unknown)";
- if(SelectFile(0x0E11) && ReadRecord(buff,0xD6)>=18) n=(char *)buff+2;
- infoStr.Printf("Provider %d: 0x%02x (%.16s)\n",i,provId[i],n);
- PRINTF(L_SC_INIT,"provider %d: 0x%02x %.16s",i,provId[i],n);
- static unsigned char insa2_0[] = { 0xA4,0xA2,0x01,0x00,0x03,0x83,0x01,0x00 };
- static unsigned char insa2_1[] = { 0xA4,0xA2,0x01,0x00,0x05,0x8C,0x00,0x00,0x00,0x00 };
- static unsigned char insb2[] = { 0xA4,0xB2,0x00,0x00,0x00 };
- static const unsigned int fn[] = { 0x0f00,0x0f20,0x0f40,0x0f60,0 };
- static const char *fnName[] = { "Download","Subscriptions","PPV Events","PPV Events",0 };
- bool first=true;
- for(int j=0; fn[j]; j++) {
- if(SelectFile(fn[j])) {
- insa2_0[7]=provId[i];
- unsigned char *ins=(j==1) ? insa2_1 : insa2_0;
- int l;
- if(IsoWrite(ins,&ins[5]) && Status() && (l=GetLen())>0) {
- if(first) {
- infoStr.Printf("id|chid|st|date |name\n");
- PRINTF(L_SC_INIT,"| id | chid | stat | date | version | name ");
- first=false;
- }
- infoStr.Printf( "--+----+--+-----------------+------\n"
- "%s\n",
- fnName[j]);
- PRINTF(L_SC_INIT,"+----+------+------+-------------------+----------+-------------");
- PRINTF(L_SC_INIT,"| %s",fnName[j]);
- insb2[3]=0x00;
- insb2[4]=l;
- while(IsoRead(insb2,buff) && !EndOfData() && Status()) {
- struct chid_dat chid;
- memset(&chid,0,sizeof(chid));
- for(int k=0; k<l; k+=buff[k+1]+2) {
- switch(buff[k]) {
- case 0x83:
- chid.id=buff[k+2];
- break;
- case 0x8c:
- chid.status=buff[k+2];
- chid.chid=buff[k+3]*256+buff[k+4];
- break;
- case 0x8D:
- snprintf(chid.from,sizeof(chid.from),"%02d.%02d.%02d",buff[k+3]&0x1F,((buff[k+2]&1)<<3)+(buff[k+3]>>5),(1990+(buff[k+2]>>1))%100);
- snprintf(chid.to ,sizeof(chid.to) ,"%02d.%02d.%02d",buff[k+5]&0x1F,((buff[k+4]&1)<<3)+(buff[k+5]>>5),(1990+(buff[k+4]>>1))%100);
- break;
- case 0xD5:
- snprintf(chid.name,sizeof(chid.name),"%.12s",&buff[k+2]);
- chid.version=Bin2Int(&buff[k+14],4);
- break;
- }
- }
- infoStr.Printf("%02x|%04x|%02x|%s-%s|%.12s\n",
- chid.id,chid.chid,chid.status,chid.from,chid.to,chid.name);
- PRINTF(L_SC_INIT,"| %02x | %04x | %02x | %s-%s | %08x | %.12s",
- chid.id,chid.chid,chid.status,chid.from,chid.to,chid.version,chid.name);
- insb2[3]=0x01;
- }
- }
- }
- }
- }
- }
-
- if(disableParental) {
- bool pinOK=false;
- if(SelectFile(0x2F11) && ReadRecord(buff,atr->hist[3])>=7) {
- pinOK=true;
- PRINTF(L_SC_INIT,"read PIN from card.");
- }
- if(!pinOK) {
- cSmartCardDataCryptoworks cd(dtPIN,serial);
- cSmartCardDataCryptoworks *entry=(cSmartCardDataCryptoworks *)smartcards.FindCardData(&cd);
- if(entry) {
- memcpy(&buff[2],entry->pin,4);
- pinOK=true;
- PRINTF(L_SC_INIT,"got PIN from smartcard.conf.");
- }
- }
- if(pinOK) {
- static const unsigned char ins24[] = { 0xA4,0x24,0x00,0x01,0x05 };
- PRINTF(L_SC_INIT,"your card PIN is %.4s",&buff[2]);
- // parental rating
- // 0x00 - undefined
- // 0x01-0x0f - minimum age=rating+3 years
- // 0x10-0xff - reserved for provider usage
- buff[6]=0;
- if(IsoWrite(ins24,&buff[2]) && Status())
- PRINTF(L_SC_INIT,"parental rating set to %02x",buff[6]);
- else
- PRINTF(L_SC_ERROR,"failed to set parental rating.");
- }
- else PRINTF(L_SC_INIT,"no PIN available.");
- }
-
- infoStr.Finish();
- return true;
-}
-
-bool cSmartCardCryptoworks::CanHandle(unsigned short CaId)
-{
- return CaId==caid;
-}
-
-bool cSmartCardCryptoworks::Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
-{
- static unsigned char ins4c[] = { 0xA4,0x4C,0x00,0x00,0x00 };
-
- unsigned char nanoD4[10];
- int l=CheckSctLen(data,-5+(ucpkValid ? sizeof(nanoD4):0));
- if(l>5) {
- unsigned char buff[MAX_LEN];
- if(ucpkValid) {
- memcpy(buff,data,l);
- nanoD4[0]=0xD4;
- nanoD4[1]=0x08;
- for(unsigned int i=2; i<sizeof(nanoD4); i++) nanoD4[i]=rand();
- memcpy(&buff[l],nanoD4,sizeof(nanoD4));
- data=buff; l+=sizeof(nanoD4);
- }
- ins4c[3]=ucpkValid ? 2 : 0;
- ins4c[4]=l-5;
- if(IsoWrite(ins4c,&data[5]) && Status() &&
- (l=GetLen())>0 && ReadData(buff,l)==l) {
- int r=0;
- for(int i=0; i<l && r<2; ) {
- int n=buff[i+1];
- switch(buff[i]) {
- case 0xDB: // CW
- PRINTF(L_SC_EXTRA,"nano DB (cw)");
- if(n==0x10) {
- memcpy(cw,&buff[i+2],16);
- r|=1;
- }
- break;
- case 0xDF: // signature
- PRINTF(L_SC_EXTRA,"nano DF %02x (sig)",n);
- if(n==0x08) {
- if((buff[i+2]&0x50)==0x50) {
- if(buff[i+3]&0x01) PRINTF(L_SC_ERROR,"not decyphered. PIN protected?");
- else if(!(buff[i+5]&0x80)) PRINTF(L_SC_ERROR,"missing entitlement. Check your subscription");
- else r|=2;
- }
- }
- else if(n==0x40) { // camcrypt
- if(ucpkValid) {
- if(rsa.RSA(&buff[i+2],&buff[i+2],n,exp,ucpk,false)<=0) {
- PRINTF(L_SC_ERROR,"camcrypt RSA failed.");
- return false;
- }
- HEXDUMP(L_SC_EXTRA,&buff[i+2],n,"after camcrypt");
- if(!memmem(&buff[i+2+4],n-4,nanoD4,sizeof(nanoD4))) {
- PRINTF(L_SC_ERROR,"camcrypt failed. Check IPK/UCPK in your smartcard.conf!");
- return false;
- }
- r=0; l=n-4; n=4;
- }
- else {
- PRINTF(L_SC_ERROR,"valid UCPK needed for camcrypt! Check your smartcard.conf for a IPK/UCPK!");
- return false;
- }
- }
- break;
- default:
- PRINTF(L_SC_EXTRA,"nano %02x (unhandled)",buff[i]);
- break;
- }
- i+=n+2;
- }
- return r==3;
- }
- }
- return false;
-}
-
-bool cSmartCardCryptoworks::Update(int pid, int caid, const unsigned char *data)
-{
- static unsigned char ins[] = { 0xA4,0x42,0x00,0x00,0x00 };
-
- cAssembleData ad(data);
- if(MatchAndAssemble(&ad,0,0)) {
- while((data=ad.Assembled())) {
- int c, n;
- switch(data[0]) {
- case 0x82: c=0x42; n=10; break;
- case 0x84: c=0x48; n=9; break;
- case 0x88:
- case 0x89: c=0x44; n=5; break;
- default: continue;
- }
-
- int len=CheckSctLen(data,-n);
- if(len>n) {
- ins[1]=c;
- ins[4]=len-n;
- if(IsoWrite(ins,&data[n])) Status();
- }
- }
- return true;
- }
- return false;
-}
-
-// -- cSmartCardLinkCryptoworks -------------------------------------------------------
-
-class cSmartCardLinkCryptoworks : public cSmartCardLink {
-public:
- cSmartCardLinkCryptoworks(void):cSmartCardLink(SC_NAME,SC_ID) {}
- virtual cSmartCard *Create(void) { return new cSmartCardCryptoworks(); }
- virtual cSmartCardData *CreateData(void) { return new cSmartCardDataCryptoworks; }
- };
-
-static cSmartCardLinkCryptoworks staticScInit;
+++ /dev/null
-#
-# Smartcard Cryptoworks
-#
-TARGET = sc_cryptoworks
-OBJS = sc-cryptoworks.o
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/rand.h>
-
-#include "system-common.h"
-#include "smartcard.h"
-#include "crypto.h"
-#include "data.h"
-#include "misc.h"
-#include "parse.h"
-#include "log-sc.h"
-#include "log-core.h"
-
-#define SYSTEM_NAME "SC-Irdeto"
-#define SYSTEM_PRI -5
-
-#define SC_NAME "Irdeto"
-#define SC_ID MAKE_SC_ID('I','r','d','t')
-
-#define L_SC 8
-#define L_SC_ALL LALL(L_SC_LASTDEF)
-
-static const struct LogModule lm_sc = {
- (LMOD_ENABLE|L_SC_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_SC_DEFDEF)&LOPT_MASK,
- "sc-irdeto",
- { L_SC_DEFNAMES }
- };
-ADD_MODULE(L_SC,lm_sc)
-
-static void BN_complement(const unsigned char *data, int len, BIGNUM *bn)
-{
- unsigned char *buff=AUTOMEM(len);
- for(int i=len-1; i>=0; i--) buff[i]=~data[i];
- BN_bin2bn(buff,len,bn);
- BN_add_word(bn,1);
-}
-
-// -- cSystemScIrdeto ----------------------------------------------------------
-
-class cSystemScIrdeto : public cSystemScCore {
-public:
- cSystemScIrdeto(void);
- };
-
-cSystemScIrdeto::cSystemScIrdeto(void)
-:cSystemScCore(SYSTEM_NAME,SYSTEM_PRI,SC_ID,"SC Irdeto")
-{
- hasLogger=true;
-}
-
-// -- cSystemLinkScIrdeto ------------------------------------------------------
-
-class cSystemLinkScIrdeto : public cSystemLink {
-public:
- cSystemLinkScIrdeto(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemScIrdeto; }
- };
-
-static cSystemLinkScIrdeto staticInit;
-
-cSystemLinkScIrdeto::cSystemLinkScIrdeto(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- Feature.NeedsSmartCard();
-}
-
-bool cSystemLinkScIrdeto::CanHandle(unsigned short SysId)
-{
- bool res=false;
- cSmartCard *card=smartcards.LockCard(SC_ID);
- if(card) {
- res=card->CanHandle(SysId);
- smartcards.ReleaseCard(card);
- }
- return res;
-}
-
-// -- cCamCrypt ----------------------------------------------------------------
-
-class cCamCrypt {
-private:
- static const unsigned char cryptTable[];
- bool randomInit;
- cRSA rsa;
- cBN cardExp, cardMod;
- //
- void GenerateRandom(unsigned char *buf, int len);
- void RotateRight8Byte(unsigned char *key);
- void RotateLeft8Byte(unsigned char *key);
-protected:
- void CamCrypt(const unsigned char *key, unsigned char *data);
- void RevCamCrypt(const unsigned char *key, unsigned char *data);
- //
- bool SetupCardFiles(unsigned char *data, int len, BIGNUM *exp, BIGNUM *mod);
- void PrepareCamMessage(unsigned char *plain);
- bool EncryptCamMessage(unsigned char *encrypted, const unsigned char *plain);
- const unsigned char *CamKey(const unsigned char *data) { return data+8; }
- const unsigned char *HelperKey(const unsigned char *data) { return data+24; }
-public:
- cCamCrypt(void);
- };
-
-const unsigned char cCamCrypt::cryptTable[256] = {
- 0xDA,0x26,0xE8,0x72,0x11,0x52,0x3E,0x46,0x32,0xFF,0x8C,0x1E,0xA7,0xBE,0x2C,0x29,
- 0x5F,0x86,0x7E,0x75,0x0A,0x08,0xA5,0x21,0x61,0xFB,0x7A,0x58,0x60,0xF7,0x81,0x4F,
- 0xE4,0xFC,0xDF,0xB1,0xBB,0x6A,0x02,0xB3,0x0B,0x6E,0x5D,0x5C,0xD5,0xCF,0xCA,0x2A,
- 0x14,0xB7,0x90,0xF3,0xD9,0x37,0x3A,0x59,0x44,0x69,0xC9,0x78,0x30,0x16,0x39,0x9A,
- 0x0D,0x05,0x1F,0x8B,0x5E,0xEE,0x1B,0xC4,0x76,0x43,0xBD,0xEB,0x42,0xEF,0xF9,0xD0,
- 0x4D,0xE3,0xF4,0x57,0x56,0xA3,0x0F,0xA6,0x50,0xFD,0xDE,0xD2,0x80,0x4C,0xD3,0xCB,
- 0xF8,0x49,0x8F,0x22,0x71,0x84,0x33,0xE0,0x47,0xC2,0x93,0xBC,0x7C,0x3B,0x9C,0x7D,
- 0xEC,0xC3,0xF1,0x89,0xCE,0x98,0xA2,0xE1,0xC1,0xF2,0x27,0x12,0x01,0xEA,0xE5,0x9B,
- 0x25,0x87,0x96,0x7B,0x34,0x45,0xAD,0xD1,0xB5,0xDB,0x83,0x55,0xB0,0x9E,0x19,0xD7,
- 0x17,0xC6,0x35,0xD8,0xF0,0xAE,0xD4,0x2B,0x1D,0xA0,0x99,0x8A,0x15,0x00,0xAF,0x2D,
- 0x09,0xA8,0xF5,0x6C,0xA1,0x63,0x67,0x51,0x3C,0xB2,0xC0,0xED,0x94,0x03,0x6F,0xBA,
- 0x3F,0x4E,0x62,0x92,0x85,0xDD,0xAB,0xFE,0x10,0x2E,0x68,0x65,0xE7,0x04,0xF6,0x0C,
- 0x20,0x1C,0xA9,0x53,0x40,0x77,0x2F,0xA4,0xFA,0x6D,0x73,0x28,0xE2,0xCD,0x79,0xC8,
- 0x97,0x66,0x8E,0x82,0x74,0x06,0xC7,0x88,0x1A,0x4A,0x6B,0xCC,0x41,0xE9,0x9D,0xB8,
- 0x23,0x9F,0x3D,0xBF,0x8D,0x95,0xC5,0x13,0xB9,0x24,0x5A,0xDC,0x64,0x18,0x38,0x91,
- 0x7F,0x5B,0x70,0x54,0x07,0xB6,0x4B,0x0E,0x36,0xAC,0x31,0xE6,0xD6,0x48,0xAA,0xB4
- };
-
-cCamCrypt::cCamCrypt(void)
-{
- randomInit=false;
-}
-
-void cCamCrypt::GenerateRandom(unsigned char *randVal, int len)
-{
- static const unsigned int seed = 0x9E3779B9;
- if(!randomInit) {
- RAND_seed(&seed,sizeof(seed));
- randomInit=true;
- }
- RAND_bytes(randVal,len);
-}
-
-//
-// Rotates the 8 bytes bitwise right
-//
-void cCamCrypt::RotateRight8Byte(unsigned char *key)
-{
- unsigned char t1=key[0];
- for(int k=7 ; k>=0 ; k--) {
- unsigned char t2=t1<<7;
- t1=key[k]; key[k]=(t1>>1) | t2;
- }
-}
-
-//
-// Rotates the 8 bytes bitwise left
-//
-void cCamCrypt::RotateLeft8Byte(unsigned char *key)
-{
- unsigned char t1=key[7];
- for(int k=0 ; k<8 ; k++) {
- unsigned char t2=t1>>7;
- t1=key[k]; key[k]=(t1<<1) | t2;
- }
-}
-
-void cCamCrypt::RevCamCrypt(const unsigned char *key, unsigned char *data)
-{
- unsigned char localKey[8];
- memcpy(localKey,key,sizeof(localKey));
- for(int idx1=0 ; idx1<8 ; idx1++) {
- for(int idx2=0 ; idx2<8 ; idx2++) {
- const unsigned char tmp1=cryptTable[data[7] ^ localKey[idx2] ^ idx1];
- const unsigned char tmp2=data[0];
- data[0]=data[1];
- data[1]=data[2];
- data[2]=data[3];
- data[3]=data[4];
- data[4]=data[5];
- data[5]=data[6] ^ tmp1;
- data[6]=data[7];
- data[7]=tmp1 ^ tmp2 ;
- }
- RotateLeft8Byte(localKey);
- }
-}
-
-void cCamCrypt::CamCrypt(const unsigned char *key, unsigned char *data)
-{
- unsigned char localKey[8];
- memcpy(localKey,key,sizeof(localKey));
- for(int idx1=0 ; idx1<7 ; idx1++) RotateLeft8Byte(localKey);
- for(int idx1=7 ; idx1>=0 ; idx1--) {
- for(int idx2=7 ; idx2>=0 ; idx2--) {
- const unsigned char tmp1=cryptTable[data[6] ^ localKey[idx2] ^ idx1];
- const unsigned char tmp2=data[0];
- data[0]=data[7] ^ tmp1;
- data[7]=data[6];
- data[6]=data[5] ^ tmp1;
- data[5]=data[4];
- data[4]=data[3];
- data[3]=data[2];
- data[2]=data[1];
- data[1]=tmp2;
- }
- RotateRight8Byte(localKey);
- }
-}
-
-bool cCamCrypt::SetupCardFiles(unsigned char *data, int len, BIGNUM *exp, BIGNUM *mod)
-{
- if(rsa.RSA(data,data,len,exp,mod,false)<=0 || (data[0]!=0x80 || data[11]!=0x40 || data[12]!=0x06))
- return false;
- BN_complement(data+13,64,cardMod);
- BN_bin2bn(data+13+64,6,cardExp);
- return true;
-}
-
-void cCamCrypt::PrepareCamMessage(unsigned char *plain)
-{
-/*
- static const unsigned char camMsg[] = {
- 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00
- };
- memcpy(plain,camMsg,sizeof(camMsg));
-*/
- plain[0]=0x80;
- memset(plain+1 ,0x00,7);
- GenerateRandom(plain+16,16);
- memcpy(plain+8,plain+16,8);
- memset(plain+32,0xFF,31);
- plain[63]=0x00;
-}
-
-bool cCamCrypt::EncryptCamMessage(unsigned char *encrypted, const unsigned char *plain)
-{
- return rsa.RSA(encrypted,plain,64,cardExp,cardMod,false)>0;
-}
-
-// -- cSmartCardDataIrdeto -----------------------------------------------------
-
-class cSmartCardDataIrdeto : public cSmartCardData {
-public:
- int acs, caid;
- cBN mod, exp;
- bool plain;
- //
- cSmartCardDataIrdeto(void);
- cSmartCardDataIrdeto(int Acs, int Caid);
- virtual bool Parse(const char *line);
- virtual bool Matches(cSmartCardData *param);
- };
-
-cSmartCardDataIrdeto::cSmartCardDataIrdeto(void)
-:cSmartCardData(SC_ID)
-{
- plain=false;
-}
-
-cSmartCardDataIrdeto::cSmartCardDataIrdeto(int Acs, int Caid)
-:cSmartCardData(SC_ID)
-{
- acs=Acs; caid=Caid;
- plain=false;
-}
-
-bool cSmartCardDataIrdeto::Matches(cSmartCardData *param)
-{
- cSmartCardDataIrdeto *cd=(cSmartCardDataIrdeto *)param;
- return cd->acs==acs && (cd->caid==caid || caid==-1);
-}
-
-bool cSmartCardDataIrdeto::Parse(const char *line)
-{
- unsigned char buff[512];
- acs=caid=-1; // default
- line=skipspace(line);
- if(*line=='[') { // parse acs & caid
- line++;
- if(GetHex(line,buff,2)!=2) {
- PRINTF(L_CORE_LOAD,"smartcarddatairdeto: format error: acs");
- return false;
- }
- acs=buff[0]*256+buff[1];
-
- line=skipspace(line);
- if(*line=='/') {
- line++;
- if(GetHex(line,buff,2)!=2) {
- PRINTF(L_CORE_LOAD,"smartcarddatairdeto: format error: caid");
- return false;
- }
- caid=buff[0]*256+buff[1];
- line=skipspace(line);
- }
-
- if(!*line==']') {
- PRINTF(L_CORE_LOAD,"smartcarddatairdeto: format error: closing ]");
- return false;
- }
- line++;
- }
-
- line=skipspace(line);
- if(!strncasecmp(line,"plain",5)) {
- plain=true;
- return true;
- }
- int l;
- if((l=GetHex(line,buff,sizeof(buff),false))<=0) {
- PRINTF(L_CORE_LOAD,"smartcarddatairdeto: format error: mod");
- return false;
- }
- BN_complement(buff,l,mod);
- if((l=GetHex(line,buff,sizeof(buff),false))<=0) {
- PRINTF(L_CORE_LOAD,"smartcarddatairdeto: format error: exp");
- return false;
- }
- BN_bin2bn(buff,l,exp);
- return true;
-}
-
-// -- cSmartCardIrdeto ---------------------------------------------------------
-
-#define XOR_START 0x3F // Start value for xor checksumm
-#define ADDRLEN 4 // Address length in EMM commands
-#define MAX_PROV 16
-#define RECOVER_TIME 100 // Time in ms which the card needs to recover after
- // a failed command
-
-class cSmartCardIrdeto : public cSmartCard, private cCamCrypt, private cIdSet {
-private:
- unsigned char buff[MAX_LEN+1];
- unsigned char camKey[8];
- char asciiSerial[22], coco[4];
- int ACS, caId;
- int numProv;
- cTimeMs recoverTime;
- //
- int DoCmd(unsigned char *cmd, int goodSB, int secGoodSB=-1);
- bool ReadCardInfo(void);
- time_t Date(int date, char *buff, int len);
-public:
- cSmartCardIrdeto(void);
- virtual bool Init(void);
- virtual bool Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw);
- virtual bool Update(int pid, int caid, const unsigned char *data);
- virtual bool CanHandle(unsigned short CaId);
- };
-
-static const struct StatusMsg msgs[] = {
- { { 0x00,0x00 }, "Instruction executed without error", true },
- { { 0x55,0x00 }, "Instruction executed without error", true },
- { { 0x57,0x00 }, "CAM string rejected", false },
- { { 0x58,0x00 }, "Instruction executed without error", true },
- { { 0x9D,0x00 }, "Decoding successfull", true },
- { { 0x90,0x00 }, "ChID missing. Not subscribed?", false },
- { { 0x93,0x00 }, "ChID out of date. Subscription expired?", false },
- { { 0x9C,0x00 }, "Master key error", false },
- { { 0x9E,0x00 }, "Wrong decryption key", false },
- { { 0x9F,0x00 }, "Missing key", false },
- { { 0x70,0x00 }, "Wrong hex serial", false },
- { { 0x71,0x00 }, "Wrong provider", false },
- { { 0x72,0x00 }, "Wrong provider group", false },
- { { 0x73,0x00 }, "Wrong provider group", false },
- { { 0x7C,0x00 }, "Wrong signature", false },
- { { 0x7D,0x00 }, "Masterkey missing", false },
- { { 0x7E,0x00 }, "Wrong provider identifier", false },
- { { 0x7F,0x00 }, "Invalid nano", false },
- { { 0x54,0x00 }, "No more ChID's", true },
- { { 0xFF,0xFF }, 0, false }
- };
-
-static const struct CardConfig cardCfg = {
- SM_8N2,3000,100
- };
-
-cSmartCardIrdeto::cSmartCardIrdeto(void)
-:cSmartCard(&cardCfg,msgs)
-{}
-
-bool cSmartCardIrdeto::Init(void)
-{
- ResetIdSet();
- recoverTime.Set(-RECOVER_TIME);
- if(atr->histLen<6 || memcmp(atr->hist,"IRDETO",6)) {
- PRINTF(L_SC_INIT,"doesn't looks like a Irdeto/Beta card");
- return false;
- }
-
- infoStr.Begin();
- infoStr.Strcat("Irdeto smartcard\n");
- int r;
- static unsigned char getCountryCode[] = { 0x01,0x02,0x02,0x03,0x00,0x00,0xCC };
- if((r=DoCmd(getCountryCode,0x0000))<=0 || !Status() || r<16) {
- PRINTF(L_SC_ERROR,"country code error");
- return false;
- }
- ACS=buff[8]*256+buff[9];
- caId=buff[13]*256+buff[14];
- memcpy(coco,&buff[21],3); coco[3]=0;
- PRINTF(L_SC_INIT,"ACS Version %04x, CAID %04x, CoCo %s",ACS,caId,coco);
- snprintf(idStr,sizeof(idStr),"%s (ACS %x)",SC_NAME,ACS);
- infoStr.Printf("ACS: %04x CAID: %04x CoCo: %s\n",ACS,caId,coco);
-
- static unsigned char getAsciiSerial[] = { 0x01,0x02,0x00,0x03,0x00,0x00,0xCC };
- if((r=DoCmd(getAsciiSerial,0x0000))<=0 || !Status() || r<10) {
- PRINTF(L_SC_ERROR,"ASCII serial error");
- return false;
- }
- strn0cpy(asciiSerial,(char*)buff+8,sizeof(asciiSerial));
- PRINTF(L_SC_INIT,"ASCII serial %s",asciiSerial);
-
- static unsigned char getHexSerial[] = { 0x01,0x02,0x01,0x03,0x00,0x00,0xCC };
- if((r=DoCmd(getHexSerial,0x0000))<=0 || !Status() || r<25) {
- PRINTF(L_SC_ERROR,"hex serial error");
- return false;
- }
- int numProv=buff[18];
- SetCard(new cCardIrdeto(buff[23],&buff[20]));
- PRINTF(L_SC_INIT,"Providers: %d HEX Serial: %02X%02X%02X HEX Base: %02X",numProv,buff[20],buff[21],buff[22],buff[23]);
- infoStr.Printf("HEX: %02X/%02X%02X%02X ASCII: %s\n",buff[23],buff[20],buff[21],buff[22],asciiSerial);
-
- static unsigned char getCardFile[] = { 0x01,0x02,0x0E,0x02,0x00,0x00,0xCC };
- unsigned char encr[128], plain[64+6+2];
- PrepareCamMessage(plain+6);
- getCardFile[3]=0x02;
- if((r=DoCmd(getCardFile,0x0000))<=0 || !Status() || r<73) {
- PRINTF(L_SC_ERROR,"cardfile2 error");
- return false;
- }
- memcpy(encr,buff+8,64);
- getCardFile[3]=0x03;
- if((r=DoCmd(getCardFile,0x0000))<=0 || !Status() || r<73) {
- PRINTF(L_SC_ERROR,"cardfile3 error");
- return false;
- }
- memcpy(encr+64,buff+8,64);
-
- bool doPlain=false;
- if((ACS==0x0383 || ACS==0x0384) && atr->histLen>=12 && atr->hist[12]==0x95)
- doPlain=true;
- cSmartCardDataIrdeto *entry=0;
- if(!doPlain) {
- cSmartCardDataIrdeto cd(ACS,caId);
- if(!(entry=(cSmartCardDataIrdeto *)smartcards.FindCardData(&cd))) {
- PRINTF(L_GEN_WARN,"didn't find Irdeto card specific certificate, falling back to default");
- cSmartCardDataIrdeto cd(-1,-1);
- if(!(entry=(cSmartCardDataIrdeto *)smartcards.FindCardData(&cd))) {
- PRINTF(L_GEN_WARN,"didn't find default Irdeto certificate, please add one");
- if(ACS!=0x0384) return false;
- PRINTF(L_GEN_WARN,"trying pre-coded ACS 384 challenge. This mode is DEPRECATED. There ARE valid certificates for these cards available!");
- }
- }
- else doPlain=entry->plain;
- }
- static unsigned char doCamKeyExchange[] = { 0x01,0x02,0x09,0x03,0x00,0x40 };
- if(doPlain) {
- // plain challenge
- memcpy(plain,doCamKeyExchange,sizeof(doCamKeyExchange));
- plain[4]=1; // set block counter
- r=DoCmd(plain,0x5500,0x0000);
- }
- else {
- // RSA challenge
- if(entry) {
- if(!SetupCardFiles(encr,sizeof(encr),entry->exp,entry->mod)) {
- PRINTF(L_SC_ERROR,"decrypting cardfiles failed. Probably bad certificate.");
- return false;
- }
- if(!EncryptCamMessage(encr+6,plain+6)) {
- PRINTF(L_SC_ERROR,"encrypting CAM message failed. Probably bad certificate.");
- return false;
- }
-
- static unsigned char doRSACheck[] = { 0x01,0x02,0x11,0x00,0x00,0x40 };
- memcpy(plain,doRSACheck,sizeof(doRSACheck));
- if((r=DoCmd(plain,0x5800,0x0000))<=0 || !Status() || r<73) {
- PRINTF(L_SC_ERROR,"card didn't give a proper reply (buggy RSA unit?), trying to continue...");
- // non-fatal
- }
- if(r==73 && memcmp(encr+6,buff+8,64)) {
- PRINTF(L_SC_ERROR,"card failed on RSA check, trying to continue...");
- // non-fatal
- }
- }
- else {
- static const unsigned char enc384cz[] = {
- 0x18,0xD7,0x55,0x14,0xC0,0x83,0xF1,0x38, 0x39,0x6F,0xF2,0xEC,0x4F,0xE3,0xF1,0x85,
- 0x01,0x46,0x06,0xCE,0x7D,0x08,0x2C,0x74, 0x46,0x8F,0x72,0xC4,0xEA,0xD7,0x9C,0xE0,
- 0xE1,0xFF,0x58,0xE7,0x70,0x0C,0x92,0x45, 0x26,0x18,0x4F,0xA0,0xE2,0xF5,0x9E,0x46,
- 0x6F,0xAE,0x95,0x35,0xB0,0x49,0xB2,0x0E, 0xA4,0x1F,0x8E,0x47,0xD0,0x24,0x11,0xD0
- };
- static const unsigned char enc384dz[] = {
- 0x27,0xF2,0xD6,0xCD,0xE6,0x88,0x62,0x46, 0x81,0xB0,0xF5,0x3E,0x6F,0x13,0x4D,0xCC,
- 0xFE,0xD0,0x67,0xB1,0x93,0xDD,0xF4,0xDE, 0xEF,0xF5,0x3B,0x04,0x1D,0xE5,0xC3,0xB2,
- 0x54,0x38,0x57,0x7E,0xC8,0x39,0x07,0x2E, 0xD2,0xF4,0x05,0xAA,0x15,0xB5,0x55,0x24,
- 0x90,0xBB,0x9B,0x00,0x96,0xF0,0xCB,0xF1, 0x8A,0x08,0x7F,0x0B,0xB8,0x79,0xC3,0x5D
- };
- static const unsigned char ck[] = { 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88 };
- static const unsigned char hk[] = { 0x12,0x34,0x56,0x78,0x90,0xAB,0xCD,0xEF };
-
- if(caId==0x1702) memcpy(encr+6,enc384cz,sizeof(enc384cz));
- else if(caId==0x1722) memcpy(encr+6,enc384dz,sizeof(enc384dz));
- else {
- PRINTF(L_GEN_WARN,"no pre-coded Irdeto camkey challenge for caid %04x",caId);
- return false;
- }
- memcpy((void *)CamKey(plain+6),ck,sizeof(ck));
- memcpy((void *)HelperKey(plain+6),hk,sizeof(hk));
- }
-
- memcpy(encr,doCamKeyExchange,sizeof(doCamKeyExchange));
- r=DoCmd(encr,0x5500,0x0000);
- }
-
- if(r>0 && Status() && r>=9) {
- memcpy(camKey,CamKey(plain+6),8);
- if(r>=17) {
- RevCamCrypt(camKey,buff+8);
- if(memcmp(HelperKey(plain+6),buff+8,8)) {
- PRINTF(L_SC_ERROR,"camkey challenge failed");
- return false;
- }
- }
- LDUMP(L_SC_INIT,camKey,sizeof(camKey),"camkey");
- }
- else {
- PRINTF(L_SC_ERROR,"camkey error");
- return false;
- }
-
- static unsigned char getProvider[] = { 0x01,0x02,0x03,0x03,0x00,0x00,0xCC };
- static unsigned char getChanelIds[] = { 0x01,0x02,0x04,0x00,0x00,0x01,0x00,0xCC };
- for(int i=0; i<numProv; i++) {
- getProvider[4]=i;
- if((r=DoCmd(getProvider,0x0000))>0 && Status() && r>=33) {
- AddProv(new cProviderIrdeto(buff[8]&0x0f,&buff[9]));
- PRINTF(L_SC_INIT,"provider %d with ProvBase 0x%02x ProvId 0x%02x%02x%02x",i,buff[8]&0x0f,buff[9],buff[10],buff[11]);
- infoStr.Printf("Provider %d Id: %02X/%02X%02X%02X\n",i,buff[8]&0x0f,buff[9],buff[10],buff[11]);
-
- getChanelIds[4]=i;
- for(int l=0; l<10; l++) {
- getChanelIds[6]=l;
- if((r=DoCmd(getChanelIds,0x0000,0x5400))<=0 || !Status() || r<69) break;
- for(int k=0; k<buff[7]; k+=6) {
- int chanId=buff[k+8+0]*256+buff[k+8+1];
- int date =buff[k+8+2]*256+buff[k+8+3];
- int durr =buff[k+8+4];
- if(chanId!=0x0000 && chanId!=0xFFFF) {
- char sdate[16], edate[16];
- Date(date,sdate,sizeof(sdate));
- Date(date+durr,edate,sizeof(edate));
- PRINTF(L_SC_INIT,"ChanId 0x%04x Date 0x%04x %s Duration 0x%02x %s",chanId,date,sdate,durr,edate);
- infoStr.Printf("ChanId: %04X Date: %s-%s\n",chanId,sdate,edate);
- }
- }
- }
- }
- }
-
-#if 0
- static unsigned char getCountryCode2[] = { 0x01,0x02,0x0B,0x00,0x00,0x00,0xCC };
- if((r=DoCmd(getCountryCode2,0x0000))>0 && Status() && r>=32) {
- PRINTF(L_SC_INIT,"max ChID's %d,%d,%d,%d",buff[14],buff[15],buff[16],buff[17]);
- }
-#endif
-
- infoStr.Finish();
- return true;
-}
-
-time_t cSmartCardIrdeto::Date(int date, char *buff, int len)
-{
- // Irdeto date starts 01.08.1997 which is
- // 870393600 seconds in unix calendar time
- time_t utcTime=870393600L+date*(24*3600);
- if(buff) {
- struct tm utcTm;
- gmtime_r(&utcTime,&utcTm);
- snprintf(buff,len,"%04d/%02d/%02d",utcTm.tm_year+1900,utcTm.tm_mon+1,utcTm.tm_mday);
- }
- return utcTime;
-}
-
-bool cSmartCardIrdeto::CanHandle(unsigned short CaId)
-{
- return (CaId==caId);
-}
-
-bool cSmartCardIrdeto::Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
-{
- static const unsigned char ecmCmd[] = { 0x01,0x05,0x00,0x00,0x02,0x00 };
-
- int r=SCT_LEN(data)-6;
- if(r<=255) {
- unsigned char cmd[257+sizeof(ecmCmd)];
- memcpy(cmd,ecmCmd,sizeof(ecmCmd));
- cmd[5]=r;
- memcpy(cmd+sizeof(ecmCmd),&data[6],r);
- if((r=DoCmd(cmd,0x9D00))>0) {
- if(Status() && r>=31) {
- RevCamCrypt(camKey,&buff[14]);
- RevCamCrypt(camKey,&buff[22]);
- memcpy(cw,&buff[14],16);
- return true;
- }
- }
- }
- return false;
-}
-
-bool cSmartCardIrdeto::Update(int pid, int caid, const unsigned char *data)
-{
- static const unsigned char emmCmd[] = { 0x01,0x01,0x00,0x00,0x00,0x00 };
-
- if(MatchEMM(data)) {
- int len=cParseIrdeto::AddrLen(data)+1;
- if(len<=ADDRLEN) {
- const int dataLen=SCT_LEN(data)-5-len; // sizeof of data bytes (nanos)
- if(dataLen<=255-ADDRLEN) {
- unsigned char cmd[257+sizeof(emmCmd)];
- memcpy(cmd,emmCmd,sizeof(emmCmd));
- cmd[5]=dataLen+ADDRLEN;
- memset(cmd+sizeof(emmCmd),0,ADDRLEN);
- memcpy(cmd+sizeof(emmCmd),&data[3],len);
- memcpy(cmd+sizeof(emmCmd)+ADDRLEN,&data[len+5],dataLen);
- if(DoCmd(cmd,0x0000)>0 && Status()) return true;
- }
- }
- else PRINTF(L_SC_ERROR,"addrlen %d > %d",len,ADDRLEN);
- }
- return false;
-}
-
-int cSmartCardIrdeto::DoCmd(unsigned char *cmd, int goodSB, int secGoodSB)
-{
- int len=cmd[5]+6;
- cmd[len]=XorSum(cmd,len) ^ XOR_START;
- // wait until recover time is over
- int r=RECOVER_TIME-recoverTime.Elapsed();
- if(r>0) {
- PRINTF(L_SC_ERROR,"recover time, waiting %d ms",r);
- cCondWait::SleepMs(r+1);
- }
- r=-1;
- LDUMP(L_CORE_SC,cmd,len+1,"IRDETO: CMD ->");
- if(SerWrite(cmd,len+1)>0 && SerRead(buff,4,cardCfg.workTO)>0) {
- len=4;
- if(buff[0]==cmd[0] && buff[1]==cmd[1]) {
- sb[0]=buff[2]; sb[1]=buff[3];
- int SB=buff[2]*256+buff[3];
- if(SB==goodSB || (secGoodSB>=0 && SB==secGoodSB)) {
- if(SerRead(buff+len,5)>0) {
- len+=5;
- if(buff[7]) {
- if(SerRead(buff+len,buff[7])<=0) return -1;
- len+=buff[7];
- }
- if(XorSum(buff,len)==XOR_START) r=len;
- else LDUMP(L_CORE_SC,buff,len,"IRDETO: checksum failed");
- }
- }
- else r=len;
- }
- else {
- sb[0]=buff[1]; sb[1]=buff[2];
- r=3;
- }
- }
- if(r>0) LDUMP(L_CORE_SC,buff,r,"IRDETO: RESP <-");
- if(r<=4) {
- recoverTime.Set();
- PRINTF(L_SC_ERROR,"setting %d ms recover time",RECOVER_TIME);
- }
- return r;
-}
-
-// -- cSmartCardLinkIrdeto -----------------------------------------------------
-
-class cSmartCardLinkIrdeto : public cSmartCardLink {
-public:
- cSmartCardLinkIrdeto(void):cSmartCardLink(SC_NAME,SC_ID) {}
- virtual cSmartCard *Create(void) { return new cSmartCardIrdeto(); }
- virtual cSmartCardData *CreateData(void) { return new cSmartCardDataIrdeto; }
- };
-
-static cSmartCardLinkIrdeto staticScInit;
+++ /dev/null
-#
-# Smartcard Irdeto/Beta
-#
-TARGET = sc_irdeto
-OBJS = sc-irdeto.o
-LIBS = -lcrypto
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <openssl/rand.h>
-
-#include "system-common.h"
-#include "smartcard.h"
-#include "crypto.h"
-#include "helper.h"
-#include "log-sc.h"
-#include "log-core.h"
-
-#define SYSTEM_NAGRA 0x1801
-
-#define SYSTEM_NAME "SC-Nagra"
-#define SYSTEM_PRI -5
-#define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_NAGRA)
-
-#define SC_NAME "Nagra"
-#define SC_ID MAKE_SC_ID('N','a','g','r')
-
-#define L_SC 11
-#define L_SC_PROC LCLASS(L_SC,L_SC_LASTDEF<<1)
-#define L_SC_ALL LALL(L_SC_PROC)
-
-static const struct LogModule lm_sc = {
- (LMOD_ENABLE|L_SC_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_SC_DEFDEF|L_SC_PROC)&LOPT_MASK,
- "sc-nagra",
- { L_SC_DEFNAMES,"process" }
- };
-ADD_MODULE(L_SC,lm_sc)
-
-// -- cSystemScNagra ---------------------------------------------------------------------
-
-class cSystemScNagra : public cSystemScCore {
-public:
- cSystemScNagra(void);
- };
-
-cSystemScNagra::cSystemScNagra(void)
-:cSystemScCore(SYSTEM_NAME,SYSTEM_PRI,SC_ID,"SC Nagra")
-{
- hasLogger=true;
-}
-
-// -- cSystemLinkScNagra --------------------------------------------------------------
-
-class cSystemLinkScNagra : public cSystemLink {
-public:
- cSystemLinkScNagra(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemScNagra; }
- };
-
-static cSystemLinkScNagra staticInit;
-
-cSystemLinkScNagra::cSystemLinkScNagra(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- Feature.NeedsSmartCard();
-}
-
-bool cSystemLinkScNagra::CanHandle(unsigned short SysId)
-{
- return smartcards.HaveCard(SC_ID) && SYSTEM_CAN_HANDLE(SysId);
-}
-
-// -- cCamCryptNagra ------------------------------------------------------------------
-
-class cCamCryptNagra {
-private:
- cIDEA idea;
- cRSA rsa;
- cBN camMod, camExp;
- bool hasMod;
- unsigned char sk[16];
- //
- void Signature(unsigned char *sig, const unsigned char *key, const unsigned char *msg, int len);
-public:
- cCamCryptNagra(void);
- void InitCamKey(unsigned char *key, const unsigned char *bk, const unsigned char *data);
- void SetCamMod(BIGNUM *m);
- bool DecryptCamMod(const unsigned char *dt08, const unsigned char *key, const unsigned char *key2, BIGNUM *m);
- bool DecryptCamData(unsigned char *out, const unsigned char *key, const unsigned char *in);
- bool DecryptCW(unsigned char *dcw, const unsigned char *in);
- };
-
-cCamCryptNagra::cCamCryptNagra(void)
-{
- hasMod=false;
- BN_set_word(camExp,3);
-}
-
-void cCamCryptNagra::Signature(unsigned char *sig, const unsigned char *key, const unsigned char *msg, int len)
-{
- unsigned char buff[16];
- memcpy(buff,key,16);
- for(int i=0; i<len; i+=8) {
- IdeaKS ks;
- idea.SetEncKey(buff,&ks);
- idea.Encrypt(msg+i,8,buff,&ks,0);
- xxor(buff,8,buff,&msg[i]);
- //for(int j=7; j>=0; j--) buff[j]^=msg[i+j];
- memcpy(&buff[8],buff,8);
- }
- memcpy(sig,buff,8);
-}
-
-void cCamCryptNagra::InitCamKey(unsigned char *key, const unsigned char *bk, const unsigned char *data)
-{
- memcpy(key,bk,8);
- int d=UINT32_LE(data);
- BYTE4_LE(key+8 , d);
- BYTE4_LE(key+12,~d);
- //memcpy(key+8,data,4);
- //for(int i=0; i<4; i++) key[i+12]=~data[i];
-}
-
-void cCamCryptNagra::SetCamMod(BIGNUM *m)
-{
- BN_copy(camMod,m);
- hasMod=true;
-}
-
-bool cCamCryptNagra::DecryptCamMod(const unsigned char *dt08, const unsigned char *key, const unsigned char *cardid, BIGNUM *m)
-{
- unsigned char buff[72];
- if(rsa.RSA(buff,dt08+13,64,camExp,m)!=64) return false;
- memcpy(buff+64,dt08+13+64,8);
- buff[63]|=dt08[12]&0x80;
- IdeaKS dks;
- idea.SetDecKey(key,&dks);
- idea.Decrypt(buff,72,&dks,0);
- unsigned char sig[8];
- memcpy(sig,buff,8);
-
- memset(buff+0,0,4);
- memcpy(buff+4,cardid,4);
- Signature(buff,key,buff,72);
- BN_bin2bn(buff+8,64,camMod);
- if(memcmp(sig,buff,8)) {
- PRINTF(L_SC_PROC,"DT08 signature failed. Check boxkey/IRD modulus");
- return false;
- }
- hasMod=true;
- return true;
-}
-
-bool cCamCryptNagra::DecryptCamData(unsigned char *out, const unsigned char *key, const unsigned char *camdata)
-{
- if(!hasMod) return false;
- //decrypt $2A data here and prepare $2B reply
- if(rsa.RSA(out,camdata,64,camExp,camMod)!=64) return false;
- Signature(sk,key,out,32);
- memcpy(sk+8,sk,8);
- Signature(sk+8,sk,out,32);;
- if(rsa.RSA(out,out,64,camExp,camMod)!=64) return false;
- LDUMP(L_SC_PROC,sk,16,"established session key ->");
- return true;
-}
-
-bool cCamCryptNagra::DecryptCW(unsigned char *dcw, const unsigned char *ecw)
-{
- const int nCw=ecw[4]/2;
- if(nCw<10) return false;
- IdeaKS ks;
- ecw+=5;
- idea.SetDecKey(sk,&ks);
- memcpy(dcw+8,ecw +2,8);
- memcpy(dcw+0,ecw+nCw+2,8);
- idea.Decrypt(dcw+0,8,&ks,0);
- idea.Decrypt(dcw+8,8,&ks,0);
- return true;
-}
-
-// -- cSmartCardDataNagra ------------------------------------------------------
-
-class cSmartCardDataNagra : public cSmartCardData {
-public:
- bool global;
- int provId;
- unsigned char bk[8];
- cBN mod;
- //
- cSmartCardDataNagra(void);
- cSmartCardDataNagra(int ProvId, bool Global);
- virtual bool Parse(const char *line);
- virtual bool Matches(cSmartCardData *param);
- };
-
-cSmartCardDataNagra::cSmartCardDataNagra(void)
-:cSmartCardData(SC_ID) {}
-
-cSmartCardDataNagra::cSmartCardDataNagra(int ProvId, bool Global=false)
-:cSmartCardData(SC_ID)
-{
- provId=ProvId; global=Global;
-}
-
-bool cSmartCardDataNagra::Matches(cSmartCardData *param)
-{
- cSmartCardDataNagra *cd=(cSmartCardDataNagra *)param;
- return (cd->provId==provId) && (cd->global==global);
-}
-
-bool cSmartCardDataNagra::Parse(const char *line)
-{
- unsigned char buff[512];
- line=skipspace(line);
- if(*line++!='[' || GetHex(line,buff,2)!=2 || *(line=skipspace(line))!=']' ) {
- PRINTF(L_CORE_LOAD,"smartcarddatanagra: format error: provider id");
- return false;
- }
- provId=buff[0]*256+buff[1];
- line=skipspace(line+1);
- if(!strncasecmp(line,"IRDMOD",6)) {
- global=true;
- line+=6;
- }
- if(GetHex(line,bk,sizeof(bk),false)<=0) {
- PRINTF(L_CORE_LOAD,"smartcarddatanagra: format error: boxkey");
- return false;
- }
- int l=GetHex(line,buff,sizeof(buff),false);
- if(l!=64) {
- PRINTF(L_CORE_LOAD,"smartcarddatanagra: format error: %s",global?"IRDMOD":"CAMMOD");
- return false;
- }
- BN_bin2bn(buff,l,mod);
- return true;
-}
-
-// -- cSmartCardNagra -----------------------------------------------------------------
-
-// ISO 7816 T=1 defines
-#define NAD(a) (a[0])
-#define PCB(a) (a[1])
-#define LEN(a) (a[2])
-#define CLA(a) (a[3])
-#define INS(a) (a[4])
-#define P1(a) (a[5])
-#define P2(a) (a[6])
-#define L(a) (a[7])
-
-// Nagra NAD and reply NAD
-#define N2_NAD 0x21
-#define N2_R_NAD sn8(N2_NAD)
-#define N2_CLA 0xA0
-#define N2_INS 0xCA
-#define N2_P1 0x00
-#define N2_P2 0x00
-#define N2_CMD(a) (a[8])
-#define N2_CLEN(a) (a[9])
-#define N2_DATA(a) (a[10])
-
-#define SETIFS 0xC1
-#define CAMDATA 0x08
-
-// Datatypes
-#define IRDINFO 0x00
-#define TIERS 0x05
-#define MAX_REC 20
-
-// Card Status checks
-#define HAS_CW ((status[1]&1)&&((status[3]&6)==6))
-
-class cSmartCardNagra : public cSmartCard, private cCamCryptNagra {
-private:
- unsigned char buff[MAX_LEN+1], status[4], cardId[4], irdId[4], block;
- unsigned short provId[MAX_REC], irdProvId;
- //
- bool GetCardStatus(void);
- bool GetDataType(unsigned char dt, int len, int shots=MAX_REC);
- bool ParseDataType(unsigned char dt);
- bool DoCamExchange(const unsigned char *key);
- void Date(const unsigned char *date, char *dt, char *ti);
- bool DoBlkCmd(unsigned char cmd, int ilen, unsigned char res, int rlen, const unsigned char *data=0);
- bool SetIFS(unsigned char len);
-public:
- cSmartCardNagra(void);
- virtual bool Init(void);
- virtual bool Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw);
- virtual bool Update(int pid, int caid, const unsigned char *data);
- };
-
-static const struct StatusMsg msgs[] = {
- { { 0x6F,0x00 }, "Instruction not supported", false },
- { { 0x90,0x00 }, "Instruction executed without errors", true },
- { { 0xFF,0xFF }, 0, false }
- };
-
-static const struct CardConfig cardCfg = {
- SM_8O2,500,800
- };
-
-cSmartCardNagra::cSmartCardNagra(void)
-:cSmartCard(&cardCfg,msgs)
-{
- block=0;
-}
-
-bool cSmartCardNagra::SetIFS(unsigned char size)
-{
- unsigned char buf[5];
- // NAD, PCB, LEN
- NAD(buf)=N2_NAD; PCB(buf)=SETIFS; LEN(buf)=1;
- // Information Field size
- buf[3]=size; buf[4]=XorSum(buf,4);
- if(SerWrite(buf,5)!=5) {
- PRINTF(L_SC_ERROR,"failed to write IFS command");
- return false;
- }
- if(SerRead(buff,5,cardCfg.workTO)!=5 || XorSum(buff,5)) {
- PRINTF(L_SC_ERROR,"setting IFS to %02x failed",size);
- return false;
- }
- return true;
-}
-
-bool cSmartCardNagra::GetCardStatus(void)
-{
- if(!DoBlkCmd(0xC0,0x02,0xB0,0x06) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to read card status");
- return false;
- }
- memcpy(status,buff+5,4);
- return true;
-}
-
-bool cSmartCardNagra::Init(void)
-{
- static const unsigned char verifyBytes[] = { 'D','N','A','S','P','1' };
- if(atr->T!=1 || (atr->histLen<8 && memcmp(atr->hist,verifyBytes,sizeof(verifyBytes)))) {
- PRINTF(L_SC_INIT,"doesn't look like a nagra V2 card");
- return false;
- }
-
- infoStr.Begin();
- infoStr.Strcat("Nagra smartcard\n");
-
- char rom[12], rev[12];
- snprintf(rom,sizeof(rom),"%.3s",(char*)&atr->hist[5]);
- snprintf(rev,sizeof(rev),"%.3s",(char*)&atr->hist[12]);
-
- PRINTF(L_SC_INIT,"card version: %s revision: %s",rom,rev);
- infoStr.Printf("Card v.%s Rev.%s\n",rom,rev);
-
- if(!GetCardStatus() || !SetIFS(0x80)) return false;
- // get UA/CardID here
- if(!DoBlkCmd(0x12,0x02,0x92,0x06) || !Status()) return false;
-
- memcpy(cardId,buff+5,4);
- if(!GetDataType(IRDINFO,0x39) || !GetDataType(0x04,0x44)) return false;
- infoStr.Printf("Tiers\n");
- infoStr.Printf("|id |tier low|tier high| dates |\n");
- infoStr.Printf("+----+--------+---------+----------+\n");
-
- if(!GetDataType(TIERS,0x57))
- PRINTF(L_SC_ERROR,"failed to get tiers");
-
- if(!GetDataType(CAMDATA,0x55,1)) return false;
-
- unsigned char key[16];
- cSmartCardDataNagra *entry=0;
- bool sessOk=false;
- if(buff[5]!=0 && irdProvId==((buff[10]*256)|buff[11])) { // prepare DT08 data
- cSmartCardDataNagra cd(irdProvId,true);
- if(!(entry=(cSmartCardDataNagra *)smartcards.FindCardData(&cd))) {
- PRINTF(L_GEN_WARN,"didn't find smartcard Nagra IRD modulus");
- }
- else {
- InitCamKey(key,entry->bk,irdId);
- if(DecryptCamMod(buff+3,key,cardId,entry->mod)) sessOk=true;
- }
- }
- else {
- cSmartCardDataNagra cd(irdProvId);
- if(!(entry=(cSmartCardDataNagra *)smartcards.FindCardData(&cd))) {
- PRINTF(L_GEN_WARN,"didn't find smartcard Nagra CAM modulus");
- }
- else {
- InitCamKey(key,entry->bk,cardId);
- SetCamMod(entry->mod);
- if(GetDataType(0x08,0x03,1)) sessOk=true;;
- }
- }
- if(sessOk) DoCamExchange(key);
- infoStr.Finish();
- return true;
-}
-
-bool cSmartCardNagra::GetDataType(unsigned char dt, int len, int shots)
-{
- for(int i=0; i<shots; i++) {
- if(!DoBlkCmd(0x22,0x03,0xA2,len,&dt) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to get datatype %02X",dt);
- return false;
- }
- if(buff[5]==0) return true;
- if(!ParseDataType(dt&0x0F)) return false;
- dt|=0x80; // get next item
- }
- return true;
-}
-
-bool cSmartCardNagra::ParseDataType(unsigned char dt)
-{
- switch(dt) {
- case IRDINFO:
- {
- irdProvId=(buff[10]*256)|buff[11];
- char id[12];
- memcpy(irdId,buff+17,4);
- LDUMP(L_SC_INIT,irdId,4,"IRD system-ID: %04X, IRD ID:",irdProvId);
- HexStr(id,irdId,sizeof(irdId));
- infoStr.Printf("IRD system-ID: %04X\nIRD ID: %s\n",irdProvId,id);
- return true;
- }
- case TIERS:
- if(buff[7]==0x88 || buff[7]==0x08 || buff[7]==0x0C) {
- int id=(buff[10]*256)|buff[11];
- int tLowId=(buff[20]*256)|buff[21];
- int tHiId=(buff[31]*256)|buff[32];
- char date1[12], time1[12], date2[12], time2[12];
- Date(buff+23,date1,time1);
- Date(buff+27,date2,time2);
-
- infoStr.Printf("|%04X|%04X |%04X |%s|\n",id,tLowId,tHiId,date1);
- infoStr.Printf("| | | |%s|\n",date2);
- PRINTF(L_SC_INIT,"|%04X|%04X|%04X|%s|%s|",id,tLowId,tHiId,date1,time1);
- PRINTF(L_SC_INIT,"| | | |%s|%s|",date2,time2);
- }
- default:
- return true;
- }
- return false;
-}
-
-bool cSmartCardNagra::DoCamExchange(const unsigned char *key)
-{
- if(!GetCardStatus()) return false;
- if(!DoBlkCmd(0x2A,0x02,0xAA,0x42) || !Status()) return false;
- if(buff[4]!=64) {
- PRINTF(L_SC_ERROR,"reading CAM 2A data failed");
- return false;
- }
- unsigned char res[64];
- if(!DecryptCamData(res,key,buff+5)) return false;
- if(!DoBlkCmd(0x2B,0x42,0xAB,0x02,res) || !Status()) return false;
- return true;
-}
-
-void cSmartCardNagra::Date(const unsigned char *data, char *dt, char *ti)
-{
- int date=(data[0]<<8)|data[1];
- int time=(data[2]<<8)|data[3];
- struct tm t;
- memset(&t,0,sizeof(struct tm));
- t.tm_min =0;//-300;
- t.tm_year=92;
- t.tm_mday=date + 1;
- t.tm_sec =(time - 1) * 2;
- mktime(&t);
- snprintf(dt,11,"%.2d.%.2d.%.4d",t.tm_mon+1,t.tm_mday,t.tm_year+1900);
- snprintf(ti,9,"%.2d:%.2d:%.2d",t.tm_hour,t.tm_min,t.tm_sec);
-}
-
-bool cSmartCardNagra::Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
-{
- if(DoBlkCmd(data[3],data[4]+2,0x87,0x02,data+3+2) && Status()) {
- cCondWait::SleepMs(100);
- if(GetCardStatus() && HAS_CW &&
- DoBlkCmd(0x1C,0x02,0x9C,0x36) && Status() &&
- DecryptCW(cw,buff)) return true;
- }
- return false;
-}
-
-bool cSmartCardNagra::Update(int pid, int caid, const unsigned char *data)
-{
- if(DoBlkCmd(data[8],data[9]+2,0x84,0x02,data+8+2) && Status()) {
- cCondWait::SleepMs(500);
- if(GetCardStatus()) return true;
- }
- return false;
-}
-
-bool cSmartCardNagra::DoBlkCmd(unsigned char cmd, int ilen, unsigned char res, int rlen, const unsigned char *data)
-{
- unsigned char msg[MAX_LEN+3+1];
-
- NAD(msg)=N2_NAD; PCB(msg)=0; PCB(msg)^=block; block^=0x40; LEN(msg)=ilen+6;
- CLA(msg)=N2_CLA; INS(msg)=N2_INS; P1(msg)=N2_P1; P2(msg)=N2_P2; L(msg)=ilen;
-
- int dlen=ilen-2;
- if(dlen<0) {
- PRINTF(L_SC_ERROR,"invalid data length encountered");
- return false;
- }
-
- N2_CMD(msg)=cmd; N2_CLEN(msg)=dlen;
-
- if(data && dlen>0) memcpy(&N2_DATA(msg),data,dlen);
- int msglen=LEN(msg)+3;
- msg[msglen-1]=rlen;
- msg[msglen]=XorSum(msg,msglen);
- msglen++;
-
- if(SerWrite(msg,msglen)==msglen) {
- LDUMP(L_CORE_SC,msg,msglen,"NAGRA: <-");
- cCondWait::SleepMs(10);
- if(SerRead(buff,3,cardCfg.workTO)!=3) {
- PRINTF(L_SC_ERROR,"reading back reply failed");
- return false;
- }
- int reslen=buff[2]+1;
- if(SerRead(buff+3,reslen,cardCfg.workTO)!=reslen) {
- PRINTF(L_SC_ERROR,"reading back information block failed");
- return false;
- }
- if(XorSum(buff,reslen+3)) {
- PRINTF(L_SC_ERROR,"checksum failed");
- return false;
- }
- LDUMP(L_CORE_SC,buff,3+reslen,"NAGRA: ->");
-
- if(buff[3]!=res) {
- PRINTF(L_SC_ERROR,"result not expected (%02X != %02X)",buff[3],res);
- return false;
- }
- memcpy(sb,&buff[3+rlen],2);
- LDUMP(L_CORE_SC,sb,2,"NAGRA: ->");
- cCondWait::SleepMs(10);
- return true;
- }
- return false;
-}
-
-// -- cSmartCardLinkNagra -------------------------------------------------------------
-
-class cSmartCardLinkNagra : public cSmartCardLink {
-public:
- cSmartCardLinkNagra(void):cSmartCardLink(SC_NAME,SC_ID) {}
- virtual cSmartCard *Create(void) { return new cSmartCardNagra(); }
- virtual cSmartCardData *CreateData(void) { return new cSmartCardDataNagra; }
- };
-
-static cSmartCardLinkNagra staticScInit;
+++ /dev/null
-#
-# Smartcard Nagra
-#
-TARGET = sc_nagra
-OBJS = sc-nagra.o
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "system-common.h"
-#include "smartcard.h"
-#include "data.h"
-#include "misc.h"
-#include "opts.h"
-#include "parse.h"
-#include "log-sc.h"
-
-#define SYSTEM_SECA 0x0100
-
-#define SYSTEM_NAME "SC-Seca"
-#define SYSTEM_PRI -5
-#define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_SECA)
-
-#define SC_NAME "Seca"
-#define SC_ID MAKE_SC_ID('S','e','c','a')
-
-#define SECADATE(buff,len,odate) { \
- const unsigned char *dd=(odate); \
- snprintf(buff,len,"%04d/%02d/%02d", \
- ((dd[0]&0xFE)>>1)+1990, \
- ((dd[0]&0x01)<<3) + ((dd[1]&0xE0)>>5), \
- dd[1]&0x1F); \
- }
-
-#define L_SC 12
-#define L_SC_PROC LCLASS(L_SC,L_SC_LASTDEF<<1)
-#define L_SC_ALL LALL(L_SC_PROC)
-
-static const struct LogModule lm_sc = {
- (LMOD_ENABLE|L_SC_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_SC_DEFDEF)&LOPT_MASK,
- "sc-seca",
- { L_SC_DEFNAMES,"process" }
- };
-ADD_MODULE(L_SC,lm_sc)
-
-static int blocker=0;
-static int ppv=false;
-
-// -- cSystemScSeca ---------------------------------------------------------------
-
-class cSystemScSeca : public cSystemScCore {
-public:
- cSystemScSeca(void);
- };
-
-cSystemScSeca::cSystemScSeca(void)
-:cSystemScCore(SYSTEM_NAME,SYSTEM_PRI,SC_ID,"SC Seca")
-{
- hasLogger=true;
- needsDescrData=true;
-}
-
-// -- cSystemLinkScSeca --------------------------------------------------------
-
-static const char *block[] = {
- trNOOP("allow ALL"),
- trNOOP("block UNIQUE"),
- trNOOP("block SHARED"),
- trNOOP("block ALL")
- };
-
-class cSystemLinkScSeca : public cSystemLink {
-public:
- cSystemLinkScSeca(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemScSeca; }
- };
-
-static cSystemLinkScSeca staticInit;
-
-cSystemLinkScSeca::cSystemLinkScSeca(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- opts=new cOpts(SYSTEM_NAME,2);
- opts->Add(new cOptSel("Blocker",trNOOP("SC-Seca: EMM updates"),&blocker,sizeof(block)/sizeof(char *),block));
- cOpt *opt=new cOptBool("Ppv",trNOOP("SC-Seca: activate PPV"),&ppv);
- if(opt) opt->Persistant(false);
- opts->Add(opt);
- Feature.NeedsSmartCard();
-}
-
-bool cSystemLinkScSeca::CanHandle(unsigned short SysId)
-{
- SysId&=SYSTEM_MASK;
- return smartcards.HaveCard(SC_ID) && SYSTEM_CAN_HANDLE(SysId);
-}
-
-// -- cProviderScSeca ----------------------------------------------------------
-
-class cProviderScSeca : public cProviderSeca {
-public:
- int index;
- unsigned char date[2], pbm[8];
- char name[17];
- //
- cProviderScSeca(const unsigned char *pi, const unsigned char *s):cProviderSeca(pi,s) {}
- };
-
-// -- cSmartCardSeca -----------------------------------------------------------
-
-struct SecaProvInfo {
- unsigned char prov[2];
- char name[16];
- unsigned char sa[3];
- unsigned char cb;
- unsigned char date[2];
- unsigned char rr;
- unsigned char rstart;
- unsigned char pbm[8];
- unsigned char rend;
- };
-
-struct SecaChannelInfo {
- unsigned char pbm[8];
- unsigned char date[2];
- };
-
-class cSmartCardSeca : public cSmartCard, private cIdSet {
-private:
- char datebuff[16];
- //
- const char *Date(const unsigned char *date);
- bool CheckAccess(const unsigned char *data, const cProviderScSeca *p);
-public:
- cSmartCardSeca(void);
- virtual bool Init(void);
- virtual bool Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw);
- virtual bool Update(int pid, int caid, const unsigned char *data);
- };
-
-static const struct StatusMsg msgs[] = {
- // ECM status messages
- { { 0x90,0x00 }, "Instruction executed without errors", true },
- { { 0x90,0x02 }, "Signature failed", false },
- { { 0x90,0x27 }, "Decoding the preview (non-error)", true },
- { { 0x93,0x02 }, "No access, check your subscription", false },
- { { 0x96,0x00 }, "Chain of nonvalid entrance or null event or all the nanos process, none decoding", false },
- // EMM update status messages
- { { 0x90,0x09 }, "Card update was not meant for this card", false },
- { { 0x90,0x19 }, "Card update successfull, PPUA updated", true },
- { { 0x97,0x00 }, "Card update was successful", true },
- { { 0x97,0x40 }, "Card update was successful", true },
- { { 0x97,0x50 }, "Card update was successful", true },
- { { 0x97,0x78 }, "Card update was not necessary", false },
- { { 0x97,0xe0 }, "EEPROM update was not necessary", false },
- // unknown message
- { { 0xFF,0xFF }, 0, false }
- };
-
-static const struct CardConfig cardCfg = {
- SM_8E2,2000,300
- };
-
-cSmartCardSeca::cSmartCardSeca(void)
-:cSmartCard(&cardCfg,msgs)
-{}
-
-bool cSmartCardSeca::Init(void)
-{
- static unsigned char ins0e[] = { 0xC1,0x0e,0x00,0x00,0x08 }; // get serial nr. (UA)
- static unsigned char ins16[] = { 0xC1,0x16,0x00,0x00,0x07 }; // get nr. of providers
- static unsigned char ins12[] = { 0xC1,0x12,0x00,0x00,0x19 }; // get provider info
- static unsigned char ins34[] = { 0xC1,0x34,0x00,0x00,0x03 }; // request provider pbm (data=0x00 0x00 0x00)
- static unsigned char ins32[] = { 0xC1,0x32,0x00,0x00,0x0A }; // get the pbm data (p1=provider)
-
- static const unsigned char atrTester[] = { 0x0E,0x6C,0xB6,0xD6 };
- if(atr->T!=0 || atr->histLen<7 || memcmp(&atr->hist[3],atrTester,4)) {
- PRINTF(L_SC_INIT,"doesn't looks like a Seca card");
- return false;
- }
-
- infoStr.Begin();
- infoStr.Strcat("Seca smartcard\n");
- const char *type;
- switch(atr->hist[0]*256+atr->hist[1]) {
- case 0x5084: type="Generic"; break;
- case 0x5384: type="Philips"; break;
- case 0x5130:
- case 0x5430:
- case 0x5760: type="Thompson"; break;
- case 0x5284:
- case 0x5842:
- case 0x6060: type="Siemens"; break;
- case 0x7070: type="Canal+ NL"; break;
- default: type="Unknown"; break;
- }
- snprintf(idStr,sizeof(idStr),"%s (%s %d.%d)",SC_NAME,type,atr->hist[2]&0x0F,atr->hist[2]>>4);
- PRINTF(L_SC_INIT,"cardtype: %s %d.%d",type,atr->hist[2]&0x0F,atr->hist[2]>>4);
-
- ResetIdSet();
- unsigned char buff[MAX_LEN];
- if(!IsoRead(ins0e,buff) || !Status()) {
- PRINTF(L_SC_ERROR,"reading card serial failed");
- return false;
- }
- SetCard(new cCardSeca(&buff[2]));
- PRINTF(L_SC_INIT,"card serial number: %llu",Bin2LongLong(&buff[2],6));
- infoStr.Printf("Type: %s %d.%d Serial: %llu\n",type,atr->hist[2]&0x0F,atr->hist[2]>>4,Bin2LongLong(&buff[2],6));
-
- if(!IsoRead(ins16,buff) || !Status()) {
- PRINTF(L_SC_ERROR,"reading provider map failed");
- return false;
- }
- int provMap=buff[2]*256+buff[3];
- if(LOG(L_SC_INIT)) {
- int n=0, i=provMap;
- do { n+=i&1; i>>=1; } while(i);
- PRINTF(L_SC_INIT,"card has %d providers (0x%04x)",n,provMap);
- }
-
- for(int i=0 ; i<16 ; i++) {
- if(provMap&(1<<i)) {
- PRINTF(L_SC_INIT,"reading info for provider index %d",i);
- ins12[2]=i;
- if(!IsoRead(ins12,buff) || !Status()) {
- PRINTF(L_SC_ERROR,"reading provider info failed");
- return false;
- }
- ins32[2]=i;
- static const unsigned char ins34data[] = { 0x00,0x00,0x00 };
- if(!IsoWrite(ins34,ins34data) || !Status() ||
- !IsoRead(ins32,&buff[ins12[4]]) || !Status())
- memset(&buff[ins12[4]],0xFF,ins32[4]); // fake PBM response if card doesn't support command
-
- struct SecaProvInfo *spi=(struct SecaProvInfo *)buff;
- cProviderScSeca *p=new cProviderScSeca(spi->prov,spi->sa);
- if(p) {
- AddProv(p);
- p->index=i;
- strn0cpy(p->name,spi->name,sizeof(p->name));
- memcpy(p->date,spi->date,sizeof(p->date));
- memcpy(p->pbm,spi->pbm,sizeof(p->pbm));
- }
- infoStr.Printf("Prov %x (%.16s) until %s\n",p->provId[0]*256+p->provId[1],p->name,Date(p->date));
- char str[20];
- PRINTF(L_SC_INIT,"provider 0x%02x%02x '%.16s' expires %s pbm %s",
- p->provId[0],p->provId[1],p->name,Date(p->date),HexStr(str,p->pbm,sizeof(p->pbm)));
- }
- }
-
- infoStr.Finish();
- return true;
-}
-
-const char *cSmartCardSeca::Date(const unsigned char *date)
-{
- SECADATE(datebuff,sizeof(datebuff),date);
- return datebuff;
-}
-
-bool cSmartCardSeca::CheckAccess(const unsigned char *data, const cProviderScSeca *p)
-{
- struct SecaChannelInfo *sci=(struct SecaChannelInfo*)data;
- if(sci->date[0]>p->date[0] || (sci->date[0]==p->date[0] && sci->date[1]>p->date[1]))
- return false;
- char str[20];
- PRINTF(L_SC_PROC,"channelinfo date %s pbm %s",Date(sci->date),HexStr(str,sci->pbm,sizeof(sci->pbm)));
- int result=0;
- for(int i=7; i>=0; i--) // check pbm (is this right? seems to work though)
- result|=(sci->pbm[i]&p->pbm[i]);
- return (result!=0);
-}
-
-bool cSmartCardSeca::Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
-{
- static unsigned char ins3c[] = { 0xC1,0x3c,0x00,0x00,0x00 }; // coding cw
- static unsigned char ins3a[] = { 0xC1,0x3a,0x00,0x00,0x10 }; // decoding cw
- static unsigned char ins30[] = { 0xC1,0x30,0x00,0x02,0x09 }; // view ppv (active bx record)
- static unsigned char ins30data[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF };
-
- cProviderScSeca *p=(cProviderScSeca *)FindProv(data);
- if(p && ecm->Data()) {
- PRINTF(L_SC_PROC,"provider 0x%04x index %d '%.16s' (expires %s)",cParseSeca::ProvId(data),p->index,p->name,Date(p->date));
- if(CheckAccess(ecm->Data(),p)) {
- if(ppv) {
- PRINTF(L_SC_PROC,"activating PPV");
- if(IsoWrite(ins30,ins30data)) Status();
- ppv=false;
- }
- const unsigned char *payload;
- ins3c[2]=p->index | (cParseSeca::SysMode(data) & 0xF0);
- ins3c[3]=cParseSeca::KeyNr(data);
- ins3c[4]=cParseSeca::Payload(data,&payload);
- if(IsoWrite(ins3c,payload) && Status() &&
- IsoRead(ins3a,cw) && Status()) return true;
- }
- else PRINTF(L_SC_ERROR,"update your subscription to view this channel");
- }
- return false;
-}
-
-bool cSmartCardSeca::Update(int pid, int caid, const unsigned char *data)
-{
- static unsigned char ins40[] = { 0xC1,0x40,0x00,0x00,0x00 };
-
- if(blocker==0 || (data[0]==0x82 && blocker==2) || (data[0]==0x84 && blocker==1)) {
- cProviderScSeca *p=(cProviderScSeca *)FindProv(data);
- if(p && MatchEMM(data)) {
- PRINTF(L_SC_PROC,"got %s update",data[0]==0x82?"UNIQUE":"SHARED");
- const unsigned char *payload;
- ins40[2]=p->index | (cParseSeca::SysMode(data) & 0xF0);
- ins40[3]=cParseSeca::KeyNr(data);
- ins40[4]=cParseSeca::Payload(data,&payload);
- if(IsoWrite(ins40,payload) && Status()) return Init();
- }
- }
- return false;
-}
-
-// -- cSmartCardLinkSeca -------------------------------------------------------
-
-class cSmartCardLinkSeca : public cSmartCardLink {
-public:
- cSmartCardLinkSeca(void):cSmartCardLink(SC_NAME,SC_ID) {}
- virtual cSmartCard *Create(void) { return new cSmartCardSeca(); }
- };
-
-static cSmartCardLinkSeca staticScInit;
+++ /dev/null
-#
-# Smartcard Seca
-#
-TARGET = sc_seca
-OBJS = sc-seca.o
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "system-common.h"
-#include "smartcard.h"
-#include "parse.h"
-#include "misc.h"
-#include "log-sc.h"
-#include "log-core.h"
-
-#define SYSTEM_VIACCESS 0x0500
-
-#define SYSTEM_NAME "SC-Viaccess"
-#define SYSTEM_PRI -5
-#define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_VIACCESS)
-
-#define SC_NAME "Viaccess"
-#define SC_ID MAKE_SC_ID('V','i','a','s')
-
-#define L_SC 13
-#define L_SC_ALL LALL(L_SC_LASTDEF)
-
-static const struct LogModule lm_sc = {
- (LMOD_ENABLE|L_SC_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_SC_DEFDEF)&LOPT_MASK,
- "sc-viaccess",
- { L_SC_DEFNAMES }
- };
-ADD_MODULE(L_SC,lm_sc)
-
-// -- cSystemScViaccess ------------------------------------------------------------------
-
-class cSystemScViaccess : public cSystemScCore { //, private cTPS {
-public:
- cSystemScViaccess(void);
- virtual void ParseCADescriptor(cSimpleList<cEcmInfo> *ecms, unsigned short sysId, unsigned short source, const unsigned char *data, int len);
- };
-
-cSystemScViaccess::cSystemScViaccess(void)
-:cSystemScCore(SYSTEM_NAME,SYSTEM_PRI,SC_ID,"SC Viaccess")
-{
- hasLogger=true;
-}
-
-void cSystemScViaccess::ParseCADescriptor(cSimpleList<cEcmInfo> *ecms, unsigned short sysId, unsigned short source, const unsigned char *data, int len)
-{
- const int pid=WORD(data,2,0x1FFF);
- if(pid>=0xAA && pid<=0xCF) {
- PRINTF(L_CORE_ECMPROC,"sc-viaccess: dropped \"fake\" ecm pid 0x%04xn",pid);
- return;
- }
- cSystem::ParseCADescriptor(ecms,sysId,source,data,len);
-}
-
-// -- cSystemLinkScViaccess --------------------------------------------------------------
-
-class cSystemLinkScViaccess : public cSystemLink {
-public:
- cSystemLinkScViaccess(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemScViaccess; }
- };
-
-static cSystemLinkScViaccess staticInit;
-
-cSystemLinkScViaccess::cSystemLinkScViaccess(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- Feature.NeedsSmartCard();
-}
-
-bool cSystemLinkScViaccess::CanHandle(unsigned short SysId)
-{
- return smartcards.HaveCard(SC_ID) && SYSTEM_CAN_HANDLE(SysId);
-}
-
-// -- cProviderScViaccess ----------------------------------------------------------
-
-class cProviderScViaccess : public cProviderViaccess {
-public:
- unsigned char availKeys[16];
- char name[33];
- //
- cProviderScViaccess(const unsigned char *id, const unsigned char *s):cProviderViaccess(id,s) {}
- };
-
-// -- cSmartCardViaccess -----------------------------------------------------------------
-
-class cSmartCardViaccess : public cSmartCard, public cIdSet {
-private:
- unsigned char lastId[3];
- //
- unsigned char GetSW1(void) { return sb[1]; }
- bool CheckKey(cProviderScViaccess *p, const unsigned char keynr);
- bool SetProvider(const unsigned char *id);
-public:
- cSmartCardViaccess(void);
- virtual bool Init(void);
- virtual bool Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw);
- virtual bool Update(int pid, int caid, const unsigned char *data);
- };
-
-static const struct StatusMsg msgs[] = {
- { { 0x6b,0x00 }, "Instruction not supported", false },
- { { 0x6d,0x00 }, "Instruction not supported", false },
- { { 0x90,0x00 }, "Instruction executed without errors", true },
- { { 0x90,0x08 }, "Instruction executed without errors", true },
- { { 0xFF,0xFF }, 0, false }
- };
-
-static const struct CardConfig cardCfg = {
- SM_8O2,500,300
- };
-
-cSmartCardViaccess::cSmartCardViaccess(void)
-:cSmartCard(&cardCfg,msgs)
-{
- memset(lastId,0,sizeof(lastId));
-}
-
-bool cSmartCardViaccess::Init(void)
-{
- static const unsigned char verifyBytes[] = { 0x90,0x00 };
- if(atr->T!=0 || atr->histLen<7 || memcmp(&atr->hist[5],verifyBytes,sizeof(verifyBytes))) {
- PRINTF(L_SC_INIT,"doesn't look like a Viaccess card");
- return false;
- }
-
- infoStr.Begin();
- infoStr.Strcat("Viaccess smartcard\n");
- const char *ver=0;
- switch((atr->hist[3]<<8)|atr->hist[4]) {
- case 0x6268: ver="2.3"; break;
- case 0x6468:
- case 0x6668: ver="2.4"; break;
- case 0xa268: ver="2.5"; break;
- case 0xc168: ver="2.6"; break;
- default: ver="unknown"; break;
- }
-
- PRINTF(L_SC_INIT,"card v.%s",ver);
- snprintf(idStr,sizeof(idStr),"%s (V.%s)",SC_NAME,ver);
-
- static unsigned char insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
- static unsigned char insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
- static unsigned char insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
- static unsigned char insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
- unsigned char buff[MAX_LEN];
-
- ResetIdSet();
- insac[2]=0xa4; // request unique id
- if(!IsoWrite(insac,buff) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to request ua");
- return false;
- }
- insb8[4]=0x07; // read unique id
- if(!IsoRead(insb8,buff) || !Status() || buff[1]!=0x05) {
- PRINTF(L_SC_ERROR,"failed to read ua");
- return false;
- }
- SetCard(new cCardViaccess(&buff[2]));
- PRINTF(L_SC_INIT,"card UA: %llu",Bin2LongLong(&buff[2],5));
- infoStr.Printf("Card v.%s UA %010llu\n",ver,Bin2LongLong(&buff[2],5));
-
- insa4[2]=0x00; // select issuer 0
- if(!IsoWrite(insa4,buff) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to select issuer 0");
- return false;
- }
- do {
- insc0[4]=0x1a; // show provider properties
- if(!IsoRead(insc0,buff) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to read prov properties");
- return false;
- }
-
- unsigned char buff2[MAX_LEN];
- insac[2]=0xa5; // request sa
- if(!IsoWrite(insac,buff2) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to request sa");
- return false;
- }
- insb8[4]=0x06; // read sa
- if(!IsoRead(insb8,buff2) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to read sa");
- return false;
- }
- cProviderScViaccess *p=new cProviderScViaccess(&buff[0],&buff2[2]);
- if(p) {
- AddProv(p);
- memcpy(p->availKeys,buff+10,sizeof(p->availKeys));
-
- insac[2]=0xa7; // request name
- if(!IsoWrite(insac,buff) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to request prov name");
- return false;
- }
- insb8[4]=0x02; // read name nano + len
- if(!IsoRead(insb8,buff) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to read prov name length");
- return false;
- }
- unsigned int nameLen=buff[1];
- if(nameLen>=sizeof(p->name)) {
- PRINTF(L_SC_ERROR,"provider name buffer overflow");
- nameLen=sizeof(p->name)-1;
- }
- insb8[4]=nameLen;
- if(!IsoRead(insb8,buff) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to read prov name");
- return false;
- }
- memcpy(p->name,buff,nameLen); p->name[nameLen]=0;
-
- PRINTF(L_SC_INIT,"provider %06x (%s)",(int)p->ProvId(),p->name);
- infoStr.Printf("Prov %06x (%s) SA %08u\n",(int)p->ProvId(),p->name,Bin2Int(&buff2[2],4));
- }
- else PRINTF(L_SC_ERROR,"no memory for provider");
-
- insa4[2]=0x02; // next issuer
- if(!IsoWrite(insa4,buff) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to select next issuer");
- return false;
- }
- } while(GetSW1()==0x00);
- infoStr.Finish();
- return true;
-}
-
-bool cSmartCardViaccess::CheckKey(cProviderScViaccess *p, const unsigned char keynr)
-{
- for(unsigned int j=0; j<sizeof(p->availKeys); j++)
- if(p->availKeys[j]==keynr) return true;
- return false;
-}
-
-bool cSmartCardViaccess::SetProvider(const unsigned char *id)
-{
- static const unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 };
-
- if(id[0]!=lastId[0] || id[1]!=lastId[1] || (id[2]&0xF0)!=lastId[2]) {
- memcpy(lastId,id,3);
- lastId[2]&=0xF0;
- if(!IsoWrite(insa4,lastId) || !Status()) return false;
- }
- return true;
-}
-
-bool cSmartCardViaccess::Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
-{
- static unsigned char ins88[] = { 0xca,0x88,0x00,0x00,0x00 }; // set ecm
- static unsigned char insf8[] = { 0xca,0xf8,0x00,0x00,0x00 }; // set geographic info
- static unsigned char insc0[] = { 0xca,0xc0,0x00,0x00,0x12 }; // read dcw
-
- cProviderScViaccess *p=(cProviderScViaccess *)FindProv(data);
- if(p) {
- unsigned char keynr=cParseViaccess::KeyNr(data);
- if(CheckKey(p,keynr)) {
- if(!SetProvider(cParseViaccess::ProvIdPtr(data))) return false;
-
- const unsigned char *start=cParseViaccess::NanoStart(data)+5;
- const unsigned char *ecm88Data=start;
- int ecm88Len=SCT_LEN(data)-(start-data);
- int ecmf8Len=0;
- while(ecm88Len>0 && ecm88Data[0]<0xA0) {
- const int nanoLen=ecm88Data[1]+2;
- ecmf8Len+=nanoLen;
- ecm88Len-=nanoLen; ecm88Data+=nanoLen;
- }
- if(ecmf8Len) {
- insf8[3]=keynr;
- insf8[4]=ecmf8Len;
- if(!IsoWrite(insf8,start) || !Status()) return false;
- }
-
- ins88[2]=ecmf8Len?1:0;
- ins88[3]=keynr;
- ins88[4]=ecm88Len;
- if(!IsoWrite(ins88,ecm88Data) || !Status()) return false; // request dcw
- unsigned char buff[MAX_LEN];
- if(!IsoRead(insc0,buff) || !Status()) return false; // read dcw
- switch(buff[0]) {
- case 0xe8: // even
- if(buff[1]==8) { memcpy(cw,buff+2,8); return true; }
- break;
- case 0xe9: // odd
- if(buff[1]==8) { memcpy(cw+8,buff+2,8); return true; }
- break;
- case 0xea: // complete
- if(buff[1]==16) { memcpy(cw,buff+2,16); return true; }
- break;
- }
- }
- else PRINTF(L_SC_ERROR,"key not found on card");
- }
- else PRINTF(L_SC_ERROR,"provider not found on card");
- return false;
-}
-
-bool cSmartCardViaccess::Update(int pid, int caid, const unsigned char *data)
-{
- static unsigned char insf0[] = { 0xca,0xf0,0x00,0x00,0x00 };
- static unsigned char ins18[] = { 0xca,0x18,0x00,0x00,0x00 };
-
- int updtype;
- cAssembleData ad(data);
- if(MatchAndAssemble(&ad,&updtype,0)) {
- while((data=ad.Assembled())) {
- const unsigned char *start=cParseViaccess::NanoStart(data);
- int nanolen=SCT_LEN(data)-(start-data);
-
- if(start && start[0]==0x90 && start[1]==0x03 && nanolen>=5 && SetProvider(&start[2])) {
- insf0[3]=ins18[3]=cParseViaccess::KeyNrFromNano(start);
- start+=5; nanolen-=5;
-
- int n;
- if(start[0]==0x9e && nanolen>=(n=start[1]+2)) {
- insf0[4]=n;
- if(!IsoWrite(insf0,start) || !Status()) continue;
- start+=n; nanolen-=n;
- }
-
- if(nanolen>0) {
- ins18[2]=updtype>0 ? updtype-1 : updtype;
- ins18[4]=nanolen;
- if(IsoWrite(ins18,start)) Status();
- }
- }
- }
- return true;
- }
- return false;
-}
-
-// -- cSmartCardLinkViaccess -------------------------------------------------------------
-
-class cSmartCardLinkViaccess : public cSmartCardLink {
-public:
- cSmartCardLinkViaccess(void):cSmartCardLink(SC_NAME,SC_ID) {}
- virtual cSmartCard *Create(void) { return new cSmartCardViaccess(); }
- };
-
-static cSmartCardLinkViaccess staticScInit;
+++ /dev/null
-#
-# Smartcard Viaccess
-#
-TARGET = sc_viaccess
-OBJS = sc-viaccess.o
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "system-common.h"
-#include "smartcard.h"
-#include "data.h"
-#include "crypto.h"
-#include "misc.h"
-#include "parse.h"
-#include "helper.h"
-#include "log-sc.h"
-#include "log-core.h"
-
-#define SYSTEM_VIDEOGUARD2 0x0900
-
-#define SYSTEM_NAME "SC-VideoGuard2"
-#define SYSTEM_PRI -5
-
-#define SC_NAME "VideoGuard2"
-#define SC_ID MAKE_SC_ID('V','i','G','2')
-
-#define L_SC 17
-#define L_SC_ALL LALL(L_SC_LASTDEF)
-
-static const struct LogModule lm_sc = {
- (LMOD_ENABLE|L_SC_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_SC_DEFDEF)&LOPT_MASK,
- "sc-videoguard2",
- { L_SC_DEFNAMES }
- };
-ADD_MODULE(L_SC,lm_sc)
-
-// -- cSystemScVideoGuard2 ---------------------------------------------------------------
-
-class cSystemScVideoGuard2 : public cSystemScCore {
-public:
- cSystemScVideoGuard2(void);
- };
-
-cSystemScVideoGuard2::cSystemScVideoGuard2(void)
-:cSystemScCore(SYSTEM_NAME,SYSTEM_PRI,SC_ID,"SC VideoGuard2")
-{
- hasLogger=true;
-}
-
-// -- cSystemLinkScVideoGuard2 --------------------------------------------------------
-
-class cSystemLinkScVideoGuard2 : public cSystemLink {
-public:
- cSystemLinkScVideoGuard2(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemScVideoGuard2; }
- };
-
-static cSystemLinkScVideoGuard2 staticInit;
-
-cSystemLinkScVideoGuard2::cSystemLinkScVideoGuard2(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{}
-
-bool cSystemLinkScVideoGuard2::CanHandle(unsigned short SysId)
-{
- bool res=false;
- cSmartCard *card=smartcards.LockCard(SC_ID);
- if(card) {
- res=card->CanHandle(SysId);
- smartcards.ReleaseCard(card);
- }
- return res;
-}
-
-// -- cSmartCardDataVideoGuard2 -----------------------------------------------------
-
-enum eDataType { dtBoxId, dtSeed };
-
-class cSmartCardDataVideoGuard2 : public cSmartCardData {
-public:
- eDataType type;
- unsigned char boxid[4];
- unsigned char seed0[64], seed1[64];
- //
- cSmartCardDataVideoGuard2(void);
- cSmartCardDataVideoGuard2(eDataType Type);
- virtual bool Parse(const char *line);
- virtual bool Matches(cSmartCardData *param);
- };
-
-cSmartCardDataVideoGuard2::cSmartCardDataVideoGuard2(void)
-:cSmartCardData(SC_ID)
-{}
-
-cSmartCardDataVideoGuard2::cSmartCardDataVideoGuard2(eDataType Type)
-:cSmartCardData(SC_ID)
-{
- type=Type;
-}
-
-bool cSmartCardDataVideoGuard2::Matches(cSmartCardData *param)
-{
- cSmartCardDataVideoGuard2 *cd=(cSmartCardDataVideoGuard2 *)param;
- return cd->type==type;
-}
-
-bool cSmartCardDataVideoGuard2::Parse(const char *line)
-{
- line=skipspace(line);
- if(!strncasecmp(line,"BOXID",5)) { type=dtBoxId; line+=5; }
- else if(!strncasecmp(line,"SEED",4)) { type=dtSeed; line+=4; }
- else {
- PRINTF(L_CORE_LOAD,"smartcarddatavideoguard2: format error: datatype");
- return false;
- }
- line=skipspace(line);
- switch(type) {
- case dtBoxId:
- if(GetHex(line,boxid,sizeof(boxid))!=sizeof(boxid)) {
- PRINTF(L_CORE_LOAD,"smartcarddatavideoguard2: format error: boxid");
- return false;
- }
- break;
- case dtSeed:
- if(GetHex(line,seed0,sizeof(seed0))!=sizeof(seed0)) {
- PRINTF(L_CORE_LOAD,"smartcarddatacryptoworks: format error: seed0");
- return false;
- }
- line=skipspace(line);
- if(GetHex(line,seed1,sizeof(seed1))!=sizeof(seed1)) {
- PRINTF(L_CORE_LOAD,"smartcarddatacryptoworks: format error: seed1");
- return false;
- }
- break;
- }
- return true;
-}
-
-// -- cCamCryptVG2 -------------------------------------------------------------
-
-#define xor16(v1,v2,d) xxor((d),16,(v1),(v2))
-#define val_by2on3(x) ((0xaaab*(x))>>16) //fixed point *2/3
-
-class cCamCryptVG2 : private cAES {
-private:
- unsigned short cardkeys[3][32];
- unsigned char stateD3A[16];
- //
- void LongMult(unsigned short *pData, unsigned short *pLen, unsigned int mult, unsigned int carry);
- void PartialMod(unsigned short val, unsigned int count, unsigned short *outkey, const unsigned short *inkey);
- void RotateRightAndHash(unsigned char *p);
- void Reorder16A(unsigned char *dest, const unsigned char *src);
- void ReorderAndEncrypt(unsigned char *p);
- //
- void Process_D0(const unsigned char *ins, unsigned char *data, const unsigned char *status);
- void Process_D1(const unsigned char *ins, unsigned char *data, const unsigned char *status);
- void Decrypt_D3(unsigned char *ins, unsigned char *data, const unsigned char *status);
-public:
- void PostProcess_Decrypt(unsigned char *buff, int len, unsigned char *cw1, unsigned char *cw2);
- void SetSeed(const unsigned char *Key1, const unsigned char *Key2);
- void GetCamKey(unsigned char *buff);
-};
-
-void cCamCryptVG2::SetSeed(const unsigned char *Key1, const unsigned char *Key2)
-{
- memcpy(cardkeys[1],Key1,sizeof(cardkeys[1]));
- memcpy(cardkeys[2],Key2,sizeof(cardkeys[2]));
-}
-
-void cCamCryptVG2::GetCamKey(unsigned char *buff)
-{
- unsigned short *tb2=(unsigned short *)buff, c=1;
- memset(tb2,0,64);
- tb2[0]=1;
- for(int i=0; i<32; i++) LongMult(tb2,&c,cardkeys[1][i],0);
-}
-
-void cCamCryptVG2::PostProcess_Decrypt(unsigned char *buff, int len, unsigned char *cw1, unsigned char *cw2)
-{
- switch(buff[0]) {
- case 0xD0:
- Process_D0(buff,buff+5,buff+buff[4]+5);
- break;
- case 0xD1:
- Process_D1(buff,buff+5,buff+buff[4]+5);
- break;
- case 0xD3:
- Decrypt_D3(buff,buff+5,buff+buff[4]+5);
- if(buff[1]==0x54) {
- memcpy(cw1,buff+5,8);
- for(int ind=14; ind<len+5;) {
- if(buff[ind]==0x25) {
- memcpy(cw2,buff+5+ind+2,8);
- break;
- }
- if(buff[ind+1]==0) break;
- ind+=buff[ind+1];
- }
- }
- break;
- }
-}
-
-void cCamCryptVG2::Process_D0(const unsigned char *ins, unsigned char *data, const unsigned char *status)
-{
- switch(ins[1]) {
- case 0xb4:
- memcpy(cardkeys[0],data,sizeof(cardkeys[0]));
- break;
- case 0xbc:
- {
- unsigned short *idata=(unsigned short *)data;
- const unsigned short *key1=(const unsigned short *)cardkeys[1];
- unsigned short key2[32];
- memcpy(key2,cardkeys[2],sizeof(key2));
- for(int count2=0; count2<32; count2++) {
- unsigned int rem=0, div=key1[count2];
- for(int i=31; i>=0; i--) {
- unsigned int x=idata[i] | (rem<<16);
- rem=(x%div)&0xffff;
- }
- unsigned int carry=1, t=val_by2on3(div) | 1;
- while(t) {
- if(t&1) carry=((carry*rem)%div)&0xffff;
- rem=((rem*rem)%div)&0xffff;
- t>>=1;
- }
- PartialMod(carry,count2,key2,key1);
- }
- unsigned short idatacount=0;
- for(int i=31; i>=0; i--) LongMult(idata,&idatacount,key1[i],key2[i]);
- unsigned char stateD1[16];
- Reorder16A(stateD1,data);
- cAES::SetKey(stateD1);
- break;
- }
- }
-}
-
-void cCamCryptVG2::Process_D1(const unsigned char *ins, unsigned char *data, const unsigned char *status)
-{
- unsigned char iter[16], tmp[16];
- memset(iter,0,sizeof(iter));
- memcpy(iter,ins,5);
- xor16(iter,stateD3A,iter);
- memcpy(stateD3A,iter,sizeof(iter));
-
- int datalen=status-data;
- int datalen1=datalen;
- if(datalen<0) datalen1+=15;
- int blocklen=datalen1>>4;
- for(int i=0,iblock=0; i<blocklen+2; i++,iblock+=16) {
- unsigned char in[16];
- if(blocklen==i) {
- memset(in,0,sizeof(in));
- memcpy(in,&data[iblock],datalen-(datalen1&~0xf));
- }
- else if(blocklen+1==i) {
- memset(in,0,sizeof(in));
- memcpy(&in[5],status,2);
- }
- else
- memcpy(in,&data[iblock],sizeof(in));
-
- xor16(iter,in,tmp);
- ReorderAndEncrypt(tmp);
- xor16(tmp,stateD3A,iter);
- }
- memcpy(stateD3A,tmp,16);
-}
-
-void cCamCryptVG2::Decrypt_D3(unsigned char *ins, unsigned char *data, const unsigned char *status)
-{
- if(ins[4]>16) ins[4]-=16;
- if(ins[1]==0xbe) memset(stateD3A,0,sizeof(stateD3A));
-
- unsigned char tmp[16];
- memset(tmp,0,sizeof(tmp));
- memcpy(tmp,ins,5);
- xor16(tmp,stateD3A,stateD3A);
-
- int len1=ins[4];
- int blocklen=len1>>4;
- if(ins[1]!=0xbe) blocklen++;
-
- unsigned char iter[16], states[16][16];
- memset(iter,0,sizeof(iter));
- for(int blockindex=0; blockindex<blocklen; blockindex++) {
- iter[0]+=blockindex;
- xor16(iter,stateD3A,iter);
- ReorderAndEncrypt(iter);
- xor16(iter,&data[blockindex*16],states[blockindex]);
- if(blockindex==(len1>>4)) {
- int c=len1-(blockindex*16);
- if(c<16) memset(&states[blockindex][c],0,16-c);
- }
- xor16(states[blockindex],stateD3A,stateD3A);
- RotateRightAndHash(stateD3A);
- }
- memset(tmp,0,sizeof(tmp));
- memcpy(tmp+5,status,2);
- xor16(tmp,stateD3A,stateD3A);
- ReorderAndEncrypt(stateD3A);
-
- memcpy(stateD3A,status-16,sizeof(stateD3A));
- ReorderAndEncrypt(stateD3A);
-
- memcpy(data,states[0],len1);
- if(ins[1]==0xbe) {
- Reorder16A(tmp,states[0]);
- cAES::SetKey(tmp);
- }
-}
-
-void cCamCryptVG2::ReorderAndEncrypt(unsigned char *p)
-{
- unsigned char tmp[16];
- Reorder16A(tmp,p); cAES::Encrypt(tmp,16,tmp); Reorder16A(p,tmp);
-}
-
-// reorder AAAABBBBCCCCDDDD to ABCDABCDABCDABCD
-
-void cCamCryptVG2::Reorder16A(unsigned char *dest, const unsigned char *src)
-{
- for(int i=0,k=0; i<4; i++)
- for(int j=i; j<16; j+=4,k++)
- dest[k]=src[j];
-}
-
-void cCamCryptVG2::LongMult(unsigned short *pData, unsigned short *pLen, unsigned int mult, unsigned int carry)
-{
- for(int i=0; i<*pLen; i++) {
- carry+=pData[i]*mult;
- pData[i]=(unsigned short)carry;
- carry>>=16;
- }
- if(carry) pData[(*pLen)++]=carry;
-}
-
-void cCamCryptVG2::PartialMod(unsigned short val, unsigned int count, unsigned short *outkey, const unsigned short *inkey)
-{
- if(count) {
- unsigned int mod=inkey[count];
- unsigned short mult=(inkey[count]-outkey[count-1])&0xffff;
- for(unsigned int i=0,ib1=count-2; i<count-1; i++,ib1--) {
- unsigned int t=(inkey[ib1]*mult)%mod;
- mult=t-outkey[ib1];
- if(mult>t) mult+=mod;
- }
- mult+=val;
- if((val>mult) || (mod<mult)) mult-=mod;
- outkey[count]=(outkey[count]*mult)%mod;
- }
- else
- outkey[0]=val;
-}
-
-static const unsigned char table1[256] = {
- 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5, 0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
- 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0, 0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
- 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc, 0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
- 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a, 0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
- 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0, 0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
- 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b, 0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
- 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85, 0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
- 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5, 0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
- 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17, 0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
- 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88, 0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
- 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c, 0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
- 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9, 0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
- 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6, 0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
- 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e, 0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
- 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94, 0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
- 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68, 0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16,
- };
-
-void cCamCryptVG2::RotateRightAndHash(unsigned char *p)
-{
- unsigned char t1=p[15];
- for(int i=0; i<16; i++) {
- unsigned char t2=t1;
- t1=p[i]; p[i]=table1[(t1>>1)|((t2&1)<<7)];
- }
-}
-
-// -- cCmdTable ----------------------------------------------------------------
-
-struct CmdTabEntry {
- unsigned char cla;
- unsigned char cmd;
- unsigned char len;
- unsigned char mode;
-};
-
-struct CmdTab {
- unsigned char index;
- unsigned char size;
- unsigned char Nentries;
- unsigned char dummy;
- CmdTabEntry e[1];
-};
-
-class CmdTable {
-private:
- struct CmdTab *tab;
-public:
- CmdTable(const unsigned char *mem, int size);
- ~CmdTable();
- bool GetInfo(const unsigned char *cmd, unsigned char &rlen, unsigned char &rmode);
- };
-
-CmdTable::CmdTable(const unsigned char *mem, int size)
-{
- tab=(struct CmdTab *)new unsigned char[size];
- memcpy(tab,mem,size);
-}
-
-CmdTable::~CmdTable()
-{
- delete tab;
-}
-
-bool CmdTable::GetInfo(const unsigned char *cmd, unsigned char &rlen, unsigned char & rmode)
-{
- struct CmdTabEntry *pcte=tab->e;
- for(int i=0; i<tab->Nentries; i++,pcte++)
- if(cmd[1]==pcte->cmd) {
- rlen=pcte->len;
- rmode=pcte->mode;
- return true;
- }
- return false;
-}
-
-// -- cSmartCardVideoGuard2 -----------------------------------------------------------
-
-#define BASEYEAR 2000 // for date calculation
-
-class cSmartCardVideoGuard2 : public cSmartCard, private cIdSet {
-private:
- unsigned char CW1[8], CW2[8];
- unsigned char cardID[4], groupID[4], boxID[4];
- unsigned int CAID;
- cCamCryptVG2 state;
- CmdTable *cmdList;
-public:
- void ReadTiers(void);
- void RevDateCalc(const unsigned char *Date, int &year, int &mon, int &day, int &hh, int &mm, int &ss);
- void Datecalc(int year, int mon, int day, int hh, int mm, int ss , unsigned char * Date);
- int DoCmd(const unsigned char *ins, const unsigned char *txbuff=0, unsigned char *rxbuff=0);
- int ReadCmdLen(const unsigned char *cmd);
-public:
- cSmartCardVideoGuard2(void);
- ~cSmartCardVideoGuard2();
- virtual bool Init(void);
- virtual bool Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw);
- virtual bool Update(int pid, int caid, const unsigned char *data);
- virtual bool CanHandle(unsigned short SysId);
- };
-
-static const struct StatusMsg msgs[] = {
- { { 0x90,0x00 }, "Instruction executed without errors, noupdate, nofilter, IRD# not set", true },
- { { 0x90,0x01 }, "Instruction executed without errors, update, nofilter, IRD# not set", true },
- { { 0x90,0x20 }, "Instruction executed without errors, noupdate, nofilter, IRD# set", true },
- { { 0x90,0x21 }, "Instruction executed without errors, update, nofilter, IRD# set", true },
- { { 0x90,0x80 }, "Instruction executed without errors, noupdate, filter, IRD# not set", true },
- { { 0x90,0x81 }, "Instruction executed without errors, update, filter, IRD# not set", true },
- { { 0x90,0xa0 }, "Instruction executed without errors, noupdate, filter, IRD# set", true },
- { { 0x90,0xa1 }, "Instruction executed without errors, update, filter, IRD# set", true },
- { { 0x91,0x00 }, "Instruction executed without errors, noupdate, nofilter, IRD# not set", true },
- { { 0x91,0x01 }, "Instruction executed without errors, update, nofilter, IRD# not set", true },
- { { 0x91,0x20 }, "Instruction executed without errors, noupdate, nofilter, IRD# set", true },
- { { 0x91,0x21 }, "Instruction executed without errors, update, nofilter, IRD# set", true },
- { { 0x91,0x80 }, "Instruction executed without errors, noupdate, filter, IRD# not set", true },
- { { 0x91,0x81 }, "Instruction executed without errors, update, filter, IRD# not set", true },
- { { 0x91,0xa0 }, "Instruction executed without errors, noupdate, filter, IRD# set", true },
- { { 0x91,0xa1 }, "Instruction executed without errors, update, filter, IRD# set", true },
- { { 0xFF,0xFF }, 0, false }
- };
-
-static const struct CardConfig cardCfg = {
- SM_8O2,2000,1400
- };
-
-cSmartCardVideoGuard2::cSmartCardVideoGuard2(void)
-:cSmartCard(&cardCfg,msgs)
-{
- cmdList=0;
-}
-
-cSmartCardVideoGuard2::~cSmartCardVideoGuard2(void)
-{
- delete cmdList;
-}
-
-bool cSmartCardVideoGuard2::CanHandle(unsigned short SysId)
-{
- return SysId==CAID;
-}
-
-bool cSmartCardVideoGuard2::Init(void)
-{
- static const unsigned char vg2Hist[] = { 'i',0xff,'J','P' };
- if(atr->histLen<4 || memcmp(&atr->hist[3],vg2Hist,4)) {
- PRINTF(L_SC_INIT,"doesn't look like a VideoGuard2 card");
- return false;
- }
-
- infoStr.Begin();
- infoStr.Strcat("VideoGuard2 smartcard\n");
- snprintf(idStr,sizeof(idStr),"%s (%c%c.%d)",SC_NAME,atr->hist[10],atr->hist[11],atr->hist[12]);
-
- ResetIdSet();
- delete cmdList; cmdList=0;
-
- static unsigned char ins7401[] = { 0xD0,0x74,0x01,0x00,0x00 };
- int l;
- if((l=ReadCmdLen(ins7401))<0) return false;
- ins7401[4]=l;
- unsigned char buff[256];
- if(!IsoRead(ins7401,buff) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to read cmd list");
- return false;
- }
- cmdList=new CmdTable(buff,l);
-
- static const unsigned char ins7416[5] = { 0xD0,0x74,0x16,0x00,0x00 };
- if(DoCmd(ins7416)<0 || !Status()) {
- PRINTF(L_SC_ERROR,"cmd 7416 failed");
- return false;
- }
-
- static const unsigned char ins36[5] = { 0xD0,0x36,0x00,0x00,0x00 };
- bool boxidOK=false;
- if((l=DoCmd(ins36,0,buff))>0 && Status())
- for(int i=0; i<l ;i++) {
- if(buff[i]==0x00 && buff[i+1]==0xF3) {
- memcpy(&boxID,&buff[i+2],sizeof(boxID));
- boxidOK=true;
- break;
- }
- }
- if(!boxidOK) {
- cSmartCardDataVideoGuard2 cd(dtBoxId);
- cSmartCardDataVideoGuard2 *entry=(cSmartCardDataVideoGuard2 *)smartcards.FindCardData(&cd);
- if(entry) {
- memcpy(&boxID,entry->boxid,sizeof(boxID));
- boxidOK=true;
- }
- }
- if(!boxidOK) {
- PRINTF(L_SC_ERROR,"no boxID available");
- return false;
- }
-
- static const unsigned char ins4C[5] = { 0xD0,0x4C,0x00,0x00,0x00 };
- static unsigned char payload4C[9] = { 0,0,0,0, 3,0,0,2,4 };
- memcpy(payload4C,boxID,4);
- if(DoCmd(ins4C,payload4C)<0 || !Status()) {
- PRINTF(L_SC_ERROR,"sending boxid failed");
- return false;
- }
-
- static const unsigned char ins58[5] = { 0xD0,0x58,0x00,0x00,0x00 };
- if(DoCmd(ins58,0,buff)<0 || !Status()) {
- PRINTF(L_SC_ERROR,"failed to read card details");
- return false;
- }
-
- CAID=WORD(buff,0x1D,0xFFFF);
- memcpy(&cardID,&buff[8],4);
- memcpy(&groupID,&buff[8],4); groupID[3]=0;
- SetCard(new cCardNDS(cardID));
- AddProv(new cProviderNDS(groupID));
- char str[20], str2[20];
- infoStr.Printf("Cardtype: %c%c.%d\n"
- "BoxID %s Caid %04x CardID %s\n",
- atr->hist[10],atr->hist[11],atr->hist[12],HexStr(str,boxID,4),CAID,HexStr(str2,cardID,4));
- PRINTF(L_SC_INIT,"cardtype: %c%c.%d boxID %s caid %04x cardID %s",atr->hist[10],atr->hist[11],atr->hist[12],HexStr(str,boxID,4),CAID,HexStr(str2,cardID,4));
-
- cSmartCardDataVideoGuard2 cd(dtSeed);
- cSmartCardDataVideoGuard2 *entry=(cSmartCardDataVideoGuard2 *)smartcards.FindCardData(&cd);
- if(!entry) {
- PRINTF(L_SC_ERROR,"no NDS seed available");
- return false;
- }
- state.SetSeed(entry->seed0,entry->seed1);
- unsigned char tbuff[64];
- state.GetCamKey(tbuff);
-
- static const unsigned char insB4[5] = { 0xD0,0xB4,0x00,0x00,0x00 };
- if(DoCmd(insB4,tbuff)<0 || !Status()) {
- PRINTF(L_SC_ERROR,"cmd D0B4 failed");
- return false;
- }
-
- static const unsigned char insBC[5] = { 0xD0,0xBC,0x00,0x00,0x00 };
- if(DoCmd(insBC)<0 || !Status()) {
- PRINTF(L_SC_ERROR,"cmd D0BC failed");
- return false;
- }
- static const unsigned char insBE[5] = { 0xD3,0xBE,0x00,0x00,0x00 };
- if(DoCmd(insBE)<0 || !Status()) {
- PRINTF(L_SC_ERROR,"cmd D3BE failed");
- return false;
- }
-
- static const unsigned char ins58a[5] = { 0xD1,0x58,0x00,0x00,0x00 };
- if(DoCmd(ins58a)<0 || !Status()) {
- PRINTF(L_SC_ERROR,"cmd D158 failed");
- return false;
- }
- static const unsigned char ins4Ca[5] = { 0xD1,0x4C,0x00,0x00,0x00 };
- if(DoCmd(ins4Ca,payload4C)<0 || !Status()) {
- PRINTF(L_SC_ERROR,"cmd D14C failed");
- return false;
- }
- ReadTiers();
- return true;
-}
-
-bool cSmartCardVideoGuard2::Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
-{
- static unsigned char ins40[5] = { 0xD1,0x40,0x40,0x80,0xFF };
- static const unsigned char ins54[5] = { 0xD3,0x54,0x00,0x00,0x00 };
- int posECMpart2=data[6]+7;
- int lenECMpart2=data[posECMpart2]+1;
- unsigned char tbuff[264];
- tbuff[0]=0;
- memcpy(&tbuff[1],&data[posECMpart2+1],lenECMpart2);
- ins40[4]=lenECMpart2;
- if(DoCmd(ins40,tbuff)>0 && Status()) {
- if(DoCmd(ins54)>0 && Status()) {
- if(data[0]&1) memcpy(cw+8,CW1,8);
- else memcpy(cw+0,CW1,8);
- return true;
- }
- }
- return false;
-}
-
-bool cSmartCardVideoGuard2::Update(int pid, int caid, const unsigned char *data)
-{
- static unsigned char ins42[5] = { 0xD1,0x42,0x00,0x00,0xFF };
- if(MatchEMM(data)) {
- const unsigned char *payloaddata=cParseNDS::PayloadStart(data); //points to 02 xx yy
- int lenEMM;
- switch(payloaddata[0]) {
- case 2:
- lenEMM=payloaddata[payloaddata[1]+2];
- payloaddata+=3+payloaddata[1]; // skip len specifier
- break;
- default:
-// di(printf("scvg2: ***ERROR***: EMM: bad payload type byte %02x\n",payloaddata[0]));
-// DUMP3("VG2EMM",data,32);
- return false;
- }
-// di(printf("scvg2: EMM: pid %d (%x) caid %d (%x) len %d (%x)\n",pid,pid,caid,caid,lenEMM,lenEMM));
-// DUMP3("VG2EMM",data,32);
- if(lenEMM<=8 || lenEMM>188) {
-// di(printf("scvg2: ***ERROR***: EMM: len %d bad\n",lenEMM));
- return false;
- }
- ins42[4]=lenEMM;
- if(DoCmd(ins42,payloaddata)>0 && Status())
- return true;
- }
- return false;
-}
-
-/*
-bool cSmartCardVideoGuard2::ZKT(void)
-{
- static unsigned char payload4A[1] = { 0x01 };
- static unsigned char ins4A[5] = { 0xD0,0x4A,0x15,0x01,0x01 };
- DoCmd(ins4A,payload4A);
- static unsigned char ins5A1[5] = { 0xD0,0x5A,0x15,0x01,0x10 };
- DoCmd(ins5A1);
- static unsigned char ins5A2[5] = { 0xD0,0x5A,0x11,0x02,0x40 };
- DoCmd(ins5A2);
- DoCmd(ins4A,payload4A);
- DoCmd(ins5A1);
- static unsigned char ins5A3[5] = { 0xD0,0x5A,0x10,0x02,0x40 };
- DoCmd(ins5A3);
- return true;
-}
-*/
-
-void cSmartCardVideoGuard2::ReadTiers(void)
-{
- static const unsigned char ins2a[5] = { 0xd0,0x2a,0x00,0x00,0x00 };
- if(DoCmd(ins2a)<0 || !Status()) return;
- static unsigned char ins76[5] = { 0xd0,0x76,0x00,0x00,0x00 };
- ins76[3]=0x7f; ins76[4]=2;
- unsigned char buff[270];
- if(!IsoRead(ins76,buff) || !Status()) return;
- ins76[3]=0; ins76[4]=0;
- int num=buff[1];
- if(num>0) {
- infoStr.Strcat("Tier\tExpiry Date\n");
- infoStr.Strcat("----\t-----------\n");
- }
- for(int i=0; i<num; i++) {
- ins76[2]=i;
- if(DoCmd(ins76,0,buff)<0 || !Status()) return;
- if(buff[5+2]==0 && buff[5+3]==0) break;
- int y,m,d,H,M,S;
- RevDateCalc(&buff[5+4],y,m,d,H,M,S);
- char str[100];
- snprintf(str,sizeof(str),"%02x%02x\t%04d/%02d/%02d-%02d:%02d:%02d\n",buff[5+2],buff[5+3],y,m,d,H,M,S);
- infoStr.Strcat(str);
- PRINTF(L_SC_INIT,"Tier %02x%02x expires %04d/%02d/%02d-%02d:%02d:%02d",buff[5+2],buff[5+3],y,m,d,H,M,S);
- }
-}
-
-void cSmartCardVideoGuard2::RevDateCalc(const unsigned char *Date, int &year, int &mon, int &day, int &hh, int &mm, int &ss)
-{
- year=(Date[0]/12)+BASEYEAR;
- mon=(Date[0]%12)+1;
- day=Date[1];
- hh=Date[2]/8;
- mm=(0x100*(Date[2]-hh*8)+Date[3])/32;
- ss=(Date[3]-mm*32)*2;
-}
-
-void cSmartCardVideoGuard2::Datecalc(int year, int mon, int day, int hh, int mm, int ss , unsigned char *Date)
-{
- Date[0]=((year-BASEYEAR)*12 + (mon-1));
- Date[1]=day;
- Date[2]=hh*8+mm/8;
- Date[3]=ss/2+mm*32;
-}
-
-int cSmartCardVideoGuard2::DoCmd(const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff)
-{
- unsigned char ins2[5];
- memcpy(ins2,ins,5);
- unsigned char len=0, mode=0;
- if(cmdList->GetInfo(ins2,len,mode)) {
- if(len==0xFF && mode==2) {
- if(ins2[4]==0) ins2[4]=len=ReadCmdLen(ins2);
- }
- else if(mode!=0) ins2[4]=len;
- }
- if(ins2[0]==0xd3) ins2[4]=len+16;
- len=ins2[4];
-
- unsigned char b[256], tmp[264];
- if(!rxbuff) rxbuff=tmp;
- if(mode>1) {
- if(!IsoRead(ins2,b) || !Status()) return -1;
- memcpy(rxbuff,ins2,5);
- memcpy(rxbuff+5,b,len);
- memcpy(rxbuff+5+len,sb,2);
- }
- else {
- if(!IsoWrite(ins2,txbuff) || !Status()) return -1;
- memcpy(rxbuff,ins2,5);
- memcpy(rxbuff+5,txbuff,len);
- memcpy(rxbuff+5+len,sb,2);
- }
- state.PostProcess_Decrypt(rxbuff,len,CW1,CW2);
- return len;
-}
-
-int cSmartCardVideoGuard2::ReadCmdLen(const unsigned char *cmd)
-{
- unsigned char cmd2[5], resp[16];
- memcpy(cmd2,cmd,5);
- cmd2[3]=0x80;
- cmd2[4]=1;
- if(!IsoRead(cmd2,resp) || !Status()) {
- PRINTF(L_SC_ERROR,"failed to read %02x%02x cmd length",cmd[1],cmd[2]);
- return -1;
- }
- return resp[0];
-}
-
-// -- cSmartCardLinkVG2 -------------------------------------------------------
-
-class cSmartCardLinkVG2 : public cSmartCardLink {
-public:
- cSmartCardLinkVG2(void):cSmartCardLink(SC_NAME,SC_ID) {}
- virtual cSmartCard *Create(void) { return new cSmartCardVideoGuard2; }
- virtual cSmartCardData *CreateData(void) { return new cSmartCardDataVideoGuard2; }
- };
-
-static cSmartCardLinkVG2 staticScInit;
+++ /dev/null
-#
-# Smartcard VideoGuard2
-#
-TARGET = sc_videoguard2
-OBJS = sc-videoguard2.o
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <byteswap.h>
-
-#include <openssl/sha.h>
-
-#include "system-common.h"
-#include "data.h"
-#include "helper.h"
-#include "crypto.h"
-#include "parse.h"
-#include "misc.h"
-#include "log-sys.h"
-#include "log-core.h"
-
-#define SYSTEM_SECA 0x0100
-
-#define SYSTEM_NAME "Seca"
-#define SYSTEM_PRI -10
-#define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_SECA)
-
-#define FILEMAP_DOMAIN "seca"
-
-#define L_SYS 14
-#define L_SYS_ALL LALL(L_SYS_LASTDEF)
-
-static const struct LogModule lm_sys = {
- (LMOD_ENABLE|L_SYS_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_SYS_DEFDEF)&LOPT_MASK,
- "seca",
- { L_SYS_DEFNAMES }
- };
-ADD_MODULE(L_SYS,lm_sys)
-
-// -- cPlainKeySeca ------------------------------------------------------------
-
-#define PLAINLEN_SECA_H 8
-#define PLAINLEN_SECA_D 16
-#define PLAINLEN_SECA_B 90
-#define PLAINLEN_SECA_E 6 // exponent key len
-#define EMM_MAGIC 1
-#define N51_MAGIC 2
-
-class cPlainKeySeca : public cDualKey {
-protected:
- virtual bool IsBNKey(void) const;
- virtual int IdSize(void) { return 4; }
- virtual cString PrintKeyNr(void);
-public:
- cPlainKeySeca(bool Super);
- virtual bool Parse(const char *line);
- };
-
-static cPlainKeyTypeReg<cPlainKeySeca,'S'> KeyReg;
-
-cPlainKeySeca::cPlainKeySeca(bool Super)
-:cDualKey(Super,true)
-{}
-
-bool cPlainKeySeca::IsBNKey(void) const
-{
- switch(keynr&C2MASK) {
- case MBC('E','1'):
- case MBC('M','1'):
- case MBC('E','3'):
- case MBC('M','3'):
- case MBC('E','5'):
- case MBC('M','5'):
- case MBC('E','9'):
- case MBC('M','9'): return true;
- }
- return false;
-}
-
-bool cPlainKeySeca::Parse(const char *line)
-{
- unsigned char sid[2];
- int len;
- if(GetChar(line,&type,1) && (len=GetHex(line,sid,2,false))) {
- type=toupper(type); id=Bin2Int(sid,len);
- line=skipspace(line);
- int emmnr=0, keylen=PLAINLEN_SECA_B;
- if(!strncasecmp(line,"EMM",3)) { // EMM RSA key
- emmnr=EMM_MAGIC;
- line+=3;
- line=skipspace(line);
- }
- else if(!strncasecmp(line,"N51",3)) { // Nano 51 RSA key
- emmnr=N51_MAGIC;
- line+=3;
- line=skipspace(line);
- keylen=toupper(*line)=='E'?1:129;
- }
- bool ok;
- switch(toupper(*line)) {
- case 'E':
- case 'M': ok=GetChar(line,&keynr,2);
- keynr=ADDC3(keynr,emmnr);
- break;
- default: ok=emmnr ? false : GetHex(line,sid,1);
- keynr=sid[0];
- break;
- }
- if(ok) {
- unsigned char *skey=AUTOMEM(keylen);
- len=GetHex(line,skey,keylen,false);
- if(IsBNKey()) {
- if(C2(keynr)=='E' && len==PLAINLEN_SECA_E) {
- // support short exponent keys
- keylen=len;
- }
- }
- else {
- if(len==PLAINLEN_SECA_H || len==PLAINLEN_SECA_D) {
- // support for 16 & 8 byte keys
- keylen=len;
- }
- }
- if(len==keylen) {
- SetBinKey(skey,keylen);
- return true;
- }
- }
- }
- return false;
-}
-
-cString cPlainKeySeca::PrintKeyNr(void)
-{
- char nr[32];
- int q=0;
- switch(C3(keynr)) {
- case EMM_MAGIC: q+=snprintf(nr+q,sizeof(nr)-q,"EMM "); break;
- case N51_MAGIC: q+=snprintf(nr+q,sizeof(nr)-q,"N51 "); break;
- }
- if(IsBNKey()) {
- nr[q ]=(keynr>>8) & 0xff;
- nr[q+1]= keynr & 0xff;
- nr[q+2]=0;
- q+=2;
- }
- else q+=snprintf(nr+q,sizeof(nr)-q,"%.2X",keynr);
- return nr;
-}
-
-// -- cSecaCardInfo ------------------------------------------------------------
-
-class cSecaCardInfo : public cStructItem, public cProviderSeca {
-private:
- int len;
-public:
- unsigned char key[16];
- //
- bool Parse(const char *line);
- int KeySize(void) { return len; }
- };
-
-bool cSecaCardInfo::Parse(const char *line)
-{
- return GetHex(line,provId,sizeof(provId)) &&
- GetHex(line,sa,sizeof(sa)) &&
- (len=GetHex(line,key,sizeof(key),false)) &&
- (len==PLAINLEN_SECA_H || len==PLAINLEN_SECA_D);
-}
-
-// -- cSecaCardInfos -----------------------------------------------------------
-
-class cSecaCardInfos : public cCardInfos<cSecaCardInfo> {
-public:
- cSecaCardInfos(void):cCardInfos<cSecaCardInfo>("Seca cards","Seca.KID",0) {}
- };
-
-static cSecaCardInfos Scards;
-
-// -- cSeca --------------------------------------------------------------------
-
-static const unsigned char secaPC1[] = {
- 42,57,29,34, 41,53,30,15,
- 19,36,23,14, 43,61,12, 3,
- 51,49,5, 6, 45,54,52,47,
- 63,38,58,22, 60,33,10,26,
- 37,35,44, 1, 20,62,28,18,
- 46, 9,39, 4, 27,11,21,50,
- 31,25, 2, 7, 13,55,59,17
- };
-
-static const unsigned char secaPC2[] = {
- 18, 3,21,15, 42,35,37, 8,
- 49,41,30,55, 56,29,12,23,
- 43,14,7 ,27, 13, 2,11,45,
- 4,34,54,51, 22,40,16,25,
- 26,48,53,28, 1,17, 5,31,
- 50, 6,39,24, 33,47,38,32
- };
-
-static inline void __swap8_4(unsigned char *data)
-{
- unsigned char temp[4];
- memcpy(temp,data,4);
- memcpy(data,&data[4],4);
- memcpy(&data[4],temp,4);
-}
-#define swap8_4(d) __swap8_4(d)
-
-class cSeca {
-private:
- static const unsigned char TD[];
- //
- void Fase(unsigned char *data, const unsigned char *key, const unsigned char *T1, const unsigned char *T2);
-protected:
- static const unsigned char T1_S1[], T2_S1[];
- //
- void Decrypt(unsigned char *data, const unsigned char *key, const unsigned char *T1, const unsigned char *T2);
- void Encrypt(unsigned char *data, const unsigned char *key, const unsigned char *T1, const unsigned char *T2);
- void CalcSignature(const unsigned char *buff, int len, unsigned char *signature, const unsigned char *k, const unsigned char *T1, const unsigned char *T2);
- // Seca2 functions
- void AdditionalAlgo(unsigned char *data, const unsigned char *key, const int mode);
- };
-
-const unsigned char cSeca::TD[4] = { 1,3,0,2 };
-
-const unsigned char cSeca::T1_S1[256] = { // Original Tables
- 0x2a,0xe1,0x0b,0x13,0x3e,0x6e,0x32,0x48, 0xd3,0x31,0x08,0x8c,0x8f,0x95,0xbd,0xd0,
- 0xe4,0x6d,0x50,0x81,0x20,0x30,0xbb,0x75, 0xf5,0xd4,0x7c,0x87,0x2c,0x4e,0xe8,0xf4,
- 0xbe,0x24,0x9e,0x4d,0x80,0x37,0xd2,0x5f, 0xdb,0x04,0x7a,0x3f,0x14,0x72,0x67,0x2d,
- 0xcd,0x15,0xa6,0x4c,0x2e,0x3b,0x0c,0x41, 0x62,0xfa,0xee,0x83,0x1e,0xa2,0x01,0x0e,//8
- 0x7f,0x59,0xc9,0xb9,0xc4,0x9d,0x9b,0x1b, 0x9c,0xca,0xaf,0x3c,0x73,0x1a,0x65,0xb1,
- 0x76,0x84,0x39,0x98,0xe9,0x53,0x94,0xba, 0x1d,0x29,0xcf,0xb4,0x0d,0x05,0x7d,0xd1,
- 0xd7,0x0a,0xa0,0x5c,0x91,0x71,0x92,0x88, 0xab,0x93,0x11,0x8a,0xd6,0x5a,0x77,0xb5,
- 0xc3,0x19,0xc1,0xc7,0x8e,0xf9,0xec,0x35, 0x4b,0xcc,0xd9,0x4a,0x18,0x23,0x9f,0x52,//16
- 0xdd,0xe3,0xad,0x7b,0x47,0x97,0x60,0x10, 0x43,0xef,0x07,0xa5,0x49,0xc6,0xb3,0x55,
- 0x28,0x51,0x5d,0x64,0x66,0xfc,0x44,0x42, 0xbc,0x26,0x09,0x74,0x6f,0xf7,0x6b,0x4f,
- 0x2f,0xf0,0xea,0xb8,0xae,0xf3,0x63,0x6a, 0x56,0xb2,0x02,0xd8,0x34,0xa4,0x00,0xe6,
- 0x58,0xeb,0xa3,0x82,0x85,0x45,0xe0,0x89, 0x7e,0xfd,0xf2,0x3a,0x36,0x57,0xff,0x06,//24
- 0x69,0x54,0x79,0x9a,0xb6,0x6c,0xdc,0x8b, 0xa7,0x1f,0x90,0x03,0x17,0x1c,0xed,0xd5,
- 0xaa,0x5e,0xfe,0xda,0x78,0xb0,0xbf,0x12, 0xa8,0x22,0x21,0x3d,0xc2,0xc0,0xb7,0xa9,
- 0xe7,0x33,0xfb,0xf1,0x70,0xe5,0x17,0x96, 0xf8,0x8d,0x46,0xa1,0x86,0xe2,0x40,0x38,
- 0xf6,0x68,0x25,0x16,0xac,0x61,0x27,0xcb, 0x5b,0xc8,0x2b,0x0f,0x99,0xde,0xce,0xc5
- };
-
-const unsigned char cSeca::T2_S1[256] = {
- 0xbf,0x11,0x6d,0xfa,0x26,0x7f,0xf3,0xc8, 0x9e,0xdd,0x3f,0x16,0x97,0xbd,0x08,0x80,
- 0x51,0x42,0x93,0x49,0x5b,0x64,0x9b,0x25, 0xf5,0x0f,0x24,0x34,0x44,0xb8,0xee,0x2e,
- 0xda,0x8f,0x31,0xcc,0xc0,0x5e,0x8a,0x61, 0xa1,0x63,0xc7,0xb2,0x58,0x09,0x4d,0x46,
- 0x81,0x82,0x68,0x4b,0xf6,0xbc,0x9d,0x03, 0xac,0x91,0xe8,0x3d,0x94,0x37,0xa0,0xbb, //8
- 0xce,0xeb,0x98,0xd8,0x38,0x56,0xe9,0x6b, 0x28,0xfd,0x84,0xc6,0xcd,0x5f,0x6e,0xb6,
- 0x32,0xf7,0x0e,0xf1,0xf8,0x54,0xc1,0x53, 0xf0,0xa7,0x95,0x7b,0x19,0x21,0x23,0x7d,
- 0xe1,0xa9,0x75,0x3e,0xd6,0xed,0x8e,0x6f, 0xdb,0xb7,0x07,0x41,0x05,0x77,0xb4,0x2d,
- 0x45,0xdf,0x29,0x22,0x43,0x89,0x83,0xfc, 0xd5,0xa4,0x88,0xd1,0xf4,0x55,0x4f,0x78,//16
- 0x62,0x1e,0x1d,0xb9,0xe0,0x2f,0x01,0x13, 0x15,0xe6,0x17,0x6a,0x8d,0x0c,0x96,0x7e,
- 0x86,0x27,0xa6,0x0d,0xb5,0x73,0x71,0xaa, 0x36,0xd0,0x06,0x66,0xdc,0xb1,0x2a,0x5a,
- 0x72,0xbe,0x3a,0xc5,0x40,0x65,0x1b,0x02, 0x10,0x9f,0x3b,0xf9,0x2b,0x18,0x5c,0xd7,
- 0x12,0x47,0xef,0x1a,0x87,0xd2,0xc2,0x8b, 0x99,0x9c,0xd3,0x57,0xe4,0x76,0x67,0xca,//24
- 0x3c,0xfb,0x90,0x20,0x14,0x48,0xc9,0x60, 0xb0,0x70,0x4e,0xa2,0xad,0x35,0xea,0xc4,
- 0x74,0xcb,0x39,0xde,0xe7,0xd4,0xa3,0xa5, 0x04,0x92,0x8c,0xd9,0x7c,0x1c,0x7a,0xa8,
- 0x52,0x79,0xf2,0x33,0xba,0x1f,0x30,0x9a, 0x00,0x50,0x4c,0xff,0xe5,0xcf,0x59,0xc3,
- 0xe3,0x0a,0x85,0xb3,0xae,0xec,0x0b,0xfe, 0xe2,0xab,0x4a,0xaf,0x69,0x6c,0x2c,0x5d
- };
-
-void cSeca::Fase(unsigned char *D, const unsigned char *key, const unsigned char *T1, const unsigned char *T2)
-{
- for(int l=0; l<4; ++l) { D[l]^=key[l]; D[l]=T1[D[l]&0xff]; }
- for(int l=6; l>3; --l) {
- D[(l+2)&3]^=D[(l+1)&3];
- D[l&3]=T2[(sn8(D[(l+1)&3])+D[l&3])&0xff];
- }
- for(int l=3; l>0; --l) {
- D[(l+2)&3]^=D[(l+1)&3];
- D[l&3]=T1[(sn8(D[(l+1)&3])+D[l&3])&0xff];
- }
- D[2]^=D[1];
- D[1]^=D[0];
-}
-
-void cSeca::Decrypt(unsigned char *d, const unsigned char *key, const unsigned char *T1, const unsigned char *T2)
-{
- unsigned char k[16],D[4];
- memcpy(k,key,sizeof(k));
- unsigned char C=0xff;
- for(int j=0; j<4; ++j) {
- for(int i=0; i<16; ++i) {
- if((i&3)==0) ++C;
- k[i]^=T1[(k[(15+i)&0xf]^k[(i+1)&0xf]^C)&0xff];
- }
- }
- int j=0;
- for(int i=0; i<16; ++i) {
- for(int l=0; l<4; ++l) D[l]=d[l+4];
- j=(j+12)&0xf;
- Fase(D,&k[j&0xc],T1,T2);
- for(int l=0; l<4; ++l) d[l]^=T2[D[TD[l]]&0xff];
- for(int l=3; l>=0; --l) k[(j+l)&0xf]^=T1[(k[(j+l+1)&0xf]^k[(j+l+15)&0xf]^(15-i))&0xff];
- if(i<15) swap8_4(d);
- }
-}
-
-void cSeca::Encrypt(unsigned char *d, const unsigned char *key, const unsigned char *T1, const unsigned char *T2)
-{
- unsigned char D[4],kk[16];
- memcpy(kk, key, sizeof(kk));
- for(int j=0, i=0; i<16; ++i, j=(j+4)&0xf) {
- for(int l=0; l<4; ++l) kk[(j+l)&0xf] ^= T1[(kk[(j+l+1)&0xf]^kk[(j+l+15)&0xf]^i)&0xff];
- if(i>0) swap8_4(d);
- for(int l=0; l<4; ++l) D[l]=d[l+4];
- Fase(D,&kk[j&0xc],T1,T2);
- for(int l=0; l<4; ++l) d[l]^=T2[D[TD[l]]&0xff];
- }
-}
-
-void cSeca::CalcSignature(const unsigned char *buff, int len, unsigned char *signature, const unsigned char *k, const unsigned char *T1, const unsigned char *T2)
-{
- memset(signature,0,8);
- for(int i=0 ; i<len ; i+=8) {
- for(int j=0 ; j<8 && i+j<len; j++) signature[j]^=buff[i+j];
- Encrypt(signature,k,T1,T2);
- }
-}
-
-void cSeca::AdditionalAlgo(unsigned char *data, const unsigned char *key, const int mode)
-{
- static const unsigned int adders[] = {
- 0x0000,0xe555,0xafff,0x5ffe,0xf552,0x6ffb,0xcff9,0x154c,
- 0x3ff4,0x4ff1,0x4543,0x1fea,0xdfe6,0x8537,0x0fdd,0x7fd8
- };
- const unsigned short * const k = (const unsigned short *)key;
- unsigned short * const dd = (unsigned short *)data;
- unsigned int d1=dd[0], d2=dd[1], d3=dd[2], d4=dd[3];
- PRINTF(L_SYS_VERBOSE,"additional algo: %s",!mode?"encrypt":"decrypt");
- if(!mode) {
- for(int i=0; i<0x10; i++) {
- const unsigned int adder = adders[i];
- d1 += (k[0] + d3 + adder) ^ (k[1] + d4 + adder);
- d2 += (k[2] + d3 + adder) ^ (k[3] + d4 + adder);
- d1 = ror16(d1,5);
- d2 = rol16(d2,3);
- d3 += (k[0] + d1 + adder) ^ (k[1] + d2 + adder);
- d4 += (k[2] + d1 + adder) ^ (k[3] + d2 + adder);
- d3 = rol16(d3,3);
- d4 = ror16(d4,5);
- }
- }
- else {
- for(int i=0xf; i>=0; i--) {
- const unsigned int adder = adders[i];
- d4 = rol16(d4,5);
- d3 = ror16(d3,3);
- d4 -= (k[2] + d1 + adder) ^ (k[3] + d2 + adder);
- d3 -= (k[0] + d1 + adder) ^ (k[1] + d2 + adder);
- d2 = ror16(d2,3);
- d1 = rol16(d1,5);
- d2 -= (k[2] + d3 + adder) ^ (k[3] + d4 + adder);
- d1 -= (k[0] + d3 + adder) ^ (k[1] + d4 + adder);
- }
- }
- dd[0]=d1; dd[1]=d2; dd[2]=d3; dd[3]=d4;
-}
-
-// -- cSeca2Prov ---------------------------------------------------------------
-
-#define MAX_PERMS 10
-#define KEY2INDEX(x) (((x)>>5)&0x03)
-
-struct Perm {
- unsigned char P1[8], P2[8], P3[8], P4[8];
- };
-
-struct ProvData {
- unsigned short LoadId, MTLoadSize, MTSize;
- unsigned char SHA1Pad, SHA1End;
- unsigned char FP[8];
- };
-
-class cSeca2Prov: protected cSeca {
-private:
- cFileMap *hash, *mask;
- unsigned short id;
- //
- unsigned short Sum(const unsigned char *data, int n) const;
-protected:
- const struct ProvData *pData;
- const struct Perm *perm;
- //
- cFileMap *GetMap(const char *type, int size, bool generic) const;
-public:
- cSeca2Prov(unsigned short Id);
- virtual ~cSeca2Prov();
- // provider specific mods
- virtual void PreSSE(unsigned char *data, int pos) {}
- virtual void PostSSE(unsigned char *data, int pos) {}
- virtual void SignatureMod(unsigned char *MD, const unsigned char *PK) {}
- virtual void PreCW(unsigned char *data) {}
- virtual void PostCW(unsigned char *data) {}
- virtual void ChainTableXor(unsigned char *data, unsigned short index)=0;
- virtual bool DoSigCheck(void) { return true; }
- //
- virtual bool Init(void);
- void CalcSHASignature(const unsigned char *data, int n, unsigned char *signature, bool PadMode=true);
- bool DecryptSE(unsigned char *data, const unsigned char *key, int n, int start, const unsigned char *T1, const unsigned char *T2);
- bool Matches(unsigned short Id) const { return Id==id; }
- //
- const unsigned char *T1(int index) const;
- const unsigned char *T2(int index) const;
- const struct Perm *P(int index) const;
- inline const unsigned char *MT(void) const { return mask->Addr(); }
- inline int MTSize(void) const { return pData->MTSize; }
- inline const unsigned char *FP(void) const { return pData->FP; }
- };
-
-cSeca2Prov::cSeca2Prov(unsigned short Id)
-{
- id=Id;
- pData=0; perm=0; hash=0; mask=0;
-}
-
-cSeca2Prov::~cSeca2Prov()
-{
- if(hash) hash->Unmap();
- if(mask) mask->Unmap();
-}
-
-bool cSeca2Prov::Init(void)
-{
- hash=GetMap("hash",1536,false);
- mask=GetMap("mt",pData->MTLoadSize,false);
- if(!hash || !mask) return false;
- return true;
-}
-
-cFileMap *cSeca2Prov::GetMap(const char *type, int size, bool generic) const
-{
- char name[32];
- snprintf(name,sizeof(name),generic ? "s2_%s.bin" : "s2_%s_%04x.bin",type,pData->LoadId);
- cFileMap *map=filemaps.GetFileMap(name,FILEMAP_DOMAIN,false);
- if(!map)
- PRINTF(L_SYS_CRYPTO,"no filemap for %s",name);
- else if(!map->Map()) {
- PRINTF(L_SYS_CRYPTO,"mapping failed for %s",name);
- map=0;
- }
- else if(map->Size()<size) {
- PRINTF(L_SYS_CRYPTO,"%s file %s has wrong size (has=%d wanted=%d)",type,name,map->Size(),size);
- map->Unmap();
- map=0;
- }
- return map;
-}
-
-// Hash file layout is (Yankse style):
-// Table T1 for 9x,
-// Table T1 for Bx,
-// Table T1 for FX,
-// Table T2 for 9x,
-// Table T2 for Bx,
-// Table T2 for FX (total: 1536 bytes)
-
-const unsigned char *cSeca2Prov::T1(int index) const
-{
- static int idxTrans[] = { 0,1,2,2 };
- if(index>=0 && index<=3) {
- return hash->Addr()+(idxTrans[index]*256);
- }
- PRINTF(L_SYS_CRYPTO,"bad T1 table index %d",index);
- return 0;
-}
-
-const unsigned char *cSeca2Prov::T2(int index) const
-{
- static int idxTrans[] = { 0,1,2,2 };
- if(index>=0 && index<=3) {
- return hash->Addr()+(idxTrans[index]*256)+768;
- }
- PRINTF(L_SYS_CRYPTO,"bad T2 table index %d",index);
- return 0;
-}
-
-const struct Perm *cSeca2Prov::P(int index) const
-{
- if(index>=0 && index<MAX_PERMS && perm) {
- return &perm[index];
- }
- PRINTF(L_SYS_CRYPTO,"no perm table or bad index %d",index);
- return 0;
-}
-
-unsigned short cSeca2Prov::Sum(const unsigned char *data, int n) const
-{
- unsigned int sum=0;
- for(int i=1; i<n; i+=2) sum+=((data[i-1]<<8)+data[i]);
- if(n&1) sum+=(data[n-1]<<4);
- return sum&0x3FFF;
-}
-
-bool cSeca2Prov::DecryptSE(unsigned char *data, const unsigned char *key, int n, int start, const unsigned char *T1, const unsigned char *T2)
-{
- const int sigStart=n-data[n-1]-9; // 82 <8 bytes> P5(sigStart)
- const int encrLen=sigStart-16;
-
-#ifdef DEBUG_SECA_EXTRA
- if(encrLen>=n || encrLen<0) printf("encrLen error in SE\n");
- if(sigStart<16) printf("sigStart error in SE\n");
-#endif
- if(encrLen>=n || encrLen<0 || sigStart<16) return false;
-
- Decrypt(data+sigStart-8,key,T1,T2);
- ChainTableXor(data+sigStart-8,Sum(data+start,sigStart-8-start));
- int i;
-
- for(i=start; i<encrLen; i+=8) {
- Decrypt(data+i,key,T1,T2);
- ChainTableXor(data+i,Sum(&data[i+8],8));
- }
-
- int restBytes=sigStart&0x07;
- if(!restBytes) restBytes=8;
-
- // Last Block
- unsigned char lastBlock[8];
- memset(lastBlock,0,sizeof(lastBlock));
- memcpy(lastBlock,data+sigStart-restBytes,restBytes);
- Decrypt(lastBlock,key,T1,T2);
-
- Decrypt(data+i,key,T1,T2);
- ChainTableXor(data+i,Sum(lastBlock,sizeof(lastBlock)));
- return true;
-}
-
-void cSeca2Prov::CalcSHASignature(const unsigned char *data, int n, unsigned char *signature, bool PadMode)
-{
- SHA_CTX ctx;
- SHA1_Init(&ctx);
- SHA1_Update(&ctx,data,n);
- unsigned char Pad=0;
- if(PadMode) {
- unsigned char End=pData->SHA1End;
- SHA1_Update(&ctx,&End,1);
- int l=(n&63)+1;
- Pad=pData->SHA1Pad;
- if(l>62) {
- for(; l<64; l++) SHA1_Update(&ctx,&Pad,1);
- l=0;
- }
- for(; l<62; l++) SHA1_Update(&ctx,&Pad,1);
- unsigned short s=bswap_16(n);
- SHA1_Update(&ctx,&s,2);
- }
- else for(; n&63; n++) SHA1_Update(&ctx,&Pad,1);
-
- *((unsigned int *)(signature ))=bswap_32(ctx.h0);
- *((unsigned int *)(signature+ 4))=bswap_32(ctx.h1);
- *((unsigned int *)(signature+ 8))=bswap_32(ctx.h2);
- *((unsigned int *)(signature+12))=bswap_32(ctx.h3);
- *((unsigned int *)(signature+16))=bswap_32(ctx.h4);
-}
-
-// -- cSecaProviders & cSecaProviderLink ---------------------------------------
-
-class cSeca2ProvLink {
-friend class cSeca2Providers;
-private:
- cSeca2ProvLink *next;
- const unsigned short *ids;
-public:
- cSeca2ProvLink(const unsigned short *Ids);
- bool CanHandle(unsigned short Id);
- virtual cSeca2Prov *Create(unsigned short Id)=0;
- virtual ~cSeca2ProvLink() {};
- };
-
-template<class CC> class cSeca2ProvLinkReg : public cSeca2ProvLink {
-public:
- cSeca2ProvLinkReg(const unsigned short *Ids):cSeca2ProvLink(Ids) {}
- virtual cSeca2Prov *Create(unsigned short Id) { return new CC(Id); }
- };
-
-class cSeca2Providers {
-friend class cSeca2ProvLink;
-private:
- static cSeca2ProvLink *first;
- //
- static void Register(cSeca2ProvLink *spl);
-public:
- static cSeca2Prov *GetProv(unsigned short id);
- };
-
-cSeca2ProvLink *cSeca2Providers::first=0;
-
-void cSeca2Providers::Register(cSeca2ProvLink *spl)
-{
- LBSTART(L_CORE_DYN);
- LBPUT("seca2prov: registering Seca2 provider");
- for(int i=0; spl->ids[i]; i++) LBPUT(" %.4x",spl->ids[i]);
- LBEND();
- spl->next=first;
- first=spl;
-}
-
-cSeca2Prov *cSeca2Providers::GetProv(unsigned short id)
-{
- cSeca2ProvLink *spl=first;
- while(spl) {
- if(spl->CanHandle(id)) {
- cSeca2Prov *sp=spl->Create(id);
- if(sp && sp->Init()) return sp;
- delete sp;
- }
- spl=spl->next;
- }
- return 0;
-}
-
-cSeca2ProvLink::cSeca2ProvLink(const unsigned short *Ids)
-{
- ids=Ids;
- cSeca2Providers::Register(this);
-}
-
-bool cSeca2ProvLink::CanHandle(unsigned short Id)
-{
- for(int i=0; ids[i]; i++) if(ids[i]==Id) return true;
- return false;
-}
-
-// -- cSeca2ProvSSE ------------------------------------------------------------
-
-#define beforeSig (pos-8)
-#define afterSig (pos+1)
-
-class cSeca2ProvSSE : public cSeca2Prov {
-private:
- virtual void PreSSECore(unsigned char *buf, const unsigned char *data, int i)=0;
- virtual void PostSSECore1(unsigned char *data, int pos)=0;
- virtual void PostSSECore2(unsigned char *buf, const unsigned char *data, int pos)=0;
- virtual void PostSSECore3(unsigned char *data, const unsigned char *buf, int pos)=0;
- virtual void PostSSECore4(unsigned char *data, int pos)=0;
-protected:
- cDes des;
- cFileMap *sse, *sseP, *cw;
- //
- virtual bool InitSSE(void)=0;
- virtual void PreSSE(unsigned char *data, int pos);
- virtual void PostSSE(unsigned char *data, int pos);
- //
- inline const unsigned char *SSET1(void) const { return sse->Addr(); }
- inline const unsigned char *SSET2(void) const { return sse->Addr()+3072; }
- inline const unsigned char *SSEPT1(void) const { return sseP->Addr(); }
- inline const unsigned char *SSEPT2(void) const { return sseP->Addr()+80; }
- inline const unsigned char *CWT1(void) const { return cw->Addr(); }
-public:
- cSeca2ProvSSE(unsigned short Id);
- virtual ~cSeca2ProvSSE();
- virtual bool Init(void);
- };
-
-cSeca2ProvSSE::cSeca2ProvSSE(unsigned short Id)
-:cSeca2Prov(Id)
-,des(secaPC1,secaPC2)
-{
- sse=0; sseP=0; cw=0;
-}
-
-cSeca2ProvSSE::~cSeca2ProvSSE()
-{
- if(sse) sse->Unmap();
- if(sseP) sseP->Unmap();
- if(cw) cw->Unmap();
-}
-
-bool cSeca2ProvSSE::Init(void)
-{
- return InitSSE() && cSeca2Prov::Init();
-}
-
-void cSeca2ProvSSE::PreSSE(unsigned char *data, int pos)
-{
- const unsigned char *T1=SSEPT1();
- unsigned char tmpBuf[80];
-
- data+=pos+5; // Start at offset 5
- for(int i=4; i>=0; i--) {
- int j=i*16;
- PreSSECore(&tmpBuf[j],&data[j],i);
- }
- for(int i=79; i>=0; i--) data[i]=tmpBuf[i]^T1[i];
-}
-
-void cSeca2ProvSSE::PostSSE(unsigned char *data, int pos)
-{
- PostSSECore1(data,pos);
- // create the SHA hash buffer
- unsigned char tmpBuf[64];
- memcpy(tmpBuf+0,&data[beforeSig+0],4);
- memcpy(tmpBuf+4,&data[afterSig +4],4);
- PostSSECore2(tmpBuf+8,data,pos);
- // Calc Signature of the generated buffer here
- unsigned char MD[20];
- CalcSHASignature(tmpBuf,sizeof(tmpBuf),MD,false);
- // Prepare DES data
- memcpy(tmpBuf+0,&data[beforeSig+4],4);
- memcpy(tmpBuf+4,&data[afterSig +0],4);
- // DES Enrypt
- des.Des(tmpBuf,MD,SECA_DES_ENCR);
- // modify data with encrypted DES data
- PostSSECore3(data,tmpBuf,pos);
- // save the signature
- memcpy(tmpBuf,data+afterSig,8);
- PostSSECore4(data,pos);
- // put the signature in the data
- memcpy(data+beforeSig,tmpBuf,8);
-}
-
-// -- France -------------------------------------------------------------------
-
-class cSeca2ProvFR : public cSeca2ProvSSE {
-private:
- virtual void PreSSECore(unsigned char *buf, const unsigned char *data, int i);
- virtual void PostSSECore1(unsigned char *data, int pos);
- virtual void PostSSECore2(unsigned char *buf, const unsigned char *data, int pos);
- virtual void PostSSECore3(unsigned char *data, const unsigned char *buf, int pos);
- virtual void PostSSECore4(unsigned char *data, int pos);
-protected:
- virtual bool InitSSE(void);
- virtual void PostCW(unsigned char *data);
- virtual void ChainTableXor(unsigned char *data, unsigned short index);
- virtual void SignatureMod(unsigned char *MD, const unsigned char *PK);
-public:
- cSeca2ProvFR(unsigned short Id);
- };
-
-static const unsigned short IdsFR[] = { 0x80,0x81,0 };
-
-static cSeca2ProvLinkReg<cSeca2ProvFR> staticLinkFR(IdsFR);
-
-static const struct ProvData provDataFR = {
- 0x80,16895,16895,0x7F,0xF7, { 3, 0, 0, 0, 2, 4, 3, 0 }
- };
-
-cSeca2ProvFR::cSeca2ProvFR(unsigned short Id)
-:cSeca2ProvSSE(Id)
-{
- pData=&provDataFR;
-}
-
-bool cSeca2ProvFR::InitSSE(void)
-{
- sse=GetMap("sse",5120,true);
- sseP=GetMap("sse",1104,false);
- cw=GetMap("cw",512,false);
- return sse && sseP && cw;
-}
-
-void cSeca2ProvFR::PreSSECore(unsigned char *buf, const unsigned char *data, int i)
-{
- const unsigned char *T1=SSET1(), *T2=SSET2();
-
- buf[ 0]=data[0x06]^T2[i+0x0a];
- buf[ 1]=data[0x01]^T2[i+0x00];
- buf[ 2]=data[0x02]^T1[i+0x00];
- buf[ 3]=data[0x03]^T2[i+0x04];
- buf[ 4]=~data[0x04];
- buf[ 5]=data[0x05]^T1[i+0x01];
- buf[ 6]=data[0x00]^T2[i+0x0f];
- buf[ 7]=data[0x07]^T1[i+0x02];
- buf[ 8]=data[0x08]^T1[i+0x00];
- buf[ 9]=data[0x0d]^T2[i+0x14];
- buf[10]=data[0x0f]^T2[i+0x07];
- buf[11]=~data[0x0b];
- buf[12]=data[0x0c]^T1[i+0x00];
- buf[13]=data[0x09]^T2[i+0x19];
- buf[14]=data[0x0e]^T2[i+0x1e];
- buf[15]=data[0x0a]^T1[i+0x01];
-}
-
-void cSeca2ProvFR::PostSSECore1(unsigned char *data, int pos)
-{
- data[beforeSig+0]^=-(0x2d);
- data[beforeSig+1]-=0x22;
- data[beforeSig+2]^=0x1d;
- data[beforeSig+3]^=-(0x68);
- data[beforeSig+4] =~data[beforeSig + 4];
- data[beforeSig+5]^=0x26;
- data[beforeSig+6]^=0x09;
- data[beforeSig+7]-=0x3e;
- data[afterSig +0]^=-(0x5d);
- data[afterSig +1]-=0x74;
- data[afterSig +2]^=0x2d;
- data[afterSig +3]^=-(0x2a);
- data[afterSig +4]+=0x0d;
- data[afterSig +5]^=-(0x6c);
- data[afterSig +6]^=-(0x76);
- data[afterSig +7]+=0x31;
-}
-
-void cSeca2ProvFR::PostSSECore2(unsigned char *buf, const unsigned char *data, int pos)
-{
- const unsigned char *T1=SSEPT2();
- memcpy(buf, &T1[data[afterSig+4]+0x48], 56);
-}
-
-void cSeca2ProvFR::PostSSECore3(unsigned char *data, const unsigned char *buf, int pos)
-{
- data[beforeSig+4]=buf[5];
- data[beforeSig+5]=buf[4];
- data[beforeSig+6]=buf[7];
- data[beforeSig+7]=buf[2];
- data[afterSig +0]=buf[3];
- data[afterSig +1]=buf[1];
- data[afterSig +2]=buf[0];
- data[afterSig +3]=buf[6];
-}
-
-void cSeca2ProvFR::PostSSECore4(unsigned char *data, int pos)
-{
- data[afterSig+0]=data[beforeSig+3]^0x3e;
- data[afterSig+1]=data[beforeSig+1]^0x5e;
- data[afterSig+2]=data[beforeSig+5]^0x2f;
- data[afterSig+3]=data[beforeSig+0]^0x77;
- data[afterSig+4]=data[beforeSig+6]^-(0x4b);
- data[afterSig+5]=data[beforeSig+2]^-(0x38);
- data[afterSig+6]=data[beforeSig+7]^0x29;
- data[afterSig+7]=data[beforeSig+4]^0x2b;
-}
-
-void cSeca2ProvFR::PostCW(unsigned char *data)
-{
- const unsigned char *T1=SSET1(), *T2=SSET2(), *T3=SSEPT2(), *T4=CWT1();
- unsigned int idx;
- unsigned char key[8];
- idx=((data[0]<<8)|data[1]); key[0]=T3[idx & 0x3FF];
- idx=(idx + key[0]); key[1]=T3[idx & 0x3FF];
- idx=((data[2]<<8)|data[3]); key[2]=T4[idx & 0x1FF];
- idx=idx + key[2]; key[3]=T4[idx & 0x1FF];
- idx=((data[8+4]<<8)|data[8+5]); key[4]=T2[idx & 0x7FF];
- idx=idx + key[4]; key[5]=T2[idx & 0x7FF];
- idx=((data[8+6]<<8)|data[8+7]); key[6]=T1[idx & 0xBFF];
- idx=idx + key[6]; key[7]=T1[idx & 0xBFF];
- des.Des(data+4,key,SECA_DES_ENCR);
-}
-
-void cSeca2ProvFR::ChainTableXor(unsigned char *data, unsigned short index)
-{
- static const unsigned char tabIdx[] = { 0x00, 0x08, 0x03, 0x1F, 0x06, 0x32, 0x12, 0x0C };
- static const unsigned char tabXor[] = { 0x77, 0x2B, 0xC8, 0xEE, 0x2F, 0xD3, 0x22, 0x29 };
- static const unsigned char tabPos[] = { 0, 2, 1, 6, 4, 5, 7, 3 };
-
- unsigned int idx1, idx2;
- unsigned char xorVal=0;
- const unsigned char *T1=MT(), *T2=SSET1();
-
- idx1 = (index^0x17AC) & 0x3FFF;
- idx2 = idx1 & 0xBFF;
- for(int i=0; i<8; i++) {
- idx1 = (idx1 + tabIdx[i]) & 0x3FFF;
- idx2 = (idx2 + xorVal) & 0xBFF;
- xorVal ^= T1[idx1] ^ tabXor[i];
- data[tabPos[i]] ^= xorVal ^ T2[idx2];
- }
-}
-
-void cSeca2ProvFR::SignatureMod(unsigned char *MD, const unsigned char *PK)
-{
- const unsigned char *T1=SSEPT2();
- unsigned int idx;
-
- idx = ((MD[18] << 8) | MD[19]) & 0x3FF;
- MD[10] = T1[idx];
- MD[13] ^= PK[6];
- idx = ((MD[15] << 8) | MD[13]) & 0x3FF;
- MD[16] = T1[idx];
- des.Des(MD,MD+10,SECA_DES_ENCR);
-}
-
-// -- Netherlands --------------------------------------------------------------
-
-class cSeca2ProvNL : public cSeca2ProvSSE {
-private:
- virtual void PreSSECore(unsigned char *buf, const unsigned char *data, int i);
- virtual void PostSSECore1(unsigned char *data, int pos);
- virtual void PostSSECore2(unsigned char *buf, const unsigned char *data, int pos);
- virtual void PostSSECore3(unsigned char *data, const unsigned char *buf, int pos);
- virtual void PostSSECore4(unsigned char *data, int pos);
-protected:
- virtual bool InitSSE(void);
- virtual void PostCW(unsigned char *data);
- virtual void ChainTableXor(unsigned char *data, unsigned short index);
- virtual bool DoSigCheck(void) { return false; }
-public:
- cSeca2ProvNL(unsigned short Id);
- };
-
-static const unsigned short IdsNL[] = { 0x6a,0 };
-
-static cSeca2ProvLinkReg<cSeca2ProvNL> staticLinkNL(IdsNL);
-
-static const struct ProvData provDataNL = {
- 0x6a,16895,16895,0xa3,0x3a, { 3, 0, 0, 0, 2, 4, 3, 0 }
- };
-
-cSeca2ProvNL::cSeca2ProvNL(unsigned short Id)
-:cSeca2ProvSSE(Id)
-{
- pData=&provDataNL;
-}
-
-bool cSeca2ProvNL::InitSSE(void)
-{
- sse=GetMap("sse",5120,true);
- sseP=GetMap("sse",336,false);
- cw=GetMap("cw",512,false);
- return sse && sseP && cw;
-}
-
-void cSeca2ProvNL::PreSSECore(unsigned char *buf, const unsigned char *data, int i)
-{
- const unsigned char *T1=SSET1(), *T2=SSET2();
-
- buf[0] =data[7] ^T1[i+0x17];
- buf[1] =data[1] ^T2[i+0x07];
- buf[2] =data[2] ^T1[i+0x03];
- buf[3] =data[3] ^T2[i+0x0C];
- buf[4] =~data[4];
- buf[5] =data[5] ^T1[i+0x1E];
- buf[6] =data[6] ^T1[i+0x11];
- buf[7] =data[0] ^T2[i+0x0F];
- buf[8] =data[9] ^T1[i+0x15];
- buf[9] =data[8] ^T2[i+0x04];
- buf[10]=data[12]^T2[i+0x07];
- buf[11]=data[11]^T1[i+0x16];
- buf[12]=data[10]^T1[i+0x01];
- buf[13]=data[13]^T1[i+0x0F];
- buf[14]=~data[14];
- buf[15]=data[15]^T2[i+0x0B];
-}
-
-void cSeca2ProvNL::PostSSECore1(unsigned char *data, int pos)
-{
- // modify 8 bytes before signature byte (0x82)
- data[beforeSig+0] ^= 0xd6; data[beforeSig+1] ^= 0x96;
- data[beforeSig+2] -= 0x51; data[beforeSig+3] ^= 0x3a;
- data[beforeSig+4] -= 0x8d; data[beforeSig+5] ^= 0xf1;
- data[beforeSig+6] -= 0xc2; data[beforeSig+7] ^= 0xb1;
-
- data[afterSig+0] ^= 0x84; data[afterSig+1] ^= 0xf8;
- data[afterSig+2] -= 0x7d; data[afterSig+3] = ~(data[afterSig+3]);
- data[afterSig+4] ^= 0xfd; data[afterSig+5] ^= 0xd0;
- data[afterSig+6] ^= 0x77; data[afterSig+7] ^= 0x25;
-}
-
-void cSeca2ProvNL::PostSSECore2(unsigned char *buf, const unsigned char *data, int pos)
-{
- const unsigned char *T1=SSEPT2();
- memcpy(buf,&T1[(data[afterSig+6]+0x19)&0x7F],56);
-}
-
-void cSeca2ProvNL::PostSSECore3(unsigned char *data, const unsigned char *buf, int pos)
-{
- data[beforeSig+4]=buf[7];
- data[beforeSig+5]=buf[0];
- data[beforeSig+6]=buf[3];
- data[beforeSig+7]=buf[5];
- data[afterSig+0]=buf[6];
- data[afterSig+1]=buf[2];
- data[afterSig+2]=buf[1];
- data[afterSig+3]=buf[4];
-}
-
-void cSeca2ProvNL::PostSSECore4(unsigned char *data, int pos)
-{
- data[afterSig+0]=data[beforeSig+1] ^ 0x65; data[afterSig+1]=data[beforeSig+0] ^ 0x75;
- data[afterSig+2]=data[beforeSig+5] ^ 0x35; data[afterSig+3]=data[beforeSig+3] ^ 0xd9;
- data[afterSig+4]=data[beforeSig+6] ^ 0xb7; data[afterSig+5]=data[beforeSig+7] ^ 0x9a;
- data[afterSig+6]=data[beforeSig+4] ^ 0xc7; data[afterSig+7]=data[beforeSig+2] ^ 0x1f;
-}
-
-void cSeca2ProvNL::PostCW(unsigned char *data)
-{
- const unsigned char *T1=SSET1(), *T2=SSET2(), *T3=CWT1(), *T4=SSEPT2();
- unsigned char key[8];
- unsigned int off2;
-
- off2=data[2]^data[8+6];
- key[2]=T4[off2]; key[5]=T4[(off2+key[2])&0xff];
-
- off2=(data[3]<<8)|data[8+4]; key[0]=T3[off2&0x1ff];
- off2+=key[2]; key[4]=T3[off2&0x1ff];
-
- off2=(data[0]<<8)|data[8+7]; key[7]=T2[off2&0x7ff];
- off2+=key[0]; key[1]=T2[off2&0x7ff];
-
- off2=(data[1]<<8)|data[8+5]; key[3]=T1[off2&0xbff];
- off2+=key[4]; key[6]=T1[off2&0xbff];
-
- des.Des(data+4,key,SECA_DES_ENCR);
-}
-
-void cSeca2ProvNL::ChainTableXor(unsigned char *data, unsigned short index)
-{
- static const unsigned short tabIdx[] = { 0x000, 0x4C3, 0x5D8, 0x63A, 0x471, 0x639, 0x417, 0x6CD };
- static const unsigned char tabXor[] = { 0x84, 0xD6, 0x3A, 0x1F, 0x25, 0xB1, 0x7D, 0xF7 };
- static const unsigned char tabPos1[] = { 2, 4, 3, 4, 5, 7, 6, 7 };
- static const unsigned char tabPos2[] = { 3, 1, 5, 6, 0, 1, 0, 2 };
-
- unsigned int idx1, idx2;
- unsigned char xorVal=0;
- const unsigned char *T1=MT(), *T2=SSET1();
-
- idx1=(index^0x2B36) & 0x3FFF;
- idx2=idx1 & 0xBFF;
- for(int i=0; i<8; i++) {
- idx1=(idx1 + tabIdx[i]) & 0x3FFF;
- idx2=(idx2 + xorVal) & 0xBFF;
- xorVal ^= T1[idx1] ^ tabXor[i];
- data[tabPos1[i]]^=xorVal;
- data[tabPos2[i]]^=T2[idx2];
- }
-}
-
-#undef beforeSig
-#undef afterSig
-
-// -- Poland -------------------------------------------------------------------
-
-class cSeca2ProvPL : public cSeca2Prov {
-protected:
- virtual void PreCW(unsigned char *data);
- virtual void ChainTableXor(unsigned char *data, unsigned short index);
-public:
- cSeca2ProvPL(unsigned short Id);
- };
-
-static const unsigned short IdsPL[] = { 0x65,0 };
-
-static cSeca2ProvLinkReg<cSeca2ProvPL> staticLinkPL(IdsPL);
-
-static const struct ProvData provDataPL = {
- 0x65,16895,16895,0x96,0x69, { 3, 0, 0, 0, 2, 4, 3, 0 }
- };
-
-static const struct Perm ptPL[MAX_PERMS] = {
- { // 1
- { 2, 4, 4, 3, 2, 2, 4, 4 },
- { 3, 2, 4, 3, 4, 4, 2, 3 },
- { 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0 }
- },{ // 2
- { 4, 4, 3, 2, 2, 3, 3, 4 },
- { 4, 2, 3, 4, 3, 2, 4, 2 },
- { 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0 }
- },{ // 3
- },{ // 4
- },{ // 5
- },{ // 6
- },{ // 7
- },{ // 8
- },{ // 9
- { 4, 4, 3, 2, 3, 4, 3, 2 },
- { 2, 4, 3, 2, 2, 4, 4, 3 },
- { 2, 3, 4, 1, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0 },
- },{ // 10
- } };
-
-cSeca2ProvPL::cSeca2ProvPL(unsigned short Id)
-:cSeca2Prov(Id)
-{
- pData=&provDataPL; perm=ptPL;
-}
-
-void cSeca2ProvPL::PreCW(unsigned char *data)
-{
- static const unsigned char XT[]={ 0xA0,0x12,0x23,0x35,0x46,0xB0,0xDF,0xCA, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
- static const unsigned char PT[]={ 0x05,0x04,0x06,0x07,0x03,0x00,0x01,0x02, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F };
- unsigned char temp[16];
-
- xxor(temp,16,data,XT);
- for(int i=15; i>=0; i--) data[i]=temp[PT[i]];
-}
-
-void cSeca2ProvPL::ChainTableXor(unsigned char *data, unsigned short index)
-{
- const unsigned char *T1=MT();
- for(int i=0; i<8; i++) data[i]^=T1[index++];
-}
-
-// -- cSystemSeca ---------------------------------------------------------------
-
-class cSystemSeca : public cSystem, private cSeca {
-private:
- cSeca2Prov *sp, *spL;
- int emmLenCnt;
- cDes des;
- cRSA rsa;
- //
- bool GetSeca2Prov(int provId, cSeca2Prov * &sp);
- bool Process0FNano(int count, unsigned char *hashDW, unsigned char *PK, const unsigned char *T1, const unsigned char *T2);
- bool Process51Nano(unsigned char *CW, const unsigned char *PermData, const unsigned char *hashDW, const unsigned char *T1, const unsigned char *T2, int provId);
- void Crypto51Nano(unsigned char *data, const unsigned char *key, const unsigned char crypto, const unsigned char mode);
- void Permute(unsigned char *data, const unsigned char *pdata, const unsigned char *P);
-public:
- cSystemSeca(void);
- virtual ~cSystemSeca();
- virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *data);
- virtual void ProcessEMM(int pid, int caid, unsigned char *buffer);
- };
-
-cSystemSeca::cSystemSeca(void)
-:cSystem(SYSTEM_NAME,SYSTEM_PRI),
-des(secaPC1,secaPC2)
-{
- sp=spL=0; emmLenCnt=0;
- hasLogger=true;
-}
-
-cSystemSeca::~cSystemSeca()
-{
- delete sp;
- delete spL;
-}
-
-bool cSystemSeca::GetSeca2Prov(int provId, cSeca2Prov * &sp)
-{
- if(!sp || !sp->Matches(provId)) {
- delete sp;
- sp=cSeca2Providers::GetProv(provId);
- }
- return sp!=0;
-}
-
-bool cSystemSeca::ProcessECM(const cEcmInfo *ecmD, unsigned char *data)
-{
- bool SE=false;
- unsigned char *ecm;
- const int msgLen=cParseSeca::Payload(data,(const unsigned char **)&ecm);
- const int keyNr=cParseSeca::KeyNr(data);
-
- if(keyNr&0x80) {
- PRINTF(L_SYS_VERBOSE,"Super Encryption enabled");
- SE=true;
- if(!GetSeca2Prov(ecmD->provId,sp)) {
- if(doLog) PRINTF(L_SYS_ECM,"Seca2 provider %04x not supported",ecmD->provId);
- return false;
- }
- }
- HEXDUMP(L_SYS_VERBOSE,data,SCT_LEN(data),"ECM:");
- if(ecm[0]==0x10) {
- if(msgLen<0x5c) {
- if(doLog) PRINTF(L_SYS_ECM,"ECM length too small (%d)",msgLen);
- return false;
- }
-
- if(SE) {
- HEXDUMP(L_SYS_VERBOSE,ecm+(msgLen-0x5a),0x5a,"ECM before SSE data modification :");
- sp->PreSSE(ecm,msgLen-0x5a);
- HEXDUMP(L_SYS_VERBOSE,ecm+(msgLen-0x5a),0x5a,"ECM after SSE data modification :");
- }
-
- const int rsaKeynr=(ecm[1]&0x0F)+'0';
- cBN exp, mod;
- cPlainKey *rsaKey;
- if(!(rsaKey=keys.FindKey('S',ecmD->provId,MBC('E',rsaKeynr),-1))) {
- if(doLog) PRINTF(L_SYS_KEY,"missing %04x E%c key",ecmD->provId,rsaKeynr);
- return false;
- }
- rsaKey->Get(exp);
- if(!(rsaKey=keys.FindKey('S',ecmD->provId,MBC('M',rsaKeynr),-1))) {
- if(doLog) PRINTF(L_SYS_KEY,"missing %04x M%c key",ecmD->provId,rsaKeynr);
- return false;
- }
- rsaKey->Get(mod);
- HEXDUMP(L_SYS_VERBOSE,ecm+(msgLen-0x5a),0x5a,"ECM before RSA decrypt :");
- if(rsa.RSA(ecm+(msgLen-0x5a),ecm+(msgLen-0x5a),0x5a,exp,mod)!=0x5a) {
- PRINTF(L_SYS_CRYPTO,"RSA decrypt failed (ECM)");
- return false;
- }
- HEXDUMP(L_SYS_VERBOSE,ecm+(msgLen-0x5a),0x5a,"ECM after RSA decrypt :");
-
- if(SE) { // PostSSE needed
- const int hashPtr=msgLen-ecm[msgLen-1]-9;
- if(hashPtr>=msgLen-9 || ecm[hashPtr]!=0x82) {
- PRINTF(L_SYS_CRYPTO,"RSA decrypt failed, signature pointer not found");
- return false;
- }
- HEXDUMP(L_SYS_VERBOSE,ecm+(msgLen-0x5a),0x5a,"ECM before SSE result modification :");
- sp->PostSSE(ecm,hashPtr);
- HEXDUMP(L_SYS_VERBOSE,ecm+(msgLen-0x5a),0x5a,"ECM after SSE result modification :");
- }
- }
-
- const unsigned char *T1=T1_S1, *T2=T2_S1;
- int decrLen=msgLen;
- if(SE) {
- if(!(T1=sp->T1(KEY2INDEX(keyNr))) ||
- !(T2=sp->T2(KEY2INDEX(keyNr)))) return false;
- decrLen-=ecm[msgLen-1]; if(decrLen<8) return false;
- }
-
- bool key8=!(cParseSeca::SysMode(data)&0x10);
- cPlainKey *pk=0;
- cKeySnoop ks(this,'S',ecmD->provId,keyNr&0x0F);
- unsigned char *buff=AUTOMEM(msgLen);
- while((pk=keys.FindKey('S',ecmD->provId,keyNr&0x0F,key8?8:16,pk))) {
- memcpy(buff,ecm,msgLen); // if decoding fails we need the original data
-
- unsigned char PK[16], signature[20];
- pk->Get(PK);
- if(key8) memcpy(&PK[8],&PK[0],8); // duplicate key
-
- if(SE) {
- sp->CalcSHASignature(buff,decrLen-8,signature);
- LDUMP(L_SYS_VERBOSE,signature,8,"signature before encrypt :");
- sp->SignatureMod(signature,PK);
- Encrypt(signature,PK,T1,T2);
- LDUMP(L_SYS_VERBOSE,signature,8,"signature after encrypt :");
-
- if(sp->DoSigCheck() && memcmp(signature,&buff[decrLen-8],8)) {
- PRINTF(L_SYS_VERBOSE,"signature check failed before SE decrypt");
- continue;
- }
- HEXDUMP(L_SYS_VERBOSE,buff+2,msgLen-2,"ECM before SE decrypt :");
- if(!sp->DecryptSE(buff+2,PK,msgLen-2,8,T1,T2)) {
- PRINTF(L_SYS_VERBOSE,"SE decrypt failed");
- continue;
- }
- HEXDUMP(L_SYS_VERBOSE,buff+2,msgLen-2,"ECM after SE decrypt :");
- }
- else {
- CalcSignature(buff,decrLen-8,signature,PK,T1,T2);
- }
- unsigned char hashDW[28]; // actually 16 bytes used for processing, but SHA needs more
- unsigned char *cCW=0;
- const unsigned char *nano51Data=0;
- int nr0F=0;
-
- for(int i=0 ; i<decrLen; ) {
- int param=buff[i++];
- int extra=(param >> 4) & 0x0f;
- switch(extra) {
- case 0x0d: extra=0x10; break;
- case 0x0e: extra=0x18; break;
- case 0x0f: extra=0x20; break;
- }
- switch(param) {
- case 0x0f:
- if(SE) nr0F++;
- break;
- case 0x51:
- if(SE) nano51Data=&buff[i];
- break;
- case 0xd1:
- cCW=&buff[i];
- if(SE) {
- sp->CalcSHASignature(buff,i,hashDW,false);
- memcpy(&hashDW[20],hashDW,8);
- Decrypt(&hashDW[20],PK,sp->T1(0),sp->T2(0));
- sp->CalcSHASignature(hashDW,28,hashDW,false);
- }
- break;
- case 0x82:
- if((!SE || sp->DoSigCheck()) && memcmp(&buff[i],signature,8)) {
- PRINTF(L_SYS_VERBOSE,"signature check failed after decrypt");
- cCW=0; i=decrLen;
- }
- break;
- }
- i+=extra;
- }
- if(cCW) {
- if(!nr0F || Process0FNano(nr0F,hashDW,PK,T1,T2)) {
- if(SE) sp->PreCW(cCW);
- if(!nano51Data || Process51Nano(cCW,nano51Data,hashDW,T1,T2,ecmD->provId)) {
- LDUMP(L_SYS_VERBOSE,cCW,16,"crypted CW :");
- Decrypt(&cCW[0],PK,T1,T2); Decrypt(&cCW[8],PK,T1,T2);
- LDUMP(L_SYS_VERBOSE,cCW,16,"decrypted CW :");
- if(SE) {
- LDUMP(L_SYS_VERBOSE,cCW,16,"decrypted CW before modification :");
- sp->PostCW(cCW);
- LDUMP(L_SYS_VERBOSE,cCW,16,"decrypted CW after modification :");
- }
- memcpy(cw,cCW,16);
- ks.OK(pk);
- return true;
- }
- }
- }
- }
- return false;
-}
-
-bool cSystemSeca::Process0FNano(int count, unsigned char *hashDW, unsigned char *PK, const unsigned char *T1, const unsigned char *T2)
-{
- const unsigned char *MT=sp->MT();
- unsigned char buffB[8];
-
- LDUMP(L_SYS_VERBOSE,hashDW,16,"0f: initial hashDW:");
- LDUMP(L_SYS_VERBOSE,PK,16,"0f: PK:");
- while(count--) {
- unsigned char buffA[8];
- swap8_4(hashDW);
- memcpy(buffA,hashDW,8);
- Decrypt(hashDW,PK,sp->T1(0),sp->T2(0));
- LDUMP(L_SYS_VERBOSE,hashDW,16,"0f: hashDW:");
-
- unsigned char buffE[8];
- int off=WORD(hashDW,0,0x3FFF);
- xxor(buffE,8,&MT[off],&MT[0x3FFF-off]);
- xxor(buffE,8,&MT[( ((buffE[0] ^ hashDW[6])<<8)
- + buffE[7] ^ hashDW[7] )&0x3FFF],buffE);
- LDUMP(L_SYS_VERBOSE,buffE,8,"0f: buffE:");
-
- unsigned char buffC[16];
- off=WORD(hashDW,2,0x3FFF);
- xxor(buffC,16,&MT[off],&MT[0x3FFF-off]);
- xxor(buffC,16,&MT[( ((hashDW[6] ^ buffC[0])<<8)
- + (hashDW[7] ^ buffC[15]) )&0x3FFF],buffC);
- LDUMP(L_SYS_VERBOSE,buffC,16,"0f: buffC:");
-
- off=WORD(hashDW,4,0x3FFF);
- for(int i=0; i<16; ++i) off=WORD(MT,off,0x3FFF);
- if(off+512 >= sp->MTSize()) {
- printf("BUG!!!: error: masking table overflow\n");
- return false;
- }
- PRINTF(L_SYS_VERBOSE,"0f: off=%04x",off);
-
- memcpy(buffB,buffE,8);
- Decrypt(buffB,buffC,&MT[off],&MT[off+256]);
- LDUMP(L_SYS_VERBOSE,buffB,8,"0f: buffB after 1st decr:");
- xxor(buffB,8,buffB,buffE);
- LDUMP(L_SYS_VERBOSE,buffB,8,"0f: buffB after xor:");
- Decrypt(buffB,PK,T1,T2);
- LDUMP(L_SYS_VERBOSE,buffB,8,"0f: buffB after 2nd decr:");
- xxor(hashDW,8,buffA,buffB);
- }
-
- for(int i=0; i<8; ++i) {
- PK[i] = buffB[i];
- PK[i+8] = ~sn8(buffB[i]);
- }
- LDUMP(L_SYS_VERBOSE,hashDW,16,"0f: hashDW:");
- LDUMP(L_SYS_VERBOSE,PK,16,"0f: new PK:");
- return true;
-}
-
-void cSystemSeca::Crypto51Nano(unsigned char *data, const unsigned char *key, const unsigned char crypto, const unsigned char mode)
-{
- switch(crypto) {
- case 0: // Xor
- PRINTF(L_SYS_VERBOSE,"51: XOR crypto selected");
- xxor(data+0,8,key,data+0); xxor(data+8,8,key,data+8);
- break;
- case 1: // Seca crypto, with 9x table, always!
- {
- unsigned char PK[16];
- const unsigned char *T1 = sp->T1(0);
- const unsigned char *T2 = sp->T2(0);
- memcpy(PK+0,key,8); memcpy(PK+8,key,8);
- PRINTF(L_SYS_VERBOSE,"51: SECA crypto selected: %s",mode?"decrypt":"encrypt");
- if(mode) { Decrypt(data,PK,T1,T2); Decrypt(data+8,PK,T1,T2); }
- else { Encrypt(data,PK,T1,T2); Encrypt(data+8,PK,T1,T2); }
- break;
- }
- case 2: // DES crypto (Modified PC1,PC2)
- PRINTF(L_SYS_VERBOSE,"51: DES crypto selected: %s",mode?"decrypt":"encrypt");
- if(mode) { des.Des(data,key,SECA_DES_DECR); des.Des(data+8,key,SECA_DES_DECR); }
- else { des.Des(data,key,SECA_DES_ENCR); des.Des(data+8,key,SECA_DES_ENCR); }
- break;
- case 3: // Additional Algo
- PRINTF(L_SYS_VERBOSE,"51: Additional crypto selected: %s",mode?"decrypt":"encrypt");
- AdditionalAlgo(data,key,mode); AdditionalAlgo(data+8,key,mode);
- break;
- }
-}
-
-bool cSystemSeca::Process51Nano(unsigned char *CW, const unsigned char *PermData, const unsigned char *hashDW, const unsigned char *T1, const unsigned char *T2, int provId)
-{
- const int pMode=(PermData[0]&0x3F)-1;
- const struct Perm *PT=sp->P(pMode);
- if(!PT) {
- PRINTF(L_SYS_VERBOSE,"51: failed to get permutation table");
- return false;
- }
- unsigned char buffF[8], buffG[8];
- switch(pMode) {
- case 0x00:
- case 0x01:
- {
- // Permutation 1
- Permute(buffF,PermData,PT->P1);
- LDUMP(L_SYS_VERBOSE,buffF,8,"51: buffF:");
- xxor(buffG,8,buffF,hashDW);
- const int addAlgoMode=(PermData[0]&1)^1;
- for(int i=(PermData[1]&0x0f); i>0; i--) AdditionalAlgo(buffG,hashDW+8,addAlgoMode);
- // Permutation 2
- Permute(buffF,PermData,PT->P2);
- xxor(buffG,8,buffF,buffG);
- LDUMP(L_SYS_VERBOSE,buffG,8,"51: buffG:");
- // Permutation 3
- Permute(buffF,PermData,PT->P3);
- xxor(buffG,8,buffF,buffG);
- // Permutation 4
- Permute(buffF,PermData,PT->P4);
- xxor(buffG,8,buffF,buffG);
- break;
- }
- case 0x08:
- {
- unsigned char buff1[128], buff2[64], buff3[9];
- // prepare buffers for rsa data
- for(int i=0; i<20; i++)
- buff1[i]=buff2[i]=buff2[i+20]=buff2[i+40]=hashDW[i];
- memcpy(buff3,PermData+2,3);
- for(int i=0; i<8; i++) buff1[i] = buff3[PT->P1[i]-2] ^= buff1[i];
- LDUMP(L_SYS_VERBOSE,buff1,20,"51: permuted hashDW:");
- for(int i=0; i<20; i++)
- buff1[i+24]=buff1[i+44]=buff1[i+68]=buff1[i+88]=buff1[i+108]=buff1[i];
- LBSTARTF(L_SYS_VERBOSE);
- LBPUT("51: nano51Data:");
- for(int i=0; i<4; i++) {
- unsigned char t=PermData[PT->P3[i]];
- if(PT->P3[i]==1) t&=0x0F;
- buff1[i+20]=buff1[i+64]=buff2[i+60]=t;
- LBPUT(" %02x",t);
- }
- LBEND();
- HEXDUMP(L_SYS_VERBOSE,buff1,128,"51: buff1:");
- HEXDUMP(L_SYS_VERBOSE,buff2,64,"51: buff2:");
-
- memcpy(buff3,buff1,9);
- for(int j=0; j<64; j++) { // XOR even with buff2, odd with 0xFF
- buff1[ j*2 ] ^= buff2[j];
- buff1[(j*2)+1] ^= 0xFF;
- }
- HEXDUMP(L_SYS_VERBOSE,buff1,128,"51: buff1 rsa prepped:");
-
- // RSA decrypt
- {
- cBN exp, mod;
- cPlainKey *pk;
- if(!(pk=keys.FindKey('S',provId,MBC3('E','9',N51_MAGIC),-1))) {
- if(doLog) PRINTF(L_SYS_KEY,"missing %04x N51 E9 key",provId);
- return false;
- }
- pk->Get(exp);
- if(!(pk=keys.FindKey('S',provId,MBC3('M','9',N51_MAGIC),-1))) {
- if(doLog) PRINTF(L_SYS_KEY,"missing %04x N51 M9 key",provId);
- return false;
- }
- pk->Get(mod);
- if(rsa.RSA(buff1,buff1,128,exp,mod)<9) return false;
- HEXDUMP(L_SYS_VERBOSE,buff1,128,"51: buff1 rsa decrypted:");
- }
-
- unsigned int sum=0;
- for(int j=0; j<9; j++) {
- unsigned int nextSum=(buff1[j]&0x80) ? 1:0;
- buff1[j]=(sum+2*buff1[j])^buff3[j];
- sum=nextSum;
- }
- LDUMP(L_SYS_VERBOSE,buff1,9,"51: buff1 after sumalgo:");
-
- memcpy(buffG,buff1,8);
- memcpy(buff3,PermData+2,3);
- for(int i=0; i<8; i++) buffG[i] = buff3[PT->P2[i]-2] ^= buffG[i];
- break;
- }
-
- default:
- PRINTF(L_SYS_VERBOSE,"51: data incorrect or proccessing not needed");
- return false;
- }
- LDUMP(L_SYS_VERBOSE,buffG,8,"51: cryptokey:");
- Crypto51Nano(CW,buffG,(PermData[1]>>6)&3,PermData[0]&0x80);
- // Final Permutation
- Permute(buffF,PermData,sp->FP());
- xxor(CW+0,8,CW+0,buffF); xxor(CW+8,8,CW+8,buffF);
- LDUMP(L_SYS_VERBOSE,hashDW,8,"51: cryptokey:");
- Crypto51Nano(CW,hashDW,(PermData[1]>>4)&0x03,PermData[0]&0x40);
- LDUMP(L_SYS_VERBOSE,CW,16,"51: new encrypted CW:");
- return true;
-}
-
-void cSystemSeca::Permute(unsigned char *data, const unsigned char *pdata, const unsigned char *P)
-{
- for(int i=7; i>=0; i--) data[i] = P[i] ? pdata[P[i]] : 0;
-}
-
-void cSystemSeca::ProcessEMM(int pid, int caid, unsigned char *buffer)
-{
- if(buffer[0]!=0x84) return; // we only support shared updates
-
- int msgLen=cParseSeca::CmdLen(buffer);
- if(msgLen!=0x55 && msgLen!=0x63) {
- if(++emmLenCnt<=5)
- PRINTF(L_SYS_EMM,"length of EMM does not match (%02x <> 55/63)%s",msgLen,emmLenCnt==5 ? " ....":"");
- return;
- }
- emmLenCnt=0;
- unsigned char *emm;
- msgLen=cParseSeca::Payload(buffer,(const unsigned char **)&emm);
- int provId=cParseSeca::ProvId(buffer);
- bool SE=false;
- const unsigned char *T1=T1_S1, *T2=T2_S1;
- int decrLen=msgLen;
- if(emm[0]==0x10) { // de-SSE
- const int rsaKeynr = emm[1]+'0';
- cPlainKey *pk;
- cBN exp, mod;
-
- if(!(pk=keys.FindKeyNoTrig('S',provId,MBC3('E',rsaKeynr,EMM_MAGIC),-1))) return;
- pk->Get(exp);
- if(!(pk=keys.FindKeyNoTrig('S',provId,MBC3('M',rsaKeynr,EMM_MAGIC),-1))) return;
- pk->Get(mod);
-
- if(rsa.RSA(emm+2,emm+2,msgLen-2,exp,mod)!=msgLen-2) return;
- const int keyNr=cParseSeca::KeyNr(buffer);
- if(keyNr&0x80) {
- SE=true;
- decrLen-=emm[msgLen-1];
- if(!GetSeca2Prov(provId,spL) ||
- !(T1=spL->T1(KEY2INDEX(keyNr))) ||
- !(T2=spL->T2(KEY2INDEX(keyNr))) ||
- decrLen<8) return;
- }
- }
-
- unsigned char *buff=AUTOMEM(msgLen);
- for(cSecaCardInfo *ci=Scards.First(); ci; ci=Scards.Next(ci)) {
- if(ci->MatchEMM(buffer) || (CheckNull(ci->sa,sizeof(ci->sa)) && ci->MatchID(buffer))) {
- unsigned char MK[16];
- if(cParseSeca::SysMode(buffer)&0x10) {
- if(ci->KeySize()!=16) continue; // don't bother
- memcpy(&MK[0],ci->key,16);
- }
- else {
- memcpy(&MK[0],ci->key,8);
- memcpy(&MK[8],ci->key,8);
- }
-
- unsigned char signature[20];
- memcpy(buff,emm,msgLen); // if decoding fails we need the original de-sse'd data
-
- if(!SE) {
- for(int i=0 ; i<=64 && i<msgLen-8; i+=8) Decrypt(&buff[i],MK,T1,T2);
- CalcSignature(buff,decrLen-8,signature,MK,T1,T2);
- }
- else {
- spL->CalcSHASignature(buff,decrLen-8,signature);
- Encrypt(signature,MK,T1,T2);
- if(memcmp(signature,&buff[decrLen-8],8) ||
- !spL->DecryptSE(buff+2,MK,msgLen-2,0,T1,T2)) continue;
- }
-
- unsigned char keyN[4], *key[4];
- int pos, len;
- unsigned int numKeys=0;
- bool sigOk=false;
- for(pos=0 ; pos<decrLen ; pos+=len) {
- int cmd=buff[pos++];
- len=(cmd>>4)&0x0f;
- switch(len) {
- case 0x0b: len=0x0e; break;
- case 0x0d: len=0x10; break;
- case 0x0e: len=0x18; break;
- case 0x0f: len=0x20; break;
- }
- switch(cmd) {
- case 0x82: // signature
- if(!memcmp(signature,&buff[pos],8)) sigOk=true;
- pos=decrLen;
- break;
- case 0x90: // new primary key
- if(numKeys<sizeof(keyN)) {
- keyN[numKeys]=buff[pos] & 0x0f;
- key[numKeys]=&buff[pos+1];
- numKeys++;
- }
- break;
- }
- }
- char str[20],str2[20],str3[20];
- if(sigOk) {
- LBSTARTF(L_SYS_EMM);
- LBPUT("ID %s SA %s",HexStr(str,SID(buffer),2),HexStr(str2,SA(buffer),3));
- LBPUT(" - OK (CI ID %s SA %s KEY01 %s)",HexStr(str,ci->provId,2),HexStr(str2,ci->sa,3),HexStr(str3,ci->key,8));
- for(unsigned int i=0 ; i<numKeys ; i++) {
- Decrypt(key[i],MK,T1,T2);
- LBPUT(" KEY %02x %s",keyN[i],HexStr(str,key[i],8));
- FoundKey();
- if(keys.NewKey('S',provId,keyN[i],key[i],8)) NewKey();
- }
- LBEND();
- break;
- }
- else if(!CheckNull(ci->sa,sizeof(ci->sa)))
- PRINTF(L_SYS_EMM,"ID %s SA %s - FAIL",HexStr(str,SID(buffer),2),HexStr(str2,SA(buffer),3));
- }
- }
- return;
-}
-
-// -- cSystemLinkSeca ----------------------------------------------------------
-
-class cSystemLinkSeca : public cSystemLink {
-public:
- cSystemLinkSeca(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemSeca; }
- };
-
-static cSystemLinkSeca staticInit;
-
-cSystemLinkSeca::cSystemLinkSeca(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- Feature.NeedsKeyFile();
-}
-
-bool cSystemLinkSeca::CanHandle(unsigned short SysId)
-{
- SysId&=SYSTEM_MASK;
- return SYSTEM_CAN_HANDLE(SysId);
-}
+++ /dev/null
-#
-# Seca
-#
-TARGET = seca
-OBJS = seca.o
-LIBS = -lcrypto
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <malloc.h>
-#include <sys/ioctl.h>
-#include <sys/poll.h>
-#include <linux/dvb/dmx.h>
-
-#include <openssl/des.h>
-
-#include "system-common.h"
-#include "data.h"
-#include "filter.h"
-#include "misc.h"
-#include "log-sys.h"
-
-#define SYSTEM_SHL 0x4A60
-
-#define SYSTEM_NAME "@SHL"
-#define SYSTEM_PRI -10
-#define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_SHL)
-
-#define L_SYS 15
-#define L_SYS_HOPPER LCLASS(L_SYS,L_SYS_LASTDEF<<1)
-#define L_SYS_HSTATS LCLASS(L_SYS,L_SYS_LASTDEF<<2)
-#define L_SYS_ALL LALL(L_SYS_HSTATS)
-
-static const struct LogModule lm_sys = {
- (LMOD_ENABLE|L_SYS_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_SYS_DEFDEF)&LOPT_MASK,
- "shl",
- { L_SYS_DEFNAMES,"pidHopper","hopperStats" }
- };
-ADD_MODULE(L_SYS,lm_sys)
-
-// evil hack, but it's not worth to put much effort in a dead system ...
-static cTimeMs __time;
-#define time_ms() ((int)__time.Elapsed())
-
-static cPlainKeyTypeReg<cPlainKeyStd,'Z',false> KeyReg;
-
-// -- cPesFilter ---------------------------------------------------------------
-
-class cPesFilter : public cPidFilter {
-public:
- cPesFilter(const char *Id, int Num, int DvbNum, int IdleTime);
- virtual void Start(int Pid, int Section, int Mask, int Mode, bool Crc);
- };
-
-cPesFilter::cPesFilter(const char *Id, int Num, int DvbNum, int IdleTime)
-:cPidFilter(Id,Num,DvbNum,IdleTime)
-{}
-
-void cPesFilter::Start(int Pid, int Section, int Mask, int Mode, bool Crc)
-{
- if(fd>=0) {
- Stop();
- struct dmx_pes_filter_params FilterParams;
- FilterParams.input=DMX_IN_FRONTEND;
- FilterParams.output=DMX_OUT_TAP;
- FilterParams.pes_type=DMX_PES_OTHER;
- FilterParams.flags=DMX_IMMEDIATE_START;
- FilterParams.pid=Pid;
- CHECK(ioctl(fd,DMX_SET_PES_FILTER,&FilterParams));
- pid=Pid;
- active=true;
- }
-}
-
-// -- cPidHopper ---------------------------------------------------------------
-
-struct FilterPacket {
- struct FilterPacket *next;
- int lastTime, dataLen;
- unsigned char lastData[1];
- };
-
-struct FilterData {
- cPidFilter *filter;
- int lastTime, lastRead, createTime, readCount;
- struct FilterPacket *first, *last;
- };
-
-class cPidHopper : public cAction {
-private:
- struct FilterData *d;
- int numFilters;
- cMutex sleepMutex;
- cCondVar sleep;
- //
- void PurgeFilter(struct FilterData *dd);
- void PurgePacket(struct FilterData *dd, struct FilterPacket *p);
-protected:
- virtual void Process(cPidFilter *filter, unsigned char *data, int len);
- virtual cPidFilter *CreateFilter(const char *Id, int Num, int DvbNum, int IdleTime);
-public:
- cPidHopper(int DvbNum, int NumFilters);
- virtual ~cPidHopper();
- int Read(int pid, int & now, unsigned char *buff, int len, int timeout);
- bool AddPid(int pid);
- void CutOff(int now);
- };
-
-cPidHopper::cPidHopper(int DvbNum, int NumFilters)
-:cAction("pidhopper",DvbNum)
-{
- numFilters=NumFilters;
- d=MALLOC(struct FilterData,NumFilters);
- memset(d,0,sizeof(struct FilterData)*NumFilters);
- PRINTF(L_SYS_HOPPER,"pid hopper started (%d filters)",numFilters);
-}
-
-cPidHopper::~cPidHopper()
-{
- Lock();
- int now=time_ms(), num=1;
- PRINTF(L_SYS_HSTATS,"active pids: (now=%d)\n",now);
- for(int i=0; i<numFilters; i++) {
- struct FilterData *dd=&d[i];
- if(dd->filter) {
- if(dd->filter->Pid()>=0)
- PRINTF(L_SYS_HSTATS,"%2d. pid %04x lastTime=%4d lastRead=%4d created=%4d count=%4d",
- num++,
- dd->filter->Pid(),
- dd->lastTime>0 ? (now-dd->lastTime)/1000 : -1,
- dd->lastRead>0 ? (now-dd->lastRead)/1000 : -1,
- dd->createTime>0 ? (now-dd->createTime)/1000 : -1,
- dd->readCount);
- DelFilter(dd->filter);
- dd->filter=0;
- }
- PurgeFilter(dd);
- }
- Unlock();
- free(d);
-}
-
-void cPidHopper::PurgeFilter(struct FilterData *dd)
-{
- if(dd->first && dd->last) PurgePacket(dd,dd->last);
-}
-
-void cPidHopper::PurgePacket(struct FilterData *dd, struct FilterPacket *p)
-{
- while(dd->first) {
- struct FilterPacket *del=dd->first;
- dd->first=del->next;
- if(dd->filter) PRINTF(L_SYS_HOPPER,"PID %04x purging packet %p (time=%d)",dd->filter->Pid(),del,del->lastTime);
- free(del);
- if(del==p) break;
- }
- if(!dd->first) dd->last=0;
-}
-
-void cPidHopper::CutOff(int now)
-{
- Lock();
- PRINTF(L_SYS_HOPPER,"cutoff (now=%d)",now);
- for(int i=0; i<numFilters; i++) {
- struct FilterData *dd=&d[i];
- struct FilterPacket *p=dd->first, *del=0;
- while(p) {
- if(p->lastTime>=now) break;
- del=p;
- p=p->next;
- }
- if(del) {
- PurgePacket(dd,del);
- dd->lastTime=dd->first ? dd->first->lastTime : -1;
- }
- }
- Unlock();
-}
-
-cPidFilter *cPidHopper::CreateFilter(const char *Id, int Num, int DvbNum, int IdleTime)
-{
- cPidFilter *filter=new cPesFilter(Id,Num,DvbNum,IdleTime);
- d[Num].filter=filter;
- d[Num].lastTime=-1;
- d[Num].lastRead=-1;
- d[Num].createTime=time_ms();
- d[Num].readCount=0;
- d[Num].first=0;
- d[Num].last=0;
- return filter;
-}
-
-void cPidHopper::Process(cPidFilter *filter, unsigned char *data, int len)
-{
- if(data && len>0) {
- int now=time_ms();
- for(int i=0; i<numFilters; i++)
- if(d[i].filter==filter) {
- do {
- int l=min(len,184);
- struct FilterPacket *p=(struct FilterPacket *)malloc(sizeof(struct FilterPacket)+l-1);
- if(p) {
- p->next=0;
- memcpy(p->lastData,data,l);
- p->dataLen=l;
- p->lastTime=now;
- if(d[i].first)
- d[i].last->next=p;
- else {
- d[i].first=p;
- d[i].lastTime=now;
- }
- d[i].last=p;
- PRINTF(L_SYS_HOPPER,"PID %04x queued packet %p (time=%d len=%d) (%s)",d[i].filter->Pid(),p,p->lastTime,l,d[i].first==p?"first":"queue");
- }
- len-=l; data+=l;
- } while(len>0);
- sleep.Broadcast();
- break;
- }
- }
-}
-
-bool cPidHopper::AddPid(int pid)
-{
- cPidFilter *filter=NewFilter(0);
- if(!filter) return false;
- filter->Start(pid,0,0,0,false);
- return true;
-}
-
-int cPidHopper::Read(int pid, int & now, unsigned char *buff, int len, int timeout)
-{
- Lock();
- timeout+=time_ms();
- PRINTF(L_SYS_HOPPER,"PID %04x read (now=%d)",pid,now);
- int n=-1;
- while(time_ms()<timeout) {
- struct FilterData *dd=0, *old=0;
- for(int i=0; i<numFilters; i++)
- if(d[i].filter) {
- if(d[i].filter->Pid()==pid) { dd=&d[i]; break; }
- if(!old ||
- (d[i].lastRead<0 && d[i].createTime<old->createTime) ||
- (d[i].lastRead>=0 && d[i].lastRead<old->lastRead))
- old=&d[i];
- }
- if(!dd) {
- LBSTARTF(L_SYS_VERBOSE);
- LBPUT("NEW ");
- if(!AddPid(pid)) {
- if(!old) break;
- LBPUT("{0x%04x/%d/%d} ",old->filter->Pid(),old->lastRead>0 ? (time_ms()-old->lastRead)/1000:-1,old->lastTime>0 ? (time_ms()-old->lastTime)/1000:-1);
- old->filter->Stop(); // purge LRU filter
- PurgeFilter(old);
- old->lastTime=-1;
- old->lastRead=-1;
- old->createTime=time_ms();
- old->readCount=0;
- old->filter->Start(pid,0,0,0,false);
- }
- LBEND();
- continue;
- }
- for(struct FilterPacket *p=dd->first; p; p=p->next) {
- if(p->lastTime>=now) {
- n=min(len,p->dataLen);
- memcpy(buff,p->lastData,n);
- now=p->lastTime;
- PRINTF(L_SYS_HOPPER,"PID %04x returning packet %p (time=%d)",dd->filter->Pid(),p,p->lastTime);
- PurgePacket(dd,p);
- dd->lastRead=time_ms();
- dd->readCount++;
- dd->lastTime=dd->first ? dd->first->lastTime : -1;
- break;
- }
- else {
- PRINTF(L_SYS_HOPPER,"PID %04x skipping packet %p (time=%d)",dd->filter->Pid(),p,p->lastTime);
- if(!p->next) {
- PRINTF(L_SYS_HOPPER,"PID %04x queue empty",dd->filter->Pid());
- PurgePacket(dd,p);
- break;
- }
- }
- }
- if(n>0) break;
- Unlock();
- sleepMutex.Lock();
- sleep.TimedWait(sleepMutex,200);
- sleepMutex.Unlock();
- Lock();
- }
- Unlock();
- return n;
-}
-
-// -- cShl ---------------------------------------------------------------------
-
-class cShl {
-private:
- DES_key_schedule sched;
-public:
- void SetKey( const unsigned char *key);
- void Decode(unsigned char *data, int n);
- };
-
-void cShl::SetKey(const unsigned char *key)
-{
- DES_key_sched((DES_cblock *)key,&sched);
-}
-
-void cShl::Decode(unsigned char *data, int n)
-{
- int r=n&7;
- n-=r;
- for(int i=0; i<n; i+=8)
- DES_ecb_encrypt((DES_cblock *)&data[i],(DES_cblock *)&data[i],&sched,DES_DECRYPT);
- if(r) { // possible last incomplete block
- DES_cblock out;
- DES_ecb_encrypt((DES_cblock *)&data[n],&out,&sched,DES_DECRYPT);
- memcpy(&data[n],out,r);
- }
-}
-
-// -- SHL provider -------------------------------------------------------------
-
-struct ShlProv {
- const char *name;
- unsigned short id;
- bool hasXor;
- int filters, pidRange;
- const unsigned short pids[128];
- const unsigned char xorTab[16];
- };
-
-static const struct ShlProv prov[] = {
-/*
- { "FreeX",0x4A90,false,40,0x1300,
- { 0x1389,0x138a,0x138b,0x138c,0x138d,0x138e,0x138f,0x1390,
- 0x1391,0x1392,0x1393,0x1394,0x1395,0x1396,0x1397,0x1398,
- 0x1399,0x139a,0x139b,0x139c,0x13a4,0x13a5,0x13a6,0x13a7,
- 0x13a8,0x13a9,0x13bf,0x13c0,0x13c1,0x13c2,0x13c3,0x13c4,
- 0x13c5,0x13c6,0x13c7,0x13c8,0x13c9,0x13ca,0x13cb,0x13cc },
- {} },
-*/
- { "FullX-2",0x4A90,false,128,0x0000,
- { 0x0bb9,0x0bba,0x0bbc,0x0bbf,0x0bc0,0x0bc2,0x0bc3,0x0bc4,
- 0x0bc7,0x0bc8,0x0bc9,0x0bcc,0x0bcd,0x0bce,0x0bcf,0x0bd0,
- 0x0bd3,0x0bd5,0x0bd6,0x0bd7,0x0bd8,0x0bd9,0x0bdb,0x0bdd,
- 0x0bdf,0x0be0,0x0be1,0x0be2,0x0be3,0x0be4,0x0be5,0x0be6,
- 0x0be7,0x0be8,0x0be9,0x0bea,0x1784,0x177c,0x178a,0x1796,
- 0x1774,0x1772,0x17a2,0x1783,0x1792,0x177b,0x1775,0x179b,
- 0x1794,0x1789,0x1778,0x1799,0x1793,0x1797,0x1782,0x1779,
- 0x179e,0x1787,0x178d,0x177d,0x1771,0x1791,0x1776,0x1788,
- 0x178f,0x179c,0x177e,0x178b,0x1785,0x1781,0x0bc5,0x17a1,
- 0x0bbe,0x179f,0x0bdc,0x1780,0x0bca,0x0bd2,0x0bbd,0x179a,
- 0x1773,0x178e,0x1795 },
- {} },
- { "FullX",0x6997,true,60,0x1700,
- { 0x178e,0x178f,0x1783,0x1780,0x1776,0x177b,0x1772,0x1779,
- 0x1785,0x179e,0x1791,0x1771,0x177e,0x1793,0x1778,0x179a,
- 0x17a2,0x17a1,0x178d,0x1787,0x1797,0x1796,0x177d,0x1781,
- 0x1799,0x1794,0x179b,0x1784,0x1795,0x177c,0x1782,0x179c,
- 0x1773,0x1788,0x1789,0x178b,0x179f,0x1775,0x1792,0x1774,
- 0x178a },
- { 0x4E,0x9E,0x5C,0xFA,0x62,0x80,0x4C,0x86,0x56,0xDF,0x7E,0x03,0x9B,0x05,0xB2,0xE7 } },
- { "DP",0x6996,true,48,0x1300,
- { 0x1389,0x138a,0x138b,0x138c,0x138d,0x138e,0x138f,0x1390,
- 0x1391,0x1392,0x1393,0x1394,0x1395,0x1396,0x1397,0x1398,
- 0x1399,0x139a,0x139b,0x139c,0x13a4,0x13a5,0x13a6,0x13a7,
- 0x13a8,0x13a9,0x13bf,0x13c0,0x13c1,0x13c2,0x13c3,0x13c4,
- 0x13c5,0x13c6,0x13c7,0x13c8,0x13c9,0x13ca,0x13cb,0x13cc },
- { 0x30,0x61,0xD7,0xC0,0x8E,0x41,0x2C,0xB9,0xAA,0x50,0xB2,0xF4,0x5B,0x2E,0x84,0xCF } }
- };
-
-static const struct ShlProv *FindProv(unsigned short id)
-{
- for(unsigned int i=0; i<(sizeof(prov)/sizeof(struct ShlProv)); i++)
- if(prov[i].id==id) return &prov[i];
- return 0;
-}
-
-// -- cSystemShl ---------------------------------------------------------------
-
-#define ENC_OFF 12 // encrypted bytes offset
-#define ENC_LEN 24 // encrypted bytes length
-
-#define KEY_OFF 7
-#define PID_OFF 15
-#define EMASK_OFF 8
-#define OMASK_OFF 12
-#define CW_OFF 17
-
-class cSystemShl : public cSystem, private cShl {
-private:
- cPidHopper *ph;
- int prvId;
- bool hasPrvId;
- cMutex mutex;
- cCondVar wait;
- //
- void ProcessCw(const unsigned char *data, int prvId, const unsigned char *xorTable);
-public:
- cSystemShl(void);
- virtual ~cSystemShl();
- virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *source);
- virtual void ProcessEMM(int pid, int caid, unsigned char *buffer);
- };
-
-cSystemShl::cSystemShl(void)
-:cSystem(SYSTEM_NAME,SYSTEM_PRI)
-{
- ph=0; hasPrvId=false;
- hasLogger=needsLogger=true; maxEcmTry=20;
-}
-
-cSystemShl::~cSystemShl()
-{
- delete ph;
-}
-
-bool cSystemShl::ProcessECM(const cEcmInfo *ecm, unsigned char *source)
-{
- static const unsigned char tester[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF };
- // in old SHL algo ECM starts with 12 0xFF
- if(SCT_LEN(source)<(ENC_OFF+ENC_LEN+3)) {
- PRINTF(L_SYS_VERBOSE,"short ecm");
- return false;
- }
- if(memcmp(tester,&source[3],sizeof(tester))) { // new SHL
- mutex.Lock();
- if(!hasPrvId) {
- wait.TimedWait(mutex,500); // wait for provider ID
- if(!hasPrvId) {
- PRINTF(L_SYS_ECM,"no provider ID (logger enabled?)");
- mutex.Unlock();
- return false;
- }
- }
- const struct ShlProv *prv=FindProv(prvId);
- if(!prv) {
- PRINTF(L_SYS_ECM,"provider %04x not supported",prvId);
- mutex.Unlock();
- return false;
- }
- mutex.Unlock();
- if(!ph) {
- PRINTF(L_SYS_ECM,"using card %d",CardNum());
- ph=new cPidHopper(CardNum(),prv->filters);
- if(!ph) {
- PRINTF(L_SYS_ECM,"no pid hopper");
- return false;
- }
-#if 1
- unsigned int l=min((int)(sizeof(prv->pids)/sizeof(unsigned short)),prv->filters);
- for(unsigned int i=0; i<l; i++) {
- if(prv->pids[i]<=0) break;
- ph->AddPid(prv->pids[i]);
- }
-#endif
- }
-
- int pid=ecm->ecm_pid;
- int now=time_ms();
- unsigned char buff[4096];
- unsigned char emask=0, omask=0;
- memcpy(buff+1,source,SCT_LEN(source)); buff[0]=0;
- LBSTARTF(L_SYS_VERBOSE);
- LBPUT("chain 0x%04x [%d] ",pid,SCT_LEN(source)+1);
- while(1) {
- unsigned char *ptr=buff;
- if(ptr[0]!=0) { // decrypt whole payload
- LBPUT("PES");
- unsigned char test[8];
- memcpy(test,ptr,sizeof(test)); Decode(test,sizeof(test));
- if(test[0]!=source[0] && (ptr[0]==0x11 || ptr[0]==0x12)) { // Section is available at section_pointer offset.
- SetKey(&ptr[KEY_OFF+1]); // Use the same key and pid offsets which you use
- Decode(&ptr[PID_OFF+1],183-PID_OFF); // for normal SHL section data decoding.
- ptr+=ptr[0]+1;
- if(ptr[0]==0x91 && SCT_LEN(ptr)==11) ptr+=11;
- LBPUT("s");
- }
- else if(test[0]!=source[0] && ptr[0]==0x0a) {
- SetKey(&ptr[1]);
- Decode(&ptr[9],183-9);
- ptr+=ptr[0]+1;
- LBPUT("a");
- }
- else {
- Decode(ptr,184);
- LBPUT("n");
- }
- LBPUT(" ");
- }
- else { // decrypt data only
- LBPUT("SCT ");
- ptr++;
- SetKey(&ptr[KEY_OFF]);
- Decode(&ptr[PID_OFF],SCT_LEN(ptr)-PID_OFF);
- }
- if(ptr[0]!=source[0]) {
- LBPUT("wrong section %02x != %02x",ptr[0],source[0]);
- return false;
- }
- pid=(ptr[PID_OFF]<<8)+ptr[PID_OFF+1];
- if(pid==0x1FFF) { // finished
- if(prv->hasXor) ProcessCw(ptr,prv->id,prv->xorTab);
- else {
- for(int i=0; i<8; i++) {
- const int m=1<<(7-i);
- if(!(emask & m)) cw[i ]=ptr[CW_OFF+i];
- if(!(omask & m)) cw[i+8]=ptr[CW_OFF+i+8];
- }
- }
- LBPUT("done");
- ph->CutOff(now);
- return true;
- }
- else { // next hop
- if(prv->hasXor) ProcessCw(ptr,prv->id,prv->xorTab);
- else {
- emask=ptr[EMASK_OFF];
- omask=ptr[OMASK_OFF];
- memcpy(cw,&ptr[CW_OFF],16);
- }
- LBPUT("0x%04x ",pid);
-#if 1
- if(prv->pidRange && (pid&0xFF00)!=prv->pidRange) {
- LBPUT("wrong pid range");
- return false;
- }
-#endif
- int n=ph->Read(pid,now,buff,sizeof(buff),1000);
- if(n<CW_OFF+16+1) {
- LBPUT("read failed");
- return false;
- }
- LBPUT("[%d] ",n);
- }
- }
- LBEND();
- }
- else { // old SHL
- static const unsigned char signature[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF };
- source+=ENC_OFF+3; // here's the DES crypto content
-
- cPlainKey *pk=0;
- cKeySnoop ks(this,'Z',ecm->provId,0x00);
- unsigned char key[8];
- while((pk=keys.FindKey('Z',ecm->provId,0x00,sizeof(key),pk))) {
- pk->Get(key);
- SetKey(key);
- Decode(source,ENC_LEN);
- unsigned char sigbuf[8];
- memcpy(&sigbuf[0],&source[0],2);
- memcpy(&sigbuf[2],&source[18],6);
- if(!memcmp(sigbuf,signature,sizeof(sigbuf))) {
- memcpy(cw,&source[2],16);
- ks.OK(pk);
- return true;
- }
- }
- }
- return false;
-}
-
-void cSystemShl::ProcessCw(const unsigned char *data, int prvId, const unsigned char *xorTable)
-{
- if(SCT_LEN(data)<150) {
- PRINTF(L_SYS_VERBOSE,"data is too short");
- return;
- }
- const unsigned int dataStart=data[33];
- if((dataStart+35)>184) {
- PRINTF(L_SYS_VERBOSE,"data broken (%d)",dataStart);
- return;
- }
- const unsigned int xorVal=data[dataStart+35];
- const unsigned int emask =data[dataStart+34];
- const unsigned int omask =data[dataStart+33];
- for(int i=0; i<8; i++) {
- const unsigned int m=1<<i;
- if(emask & m) cw[i ]=data[CW_OFF+i ]^xorVal^xorTable[i ];
- if(omask & m) cw[i+8]=data[CW_OFF+8+i]^xorVal^xorTable[i+8];
- }
-}
-
-void cSystemShl::ProcessEMM(int pid, int caid, unsigned char *buffer)
-{
- int n=SCT_LEN(buffer)-3;
- buffer+=3;
- for(int i=0; i<n;) {
- switch(buffer[i]) {
- case 0x0a:
- mutex.Lock();
- prvId=WORD(buffer,i+2,0xFFFF);
- if(!hasPrvId) {
- const struct ShlProv *prv=FindProv(prvId);
- PRINTF(L_SYS_EMM,"provider id %04x (%s)\n",prvId,prv ? prv->name:"unknown");
- wait.Broadcast();
- }
- hasPrvId=true;
- mutex.Unlock();
- break;
- case 0x08:
- case 0x0b:
- case 0x09:
- case 0x06:
- case 0x02:
- case 0x30:
- case 0x07:
- break;
- default:
- HEXDUMP(L_SYS_EMM,&buffer[i+2],buffer[i+1],"unknown nano: %02x:",buffer[i]);
- break;
- }
- i+=buffer[i+1]+2;
- }
-}
-
-// -- cSystemLinkShl -----------------------------------------------------------
-
-class cSystemLinkShl : public cSystemLink {
-public:
- cSystemLinkShl(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemShl; }
- };
-
-static cSystemLinkShl staticInit;
-
-cSystemLinkShl::cSystemLinkShl(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- Feature.NeedsKeyFile();
-}
-
-bool cSystemLinkShl::CanHandle(unsigned short SysId)
-{
- SysId&=0xFFF0;
- return SYSTEM_CAN_HANDLE(SysId);
-}
+++ /dev/null
-#
-# @SHL
-#
-TARGET = shl
-OBJS = shl.o
-LIBS = -lcrypto
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __LOG_VIACCESS_H
-#define __LOG_VIACCESS_H
-
-#include "log-sys.h"
-
-#define L_SYS 16
-#define L_SYS_TPS LCLASS(L_SYS,L_SYS_LASTDEF<<1)
-#define L_SYS_TPSAU LCLASS(L_SYS,L_SYS_LASTDEF<<2)
-#define L_SYS_TIME LCLASS(L_SYS,L_SYS_LASTDEF<<3)
-#define L_SYS_ST20 LCLASS(L_SYS,L_SYS_LASTDEF<<4)
-#define L_SYS_DISASM LCLASS(L_SYS,L_SYS_LASTDEF<<5)
-#define L_SYS_ALL LALL(L_SYS_DISASM)
-
-#endif
-
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __OPENTV_H
-#define __OPENTV_H
-
-#define COMP_SECTION_HDR 0x434F4D50
-#define INFO_SECTION_HDR 0x494E464F
-#define CODE_SECTION_HDR 0x434F4445
-#define DATA_SECTION_HDR 0x44415441
-#define GDBO_SECTION_HDR 0x4744424F
-#define LAST_SECTION_HDR 0x4C415354
-#define SWAP_SECTION_HDR 0x53574150
-
-typedef struct comp_header {
- unsigned int magic;
- unsigned int csize, dsize, usize;
- unsigned char end;
-} comp_header_t;
-
-typedef struct info_header {
- unsigned int magic;
- unsigned int bsssize;
- unsigned int stacksize;
-} info_header_t;
-
-typedef struct code_header {
- unsigned int magic;
- unsigned int size, m_id;
- unsigned short entry_point;
- unsigned short end;
- const unsigned char *code;
-} code_header_t;
-
-typedef struct data_header {
- unsigned int magic;
- unsigned int dlen;
- const unsigned char *data;
-} data_header_t;
-
-#endif /* __OPENTV_H */
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <vdr/tools.h>
-
-#include "log-viaccess.h"
-#include "st20.h"
-
-#include "helper.h"
-#include "misc.h"
-
-//#define SAVE_DEBUG // add some (slow) failsafe checks and stricter emulation
-
-#define INVALID_VALUE 0xCCCCCCCC
-#define ERRORVAL 0xDEADBEEF
-
-#define MININT 0x7FFFFFFF
-#define MOSTPOS 0x7FFFFFFF
-#define MOSTNEG 0x80000000
-
-#ifndef SAVE_DEBUG
-#define POP() stack[(sptr++)&STACKMASK]
-#else
-#define POP() ({ int __t=stack[sptr&STACKMASK]; stack[(sptr++)&STACKMASK]=INVALID_VALUE; __t; })
-#endif
-#define PUSH(v) do { int __v=(v); stack[(--sptr)&STACKMASK]=__v; } while(0)
-#define DROP(n) sptr+=n
-
-#define AAA stack[sptr&STACKMASK]
-#define BBB stack[(sptr+1)&STACKMASK]
-#define CCC stack[(sptr+2)&STACKMASK]
-
-#define GET_OP() operand|=op1&0x0F
-#define CLEAR_OP() operand=0
-#define JUMP(x) Iptr+=(x)
-#define POP64() ({ unsigned int __b=POP(); ((unsigned long long)POP()<<32)|__b; })
-#define PUSHPOP(op,val) do { int __a=val; AAA op##= (__a); } while(0)
-
-#ifndef SAVE_DEBUG
-#define RB(off) UINT8_LE(Addr(off))
-#define RW(off) UINT32_LE(Addr(off))
-#define WW(off,val) BYTE4_LE(Addr(off),val)
-#else
-#define RB(off) ReadByte(off)
-#define RW(off) ReadWord(off)
-#define WW(off,val) WriteWord(off,val)
-#endif
-
-#define LOG_OP(op) do { if(v) LogOp(op); } while(0)
-
-// -- cST20 --------------------------------------------------------------------
-
-cST20::cST20(void)
-{
- flash=ram=0;
- loglb=new cLineBuff(128);
-}
-
-cST20::~cST20()
-{
- free(flash);
- free(ram);
- delete loglb;
-}
-
-void cST20::SetFlash(unsigned char *m, int len)
-{
- free(flash);
- flash=MALLOC(unsigned char,len);
- if(flash && m) memcpy(flash,m,len);
- else memset(flash,0,len);
- flashSize=len;
-}
-
-void cST20::SetRam(unsigned char *m, int len)
-{
- free(ram);
- ram=MALLOC(unsigned char,len);
- if(ram && m) memcpy(ram,m,len);
- else memset(ram,0,len);
- ramSize=len;
-}
-
-void cST20::Init(unsigned int IPtr, unsigned int WPtr)
-{
- Wptr=WPtr; Iptr=IPtr;
- memset(stack,INVALID_VALUE,sizeof(stack)); sptr=STACKMAX-3;
- memset(iram,0,sizeof(iram));
- verbose=LOG(L_SYS_DISASM);
-}
-
-void cST20::SetCallFrame(unsigned int raddr, int p1, int p2, int p3)
-{
- Wptr-=16;
- WriteWord(Wptr,raddr); // RET
- WriteWord(Wptr+4,0);
- WriteWord(Wptr+8,0);
- WriteWord(Wptr+12,p1);
- WriteWord(Wptr+16,p2);
- WriteWord(Wptr+20,p3);
- SetReg(AREG,raddr); // RET
-}
-
-unsigned int cST20::GetReg(int reg) const
-{
- switch(reg) {
- case IPTR: return Iptr;
- case WPTR: return Wptr;
- case AREG: return AAA;
- case BREG: return BBB;
- case CREG: return CCC;
- default: PRINTF(L_SYS_ST20,"getreg: unknown reg"); return ERRORVAL;
- }
-}
-
-void cST20::SetReg(int reg, unsigned int val)
-{
- switch(reg) {
- case IPTR: Iptr=val; return;
- case WPTR: Wptr=val; return;
- case AREG: AAA=val; return;
- case BREG: BBB=val; return;
- case CREG: CCC=val; return;
- default: PRINTF(L_SYS_ST20,"setreg: unknown reg"); return;
- }
-}
-
-unsigned char *cST20::Addr(unsigned int off)
-{
- if(off>=FLASHS && off<=FLASHE) {
-#ifndef SAVE_DEBUG
- return &flash[off-FLASHS];
-#else
- off-=FLASHS; if(off<flashSize && flash) return &flash[off]; break;
-#endif
- }
- else if(off>=RAMS && off<=RAME) {
-#ifndef SAVE_DEBUG
- return &ram[off-RAMS];
-#else
- off-=RAMS; if(off<ramSize && ram) return &ram[off]; break;
-#endif
- }
- else if(off>=IRAMS && off<=IRAME)
- return &iram[off-IRAMS];
-#ifndef SAVE_DEBUG
- invalid=ERRORVAL; return (unsigned char *)&invalid;
-#else
- return 0;
-#endif
-}
-
-unsigned int cST20::ReadWord(unsigned int off)
-{
-#ifndef SAVE_DEBUG
- return UINT32_LE(Addr(off));
-#else
- unsigned char *addr=Addr(off);
- return addr ? UINT32_LE(addr) : ERRORVAL;
-#endif
-}
-
-unsigned short cST20::ReadShort(unsigned int off)
-{
-#ifndef SAVE_DEBUG
- return UINT16_LE(Addr(off));
-#else
- unsigned char *addr=Addr(off);
- return addr ? UINT16_LE(addr) : ERRORVAL>>16;
-#endif
-}
-
-unsigned char cST20::ReadByte(unsigned int off)
-{
-#ifndef SAVE_DEBUG
- return UINT8_LE(Addr(off));
-#else
- unsigned char *addr=Addr(off);
- return addr ? UINT8_LE(addr) : ERRORVAL>>24;
-#endif
-}
-
-void cST20::WriteWord(unsigned int off, unsigned int val)
-{
-#ifndef SAVE_DEBUG
- BYTE4_LE(Addr(off),val);
-#else
- unsigned char *addr=Addr(off);
- if(addr) BYTE4_LE(addr,val);
-#endif
-}
-
-void cST20::WriteShort(unsigned int off, unsigned short val)
-{
-#ifndef SAVE_DEBUG
- BYTE2_LE(Addr(off),val);
-#else
- unsigned char *addr=Addr(off);
- if(addr) BYTE2_LE(addr,val);
-#endif
-}
-
-void cST20::WriteByte(unsigned int off, unsigned char val)
-{
-#ifndef SAVE_DEBUG
- BYTE1_LE(Addr(off),val);
-#else
- unsigned char *addr=Addr(off);
- if(addr) BYTE1_LE(addr,val);
-#endif
-}
-
-#define OP_COL 20
-
-void cST20::LogOpOper(int op, int oper)
-{
- const static char *cmds[] = { "j","ldlp",0,"ldnl","ldc","ldnlp",0,"ldl","adc","call","cj","ajw","eqc","stl","stnl",0 };
- const static char flags[] = { 3, 0, 0, 0, 1, 0, 0, 0, 1, 3, 3, 0, 1, 0, 0, 0 };
- if(oper==0) loglb->Printf("%08X %02X",Iptr-1,op);
- else loglb->Printf("%02X",op);
- oper|=op&0xF; op>>=4;
- if(!cmds[op]) return;
- int n=loglb->Length();
- if(flags[op]&2) oper+=Iptr;
- if(flags[op]&1) loglb->Printf("%*s%-5s $%-8X ",max(OP_COL-n,1)," ",cmds[op],oper);
- else loglb->Printf("%*s%-5s %-8d ",max(OP_COL-n,1)," ",cmds[op],oper);
-}
-
-void cST20::LogOp(const char *op)
-{
- int n=loglb->Length();
- loglb->Printf("%*s%-15s ",max(OP_COL-n,1)," ",op);
-}
-
-int cST20::Decode(int count)
-{
- int operand;
- bool v=verbose;
- CLEAR_OP();
- while(Iptr!=0) {
- int a, op1=RB(Iptr++);
- if(v) LogOpOper(op1,operand);
- GET_OP();
- switch(op1>>4) {
- case 0x0: // j / jump
-#ifdef SAVE_DEBUG
- POP(); POP(); POP();
-#endif
- JUMP(operand);
- CLEAR_OP();
- break;
- case 0x1: // ldlp
- PUSH(Wptr+(operand*4));
- CLEAR_OP();
- break;
- case 0x2: // positive prefix
- operand<<=4;
- break;
- case 0x3: // ldnl
- AAA=RW(AAA+(operand*4));
- CLEAR_OP();
- break;
- case 0x4: // ldc
- PUSH(operand);
- CLEAR_OP();
- break;
- case 0x5: // ldnlp
- PUSHPOP(+,operand*4);
- CLEAR_OP();
- break;
- case 0x6: // negative prefix
- operand=(~operand)<<4;
- break;
- case 0x7: // ldl
- PUSH(RW(Wptr+(operand*4)));
- CLEAR_OP();
- break;
- case 0x8: // adc
- PUSHPOP(+,operand);
- CLEAR_OP();
- break;
- case 0x9: // call
- Wptr-=16;
- WW(Wptr,Iptr); WW(Wptr+4,POP()); WW(Wptr+8,POP()); WW(Wptr+12,POP());
- PUSH(Iptr);
- JUMP(operand);
- CLEAR_OP();
- break;
- case 0xA: // cj / conditional jump
- if(AAA) DROP(1); else JUMP(operand);
- CLEAR_OP();
- break;
- case 0xB: // ajw / adjust workspace
- Wptr+=operand*4;
- CLEAR_OP();
- break;
- case 0xC: // eqc / equals constant
- AAA=(operand==AAA ? 1 : 0);
- CLEAR_OP();
- break;
- case 0xD: // stl
- WW(Wptr+(operand*4),POP());
- CLEAR_OP();
- break;
- case 0xE: // stnl
- a=POP(); WW(a+(operand*4),POP());
- CLEAR_OP();
- break;
- case 0xF: // opr (secondary ins)
- switch(operand) {
- case 0x00: LOG_OP("rev"); a=AAA; AAA=BBB; BBB=a; break;
- case 0x01: LOG_OP("lb"); AAA=RB(AAA); break;
- case 0x02: LOG_OP("bsub"); PUSHPOP(+,POP()); break;
- case 0x04: LOG_OP("diff"); PUSHPOP(-,POP()); break;
- case 0x05: LOG_OP("add"); PUSHPOP(+,POP()); break;
- case 0x06: LOG_OP("gcall"); a=AAA; AAA=Iptr; Iptr=a; break;
- case 0x08: LOG_OP("prod"); PUSHPOP(*,POP()); break;
- case 0x09: LOG_OP("gt"); a=POP(); AAA=(AAA>a); break;
- case 0x0A: LOG_OP("wsub"); a=POP(); AAA=a+(AAA*4); break;
- case 0x0C: LOG_OP("sub"); PUSHPOP(-,POP()); break;
-
- case 0x1B: LOG_OP("ldpi"); PUSHPOP(+,Iptr); break;
- case 0x20: LOG_OP("ret"); Iptr=RW(Wptr); Wptr=Wptr+16; break;
- case 0x2C: LOG_OP("div"); PUSHPOP(/,POP()); break;
- case 0x32: LOG_OP("not"); AAA=~AAA; break;
- case 0x33: LOG_OP("xor"); PUSHPOP(^,POP()); break;
- case 0x34: LOG_OP("bcnt"); PUSHPOP(*,4); break;
- case 0x3B: LOG_OP("sb"); a=POP(); WriteByte(a,POP()); break;
- case 0x3F: LOG_OP("wcnt"); a=POP(); PUSH(a&3); PUSH((unsigned int)a>>2); break;
- case 0x40: LOG_OP("shr"); a=POP(); AAA=(unsigned int)AAA>>a; break;
- case 0x41: LOG_OP("shl"); a=POP(); AAA=(unsigned int)AAA<<a; break;
- case 0x42: LOG_OP("mint"); PUSH(MOSTNEG); break;
- case 0x46: LOG_OP("and"); PUSHPOP(&,POP()); break;
- case 0x4A: LOG_OP("move"); { a=POP(); int b=POP(); int c=POP(); while(a--) WriteByte(b++,ReadByte(c++)); } break;
- case 0x4B: LOG_OP("or"); PUSHPOP(|,POP()); break;
- case 0x53: LOG_OP("mul"); PUSHPOP(*,POP()); break;
- case 0x5A: LOG_OP("dup"); PUSH(AAA); break;
- case 0x5F: LOG_OP("gtu"); a=POP(); AAA=((unsigned int)AAA>(unsigned int)a); break;
- case 0x1D: LOG_OP("xdble"); CCC=BBB; BBB=(AAA>=0 ? 0:-1); break;
- case 0x1A: LOG_OP("ldiv"); { a=POP(); unsigned long long ll=POP64(); PUSH(ll%(unsigned int)a); PUSH(ll/(unsigned int)a); } break;
- case 0x1F: LOG_OP("rem"); PUSHPOP(%,POP()); break;
- case 0x35: LOG_OP("lshr"); { a=POP(); unsigned long long ll=POP64()>>a; PUSH((ll>>32)&0xFFFFFFFF); PUSH(ll&0xFFFFFFFF); } break;
-
- case 0xCA: LOG_OP("ls"); AAA=ReadShort(AAA); break;
- case 0xCD: LOG_OP("gintdis"); break;
- case 0xCE: LOG_OP("gintenb"); break;
-
- case -0x40: LOG_OP("nop"); break;
-
- default:
- if(verbose) PUTLB(L_SYS_DISASM,loglb);
- PRINTF(L_SYS_ST20,"unknown opcode %X",operand);
- return ERR_ILL_OP;
- }
- CLEAR_OP();
- break;
- }
-
- if(v && operand==0) {
- loglb->Printf("%08X %08X %08X W:%08X",AAA,BBB,CCC,Wptr);
- PUTLB(L_SYS_DISASM,loglb);
- }
- if(--count<=0 && operand==0) {
- PRINTF(L_SYS_ST20,"instruction counter exceeded");
- return ERR_CNT;
- }
- }
- return 0;
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __ST20_H
-#define __ST20_H
-
-class cLineBuff;
-
-// ----------------------------------------------------------------
-
-#define IPTR 0
-#define WPTR 1
-#define AREG 2
-#define BREG 3
-#define CREG 4
-
-#define FLASHS 0x7FE00000
-#define FLASHE 0x7FFFFFFF
-#define RAMS 0x40000000
-#define RAME 0x401FFFFF
-#define IRAMS 0x80000000
-#define IRAME 0x800017FF
-
-#define ERR_ILL_OP -1
-#define ERR_CNT -2
-
-// ----------------------------------------------------------------
-
-#define STACKMAX 16
-#define STACKMASK (STACKMAX-1)
-
-class cST20 {
-private:
- unsigned int Iptr, Wptr;
- unsigned char *flash, *ram;
- unsigned int flashSize, ramSize;
- int sptr, stack[STACKMAX];
- unsigned char iram[0x1800];
- int invalid;
- //
- bool verbose;
- cLineBuff *loglb;
- //
- unsigned char *Addr(unsigned int off);
- void LogOp(const char *op);
- void LogOpOper(int op, int oper);
-public:
- cST20(void);
- ~cST20();
- void Init(unsigned int IPtr, unsigned int WPtr);
- void SetCallFrame(unsigned int raddr, int p1, int p2, int p3);
- void SetFlash(unsigned char *m, int len);
- void SetRam(unsigned char *m, int len);
- int Decode(int count);
- //
- unsigned int GetReg(int reg) const;
- void SetReg(int reg, unsigned int val);
- unsigned int ReadWord(unsigned int off);
- unsigned short ReadShort(unsigned int off);
- unsigned char ReadByte(unsigned int off);
- void WriteWord(unsigned int off, unsigned int val);
- void WriteShort(unsigned int off, unsigned short val);
- void WriteByte(unsigned int off, unsigned char val);
- };
-
-#endif // __ST20_H
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <libsi/section.h>
-
-#include "viaccess.h"
-#include "log-viaccess.h"
-#include "tps.h"
-#include "opentv.h"
-#include "st20.h"
-
-#include "sc.h"
-#include "scsetup.h"
-#include "system-common.h"
-#include "filter.h"
-#include "misc.h"
-#include "helper.h"
-
-#define CHECK_TIME 5*60*1000
-#define LOADBIN_TIME 60*60*1000
-#define TPSAU_TIME 30*60*1000
-
-//#define TRUST_BOXTIME // should we trust the local time on this machine?
-//#define DUMP_TPSAU "/var/tmp"
-
-#ifdef DUMP_TPSAU
-#include <unistd.h>
-#endif
-
-// -- cRC6 ---------------------------------------------------------------------
-
-/*
- * This code implements the RC6-32/20 block cipher.
- *
- * The algorithm is due to Ron Rivest and RSA Labs. This code is based on code
- * which was written by Martin Hinner <mhi@penguin.cz> in 1999, no copyright is
- * claimed.
- */
-
-#define RC6_WORDSIZE 32
-#define RC6_P32 0xB7E15163L
-#define RC6_Q32 0x9E3779B9L
-
-unsigned int cRC6::rol(unsigned int v, unsigned int cnt)
-{
- cnt&=(RC6_WORDSIZE-1);
- return (v<<cnt) | (v>>(RC6_WORDSIZE-cnt));
-}
-
-unsigned int cRC6::ror(unsigned int v, unsigned int cnt)
-{
- cnt&=(RC6_WORDSIZE-1);
- return (v>>cnt) | (v<<(RC6_WORDSIZE-cnt));
-}
-
-void cRC6::SetKey(const unsigned char *Key, int len)
-{
- key[0]=RC6_P32;
- for(int v=1; v<RC6_MAX; v++) key[v]=key[v-1]+RC6_Q32;
- len/=4;
- unsigned int a=0, b=0, *l=AUTOARRAY(unsigned int,len);
- memcpy(l,Key,len*4);
- for(int i=0,j=0,v=3*(len>RC6_MAX ? len : RC6_MAX) ; v>0; v--) {
- a=key[i]=rol(key[i]+a+b,3);
- b= l[j]=rol( l[j]+a+b,a+b);
- i++; i%=RC6_MAX;
- j++; j%=len;
- }
-}
-
-void cRC6::Decrypt(unsigned char *data)
-{
- unsigned int *l=(unsigned int *)data;
- unsigned int a, b, c, d;
- a=l[0]-key[RC6_MAX-2];
- b=l[1];
- c=l[2]-key[RC6_MAX-1];
- d=l[3];
- for(int i=RC6_ROUNDS; i>0; i--) {
- unsigned int t=a;
- unsigned int u=b;
- a=d; d=c; b=t; c=u;
- u=rol((d*(2*d+1)),5);
- t=rol((b*(2*b+1)),5);
- c=ror(c-key[2*i+1],t)^u;
- a=ror(a-key[2*i ],u)^t;
- }
- l[0]=a;
- l[1]=b-key[0];
- l[2]=c;
- l[3]=d-key[1];
-}
-
-// -- cTransponderTime ---------------------------------------------------------
-
-class cTransponderTime : public cSimpleItem {
-private:
- time_t sattime;
- cTimeMs reftime;
- cMutex mutex;
- cCondVar wait;
- int source, transponder;
- bool hasHandler;
-public:
- cTransponderTime(int Source, int Transponder);
- bool Is(int Source, int Transponder) const;
- void Set(time_t st);
- time_t Now(void);
- void SetHasHandler(bool on) { hasHandler=on; }
- bool HasHandler(void) const { return hasHandler; }
- };
-
-cTransponderTime::cTransponderTime(int Source, int Transponder)
-{
- source=Source; transponder=Transponder;
-#ifdef TRUST_BOXTIME
- sattime=time(0);
-#else
- sattime=-1;
-#endif
- hasHandler=false;
-}
-
-bool cTransponderTime::Is(int Source, int Transponder) const
-{
- return source==Source && transponder==Transponder;
-}
-
-void cTransponderTime::Set(time_t st)
-{
- cMutexLock lock(&mutex);
- if(sattime<0 || reftime.Elapsed()>5*1000) {
- reftime.Set(-100);
- sattime=st;
- wait.Broadcast();
-
- char str[32];
- struct tm utm;
- st=Now();
- time_t now=time(0);
- gmtime_r(&st,&utm); asctime_r(&utm,str); stripspace(str);
- PRINTF(L_SYS_TIME,"%x:%x: %s (delta %ld)",source,transponder,str,st-now);
- }
-}
-
-time_t cTransponderTime::Now(void)
-{
- cMutexLock lock(&mutex);
- if(sattime<0) {
- if(!wait.TimedWait(mutex,3*1000)) {
- PRINTF(L_SYS_TIME,"%x:%x: unsuccessfull wait",source,transponder);
- return -1;
- }
- }
- return sattime+(reftime.Elapsed()/1000);
-}
-
-// -- cSatTimeHook -------------------------------------------------------------
-
-#ifndef TESTER
-
-class cSatTimeHook : public cLogHook {
-private:
- cTransponderTime *ttime;
-public:
- cSatTimeHook(cTransponderTime *Ttime);
- ~cSatTimeHook();
- virtual void Process(int pid, unsigned char *data);
- };
-
-cSatTimeHook::cSatTimeHook(cTransponderTime *Ttime)
-:cLogHook(HOOK_SATTIME,"sattime")
-{
- ttime=Ttime;
- pids.AddPid(0x14,0x71,0xff,0x03);
- ttime->SetHasHandler(true);
-}
-
-cSatTimeHook::~cSatTimeHook()
-{
- ttime->SetHasHandler(false);
-}
-
-void cSatTimeHook::Process(int pid, unsigned char *data)
-{
- if(data && ttime) {
- if(data[0]==0x70) { // TDT
- SI::TDT tdt(data,false);
- tdt.CheckParse();
- ttime->Set(tdt.getTime());
- }
- else if(data[0]==0x73) { // TOT
- SI::TOT tot(data,false);
- if(!tot.CheckCRCAndParse()) return;
- ttime->Set(tot.getTime());
- }
- }
-}
-
-#endif //TESTER
-
-// -- cSatTime -----------------------------------------------------------------
-
-class cSatTime {
-private:
- static cMutex mutex;
- static cSimpleList<cTransponderTime> list;
- //
- int cardNum;
- cTransponderTime *ttime;
- //
- void CheckHandler(void);
-public:
- cSatTime(int CardNum, int Source, int Transponder);
- time_t Now(void);
- };
-
-cMutex cSatTime::mutex;
-cSimpleList<cTransponderTime> cSatTime::list;
-
-cSatTime::cSatTime(int CardNum, int Source, int Transponder)
-{
- cardNum=CardNum;
- cMutexLock lock(&mutex);
- for(ttime=list.First(); ttime; ttime=list.Next(ttime))
- if(ttime->Is(Source,Transponder)) break;
- if(!ttime) {
- ttime=new cTransponderTime(Source,Transponder);
- if(ttime) list.Add(ttime);
- PRINTF(L_SYS_TIME,"%x:%x: created new transpondertime",Source,Transponder);
- }
- else PRINTF(L_SYS_TIME,"%x:%x: using existing transpondertime",Source,Transponder);
- CheckHandler();
-}
-
-time_t cSatTime::Now(void)
-{
- CheckHandler();
- return ttime ? ttime->Now() : -1;
-}
-
-void cSatTime::CheckHandler(void)
-{
- if(ttime) {
- if(!cSoftCAM::TriggerHook(cardNum,HOOK_SATTIME) && !ttime->HasHandler()) {
- cSatTimeHook *hook=new cSatTimeHook(ttime);
- cSoftCAM::AddHook(cardNum,hook);
- PRINTF(L_SYS_TIME,"added hook");
- }
- }
-}
-
-// -- cOpenTVModule ------------------------------------------------------------
-
-class cOpenTVModule {
-private:
- int id, modlen;
- unsigned char *mem;
- int received;
- info_header_t info;
- code_header_t code;
- data_header_t data;
- //
- bool Decompress(void);
- bool DoDecompress(unsigned char *out_ptr, const unsigned char *in_ptr, int dsize, int data_size, int usize);
- bool ParseSections(void);
- void Dump(void);
-public:
- cOpenTVModule(const unsigned char *data);
- cOpenTVModule(int Id, const unsigned char *data, int len);
- ~cOpenTVModule();
- int AddPart(const unsigned char *data, int len);
- const info_header_t *InfoHdr(void) const { return &info; }
- const code_header_t *CodeHdr(void) const { return &code; }
- const data_header_t *DataHdr(void) const { return &data; }
- //
- inline static int Id(const unsigned char *data) { return UINT16_BE(&data[3]); }
- inline static int Offset(const unsigned char *data) { return UINT32_BE(&data[16]); }
- inline static int Length(const unsigned char *data) { return UINT32_BE(&data[20]); }
- };
-
-cOpenTVModule::cOpenTVModule(const unsigned char *data)
-{
- id=Id(data); modlen=Length(data);
- received=0;
- mem=MALLOC(unsigned char,modlen);
-}
-
-cOpenTVModule::cOpenTVModule(int Id, const unsigned char *data, int len)
-{
- id=Id; modlen=received=len;
- mem=MALLOC(unsigned char,modlen);
- memcpy(mem,data,len);
- ParseSections();
-}
-
-cOpenTVModule::~cOpenTVModule()
-{
- free(mem);
-}
-
-int cOpenTVModule::AddPart(const unsigned char *data, int slen)
-{
- if(Id(data)==id) {
- int off=Offset(data);
- int mlen=Length(data);
- int rec=slen-28;
- if(mlen!=modlen || (off+rec)>mlen || !mem) {
- PRINTF(L_SYS_TPSAU,"length mismatch while adding to OpenTV module");
- return -1;
- }
- memcpy(&mem[off],data+24,rec);
- received+=rec;
- if(received==mlen) {
- if(!Decompress()) {
- PRINTF(L_SYS_TPSAU,"failed to decompress OpenTV module");
- return -1;
- }
- if(!ParseSections()) {
- PRINTF(L_SYS_TPSAU,"DATA & CODE section not located in OpenTV module");
- return -1;
- }
- Dump();
- return 1;
- }
- }
- return 0;
-}
-
-void cOpenTVModule::Dump(void)
-{
-#ifdef DUMP_TPSAU
-#warning Dumping TPS AU data
- {
- char fname[32];
- snprintf(fname,sizeof(fname),"%s/decomp.bin.%d.%x",DUMP_TPSAU,getpid(),(int)time(0));
- int fd=open(fname,O_CREAT|O_TRUNC|O_WRONLY,DEFFILEMODE);
- if(fd>=0) {
- write(fd,mem,modlen);
- close(fd);
- PRINTF(L_SYS_TPSAU,"dumped to file '%s'",fname);
- }
- }
-#endif
-}
-
-bool cOpenTVModule::ParseSections(void)
-{
- int sections=0;
- for(int idx=0; idx<modlen;) {
- unsigned int hdr=UINT32_BE(mem+idx);
- unsigned int s_len=UINT32_BE(mem+idx+4);
- switch(hdr) {
- case INFO_SECTION_HDR:
- info.magic=hdr;
- info.bsssize=UINT32_BE(mem+idx+8);
- info.stacksize=UINT32_BE(mem+idx+12);
- sections|=1;
- break;
- case CODE_SECTION_HDR:
- code.magic=hdr;
- code.size=s_len-8;
- code.m_id=UINT32_BE(mem+idx+8);
- code.entry_point=UINT16_BE(mem+idx+12);
- code.end=UINT16_BE(mem+idx+14);
- code.code=mem+idx+8;
- sections|=2;
- break;
- case DATA_SECTION_HDR:
- data.magic=hdr;
- data.dlen=s_len-8;
- data.data=mem+idx+8;
- sections|=4;
- break;
- case SWAP_SECTION_HDR:
- case GDBO_SECTION_HDR:
- break;
- case LAST_SECTION_HDR:
- case 0:
- idx=modlen;
- break;
- case COMP_SECTION_HDR:
- PRINTF(L_GEN_DEBUG,"OpenTV module still compressed in ParseSections()");
- return 0;
- default:
- PRINTF(L_SYS_TPSAU,"unknown section hdr %08x (%c%c%c%c) in OpenTV module",hdr,(hdr>>24)&0xFF,(hdr>>16)&0xFF,(hdr>>8)&0xFF,hdr&0xFF);
- break;
- }
- idx+=s_len;
- }
- return sections>=6;
-}
-
-bool cOpenTVModule::Decompress(void)
-{
- comp_header_t comp;
- comp.magic=UINT32_BE(mem);
- comp.csize=UINT32_BE(mem+4);
- comp.dsize=UINT32_BE(mem+8);
- comp.usize=UINT32_BE(mem+12);
- comp.end =UINT8_BE(mem+16);
- if((COMP_SECTION_HDR!=comp.magic) || (comp.dsize<=comp.csize) ||
- (comp.usize>comp.dsize) || (comp.end>=1) || (comp.csize<=17))
- return true;
- unsigned char *decomp=MALLOC(unsigned char,comp.dsize);
- if(!decomp || !DoDecompress(decomp,mem+17,comp.dsize,comp.csize-17,comp.usize))
- return false;
- free(mem);
- mem=decomp; modlen=comp.dsize;
- return true;
-}
-
-#define BYTE() ((odd)?((in_ptr[0]&0x0F)|(in_ptr[1]&0xF0)):in_ptr[0])
-
-#define NIBBLE(__v) \
- do { \
- odd^=1; \
- if(odd) __v=in_ptr[0]&0xF0; \
- else { __v=(in_ptr[0]&0xF)<<4; in_ptr++; } \
- } while(0)
-
-bool cOpenTVModule::DoDecompress(unsigned char *out_ptr, const unsigned char *in_ptr, int dsize, int data_size, int usize)
-{
- if(usize==0) return false;
- const unsigned char *data_start=in_ptr;
- unsigned char *out_start=out_ptr;
- unsigned char *out_end=out_ptr+usize;
- int odd=0;
- while(1) {
- unsigned char mask=BYTE(); in_ptr++;
- for(int cnt=8; cnt>0; mask<<=1,cnt--) {
- if(mask&0x80) {
- out_ptr[0]=BYTE(); in_ptr++;
- out_ptr++;
- }
- else {
- int off=0, len=0;
- unsigned char cmd=BYTE(); in_ptr++;
- switch(cmd>>4) {
- case 0x0:
- case 0x1:
- case 0x2:
- case 0x3:
- case 0x4:
- case 0x5:
- case 0x6:
- off=((cmd&0xF)<<8)+BYTE(); in_ptr++;
- len=((cmd>>4)&0x7)+3;
- break;
- case 0x7:
- {
- unsigned char high=BYTE(); in_ptr++;
- off=((high&0x7F)<<8)+BYTE(); in_ptr++;
- if((cmd==0x7F) && (high&0x80)) {
- len=BYTE(); in_ptr++;
- if(len==0xFF) {
- len=BYTE(); in_ptr++;
- len=((len<<8)+BYTE()+0x121)&0xFFFF; in_ptr++;
- }
- else len+=0x22;
- }
- else {
- len=((cmd&0x0F)<<1)+3; if(high&0x80) len++;
- }
- break;
- }
- case 0x8:
- case 0x9:
- case 0xA:
- case 0xB:
- if(cmd&0x20) NIBBLE(off); else off=0;
- off=(off<<1)|(cmd&0x1F); len=2;
- break;
- case 0xC:
- off=cmd&0x0F; len=3;
- break;
- case 0xD:
- case 0xE:
- case 0xF:
- NIBBLE(off);
- off|=cmd&0x0F; len=((cmd>>4)&0x3)+2;
- break;
- }
- const unsigned char *from=out_ptr-(off+1);
- if(from<out_start || from>=out_ptr || len>(out_end-out_ptr)) {
- PRINTF(L_SYS_TPSAU,"length mismatch in OpenTV decompress");
- return false;
- }
- while(--len>=0) *out_ptr++=*from++;
- }
- if(out_end<=out_ptr) {
- if(out_end!=out_ptr) {
- PRINTF(L_SYS_TPSAU,"pointer mismatch in OpenTV decompress");
- return false;
- }
- int len=out_start+dsize-out_ptr;
- if(len>0) memmove(out_ptr,data_start+(data_size-(dsize-usize)),len);
- return true;
- }
- }
- }
-}
-
-#undef BYTE
-#undef NIBBLE
-
-// -- cTpsKey ------------------------------------------------------------------
-
-cTpsKey::cTpsKey(void)
-{
- timestamp=0;
-}
-
-void cTpsKey::Set(const cTpsKey *k)
-{
- timestamp=k->timestamp;
- opmode=k->opmode;
- memcpy(step,k->step,sizeof(step));
-}
-
-void cTpsKey::Set(const unsigned char *mem)
-{
- timestamp=*((unsigned int *)mem);
- opmode=mem[52+3];
- for(int i=0; i<3; i++) {
- memcpy(step[i].key,&mem[4+i*16],16);
- step[i].mode=mem[52+i];
- }
-}
-
-void cTpsKey::Put(unsigned char *mem) const
-{
- *((unsigned int *)mem)=timestamp;
- mem[52+3]=opmode;
- for(int i=0; i<3; i++) {
- memcpy(&mem[4+i*16],step[i].key,16);
- mem[52+i]=step[i].mode;
- }
-}
-
-cString cTpsKey::ToString(bool hide)
-{
- unsigned char tmp[60];
- Put(&tmp[4]);
- *((unsigned int *)tmp)=crc32_le(0,&tmp[4],sizeof(tmp)-4);
- char str[420];
- HexStr(str,tmp,sizeof(tmp));
- return str;
-}
-
-// -- cTpsAuHook ---------------------------------------------------------------
-
-#ifndef TESTER
-
-#define BUFF_SIZE 20000
-
-class cTpsAuHook : public cLogHook {
-private:
- cOpenTVModule *mod;
- int pmtpid, aupid;
-public:
- cTpsAuHook(void);
- ~cTpsAuHook();
- virtual void Process(int pid, unsigned char *data);
- };
-
-#endif //TESTER
-
-// -- cTpsKeys -----------------------------------------------------------------
-
-cTpsKeys tpskeys;
-
-cTpsKeys::cTpsKeys(void)
-:cStructListPlain<cTpsKey>("TPS keys","tps.cache",SL_READWRITE|SL_MISSINGOK|SL_WATCH|SL_NOPURGE)
-,lastLoad(-LOADBIN_TIME)
-,lastAu(-TPSAU_TIME)
-{
- first=last=0; algomem=0; loadlist=0;
-}
-
-cTpsKeys::~cTpsKeys()
-{
- free(algomem);
- delete loadlist;
-}
-
-const cTpsKey *cTpsKeys::GetKey(time_t t)
-{
- ListLock(false);
- cTpsKey *k;
- for(k=First(); k; k=Next(k)) if(t<k->Timestamp()) break;
- ListUnlock();
- return k;
-}
-
-const cTpsKey *cTpsKeys::GetV2Key(int id)
-{
- unsigned char tmp[56];
- memset(tmp,0,sizeof(tmp));
- cPlainKey *pk=keys.FindKey('V',id,MBC3('T','P','S'),16,0);
- if(pk) {
- pk->Get(&tmp[4+2*16]);
- tmp[52+2]=1;
- tmp[52+3]=0x1C;
- cTpsKey *tk=new cTpsKey;
- if(tk) {
- tk->Set(tmp);
- return tk;
- }
- }
- else PRINTF(L_SYS_KEY,"missing %.4x TPS key\n",id);
- return 0;
-}
-
-void cTpsKeys::Check(time_t now, int cardnum)
-{
- checkMutex.Lock();
- if(first==0 && last==0 && Count()>0)
- GetFirstLast();
- if(now>0 && lastCheck.Elapsed()>CHECK_TIME) {
- Purge(now);
- lastCheck.Set();
- }
- bool nokey=now+2*3600>last;
-/*
- if(lastLoad.Elapsed()>(nokey ? LOADBIN_TIME/60 : LOADBIN_TIME)) {
- PRINTF(L_SYS_TPSAU,"loading "TPSBIN" triggered");
- LoadBin();
- if(now>0) Purge(now);
- lastLoad.Set();
- }
-*/
- if(lastAu.Elapsed()>(nokey ? TPSAU_TIME/60 : TPSAU_TIME)) {
- if(ScSetup.AutoUpdate>0) {
- PRINTF(L_SYS_TPSAU,"TPS AU triggered");
- if(!cSoftCAM::TriggerHook(cardnum,HOOK_TPSAU)) {
- cTpsAuHook *hook=new cTpsAuHook;
- cSoftCAM::AddHook(cardnum,hook);
- PRINTF(L_SYS_TPSAU,"TPS AU hook added");
- }
- }
- lastAu.Set();
- }
- checkMutex.Unlock();
-}
-
-void cTpsKeys::Purge(time_t now)
-{
- PRINTF(L_SYS_TPSAU,"purging TPS keylist");
- bool del=false;
- ListLock(true);
- for(cTpsKey *k=First(); k;) {
- cTpsKey *n=Next(k);
- if(k->Timestamp()<now-3600) { Del(k); del=true; }
- k=n;
- }
- ListUnlock();
- if(del) {
- GetFirstLast();
- Modified();
- }
-}
-
-void cTpsKeys::Join(cSimpleList<cTpsKey> *nlist)
-{
- ListLock(true);
- cTpsKey *k;
- while((k=nlist->First())) {
- nlist->Del(k,false);
- cTpsKey *p=First();
- do {
- if(!p) {
- Add(k);
- Modified();
- break;
- }
- cTpsKey *n=Next(p);
- if(k->Timestamp()==p->Timestamp()) {
- p->Set(k);
- Modified();
- delete k;
- break;
- }
- if(k->Timestamp()>p->Timestamp() && (!n || k->Timestamp()<n->Timestamp())) {
- Add(k,p);
- Modified();
- break;
- }
- p=n;
- } while(p);
- }
- ListUnlock();
- delete nlist;
- GetFirstLast();
-}
-
-cString cTpsKeys::Time(time_t t)
-{
- char str[32];
- struct tm tm_r;
- strftime(str,sizeof(str),"%b %e %T",localtime_r(&t,&tm_r));
- return str;
-}
-
-void cTpsKeys::GetFirstLast(void)
-{
- if(Count()>0) {
- ListLock(false);
- cTpsKey *k=First();
- first=last=k->Timestamp();
- for(; k; k=Next(k)) {
- if(k->Timestamp()<last)
- PRINTF(L_SYS_TPSAU,"TPS keys not in accending order!");
- last=k->Timestamp();
- }
- PRINTF(L_SYS_TPS,"%d TPS keys available (from %s to %s)",Count(),*Time(first),*Time(last));
- ListUnlock();
- }
- else {
- last=first=0;
- PRINTF(L_SYS_TPS,"no TPS keys available");
- }
-}
-
-bool cTpsKeys::ProcessAu(const cOpenTVModule *mod)
-{
- PRINTF(L_SYS_TPSAU,"processing TPS AU data");
-
- const code_header_t *codehdr=mod->CodeHdr();
- const data_header_t *datahdr=mod->DataHdr();
- const unsigned char *c=codehdr->code;
- const unsigned char *d=datahdr->data;
- unsigned int kd=0, cb1=0, cb2=0, cb3=0;
- for(unsigned int i=0; i<codehdr->size; i++) {
- if(c[i]==0x81) { // PushEA DS:$xxxx
- unsigned int addr=(c[i+1]<<8)|c[i+2];
- if(addr<(datahdr->dlen-3)) {
- if(d[addr]==0x79 && d[addr+1]==0x00 && d[addr+2]==0x79 && d[addr+3]==0x00)
- kd=addr;
-//XXX this needs proper fix sometime...
- else if(d[addr+1]==0x00 && d[addr+3]==0x00 && (d[addr+4]==3||d[addr+4]==2))
- kd=addr;
-//XXX
- else if(d[addr]==0x73 && d[addr+1]==0x25 && d[addr+2]==0xFA)
- cb1=addr;
- else if(d[addr]==0x64 && (d[addr+1]&0xB0)==0xB0 && d[addr+2]==0x24)
- cb2=addr;
- else if((d[addr]&0x60)==0x60 && (d[addr+1]&0xB0)==0xB0 && (d[addr+2]&0x20)==0x20)
- cb3=addr;
-/*
- else if(d[addr]==0x73 && d[addr+1]==0x25) {
- static const unsigned char scan1[] = { 0x28, 0x20, 0x20, 0xC0 };
- for(int j=2; j < 0xC; j++)
- if(!memcmp(&d[addr+j],scan1,sizeof(scan1))) { cb1=addr; break; }
- }
- else if(cb1 && !cb2) cb2=addr;
- else if(cb1 && cb2 && !cb3) cb3=addr;
-*/
- }
- }
- }
- if(!kd || !cb1 || !cb2 || !cb3) {
- PRINTF(L_SYS_TPSAU,"couldn't locate all pointers in data section (%d,%d,%d,%d)",kd,cb1,cb2,cb3);
- return false;
- }
-
- unsigned int end=(kd>cb1 && kd>cb2 && kd>cb3) ? kd : datahdr->dlen;
- unsigned int off=min(cb1,min(cb2,cb3))-2;
- PRINTF(L_SYS_TPSAU,"pointers in data section kd=%d cb1=%d cb2=%d cb3=%d - dlen=%d off=%d end=%d - cb1=%d cb2=%d cb3=%d",kd,cb1,cb2,cb3,datahdr->dlen,off,end,cb1-off,cb2-off,cb3-off);
- RegisterAlgo3(d+off,cb1-off,cb2-off,cb3-off,end-off);
-
- const unsigned char *data=&d[kd];
- int seclen, numkeys;
- seclen=data[0] | (data[1]<<8);
- numkeys=data[2] | (data[3]<<8);
- int algo=data[4];
- int mkidx=data[5]&7;
- unsigned char *sec[7];
- sec[0]=(unsigned char *)data+6;
- for(int i=1; i<6; i++) sec[i]=sec[i-1]+seclen;
- sec[6]=sec[5]+numkeys;
- unsigned char key[16];
- cPlainKey *pk=keys.FindKey('V',0x7c00,MBC3('M','K',mkidx),16);
- if(!pk) {
- PRINTF(L_SYS_KEY,"missing V 7C00 TPSMK%d key",mkidx);
- return false;
- }
- pk->Get(key);
-
- if(sec[6]>=d+datahdr->dlen) {
- PRINTF(L_SYS_TPSAU,"section 5 exceeds buffer");
- return false;
- }
- int keylen=0;
- for(int i=0; i<numkeys; i++) keylen+=sec[5][i];
- keylen=(keylen+15)&~15;
- if(sec[6]+keylen>=d+datahdr->dlen) {
- PRINTF(L_SYS_TPSAU,"section 6 exceeds buffer");
- return false;
- }
- for(int i=0; i<keylen; i+=16) TpsDecrypt(&sec[6][i],algo,key);
-
- cSimpleList<cTpsKey> *nlist=new cSimpleList<cTpsKey>;
- for(int i=0; i<seclen; i++) {
- static const unsigned char startkey[] = { 0x01,0x01 };
- static const unsigned char startaes[] = { 0x09,0x10 };
- static const unsigned char startse[] = { 0x0a,0x10 };
- unsigned char tmp[56];
- tmp[0]=sec[0][i];
- tmp[1]=sec[1][i];
- tmp[2]=sec[2][i];
- tmp[3]=sec[3][i];
- if(CheckFF(tmp,4)) continue;
- int keyid=sec[4][i];
- int keylen=sec[5][keyid];
- if(keylen<32) continue;
- const unsigned char *tkey=sec[6];
- for(int j=0; j<keyid; j++) tkey+=sec[5][j];
-
- unsigned char ke[128];
- if(keylen!=45) {
- if(!Handle80008003(tkey,keylen,ke)) continue;
- tkey=ke;
- }
-
- if(memcmp(tkey,startkey,sizeof(startkey))) continue;
- tmp[52]=0;
- tmp[53]=tkey[5]; //tkey[4];
- tmp[54]=1; //tkey[5];
- tmp[55]=0x1c;
- tkey+=9;
- if(memcmp(tkey,startaes,sizeof(startaes))) continue;
- memset(&tmp[4+ 0],0,16);
- memcpy(&tmp[4+16],&tkey[2],16);
- tkey+=18;
- if(memcmp(tkey,startse,sizeof(startse))) continue;
- memcpy(&tmp[4+32],&tkey[2],16);
- cTpsKey *k=new cTpsKey;
- if(k) { k->Set(tmp); nlist->Add(k); }
- }
- PRINTF(L_SYS_TPSAU,"got %d keys from AU data",nlist->Count());
- bool res=nlist->Count()>0;
- Join(nlist);
- return res;
-}
-
-/*
-bool cTpsKeys::LoadBin(void)
-{
- static const unsigned char mark[] = { 'T','P','S',0 };
- cFileMap *tpsbin=filemaps.GetFileMap(TPSBIN,FILEMAP_DOMAIN,false);
- if(!tpsbin) {
- PRINTF(L_SYS_TPS,"no filemap for "TPSBIN);
- return false;
- }
- else if(!tpsbin->Map()) {
- PRINTF(L_SYS_TPS,"mapping failed for "TPSBIN);
- return false;
- }
- else if(tpsbin->Size()<65536 || memcmp(mark,tpsbin->Addr()+32,sizeof(mark)) || memcmp(mark,tpsbin->Addr()+48,sizeof(mark))) {
- PRINTF(L_SYS_TPS,TPSBIN" format not recognised");
- tpsbin->Unmap();
- return false;
- }
-
- int size=tpsbin->Size()-56;
- cSimpleList<cTpsKey> *nlist=new cSimpleList<cTpsKey>;
- for(int i=68; i<size; i+=56) {
- const unsigned char *a=tpsbin->Addr()+i;
- if(*((const unsigned int *)a)==0x00000000L || *((const unsigned int *)a)==0xFFFFFFFFL)
- break;
- unsigned char tmp[56];
- DecryptBin(a,tmp);
- cTpsKey *k=new cTpsKey;
- if(k) { k->Set(tmp); nlist->Add(k); }
- }
- tpsbin->Unmap();
- PRINTF(L_SYS_TPSAU,"loaded %d keys from "TPSBIN" file",nlist->Count());
- Join(nlist);
- return true;
-}
-
-void cTpsKeys::DecryptBin(const unsigned char *in, unsigned char *out)
-{
- unsigned int var2=*((unsigned int *)in);
- *((unsigned int *)out)=var2;
- for(int i=0; i<13; i++) {
- in+=4; out+=4;
- var2=(var2<<3) | (var2>>(32-3));
- unsigned int var1=*((unsigned int *)in) ^ var2;
- *((unsigned int *)out)=(var1<<(i+2)) | (var1>>(32-(i+2)));
- }
-}
-*/
-
-void cTpsKeys::PreLoad(void)
-{
- delete loadlist;
- loadlist=new cSimpleList<cTpsKey>;
- if(!loadlist) PRINTF(L_SYS_TPS,"no memory for loadlist");
-}
-
-void cTpsKeys::PostLoad(void)
-{
- if(loadlist) { Join(loadlist); loadlist=0; }
-}
-
-bool cTpsKeys::ParseLinePlain(const char *line)
-{
- unsigned char tmp[60];
- if(line[0]=='X') {
- if(line[1]=='S') {
- if(algomem) PRINTF(L_SYS_TPS,"multiple start extentions during cache load");
- if(sscanf(&line[2],"%x %x %x %x",&algolen,&cb1off,&cb2off,&cb3off)==4) {
- free(algomem);
- if((algomem=MALLOC(unsigned char,algolen))) {
- algoread=0;
- return true;
- }
- else PRINTF(L_SYS_TPS,"no memory for algo");
- }
- else PRINTF(L_SYS_TPS,"bad format in start extention");
- }
- else if(line[1]=='C') {
- if(algomem) {
- int off, len;
- unsigned int crc;
- if(sscanf(&line[2],"%x %x %n",&off,&crc,&len)==2) {
- line+=len+2;
- unsigned char buff[210];
- if((len=GetHex(line,buff,200,false))) {
- if(crc==crc32_le(0,buff,len) && off>=0 && off+len<=algolen) {
- memcpy(&algomem[off],buff,len);
- algoread+=len;
- if(algoread==algolen) {
- RegisterAlgo3(algomem,cb1off,cb2off,cb3off,algolen);
- free(algomem); algomem=0;
- }
- return true;
- }
- }
- }
- PRINTF(L_SYS_TPS,"bad format in code extention");
- }
- else PRINTF(L_SYS_TPS,"unexpected code extention");
- }
- else PRINTF(L_SYS_TPS,"unknown extention during cache load");
- }
- else {
- if(GetHex(line,tmp,sizeof(tmp))) {
- unsigned int crc=crc32_le(0,&tmp[4],sizeof(tmp)-4);
- if(*((unsigned int *)tmp)==crc) {
- cTpsKey *k=new cTpsKey;
- if(k) { k->Set(&tmp[4]); if(loadlist) loadlist->Add(k); }
- return true;
- }
- else PRINTF(L_SYS_TPS,"CRC failed during cache load");
- }
- }
- return false;
-}
-
-void cTpsKeys::PostSave(FILE *f)
-{
- char str[420];
- unsigned char *mem;
- int len=0, cb1=0, cb2=0, cb3=0;
- if((mem=DumpAlgo3(len,cb1,cb2,cb3))) {
- fprintf(f,"XS %04X %04X %04X %04X\n",len,cb1,cb2,cb3);
- for(int i=0; i<len; i+=200) {
- int l=min(200,len-i);
- fprintf(f,"XC %04X %08X %s\n",i,crc32_le(0,&mem[i],l),HexStr(str,&mem[i],l));
- }
- free(mem);
- }
-}
-
-// -- cTpsAuHook ---------------------------------------------------------------
-
-#ifndef TESTER
-
-#define AUSID 0x12C0
-
-cTpsAuHook::cTpsAuHook(void)
-:cLogHook(HOOK_TPSAU,"tpsau")
-{
- mod=0; pmtpid=aupid=-1;
- pids.AddPid(0x0000,0x00,0xff); // PAT
-}
-
-cTpsAuHook::~cTpsAuHook()
-{
- delete mod;
-}
-
-void cTpsAuHook::Process(int pid, unsigned char *data)
-{
- if(data) {
- if(pid==0) { // PAT
- SI::PAT pat(data,false);
- if(pat.CheckCRCAndParse()) {
- SI::PAT::Association assoc;
- for(SI::Loop::Iterator it; pat.associationLoop.getNext(assoc,it);) {
- if(!assoc.isNITPid() && assoc.getServiceId()==AUSID) {
- pmtpid=assoc.getPid();
- PRINTF(L_SYS_TPSAU,"got PMT pid %04x for SID %04x",pmtpid,AUSID);
- cPid *pid=pids.First();
- if(pid && pid->filter) {
- pid->filter->Start(pmtpid,0x02,0xFF,0x00,false);
- pid->filter->Flush();
- }
- else PRINTF(L_GEN_DEBUG,"internal: no pid/filter in cTpsAuHook/pat");
- return;
- }
- }
- PRINTF(L_SYS_TPSAU,"no PMT pid found for SID %04x",AUSID);
- BailOut();
- }
- }
- else if(pid==pmtpid) { // PMT
- SI::PMT pmt(data,false);
- if(pmt.CheckCRCAndParse() && pmt.getServiceId()==AUSID) {
- SI::PMT::Stream stream;
- for(SI::Loop::Iterator it; pmt.streamLoop.getNext(stream,it); ) {
- if(stream.getStreamType()==0x05) {
- aupid=stream.getPid();
- PRINTF(L_SYS_TPSAU,"got AU pid %04x",aupid);
- cPid *pid=pids.First();
- if(pid && pid->filter) {
- pid->filter->Start(aupid,0x87,0xFF,0x00,false);
- pid->filter->Flush();
- }
- else PRINTF(L_GEN_DEBUG,"internal: no pid/filter in cTpsAuHook/pmt");
- return;
- }
- }
- PRINTF(L_SYS_TPSAU,"could not locate AU pid in PMT %04x data",pmtpid);
- BailOut();
- }
- }
- else if(pid==aupid) {
- if(cOpenTVModule::Id(data)==2) {
- if(!mod) mod=new cOpenTVModule(data);
- if(mod) {
- int r=mod->AddPart(data,SCT_LEN(data));
- if(r>0) {
- PRINTF(L_SYS_TPSAU,"received complete OpenTV module ID 2");
- if(tpskeys.ProcessAu(mod)) BailOut();
- r=-1;
- }
- if(r<0) { delete mod; mod=0; }
- }
- }
- }
- }
-}
-
-#endif //TESTER
-
-// -- cTPSDecrypt --------------------------------------------------------------
-
-unsigned char *cTPSDecrypt::mem=0;
-int cTPSDecrypt::memLen=0;
-int cTPSDecrypt::cb1off=0;
-int cTPSDecrypt::cb2off=0;
-int cTPSDecrypt::cb3off=0;
-cMutex cTPSDecrypt::st20Mutex;
-cST20 cTPSDecrypt::st20;
-bool cTPSDecrypt::st20Inited=false;
-
-void cTPSDecrypt::TpsDecrypt(unsigned char *data, short mode, const unsigned char *key)
-{
- switch(mode) {
- case 0: break;
- case 1: cAES::SetKey(key); cAES::Decrypt(data,16); break;
- case 2: cRC6::SetKey(key,16); cRC6::Decrypt(data); break;
- case 3: if(mem) {
- if(!DecryptAlgo3(key,data))
- PRINTF(L_SYS_TPS,"decrypt failed in algo 3");
- }
- else PRINTF(L_SYS_TPS,"no callbacks for algo 3 registered");
- break;
- default: PRINTF(L_SYS_TPS,"unknown TPS decryption algo %d",mode); break;
- }
-}
-
-bool cTPSDecrypt::RegisterAlgo3(const unsigned char *data, int cb1, int cb2, int cb3, int len)
-{
- cMutexLock lock(&st20Mutex);
- free(mem);
- if(!(mem=MALLOC(unsigned char,len))) return false;
- memcpy(mem,data,len);
- memLen=len; cb1off=cb1; cb2off=cb2; cb3off=cb3;
- st20Inited=false;
- PRINTF(L_SYS_TPSAU,"registered callbacks for algo 3");
- return true;
-}
-
-unsigned char *cTPSDecrypt::DumpAlgo3(int &len, int &cb1, int &cb2, int &cb3)
-{
- cMutexLock lock(&st20Mutex);
- if(!mem) return 0;
- unsigned char *buff=MALLOC(unsigned char,memLen);
- if(!buff) return 0;
- memcpy(buff,mem,memLen);
- len=memLen; cb1=cb1off; cb2=cb2off; cb3=cb3off;
- return buff;
-}
-
-bool cTPSDecrypt::InitST20(void)
-{
- if(!mem) return false;
- if(!st20Inited) {
- st20.SetFlash(mem,memLen);
- st20.SetRam(NULL,0x10000);
- st20Inited=true;
- }
- return true;
-}
-
-bool cTPSDecrypt::Handle80008003(const unsigned char *src, int len, unsigned char *dest)
-{
- cMutexLock lock(&st20Mutex);
- if(cb1off && InitST20()) {
- for(int i=0; i<len; i++) st20.WriteByte(RAMS+0x400+i,src[i]);
- st20.WriteShort(RAMS+0x0,0x8000);
- st20.WriteShort(RAMS+0x2,0x8003);
- st20.WriteWord(RAMS+0x8,RAMS+0x400);
- st20.Init(FLASHS+cb1off,RAMS+0xF000);
- st20.SetCallFrame(0,RAMS,0,0);
- int err=st20.Decode(1000);
- if(err<0) {
- PRINTF(L_SYS_TPSAU,"ST20 processing failed in callback1 (%d)",err);
- return false;
- }
- for(int i=0; i<0x2D; i++) dest[i]=st20.ReadByte(RAMS+0x400+i);
- return true;
- }
- return false;
-}
-
-bool cTPSDecrypt::DecryptAlgo3(const unsigned char *key, unsigned char *data)
-{
- cMutexLock lock(&st20Mutex);
- if(cb2off && cb3off && InitST20()) {
- for(int i=0; i<16; i++) st20.WriteByte(RAMS+0x400+i,key[i]);
- st20.Init(FLASHS+cb2off,RAMS+0xF000);
- st20.SetCallFrame(0,RAMS+0x400,RAMS+0x800,0);
- int err=st20.Decode(30000);
- if(err<0) {
- PRINTF(L_SYS_TPS,"ST20 processing failed in callback2 (%d)",err);
- return false;
- }
-
- for(int i=0; i<16; i++) st20.WriteByte(RAMS+0x400+i,data[i]);
- st20.Init(FLASHS+cb3off,RAMS+0xF000);
- st20.SetCallFrame(0,RAMS+0x400,RAMS+0x1000,RAMS+0x800);
- err=st20.Decode(40000);
- if(err<0) {
- PRINTF(L_SYS_TPS,"ST20 processing failed in callback3 (%d)",err);
- return false;
- }
- for(int i=0; i<16; i++) data[i]=st20.ReadByte(RAMS+0x1000+i);
- return true;
- }
- return false;
-}
-
-// -- cTPS ---------------------------------------------------------------------
-
-cTPS::cTPS(void)
-{
- sattime=0;
-}
-
-cTPS::~cTPS()
-{
- delete sattime;
-}
-
-int cTPS::Decrypt(int cardNum, int Source, int Transponder, unsigned char *data, int len)
-{
- if(!sattime) {
- sattime=new cSatTime(cardNum,Source,Transponder);
- if(!sattime) {
- PRINTF(L_SYS_TPS,"failed to create time class");
- return -1;
- }
- }
- time_t now=sattime->Now();
- tpskeys.Check(now,cardNum);
- if(now<0) return -1;
-
- const cTpsKey *k=tpskeys.GetKey(now);
- doPost=0;
- int opmode=k?k->Opmode():4, doTPS=0, doPre=0, hasDF=0, ret=0;
- if((opmode&4) && data[0]==0xD2 && data[1]==0x01 && data[2]==0x01) {
- data+=3; len-=3; ret=3;
- if(data[0]==0x90) PRINTF(L_SYS_TPS,"TPS v1 is no longer supported");
- if(data[0]==0x40) data[0]=0x90;
- doTPS=1;
- if(!k) k=tpskeys.GetV2Key(0x7c00);
- }
- for(int i=0; i<len; i+=data[i+1]+2) {
- if(!k && (doTPS || doPre || doPost)) {
- PRINTF(L_SYS_TPS,"no TPS key available for current time of day");
- return -1;
- }
- switch(data[i]) {
- case 0xDF:
- if(!(opmode&4)) doTPS =(0x6996>>((data[i+2]&0xF)^(data[i+2]>>4)))&1;
- if(opmode&8) doPre =(0x6996>>((data[i+3]&0xF)^(data[i+3]>>4)))&1;
- if(opmode&16) doPost=(0x6996>>((data[i+4]&0xF)^(data[i+4]>>4)))&1;
- hasDF=1;
- break;
- case 0xEA:
- if(doPre) TpsDecrypt(&data[i+2],k->Mode(0),k->Key(0));
- if(doTPS) TpsDecrypt(&data[i+2],(hasDF)?k->Mode(2):1,k->Key(2));
- if(doPost) { postMode=k->Mode(1); memcpy(postKey,k->Key(1),sizeof(postKey)); }
- break;
- }
- }
- return ret;
-}
-
-void cTPS::PostProc(unsigned char *cw)
-{
- if(doPost) TpsDecrypt(cw,postMode,postKey);
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __VIACCESS_TPS_H
-#define __VIACCESS_TPS_H
-
-#include <time.h>
-#include <vdr/tools.h>
-#include <vdr/thread.h>
-#include "data.h"
-#include "crypto.h"
-
-class cSatTime;
-class cTpsAuHook;
-class cOpenTVModule;
-class cST20;
-
-// ----------------------------------------------------------------
-
-#define RC6_ROUNDS 20
-#define RC6_MAX (RC6_ROUNDS*2+4)
-
-class cRC6 {
-private:
- unsigned int key[RC6_MAX];
- //
- unsigned int rol(unsigned int v, unsigned int cnt);
- unsigned int ror(unsigned int v, unsigned int cnt);
-public:
- void SetKey(const unsigned char *Key, int len);
- void Decrypt(unsigned char *data);
- };
-
-// ----------------------------------------------------------------
-
-class cTPSDecrypt : private cAES, private cRC6 {
-private:
- static unsigned char *mem;
- static int memLen, cb1off, cb2off, cb3off;
- static cMutex st20Mutex;
- static cST20 st20;
- static bool st20Inited;
- //
- static bool InitST20(void);
- static bool DecryptAlgo3(const unsigned char *key, unsigned char *data);
-protected:
- void TpsDecrypt(unsigned char *data, short mode, const unsigned char *key);
- static bool RegisterAlgo3(const unsigned char *data, int cb1, int cb2, int cb3, int len);
- static unsigned char *DumpAlgo3(int &len, int &cb1, int &cb2, int &cb3);
- static bool Handle80008003(const unsigned char *src, int len, unsigned char *dest);
- };
-
-// ----------------------------------------------------------------
-
-class cTPS : private cTPSDecrypt {
-private:
- cSatTime *sattime;
- int doPost;
- short postMode;
- unsigned char postKey[16];
-public:
- cTPS(void);
- ~cTPS();
- int Decrypt(int cardNum, int Source, int Transponder, unsigned char *data, int len);
- void PostProc(unsigned char *cw);
- };
-
-// ----------------------------------------------------------------
-
-class cTpsKey : public cStructItem {
-private:
- time_t timestamp;
- int opmode;
- struct {
- unsigned char mode;
- unsigned char key[16];
- } step[3];
- //
- void Put(unsigned char *mem) const;
-public:
- cTpsKey(void);
- const unsigned char *Key(int st) const { return step[st].key; }
- int Mode(int st) const { return step[st].mode; }
- int Opmode(void) const { return opmode; }
- time_t Timestamp(void) const { return timestamp; }
- void Set(const cTpsKey *k);
- void Set(const unsigned char *mem);
- virtual cString ToString(bool hide=false);
- };
-
-// ----------------------------------------------------------------
-
-class cTpsKeys : public cStructListPlain<cTpsKey>, private cTPSDecrypt {
-friend class cTpsAuHook;
-private:
- time_t first, last;
- cSimpleList<cTpsKey> *loadlist;
- //
- cTimeMs lastCheck, lastLoad, lastAu;
- cMutex checkMutex;
- //
- unsigned char *algomem;
- int algolen, algoread, cb1off, cb2off, cb3off;
- //
- void Join(cSimpleList<cTpsKey> *nlist);
- void Purge(time_t now);
- void GetFirstLast(void);
-// bool LoadBin(void);
-// void DecryptBin(const unsigned char *in, unsigned char *out);
- cString Time(time_t t);
- bool ProcessAu(const cOpenTVModule *mod);
-protected:
- virtual bool ParseLinePlain(const char *line);
- virtual void PreLoad(void);
- virtual void PostLoad(void);
- virtual void PostSave(FILE *f);
-public:
- cTpsKeys(void);
- ~cTpsKeys();
- const cTpsKey *GetKey(time_t t);
- const cTpsKey *GetV2Key(int id);
- void Check(time_t now, int cardnum);
- };
-
-extern cTpsKeys tpskeys;
-
-#endif
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "system-common.h"
-#include "misc.h"
-#include "parse.h"
-#include "log-core.h"
-
-#include "viaccess.h"
-#include "tps.h"
-#include "log-viaccess.h"
-
-#define SYSTEM_NAME "Viaccess"
-#define SYSTEM_PRI -10
-#define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_VIACCESS)
-
-static const struct LogModule lm_sys = {
- (LMOD_ENABLE|L_SYS_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_SYS_DEFDEF|L_SYS_TPS|L_SYS_TPSAU|L_SYS_TIME|L_SYS_ST20)&LOPT_MASK,
- "viaccess",
- { L_SYS_DEFNAMES,"tps","tpsau","time","st20","disasm" }
- };
-ADD_MODULE(L_SYS,lm_sys)
-
-// -- cPlainKeyVia -------------------------------------------------------------
-
-#define VIA1_KEYLEN 8
-#define VIA2_KEYLEN 16
-#define VIATPS_KEYLEN 16
-
-class cPlainKeyVia : public cPlainKeyStd {
-protected:
- virtual int IdSize(void) { return 6; }
- virtual cString PrintKeyNr(void);
-public:
- cPlainKeyVia(bool Super);
- virtual bool Parse(const char *line);
- virtual bool SetKey(void *Key, int Keylen);
- virtual bool SetBinKey(unsigned char *Mem, int Keylen);
- };
-
-static cPlainKeyTypeReg<cPlainKeyVia,'V'> KeyReg;
-
-cPlainKeyVia::cPlainKeyVia(bool Super)
-:cPlainKeyStd(Super)
-{}
-
-bool cPlainKeyVia::SetKey(void *Key, int Keylen)
-{
- if(keynr==MBC3('T','P','S')) SetSupersede(false);
- return cPlainKeyStd::SetKey(Key,Keylen);
-}
-
-bool cPlainKeyVia::SetBinKey(unsigned char *Mem, int Keylen)
-{
- if(keynr==MBC3('T','P','S')) SetSupersede(false);
- return cPlainKeyStd::SetBinKey(Mem,Keylen);
-}
-
-bool cPlainKeyVia::Parse(const char *line)
-{
- unsigned char sid[3], skeynr, skey[VIA2_KEYLEN];
- int len;
- if(GetChar(line,&type,1) && (len=GetHex(line,sid,3,false))) {
- type=toupper(type); id=Bin2Int(sid,len);
- line=skipspace(line);
- bool ok=false;
- if(!strncasecmp(line,"TPSMK",5) && line[5]>='0' && line[5]<='9') {
- keynr=MBC3('M','K',line[5]-'0');
- line+=6;
- ok=(len=GetHex(line,skey,VIATPS_KEYLEN));
- }
- else if(!strncasecmp(line,"TPS ",4)) {
- line+=4;
- keynr=MBC3('T','P','S');
- ok=(len=GetHex(line,skey,VIATPS_KEYLEN));
- }
- else if(GetHex(line,&skeynr,1)) {
- keynr=skeynr;
- ok=((len=GetHex(line,skey,VIA2_KEYLEN,false)) && (len==VIA1_KEYLEN || len==VIA2_KEYLEN));
- }
- if(ok) {
- SetBinKey(skey,len);
- return true;
- }
- }
- return false;
-}
-
-cString cPlainKeyVia::PrintKeyNr(void)
-{
- char tmp[12];
- const char *kn=tmp;
- switch(keynr) {
- case MBC3('T','P','S'):
- kn="TPS"; break;
- case MBC3('M','K',0): case MBC3('M','K',1): case MBC3('M','K',2):
- case MBC3('M','K',3): case MBC3('M','K',4): case MBC3('M','K',5):
- case MBC3('M','K',6): case MBC3('M','K',7): case MBC3('M','K',8):
- case MBC3('M','K',9):
- snprintf(tmp,sizeof(tmp),"TPSMK%d",C3(keynr)); break;
- default:
- snprintf(tmp,sizeof(tmp),"%02X",keynr); break;
- }
- return kn;
-}
-
-// -- cViaccessCardInfo --------------------------------------------------------
-
-class cViaccessCardInfo : public cStructItem, public cProviderViaccess, public cCardViaccess {
-public:
- unsigned char keyno, key[8];
- //
- bool Parse(const char *line);
- };
-
-bool cViaccessCardInfo::Parse(const char *line)
-{
- return GetHex(line,ident,sizeof(ident)) &&
- GetHex(line,ua,sizeof(ua)) &&
- GetHex(line,sa,sizeof(sa)) &&
- GetHex(line,&keyno,1) &&
- GetHex(line,key,sizeof(key));
-}
-
-// -- cViaccessCardInfos -------------------------------------------------------
-
-class cViaccessCardInfos : public cCardInfos<cViaccessCardInfo> {
-public:
- cViaccessCardInfos(void):cCardInfos<cViaccessCardInfo>("Viaccess cards","Viaccess.KID",0) {}
- };
-
-static cViaccessCardInfos Vcards;
-
-// -- cViaccess ----------------------------------------------------------------
-
-class cViaccess : protected cDes {
-private:
- unsigned char v2key[8];
- bool v2mode;
- //
- int HashNanos(const unsigned char *data, int len);
- void Via2Mod(const unsigned char *key2, unsigned char *data);
-protected:
- unsigned char hbuff[8], hkey[8];
- int pH;
- //
- void SetV2Mode(const unsigned char *key2);
- void SetHashKey(const unsigned char *key);
- void HashByte(unsigned char c);
- void HashClear(void);
- void Hash(void);
- //
- void Decode(unsigned char *data, const unsigned char *key);
- bool Decrypt(const unsigned char *work_key, const unsigned char *data, int len, unsigned char *des_data1, unsigned char *des_data2);
- //
- virtual unsigned int Mod(unsigned int R, unsigned int key7) const;
-public:
- cViaccess(void);
- };
-
-cViaccess::cViaccess(void)
-:cDes()
-{
- v2mode=false;
-}
-
-/* viaccess DES modification */
-
-unsigned int cViaccess::Mod(unsigned int R, unsigned int key7) const
-{
- if(key7!=0) {
- const unsigned int key5=(R>>24)&0xff;
- unsigned int al=key7*key5 + key7 + key5;
- al=(al&0xff)-((al>>8)&0xff);
- if(al&0x100) al++;
- R=(R&0x00ffffffL) + (al<<24);
- }
- return R;
-}
-
-/* viaccess2 modification. Extracted from "Russian wafer" card.
- A lot of thanks to it's author :) */
-
-void cViaccess::Via2Mod(const unsigned char *key2, unsigned char *data)
-{
- int kb, db;
- for(db=7; db>=0; db--) {
- for(kb=7; kb>3; kb--) {
- int a0=kb^db;
- int pos=7;
- if(a0&4) { a0^=7; pos^=7; }
- a0=(a0^(kb&3)) + (kb&3);
- if(!(a0&4)) data[db]^=(key2[kb] ^ ((data[kb^pos]*key2[kb^4]) & 0xFF));
- }
- }
- for(db=0; db<8; db++) {
- for(kb=0; kb<4; kb++) {
- int a0=kb^db;
- int pos=7;
- if(a0&4) { a0^=7; pos^=7; }
- a0=(a0^(kb&3)) + (kb&3);
- if(!(a0&4)) data[db]^=(key2[kb] ^ ((data[kb^pos]*key2[kb^4]) & 0xFF));
- }
- }
-}
-
-void cViaccess::Decode(unsigned char *data, const unsigned char *key)
-{
- if(v2mode) Via2Mod(v2key,data);
- Des(data,key,VIA_DES);
- if(v2mode) Via2Mod(v2key,data);
-}
-
-void cViaccess::SetV2Mode(const unsigned char *key2)
-{
- if(key2) {
- memcpy(v2key,key2,sizeof(v2key));
- v2mode=true;
- }
- else v2mode=false;
-}
-
-
-void cViaccess::SetHashKey(const unsigned char *key)
-{
- memcpy(hkey,key,sizeof(hkey));
-}
-
-void cViaccess::HashByte(unsigned char c)
-{
- hbuff[pH++]^=c;
- if(pH==8) { pH=0; Hash(); }
-}
-
-void cViaccess::HashClear(void)
-{
- memset(hbuff,0,sizeof(hbuff));
- pH=0;
-}
-
-void cViaccess::Hash(void)
-{
- if(v2mode) Via2Mod(v2key,hbuff);
- Des(hbuff,hkey,VIA_DES_HASH);
- if(v2mode) Via2Mod(v2key,hbuff);
-}
-
-int cViaccess::HashNanos(const unsigned char *data, int len)
-{
- int i=0;
- pH=0;
- if(data[0]==0x9f) {
- HashByte(data[i++]);
- HashByte(data[i++]);
- for(int j=0; j<data[1]; j++) HashByte(data[i++]);
- while(pH!=0) HashByte(0);
- }
- for(; i<len; i++) HashByte(data[i]);
- return i;
-}
-
-bool cViaccess::Decrypt(const unsigned char *work_key, const unsigned char *data, int len, unsigned char *des_data1, unsigned char *des_data2)
-{
- int pos=0, encStart=0;
- unsigned char signatur[8];
- while(pos<len) {
- switch(data[pos]) {
- case 0xea: // encrypted bytes
- encStart = pos + 2;
- memcpy(des_data1,&data[pos+2],8);
- memcpy(des_data2,&data[pos+2+8],8);
- break;
- case 0xf0: // signature
- memcpy(signatur,&data[pos+2],8);
- break;
- }
- pos += data[pos+1]+2;
- }
- HashClear();
- SetHashKey(work_key);
- // key preparation
- unsigned char prepared_key[8];
- if(work_key[7]==0) {
- // 8th key-byte = 0 then like Eurocrypt-M but with viaccess mods
- HashNanos(data,encStart+16);
- memcpy(prepared_key,work_key,sizeof(prepared_key));
- }
- else { // key8 not zero
- // rotate the key 2x left
- prepared_key[0]=work_key[2];
- prepared_key[1]=work_key[3];
- prepared_key[2]=work_key[4];
- prepared_key[3]=work_key[5];
- prepared_key[4]=work_key[6];
- prepared_key[5]=work_key[0];
- prepared_key[6]=work_key[1];
- prepared_key[7]=work_key[7];
- // test if key8 odd
- if(work_key[7]&1) {
- HashNanos(data,encStart);
- // test if low nibble zero
- unsigned char k = ((work_key[7] & 0xf0) == 0) ? 0x5a : 0xa5;
- for(int i=0; i<8; i++) {
- unsigned char tmp=des_data1[i];
- des_data1[i]=(k & hbuff[pH]) ^ tmp;
- HashByte(tmp);
- }
- for(int i=0; i<8; i++) {
- unsigned char tmp=des_data2[i];
- des_data2[i]=(k & hbuff[pH]) ^ tmp;
- HashByte(tmp);
- }
- }
- else {
- HashNanos(data,encStart+16);
- }
- }
- Decode(des_data1,prepared_key);
- Decode(des_data2,prepared_key);
- Hash();
- return (memcmp(signatur,hbuff,8)==0);
-}
-
-// -- cSystemViaccess ----------------------------------------------------------
-
-#define MAX_NEW_KEYS 5
-
-class cSystemViaccess : public cSystem, private cViaccess {
-private:
- cTPS tps;
-public:
- cSystemViaccess(void);
- virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *data);
- virtual void ProcessEMM(int pid, int caid, unsigned char *data);
- virtual void ParseCADescriptor(cSimpleList<cEcmInfo> *ecms, unsigned short sysId, unsigned short source, const unsigned char *data, int len);
- };
-
-cSystemViaccess::cSystemViaccess(void)
-:cSystem(SYSTEM_NAME,SYSTEM_PRI)
-{
- hasLogger=true;
-}
-
-void cSystemViaccess::ParseCADescriptor(cSimpleList<cEcmInfo> *ecms, unsigned short sysId, unsigned short source, const unsigned char *data, int len)
-{
- const int pid=WORD(data,2,0x1FFF);
- if(pid>=0xAA && pid<=0xCF) {
- PRINTF(L_CORE_ECMPROC,"viaccess: dropped \"fake\" ecm pid 0x%04x",pid);
- return;
- }
- cSystem::ParseCADescriptor(ecms,sysId,source,data,len);
-}
-
-bool cSystemViaccess::ProcessECM(const cEcmInfo *ecm, unsigned char *data)
-{
- unsigned char *nanos=(unsigned char *)cParseViaccess::NanoStart(data);
- int len=SCT_LEN(data)-(nanos-data);
-
- bool mayHaveTps=false;
- if(ecm->provId==0x007c00) { // TPS
- maxEcmTry=4;
- mayHaveTps=true;
- int num=tps.Decrypt(CardNum(),ecm->source,ecm->transponder,nanos,len);
- if(num<0) return false;
- nanos+=num; len-=num;
- }
-
- if(cParseViaccess::CheckNano90FromNano(nanos)) {
- int keynr=cParseViaccess::KeyNrFromNano(nanos);
- cKeySnoop ks(this,'V',ecm->provId,keynr);
- cPlainKey *pk=0;
- while((pk=keys.FindKey('V',ecm->provId,keynr,-1,pk))) {
- unsigned char key[16];
- if(pk->Size()<=(int)sizeof(key)) {
- pk->Get(key);
- SetV2Mode(pk->Size()==VIA2_KEYLEN ? &key[VIA1_KEYLEN] : 0);
- if(cViaccess::Decrypt(key,&nanos[5],len-5,&cw[0],&cw[8])) {
- if(mayHaveTps) tps.PostProc(cw);
- ks.OK(pk);
- return true;
- }
- }
- }
- }
- return false;
-}
-
-void cSystemViaccess::ProcessEMM(int pid, int caid, unsigned char *data)
-{
- for(cViaccessCardInfo *mkey=Vcards.First(); mkey; mkey=Vcards.Next(mkey)) {
- int updtype;
- cAssembleData ad(data);
- if(mkey->cCardViaccess::MatchEMM(data)) {
- updtype=3;
- HashClear();
- memcpy(hbuff+3,mkey->ua,sizeof(mkey->ua));
- }
- else if(mkey->cProviderViaccess::MatchEMM(data)) {
- if(mkey->cProviderViaccess::Assemble(&ad)<0) continue;
- updtype=2;
- HashClear();
- memcpy(hbuff+5,mkey->sa,sizeof(mkey->sa)-1);
- }
- else continue;
-
- const unsigned char *buff;
- if((buff=ad.Assembled())) {
- const unsigned char *scan=cParseViaccess::NanoStart(buff);
- unsigned int scanlen=SCT_LEN(buff)-(scan-buff);
-
- if(scanlen>=5 && mkey->cProviderViaccess::MatchID(buff) &&
- cParseViaccess::KeyNrFromNano(scan)==mkey->keyno) {
- scan+=5; scanlen-=5;
- SetHashKey(mkey->key);
- Hash();
-
- unsigned int n;
- if(scan[0]==0x9e && scanlen>=(n=scan[1]+2)) {
- for(unsigned int i=0; i<n; i++) HashByte(scan[i]);
- Hash(); pH=0;
- scan+=n; scanlen-=5;
- }
- if(scanlen>0) {
- unsigned char newKey[MAX_NEW_KEYS][8];
- int numKeys=0, updPrv[MAX_NEW_KEYS]={}, updKey[MAX_NEW_KEYS]={};
-
- for(unsigned int cnt=0; cnt<scanlen && numKeys<MAX_NEW_KEYS;) {
- const unsigned int parm=scan[cnt++];
- unsigned int plen=scan[cnt++];
-
- switch(parm) {
- case 0x90:
- case 0x9E:
- cnt+=plen;
- break;
- case 0xA1: // keyupdate
- updPrv[numKeys]=(scan[cnt]<<16)+(scan[cnt+1]<<8)+(scan[cnt+2]&0xF0);
- updKey[numKeys]=scan[cnt+2]&0x0F;
- // fall through
- default:
- HashByte(parm); HashByte(plen);
- while(plen--) HashByte(scan[cnt++]);
- break;
- case 0xEF: // crypted key(s)
- HashByte(parm); HashByte(plen);
- if(plen==sizeof(newKey[0])) {
- const unsigned char k7=mkey->key[7];
- for(unsigned int kc=0 ; kc<sizeof(newKey[0]) ; kc++) {
- const unsigned char b=scan[cnt++];
- if(k7&1) newKey[numKeys][kc]=b^(hbuff[pH]&(k7<0x10 ? 0x5a : 0xa5));
- else newKey[numKeys][kc]=b;
- HashByte(b);
- }
- numKeys++;
- }
- else {
- PRINTF(L_SYS_EMM,"%d: key length mismatch %d!=%d",CardNum(),plen,(int)sizeof(newKey[0]));
- cnt=scanlen;
- }
- break;
- case 0xF0: // signature
- {
- char str[20], str2[20];
- static const char *ptext[] = { 0,0,"SHARED","UNIQUE" };
- const char *addr = (updtype==2) ? HexStr(str,mkey->sa,sizeof(mkey->sa)) : HexStr(str,mkey->ua,sizeof(mkey->ua));
-
- Hash();
- if(!memcmp(&scan[cnt],hbuff,sizeof(hbuff))) {
- unsigned char key[8];
- memcpy(key,mkey->key,sizeof(key));
- if(key[7]) { // Rotate key
- const unsigned char t1=key[0], t2=key[1];
- key[0]=key[2]; key[1]=key[3]; key[2]=key[4]; key[3]=key[5]; key[4]=key[6];
- key[5]=t1; key[6]=t2;
- }
-
- while(numKeys--) {
- Decode(newKey[numKeys],key);
- PRINTF(L_SYS_EMM,"%02X%02X %02X %s %s - KEY %06X.%02X -> %s",
- mkey->ident[0],mkey->ident[1],mkey->keyno,addr,
- ptext[updtype],updPrv[numKeys],updKey[numKeys],
- HexStr(str2,newKey[numKeys],sizeof(newKey[numKeys])));
- FoundKey();
- if(keys.NewKey('V',updPrv[numKeys],updKey[numKeys],newKey[numKeys],8)) NewKey();
- }
- }
- else
- PRINTF(L_SYS_EMM,"%02X%02X %02X %s %s - FAIL",mkey->ident[0],mkey->ident[1],mkey->keyno,addr,ptext[updtype]);
- cnt=scanlen;
- break;
- }
- }
- }
- }
- }
- }
- }
-}
-
-// -- cSystemLinkViaccess ------------------------------------------------------
-
-class cSystemLinkViaccess : public cSystemLink {
-public:
- cSystemLinkViaccess(void);
- virtual bool CanHandle(unsigned short SysId);
- virtual cSystem *Create(void) { return new cSystemViaccess; }
- };
-
-static cSystemLinkViaccess staticInit;
-
-cSystemLinkViaccess::cSystemLinkViaccess(void)
-:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
-{
- Feature.NeedsKeyFile();
-}
-
-bool cSystemLinkViaccess::CanHandle(unsigned short SysId)
-{
- SysId&=SYSTEM_MASK;
- return SYSTEM_CAN_HANDLE(SysId);
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __VIACCESS_VIACCESS_H
-#define __VIACCESS_VIACCESS_H
-
-#define SYSTEM_VIACCESS 0x0500
-
-#define FILEMAP_DOMAIN "viaccess"
-#define TPSBIN "tps.bin"
-#define HOOK_SATTIME ((SYSTEM_VIACCESS<<8)+0x01)
-#define HOOK_TPSAU ((SYSTEM_VIACCESS<<8)+0x02)
-
-#endif
+++ /dev/null
-#
-# Viaccess
-#
-TARGET = viaccess
-OBJS = viaccess.o tps.o st20.o
+++ /dev/null
-
-### The directory environment:
-
-VDRDIR = ../../../..
-
-### Allow user defined options to overwrite defaults:
-
--include $(VDRDIR)/Make.config
-
-### The C++ compiler and options:
-
-CXX ?= g++
-CXXFLAGS ?= -g -march=pentium3 -O2 -Wall -Woverloaded-virtual
-
-### Includes and Defines
-
-SCAPIVERS = $(shell sed -ne '/define SCAPIVERS/ s/^.[a-zA-Z ]*\([0-9]*\).*$$/\1/p' ../sc.c)
-APIVERSION = $(shell sed -ne '/define APIVERSION/ s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/include/vdr/config.h)
-APIVERSNUM = $(shell sed -ne '/define APIVERSNUM/ s/^.[a-zA-Z ]*\([0-9]*\) .*$$/\1/p' $(VDRDIR)/include/vdr/config.h)
-
-INCLUDES = -I.. -I$(VDRDIR)/include
-DEFINES = -DAPIVERSNUM=$(APIVERSNUM) -DAPIVERSION='"$(APIVERSION)"' -DSCAPIVERS=$(SCAPIVERS) -D_GNU_SOURCE
-
-OBJS = misc.o log.o data.o crypto.o parse.o system.o system-common.o smartcard.o network.o filter.o version.o
-SHAREDOBJS = compat.o $(VDRDIR)/tools.o $(VDRDIR)/thread.o
-LIBS = -lpthread -ljpeg -ldl -lcrypto
-
-NOBJS = $(patsubst %.o,../%.o,$(OBJS))
-
-### Implicit rules:
-
-$(VDRDIR)/%.o: $(VDRDIR)/%.c
- make -C $(VDRDIR) $(@F)
-
-../%.o: ../%.c
- make -C .. $(@F)
-
-%.o: %.c
- $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
-
-### Targets:
-
-all: testECM testEMM testN1Emu testN2Emu testN2RunEmu
-
-testECM.o: testECM.c compat.h
-testECM: testECM.o $(SHAREDOBJS) $(NOBJS)
- $(CXX) $(CXXFLAGS) -rdynamic $^ $(LIBS) -o $@
-
-testEMM.o: testEMM.c compat.h
-testEMM: testEMM.o $(SHAREDOBJS) $(NOBJS)
- $(CXX) $(CXXFLAGS) -rdynamic $^ $(LIBS) -o $@
-
-testN1Emu.o: testN1Emu.c ../systems/nagra/nagra.c ../systems/nagra/nagra1.c ../systems/nagra/cpu.c ../systems/nagra/log-nagra.h
-testN1Emu: testN1Emu.o $(SHAREDOBJS) $(NOBJS)
- $(CXX) $(CXXFLAGS) $^ $(LIBS) -o $@
-
-testN2Emu.o: testN2Emu.c compat.h
-testN2Emu: testN2Emu.o $(SHAREDOBJS) $(NOBJS)
- $(CXX) $(CXXFLAGS) $^ $(LIBS) -L../systems/nagra -lsc-nagra -o $@
- @echo "don't forget: export LD_LIBRARY_PATH=../systems/nagra"
-
-testN2RunEmu.o: testN2RunEmu.c
-testN2RunEmu: testN2RunEmu.o $(SHAREDOBJS) $(NOBJS)
- $(CXX) $(CXXFLAGS) $^ $(LIBS) -L../systems/nagra -lsc-nagra -o $@
- @echo "don't forget: export LD_LIBRARY_PATH=../systems/nagra"
-
-testTPS.o: testTPS.c ../systems/viaccess/tps.c ../systems/viaccess/st20.c ../systems/viaccess/viaccess.c
-testTPS: testTPS.o $(SHAREDOBJS) $(NOBJS)
- $(CXX) $(CXXFLAGS) $^ $(LIBS) -o $@
-
-filterhelper: filterhelper.o
- $(CXX) $(CXXFLAGS) $^ -o $@
-clean:
- @-rm -f *.o core* *~
- @-rm -f testECM testEMM testN1Emu testN2Emu testN2RunEmu testTPS
- @-rm -f filterhelper
- @-rm -f dump.txt
+++ /dev/null
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <dlfcn.h>
-#include <dirent.h>
-#include <fnmatch.h>
-
-#include "data.h"
-#include "sc.h"
-#include "scsetup.h"
-#include "opts.h"
-#include "misc.h"
-#include "system.h"
-#include "smartcard.h"
-#include "cam.h"
-#include "log-core.h"
-#include "version.h"
-
-#define LIBSC_PREFIX "libsc-"
-#define SO_INDICATOR ".so."
-
-static bool DllLoad(const char *fileName)
-{
- const char *base=rindex(fileName,'/');
- if(!base) base=fileName;
- void *handle=dlopen(fileName,RTLD_NOW|RTLD_LOCAL);
- if(handle) return true;
- printf("dload: %s: %s\n",base,dlerror());
- return false;
-}
-
-bool DllsLoad(const char *libdir)
-{
- char pat[32];
- snprintf(pat,sizeof(pat),"%s*-%d%s%s",LIBSC_PREFIX,SCAPIVERS,SO_INDICATOR,APIVERSION);
- bool res=true;
- cReadDir dir(libdir);
- struct dirent *e;
- while((e=dir.Next())) {
- if(!fnmatch(pat,e->d_name,FNM_PATHNAME|FNM_NOESCAPE)) {
- DllLoad(AddDirectory(libdir,e->d_name));
- }
- }
- return res;
-}
-
-void InitAll(const char *cfgdir)
-{
- logcfg.logCon=1;
- logcfg.noTimestamp=1;
- cSystems::ConfigParse("Cardclient.Immediate","0");
-
- filemaps.SetCfgDir(cfgdir);
- cStructLoaders::SetCfgDir(cfgdir);
-
- if(!Feature.KeyFile()) keys.Disable();
- if(!Feature.SmartCard()) smartcards.Disable();
- cStructLoaders::Load(false);
- if(Feature.KeyFile() && keys.Count()<1)
- PRINTF(L_GEN_ERROR,"no keys loaded for softcam!");
- if(!cSystems::Init(cfgdir)) exit(2);
-
-#ifdef DEFAULT_PORT
- smartcards.AddPort(DEFAULT_PORT);
-#endif
- smartcards.LaunchWatcher();
-}
-
-void LogAll(void)
-{
- for(int i=0; i<32; i++)
- cLogging::SetModuleOptions(LCLASS(i,0xFFFFFFFF));
-}
-
-void SDump(const unsigned char *buffer, int n)
-{
- for(int l=0 ; l<n ; l++) printf("%02x ",buffer[l]);
- printf("\n");
-}
-
-int ReadRaw(const char *name, unsigned char *buff, int maxlen)
-{
- FILE *f=fopen(name,"r");
- if(f) {
- char line[512];
- int len=0;
- while(len<maxlen && fgets(line,sizeof(line),f)) {
- if(strstr(line,"dump: n=")) continue;
- char *p=index(line,'#');
- if(p) *p=0;
- p=index(line,'[');
- if(p) {
- p=index(p,']');
- if(p) {
- strcpy(line,p+1);
- }
- }
- p=index(line,':');
- if(p) p++; else p=line;
- while(1) {
- char *np;
- int val=strtol(p,&np,16);
- if(p!=np) {
- buff[len++]=val;
- p=np;
- }
- else break;
- }
- }
- fclose(f);
-// printf("using raw from %s:\n",name);
-// HexDump(buff,len);
- return len;
- }
- printf("failed to open raw file %s: %s\n",name,strerror(errno));
- exit(1);
-}
-
-//
-//
-
-extern const char *I18nTranslate(const char *s, const char *Plugin)
-{
- return s;
-}
-
-//
-//
-
-static const struct LogModule lm_core = {
- (LMOD_ENABLE|L_CORE_ALL)&LOPT_MASK,
- (LMOD_ENABLE|L_CORE_LOAD|L_CORE_ECM|L_CORE_PIDS|L_CORE_AU|L_CORE_AUSTATS|L_CORE_CAIDS|L_CORE_NET|L_CORE_CI|L_CORE_SC|L_CORE_HOOK)&LOPT_MASK,
- "core",
- { "load","action","ecm","ecmProc","pids","au","auStats","auExtra","auExtern",
- "caids","keys","dynamic","csa","ci","av7110","net","netData","msgcache",
- "serial","smartcard","hook","ciFull" }
- };
-ADD_MODULE(L_CORE,lm_core)
-
-//
-//
-
-cScSetup ScSetup;
-
-cScSetup::cScSetup(void)
-{
- AutoUpdate = 1;
- memset(ScCaps,0,sizeof(ScCaps));
- ScCaps[0] = 1;
- ScCaps[1] = 2;
- ConcurrentFF = 0;
- memset(CaIgnore,0,sizeof(CaIgnore));
- LocalPriority = 0;
- ForceTransfer = 1;
- PrestartAU = 0;
-}
-
-void cScSetup::Check(void) {}
-bool cScSetup::Ignore(unsigned short caid) { return false; }
-
-//
-//
-
-void cSoftCAM::SetLogStatus(int CardNum, const cEcmInfo *ecm, bool on) {}
-void cSoftCAM::AddHook(int CardNum, cLogHook *hook) {}
-bool cSoftCAM::TriggerHook(int CardNum, int id) { return true; }
-
-//
-//
-
-// --- cOpt --------------------------------------------------------------------
-
-cOpt::cOpt(const char *Name, const char *Title)
-{
- name=Name; title=Title;
- fullname=0; persistant=true;
-}
-
-cOpt::~cOpt()
-{
- free(fullname);
-}
-
-const char *cOpt::FullName(const char *PreStr)
-{
- if(PreStr) {
- free(fullname);
- asprintf(&fullname,"%s.%s",PreStr,name);
- return fullname;
- }
- else return name;
-}
-
-// --- cOptInt -----------------------------------------------------------------
-
-cOptInt::cOptInt(const char *Name, const char *Title, int *Storage, int Min, int Max)
-:cOpt(Name,Title)
-{
- storage=Storage; min=Min; max=Max;
-}
-
-void cOptInt::Parse(const char *Value)
-{
- *storage=atoi(Value);
-}
-
-void cOptInt::Backup(void)
-{
-}
-
-bool cOptInt::Set(void)
-{
- if(value!=*storage) { *storage=value; return true; }
- return false;
-}
-
-void cOptInt::Store(const char *PreStr)
-{
-}
-
-void cOptInt::Create(cOsdMenu *menu)
-{
-}
-
-// --- cOptSel -----------------------------------------------------------------
-
-cOptSel::cOptSel(const char *Name, const char *Title, int *Storage, int NumStr, const char * const *Strings)
-:cOptInt(Name,Title,Storage,0,NumStr)
-{
- strings=Strings;
- trStrings=0;
-}
-
-cOptSel::~cOptSel()
-{
- free(trStrings);
-}
-
-void cOptSel::Create(cOsdMenu *menu)
-{
-}
-
-// --- cOptBool -----------------------------------------------------------------
-
-cOptBool::cOptBool(const char *Name, const char *Title, int *Storage)
-:cOptInt(Name,Title,Storage,0,1)
-{}
-
-void cOptBool::Create(cOsdMenu *menu)
-{
-}
-
-// --- cOptStr -----------------------------------------------------------------
-
-cOptStr::cOptStr(const char *Name, const char *Title, char *Storage, int Size, const char *Allowed)
-:cOpt(Name,Title)
-{
- storage=Storage; size=Size; allowed=Allowed;
- value=MALLOC(char,size);
-}
-
-cOptStr::~cOptStr()
-{
- free(value);
-}
-
-void cOptStr::Parse(const char *Value)
-{
- strn0cpy(storage,Value,size);
-}
-
-void cOptStr::Backup(void)
-{
-}
-
-bool cOptStr::Set(void)
-{
- if(strcmp(value,storage)) { strn0cpy(storage,value,size); return true; }
- return false;
-}
-
-void cOptStr::Store(const char *PreStr)
-{
-}
-
-void cOptStr::Create(cOsdMenu *menu)
-{
-}
-
-// --- cOptCap -----------------------------------------------------------------
-
-class cOptCap : public cOpt {
-protected:
- int *storage, *value;
- int size, disp, len;
-public:
- cOptCap(const char *Name, const char *Title, int *Storage, int Size, int Disp);
- virtual ~cOptCap();
- virtual void Parse(const char *Value);
- virtual void Backup(void);
- virtual bool Set(void);
- virtual void Store(const char *PreStr);
- virtual void Create(cOsdMenu *menu);
- };
-
-cOptCap::cOptCap(const char *Name, const char *Title, int *Storage, int Size, int Disp)
-:cOpt(Name,Title)
-{
- storage=Storage; size=Size; disp=Disp; len=sizeof(int)*size;
- value=MALLOC(int,size);
-}
-
-cOptCap::~cOptCap()
-{
- free(value);
-}
-
-void cOptCap::Parse(const char *Value)
-{
- memset(storage,0,len);
- int i=0;
- while(1) {
- char *p;
- const int c=strtol(Value,&p,10);
- if(c<=0 || p==Value || i>=size) return;
- storage[i++]=c;
- Value=p;
- }
-}
-
-void cOptCap::Backup(void)
-{
-}
-
-bool cOptCap::Set(void)
-{
- if(memcmp(value,storage,len)) { memcpy(storage,value,len); return true; }
- return false;
-}
-
-void cOptCap::Store(const char *PreStr)
-{
-}
-
-void cOptCap::Create(cOsdMenu *menu)
-{
-}
-
-// --- cOpts -------------------------------------------------------------------
-
-cOpts::cOpts(const char *PreStr, int NumOpts)
-{
- preStr=PreStr;
- numOpts=NumOpts; numAdd=0;
- if((opts=MALLOC(cOpt *,numOpts))) memset(opts,0,sizeof(cOpt *)*numOpts);
-}
-
-cOpts::~cOpts()
-{
- if(opts) {
- for(int i=0; i<numOpts; i++) delete opts[i];
- free(opts);
- }
-}
-
-void cOpts::Add(cOpt *opt)
-{
- if(opts && numAdd<numOpts) opts[numAdd++]=opt;
-}
-
-bool cOpts::Parse(const char *Name, const char *Value)
-{
- if(opts) {
- for(int i=0; i<numAdd; i++)
- if(opts[i] && opts[i]->Persistant() && !strcasecmp(Name,opts[i]->Name())) {
- opts[i]->Parse(Value);
- return true;
- }
- }
- return false;
-}
-
-bool cOpts::Store(bool AsIs)
-{
- return false;
-}
-
-void cOpts::Backup(void)
-{
-}
-
-void cOpts::Create(cOsdMenu *menu)
-{
-}
-
-//
-//
-// VDR
-//
-//
-
-#include <vdr/sources.h>
-
-cString cSource::ToString(int Code)
-{
- char buffer[16];
- char *q = buffer;
- switch (Code & st_Mask) {
- case stCable: *q++ = 'C'; break;
- case stSat: *q++ = 'S';
- {
- int pos = Code & ~st_Mask;
- q += snprintf(q, sizeof(buffer) - 2, "%u.%u", (pos & ~st_Neg) / 10, (pos & ~st_Neg) % 10); // can't simply use "%g" here since the silly 'locale' messes up the decimal point
- *q++ = (Code & st_Neg) ? 'E' : 'W';
- }
- break;
- case stTerr: *q++ = 'T'; break;
- default: *q++ = Code + '0'; // backward compatibility
- }
- *q = 0;
- return buffer;
-}
-
-int cSource::FromString(const char *s)
-{
- int type = stNone;
- switch (toupper(*s)) {
- case 'C': type = stCable; break;
- case 'S': type = stSat; break;
- case 'T': type = stTerr; break;
- case '0' ... '9': type = *s - '0'; break; // backward compatibility
- default: esyslog("ERROR: unknown source key '%c'", *s);
- return stNone;
- }
- int code = type;
- if (type == stSat) {
- int pos = 0;
- bool dot = false;
- bool neg = false;
- while (*++s) {
- switch (toupper(*s)) {
- case '0' ... '9': pos *= 10;
- pos += *s - '0';
- break;
- case '.': dot = true;
- break;
- case 'E': neg = true; // fall through to 'W'
- case 'W': if (!dot)
- pos *= 10;
- break;
- default: esyslog("ERROR: unknown source character '%c'", *s);
- return stNone;
- }
- }
- if (neg)
- pos |= st_Neg;
- code |= pos;
- }
- return code;
-}
-
-//
-//
-
-#include <vdr/channels.h>
-
-int cChannel::Transponder(int Frequency, char Polarization)
-{
- // some satellites have transponders at the same frequency, just with different polarization:
- switch (tolower(Polarization)) {
- case 'h': Frequency += 100000; break;
- case 'v': Frequency += 200000; break;
- case 'l': Frequency += 300000; break;
- case 'r': Frequency += 400000; break;
- }
- return Frequency;
-}
+++ /dev/null
-
-bool DllsLoad(const char *libdir);
-void InitAll(const char *cfgdir);
-void LogAll(void);
-void SDump(const unsigned char *buffer, int n);
-int ReadRaw(const char *name, unsigned char *buff, int maxlen);
+++ /dev/null
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-
-int main(int argc, char *argv[])
-{
- unsigned char match[256];
- int i, max;
- int filt, mask, mode;
- int mam, manm;
-
- if(argc<2) {
- printf("missing operation mode\n");
- exit(1);
- }
- if(!strcasecmp(argv[1],"MATCH")) {
- if(argc<3) {
- printf("no matches given\n");
- exit(1);
- }
- memset(match,0,sizeof(match));
- printf("searching filter settings for:");
- for(i=2; i<argc; i++) {
- int l=strtol(argv[i],0,0);
- if(l<0 || l>255) {
- printf("allowed range 0-255 / 0x00-0xFF\n");
- exit(1);
- }
- match[l]=1;
- printf(" 0x%02x",l);
- }
- printf("\n");
-
- max=5;
- for(mode=0; mode<256; mode++) {
- for(mask=0; mask<256; mask++) {
- mam =mask & (~mode);
- manm=mask & ~(~mode);
- for(filt=0; filt<256; filt++) {
- int ok=1, miss=0;
- unsigned char mm[256];
- memset(mm,0,sizeof(mm));
- for(i=0; i<256; i++) {
- int xxor=filt^i;
- if((mam&xxor) || (manm && !(manm&xxor))) {
- if(match[i]!=0) {
- ok=0;
- miss=0;
- break;
- }
- }
- else {
- if(match[i]!=1) {
- ok=0;
- miss++; mm[i]=1;
- if(miss>max) break;
- }
- }
- }
-
- if(ok) {
- printf("found exact settings filt=%02x mask=%02x mode=%02x\n",filt,mask,mode);
- exit(0);
- }
- else if(miss>0 && miss<=max) {
- printf("mismatching");
- for(i=0; i<256; i++) if(mm[i]) printf(" %02x",i);
- printf(" - settings filt=%02x mask=%02x mode=%02x\n",filt,mask,mode);
- max=miss;
- }
- }
- }
- }
- printf("no exact settings found\n");
- exit(1);
- }
- else if(!strcasecmp(argv[1],"TEST")) {
- if(argc<5) {
- printf("missing arguments\n");
- exit(1);
- }
- filt=strtol(argv[2],0,0);
- if(filt<0 || filt>255) {
- printf("filter range 0-255 exceeded\n");
- exit(1);
- }
- mask=strtol(argv[3],0,0);
- if(mask<0 || mask>255) {
- printf("mask range 0-255 exceeded\n");
- exit(1);
- }
- mode=strtol(argv[4],0,0);
- if(mode<0 || mode>255) {
- printf("mode range 0-255 exceeded\n");
- exit(1);
- }
- printf("settings file=%02x mask=%02x mode=%02x\n",filt,mask,mode);
-
- mam =mask & (~mode);
- manm=mask & ~(~mode);
- printf("matching:");
- for(i=0; i<256; i++) {
- int xxor=filt^i;
- if((mam&xxor) || (manm && !(manm&xxor))) {}
- else
- printf(" %02x",i);
- }
- printf("\n");
- }
- else {
- printf("unknown operation mode\n");
- }
- exit(1);
-}
-
+++ /dev/null
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "data.h"
-#include "system.h"
-#include "log.h"
-#include "compat.h"
-#include <vdr/sources.h>
-
-int main(int argc, char *argv[])
-{
- if(argc<6) {
- printf("usage: %s <lib-dir> <plugin-dir> <caid> <provid> <source> <ecm-dump>\n",argv[0]);
- return 1;
- }
- DllsLoad(argv[1]);
- InitAll(argv[2]);
- LogAll();
- cLogging::SetModuleOption(LCLASS(7,0x20<<2),false); // Nagra L_SYS_DISASM
- cLogging::SetModuleOption(LCLASS(7,0x20<<4),false); // Nagra L_SYS_CPUSTATS
- unsigned char ecm[4096];
- ReadRaw(argv[6],ecm,sizeof(ecm));
-
- int caid=strtol(argv[3],0,0);
- int provid=strtol(argv[4],0,0);
- printf("using caid %04x provid %04x\n",caid,provid);
- cEcmInfo ecmD("dummy",0x123,caid,provid);
- ecmD.SetSource(10,cSource::FromString(argv[5]),120);
- cSystem *sys=0;
- int lastPri=0;
- while((sys=cSystems::FindBySysId(caid,false,lastPri))) {
- lastPri=sys->Pri();
- printf("processing with module '%s'\n",sys->Name());
- bool res=sys->ProcessECM(&ecmD,ecm);
- if(res) {
- printf("resulting CW: ");
- SDump(sys->CW(),16);
- }
- delete sys;
- if(res) break;
- }
-}
+++ /dev/null
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "data.h"
-#include "system.h"
-#include "compat.h"
-
-int main(int argc, char *argv[])
-{
- if(argc<4) {
- printf("usage: %s <lib-dir> <plugin-dir> <caid> <rawemm-file>\n",argv[0]);
- return 1;
- }
- DllsLoad(argv[1]);
- InitAll(argv[2]);
- LogAll();
- unsigned char emm[4096];
- int len=ReadRaw(argv[4],emm,sizeof(emm));
-
- int caid=strtol(argv[3],0,0);
- printf("using caid %04x\n",caid);
- cSystem *sys=0;
- int lastPri=0;
- while((sys=cSystems::FindBySysId(caid,false,lastPri))) {
- sys->DoLog(true); sys->CardNum(0);
- lastPri=sys->Pri();
- if(sys->HasLogger()) {
- for(int i=0; i<len;) {
- int s=SCT_LEN(&emm[i]);
- sys->ProcessEMM(0x123,caid,&emm[i]);
- i+=s;
- }
- }
- delete sys;
- }
-}
+++ /dev/null
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#define TESTER
-#include "crypto.h"
-#include "data.h"
-#include "system-common.h"
-#include "systems/nagra/cpu.c"
-#include "systems/nagra/nagra.c"
-#include "systems/nagra/nagra1.c"
-
-#include "compat.h"
-
-class cTestNagra : public cNagra1 {
-public:
- virtual void Process(int id, unsigned char *emmdata);
- };
-
-void cTestNagra::Process(int id, unsigned char *emmdata)
-{
- cEmu *emu=0;
- cBN n1, e1;
-
- unsigned int i=0;
- bool gotKeys=false;
- unsigned char key0[8], key1[8];
- int keyId=(emmdata[i+1]<<8)+emmdata[i+2];
- switch(emmdata[i]) { // Check filter type
- case 0x00: // One card
- i+=7; break;
- case 0x01 ... 0x20: // Group of cards
- i+=emmdata[i]+0x7; break;
- case 0x3e:
- i+=6; break;
- case 0x3d: // All cards with same system ID
- case 0x3f:
- i+=3; break;
- }
- int nrKeys=0;
- while(i<sizeof(emmdata)) {
- if((emmdata[i]&0xF0)==0xF0) { // Update with CPU code
- const int romNr=emmdata[i]&0x0F;
- if(!emu || !emu->Matches(romNr,id)) {
- delete emu; emu=0;
- printf("Testing with ROM %d, 0xID %04x\n",romNr,id);
- switch(romNr) {
- case 3: emu=new cEmuRom3; break;
- case 7: emu=new cEmuRom7; break;
- case 10: emu=new cEmuRom10; break;
- case 11: emu=new cEmuRom11; break;
- default: printf("unsupported ROM"); return;
- }
- if(!emu || !emu->Init(romNr,id)) {
- delete emu; emu=0;
- printf("initialization failed for ROM %d\n",romNr);
- return;
- }
- }
- unsigned char ki[2];
- if((gotKeys=emu->GetOpKeys(emmdata,ki,key0,key1))) {
- printf("keyid: "); SDump(ki,2);
- printf("key0: "); SDump(key0,8);
- printf("key1: "); SDump(key1,8);
- keyId=(ki[0]<<8)+ki[1];
- printf("got keys for %04X (ROM %d)\n",keyId,romNr);
- }
- unsigned char select[3], pkset[3][15];
- select[0]=(keyId>>8)|0x01; // always high id for ECM RSA keys
- select[1]=keyId&0xFF;
- select[2]=0; // type 0
-HexDump(select,3);
- if(emu->GetPkKeys(&select[0],&pkset[0][0])) {
- int pkKeyId=((select[0]<<8)+select[1]);
- printf("got PK keys for %04X (ROM %d)\n",pkKeyId,romNr);
-HexDump(pkset[0],sizeof(pkset[0]));
-HexDump(pkset[1],sizeof(pkset[1]));
-HexDump(pkset[2],sizeof(pkset[2]));
- for(int i=0; i<3; i++) {
- CreateRSAPair(pkset[i],0,e1,n1);
- printf("keyE1 set=%d ",i); bprint(e1);
- printf("keyN1 set=%d ",i); bprint(n1);
- }
- }
- break; // don't process other nanos
- }
- else if(emmdata[i]==0x60) { // NULL nano
- i+=2;
- }
- else if(emmdata[i]==0x00) {
- i++;
- }
- else if(emmdata[i]==0x81) {
- i++;
- }
- else if(emmdata[i]==0x83) {
- keyId=(emmdata[i+1]<<8)+emmdata[i+2];
- i+=3;
- }
- else if(emmdata[i]==0x42) { // plain Key
- if(emmdata[i+1]==0x05) memcpy(key0,&emmdata[i+2],sizeof(key0));
- else memcpy(key1,&emmdata[i+2],sizeof(key1));
- i+=10;
- if(++nrKeys==2) {
- gotKeys=true;
- printf("got keys for %04X (plain)\n",keyId);
- break;
- }
- }
- else {
- printf("ignored nano %02x\n",emmdata[i]);
- break;
- }
- }
-
- delete emu;
-}
-
-
-int main(int argc, char *argv[])
-{
- if(argc<3) {
- printf("usage: %s <plugin-dir> <id> <rawemm-file>\n",argv[0]);
- return 1;
- }
-
- InitAll(argv[1]);
- unsigned char emmdata[64];
- int emmlen=ReadRaw(argv[3],emmdata,sizeof(emmdata));
- if(emmlen!=64) {
- printf("bad rawemm file format\n");
- return 1;
- }
- const int id=strtol(argv[2],0,0);
- cTestNagra test;
- test.Process(id,emmdata);
- return 0;
-}
+++ /dev/null
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "crypto.h"
-#include "data.h"
-#include "system-common.h"
-#include "systems/nagra/nagra2.h"
-
-#include "compat.h"
-
-static const unsigned char key3des[16] = { };
-
-static cN2Prov *emmP=0;
-
-void Emm(unsigned char *emmdata, int cmdLen, int id)
-{
- if(!emmP || (emmP && !emmP->CanHandle(id))) {
- delete emmP;
- emmP=cN2Providers::GetProv(id,N2FLAG_NONE);
- if(emmP) emmP->PrintCaps(L_SYS_EMM);
- }
-
- HEXDUMP(L_SYS_RAWEMM,emmdata,cmdLen,"Nagra2 RAWEMM");
- id=(emmdata[8]<<8)+emmdata[9];
- LBSTARTF(L_SYS_EMM);
- bool contFail=false;
- for(int i=8+2+4+4; i<cmdLen-22; ) {
- switch(emmdata[i]) {
- case 0x42: // plain Key update
- if((((emmdata[i+3]|0xF3)+1)&0xFF) != 0) {
- int len=emmdata[i+2];
- int off=emmdata[i+5];
- int ulen=emmdata[i+6];
- if(len>0 && ulen>0 && off+ulen<=len) {
- int ks=emmdata[i+3], kn;
- if(ks==0x06 || ks==0x46) kn=(ks>>6)&1; else kn=MBC(N2_MAGIC,ks);
- unsigned char key[256];
- memset(key,0,sizeof(key));
- bool ok=false;
- if((emmdata[i+1]&0x7F)==0) ok=true;
- else {
- if(emmP && emmP->HasFlags(N2FLAG_POSTAU)) {
- if(emmP->PostProcAU(id,&emmdata[i])) ok=true;
- }
- else PRINTF(L_SYS_EMM,"POSTAU for provider %04x not supported",id);
- }
- if(ok) {
- printf("key %x: off=%x ulen=%x ",kn,off,ulen);
- SDump(&emmdata[i+7],ulen);
- }
- i+=ulen;
- }
- else PRINTF(L_SYS_EMM,"nano42 key size mismatch len=%d off=%d ulen=%d",len,off,ulen);
- }
- else PRINTF(L_SYS_EMM,"nano42 0xf3 status exceeded");
- i+=7;
- break;
- case 0xE0: // DN key update
- if(emmdata[i+1]==0x25) {
- printf("key%02x: ",(emmdata[i+16]&0x40)>>6);
- SDump(&emmdata[i+23],16);
- }
- i+=emmdata[i+1]+2;
- break;
- case 0x83: // change data prov. id
- id=(emmdata[i+1]<<8)|emmdata[i+2];
- i+=3;
- break;
- case 0xB0: case 0xB1: case 0xB2: case 0xB3: // Update with ROM CPU code
- case 0xB4: case 0xB5: case 0xB6: case 0xB7:
- case 0xB8: case 0xB9: case 0xBA: case 0xBB:
- case 0xBC: case 0xBD: case 0xBE: case 0xBF:
- {
- int bx=emmdata[i]&15;
- if(!emmP || !emmP->HasFlags(N2FLAG_Bx)) {
- PRINTF(L_SYS_EMM,"B%X for provider %04x not supported",bx,id);
- i=cmdLen;
- break;
- }
- int r;
- if((r=emmP->ProcessBx(emmdata,cmdLen,i+1))>0)
- i+=r;
- else {
- PRINTF(L_SYS_EMM,"B%X executing failed for %04x",bx,id);
- i=cmdLen;
- }
- break;
- }
- case 0xA4: i+=emmdata[i+1]+2+4; break; // conditional (always no match assumed for now)
- case 0xA6: i+=15; break;
- case 0xAA: i+=emmdata[i+1]+5; break;
- case 0xAD: i+=emmdata[i+1]+2; break;
- case 0xA2:
- case 0xAE: i+=11;break;
- case 0x12: i+=emmdata[i+1]+2; break; // create tier
- case 0x20: i+=19; break; // modify tier
- case 0x9F: i+=6; break;
- case 0xE3: // Eeprom update
- {
- int ex=emmdata[i]&15;
- if(!emmP || !emmP->HasFlags(N2FLAG_Ex)) {
- i+=emmdata[i+4]+5;
- PRINTF(L_SYS_EMM,"E%X for provider %04x not supported",ex,id);
- break;
- }
- int r;
- if((r=emmP->ProcessEx(emmdata,cmdLen,i+1))>0)
- i+=r;
- else {
- PRINTF(L_SYS_EMM,"E%X executing failed for %04x",ex,id);
- i=cmdLen;
- }
- break;
- }
- case 0xE1:
- case 0xE2:
- case 0x00: i=cmdLen; break; // end of processing
- default:
- if(!contFail) LBPUT("unknown EMM nano");
- LBPUT(" %02x",emmdata[i]);
- contFail=true;
- i++;
- continue;
- }
- LBFLUSH(); contFail=false;
- }
- LBEND();
-}
-
-bool Ecm(unsigned char *buff, int cmdLen, int id)
-{
- unsigned char cw[16];
-
- cN2Prov *ecmP=cN2Providers::GetProv(id,N2FLAG_NONE);
- if(ecmP) ecmP->PrintCaps(L_SYS_ECM);
-
- int l=0, mecmAlgo=0;
- for(int i=(buff[14]&0x10)?16:20; i<cmdLen-10 && l!=3; ) {
-printf("%02x: nano %02x\n",i,buff[i]);
- switch(buff[i]) {
- case 0x10:
- case 0x11:
- if(buff[i+1]==0x09) {
- int s=(~buff[i])&1;
- mecmAlgo=buff[i+2]&0x60;
- memcpy(cw+(s<<3),&buff[i+3],8);
- i+=11; l|=(s+1);
- }
- else {
- printf("bad length %d in CW nano %02x\n",buff[i+1],buff[i]);
- i++;
- }
- break;
- case 0x00:
- i+=2; break;
- case 0x13 ... 0x15:
- i+=4; break;
- case 0x30 ... 0x36:
- case 0xB0:
- i+=buff[i+1]+2;
- break;
- default:
- i++;
- continue;
- }
- }
- if(l!=3) return false;
- if(mecmAlgo>0) {
- if(ecmP && ecmP->HasFlags(N2FLAG_MECM)) {
-static unsigned char odata[15] = { 0x80,0x30,0x47,0x07,0x45,0xec,0xc1,0xee,0xc5,0x53,0x91,0x2f,0x70,0x34,0x34 };
- if(!ecmP->MECM(buff[15],mecmAlgo,odata,cw)) return false;
- }
- else { printf("MECM for provider %04x not supported\n",id); return false; }
- }
- if(ecmP) ecmP->SwapCW(cw);
- printf("resulting CW: "); SDump(cw,16);
- return true;
-}
-
-int main(int argc, char *argv[])
-{
- if(argc<5) {
- printf("usage: %s <plugin-dir> <id> <ECM/EMM> <raw-file> [<raw-file> [..]]\n",argv[0]);
- return 1;
- }
-
- int mode;
- if(!strcasecmp(argv[3],"ECM")) mode=1;
- else if(!strcasecmp(argv[3],"EMM")) mode=2;
- else {
- printf("bad mode '%s'\n",argv[3]);
- return 1;
- }
-
- InitAll(argv[1]);
- LogAll();
- cLogging::SetModuleOption(LCLASS(L_SYS,L_SYS_DISASM),false);
-
- int id=strtol(argv[2],0,0);
- int dlen=(mode==1) ? 64 : 96;
- unsigned char data[4096];
- for(int pos=4; pos<argc; pos++) {
- int len=ReadRaw(argv[pos],data,sizeof(data));
- if(len%dlen != 0) { printf("bad raw file format\n"); exit(1); }
-
- for(int alen=0; alen<len; alen+=dlen) {
- if(mode==1) Ecm(&data[alen],dlen,id);
- else if(mode==2) Emm(&data[alen],dlen,id);
- }
- }
-}
+++ /dev/null
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "crypto.h"
-#include "data.h"
-#include "system-common.h"
-#include "systems/nagra/nagra2.h"
-
-#include "compat.h"
-
-int main(int argc, char *argv[])
-{
- if(argc<4) {
- printf("usage: %s <plugin-dir> <id> <cmdfile> [LOG]\n",argv[0]);
- return 1;
- }
-
- InitAll(argv[1]);
- LogAll();
- if(argc<=4 || strcasecmp(argv[4],"LOG"))
- cLogging::SetModuleOption(LCLASS(L_SYS,L_SYS_DISASM),false);
- unsigned char data[4096];
- unsigned int len=ReadRaw(argv[3],data,sizeof(data));
- int id=strtol(argv[2],0,0);
- cN2Prov *emmP=cN2Providers::GetProv(id,N2FLAG_NONE);
- HEXDUMP(L_SYS_EMU,data,len,"Input");
- if(emmP->RunEmu(data,len,0x90,0x90,0x00,0x00,0x460)>=0)
- HEXDUMP(L_SYS_EMU,data,0x460,"Output");
-}
+++ /dev/null
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef ___VERSION_H
-#define ___VERSION_H
-
-#define SC_RELEASE "0.9.0"
-
-extern const char *ScVersion;
-
-#endif