├── .gitignore ├── LGPL-2.1 ├── Makefile.am ├── NEWS ├── TODO ├── bootstrap ├── configure.ac ├── doc ├── Makefile.am ├── README ├── doxygen-footer.html ├── doxygen.conf.in └── opensc-logo.gif ├── etc ├── Info.plist ├── Makefile.am ├── init-script.in ├── openct-disable.fdi ├── openct-policy.fdi ├── openct.conf.in ├── openct.fdi ├── openct.hald.in ├── openct.udev.compat ├── openct.udev.in ├── openct.udev.modalias.in ├── openct.usermap ├── openct_pcmcia.in ├── openct_serial.in ├── openct_usb.in ├── openct_usb.mdev.in └── reader.conf.in ├── m4 └── ac_create_stdint_h.m4 ├── macos ├── Makefile.am └── libtool-bundle ├── solaris ├── Makefile.client ├── Makefile.server ├── README ├── checkinstall.in ├── devices-openct-fabric.xml-dist ├── openct-fabric-dist ├── openct-hotplug-dist ├── openct.conf-dist ├── pkginfo.in ├── postinstall ├── preremove └── proto └── src ├── Makefile.am ├── ct ├── Makefile.am ├── buffer.c ├── client.c ├── error.c ├── libopenct.pc.in ├── mainloop.c ├── path.c ├── socket.c ├── status.c └── tlv.c ├── ctapi ├── Makefile.am ├── ctapi.c └── ctapi.h ├── ifd ├── Makefile.am ├── apdu.c ├── atr.c ├── atr.h ├── cardman.h ├── checksum.c ├── conf.c ├── ctbcs.c ├── ctbcs.h ├── device.c ├── driver.c ├── ifd-acr30u.c ├── ifd-cardman.c ├── ifd-ccid.c ├── ifd-cm4000.c ├── ifd-cyberjack.c ├── ifd-egate.c ├── ifd-epass3k.c ├── ifd-etoken.c ├── ifd-etoken64.c ├── ifd-eutron.c ├── ifd-gempc.c ├── ifd-ikey2k.c ├── ifd-ikey3k.c ├── ifd-kaan.c ├── ifd-pertosmart1030.c ├── ifd-pertosmart1038.c ├── ifd-rutoken.c ├── ifd-smartboard.c ├── ifd-smph.c ├── ifd-starkey.c ├── ifd-towitoko.c ├── ifd-wbeiuu.c ├── ifdhandler.c ├── ifdhandler.h ├── ifdproxy.c ├── init.c ├── internal.h ├── locks.c ├── manager.c ├── modules.c ├── pcmcia-block.c ├── pcmcia.c ├── process.c ├── proto-escape.c ├── proto-gbp.c ├── proto-sync.c ├── proto-t0.c ├── proto-t1.c ├── proto-trans.c ├── protocol.c ├── reader.c ├── ria-device.c ├── ria-server.c ├── ria.c ├── ria.h ├── serial.c ├── sys-bsd.c ├── sys-linux.c ├── sys-null.c ├── sys-osx.c ├── sys-solaris.c ├── sys-sunray.c ├── usb-descriptors.c ├── usb-descriptors.h ├── usb.c └── utils.c ├── include ├── Makefile.am └── openct │ ├── Makefile.am │ ├── apdu.h │ ├── buffer.h │ ├── conf.h │ ├── device.h │ ├── driver.h │ ├── error.h │ ├── ifd.h │ ├── logging.h │ ├── openct.h │ ├── path.h │ ├── protocol.h │ ├── server.h │ ├── socket.h │ └── tlv.h ├── pcsc ├── Makefile.am └── pcsc.c └── tools ├── Makefile.am ├── openct-control.c ├── openct-tool.1.in └── openct-tool.c /.gitignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | Makefile.in 3 | core 4 | archive 5 | acinclude.m4 6 | aclocal.m4 7 | autom4te.cache 8 | compile 9 | confdefs.h 10 | config.* 11 | configure 12 | conftest 13 | conftest.c 14 | depcomp 15 | install-sh 16 | libtool 17 | libtool.m4 18 | ltmain.sh 19 | missing 20 | mkinstalldirs 21 | so_locations 22 | stamp-h* 23 | 24 | .deps 25 | .libs 26 | .#*# 27 | .*.bak 28 | .*.orig 29 | .*.rej 30 | .*~ 31 | #*# 32 | *.bak 33 | *.d 34 | *.def 35 | *.dll 36 | *.exe 37 | *.la 38 | *.lib 39 | *.lo 40 | *.o 41 | *.orig 42 | *.pdb 43 | *.rej 44 | *.u 45 | *.rc 46 | *.pc 47 | *~ 48 | *.gz 49 | *.bz2 50 | *.[0-9] 51 | *.html 52 | *.gif 53 | *.css 54 | *.out 55 | *.loT 56 | 57 | etc/openct.udev 58 | etc/openct.udev.modalias 59 | etc/openct_usb.mdev 60 | m4/ltoptions.m4 61 | m4/ltsugar.m4 62 | m4/ltversion.m4 63 | m4/lt~obsolete.m4 64 | doc/doxygen.conf 65 | etc/init-script 66 | etc/openct.conf 67 | etc/openct.hald 68 | etc/openct_pcmcia 69 | etc/openct_serial 70 | etc/openct_usb 71 | etc/reader.conf 72 | src/ifd/ifdhandler 73 | src/ifd/ifdproxy 74 | src/include/openct/types.h 75 | src/tools/openct-control 76 | src/tools/openct-tool 77 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 1.10 2 | ACLOCAL_AMFLAGS = -I m4 3 | 4 | MAINTAINERCLEANFILES = \ 5 | config.log config.status \ 6 | $(srcdir)/Makefile.in \ 7 | $(srcdir)/config.h.in $(srcdir)/config.h.in~ $(srcdir)/configure \ 8 | $(srcdir)/install-sh $(srcdir)/ltmain.sh $(srcdir)/missing \ 9 | $(srcdir)/depcomp $(srcdir)/aclocal.m4 $(srcdir)/compile \ 10 | $(srcdir)/config.guess $(srcdir)/config.sub \ 11 | $(srcdir)/m4/ltsugar.m4 $(srcdir)/m4/libtool.m4 \ 12 | $(srcdir)/m4/ltversion.m4 $(srcdir)/m4/lt~obsolete.m4 \ 13 | $(srcdir)/m4/ltoptions.m4 \ 14 | $(srcdir)/packaged 15 | EXTRA_DIST = .gitignore 16 | 17 | SUBDIRS = etc macos src doc 18 | 19 | dist_noinst_SCRIPTS = bootstrap 20 | dist_noinst_DATA = LGPL-2.1 TODO \ 21 | solaris/Makefile.client solaris/Makefile.server solaris/README \ 22 | solaris/checkinstall.in solaris/devices-openct-fabric.xml-dist \ 23 | solaris/openct-fabric-dist solaris/openct-hotplug-dist \ 24 | solaris/openct.conf-dist solaris/pkginfo.in solaris/postinstall \ 25 | solaris/preremove solaris/proto 26 | dist_doc_DATA = NEWS 27 | 28 | # Allow detection of packaged tarball 29 | dist-hook: 30 | echo > "$(distdir)/packaged" 31 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - sometimes the communication freezes, some packet does not 2 | reach the destination. can be proproduced with egate driver, 3 | cryptoflex card and opensc regression test init0004,6, 4 | but is not specific to these drivers and cards 5 | - improve pc/sc detection 6 | - error handling: use error codes everywhere 7 | - pin verification via keypad 8 | - ifdhandler should clear status file slot on exit 9 | - openct-control init: debug messages to syslog 10 | - rewrite USB layer, add native support for *BSD 11 | and MacOS X. Remove optional libusb dependency 12 | - CCID driver 13 | -------------------------------------------------------------------------------- /bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -x 5 | if test -f Makefile; then 6 | make distclean 7 | fi 8 | rm -rf *~ *.cache *.m4 config.guess config.log \ 9 | config.status config.sub depcomp ltmain.sh 10 | autoreconf --verbose --install --force 11 | -------------------------------------------------------------------------------- /doc/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = $(srcdir)/Makefile.in 2 | 3 | dist_doc_DATA = README 4 | dist_noinst_DATA = $(srcdir)/doxygen-footer.html $(srcdir)/*.gif 5 | 6 | if ENABLE_API_DOC 7 | 8 | apidoc_DATA=api.out/html/* 9 | 10 | api.out/html/*: api.out 11 | api.out: $(top_srcdir)/src/include/openct/*.h \ 12 | $(srcdir)/*.gif \ 13 | doxygen.conf 14 | -rm -fr api.out 15 | $(DOXYGEN) doxygen.conf 16 | cp "$(srcdir)"/*.gif api.out/html 17 | 18 | endif 19 | 20 | clean-local: 21 | -rm -fr api.out 22 | -------------------------------------------------------------------------------- /doc/README: -------------------------------------------------------------------------------- 1 | This directory contains a snapshot of the OpenCT Wiki 2 | ===================================================== 3 | 4 | The original wiki page is at http://www.opensc-project.org/openct/ 5 | and includes a bug tracker and source browser. 6 | 7 | The wiki was transformed to html using the export-wiki shell 8 | script and xsl style sheet. The original version is at 9 | http://www.twdata.org/trac-howto/ 10 | 11 | To update the documentation run "make dist" in the top 12 | directory of the source code. Note: to do so files are 13 | fetched from the network using wget and xsltproc is needed 14 | to transform the files. Also the API documentation is 15 | updated using doxygen. Make sure all these tools are 16 | installed. 17 | -------------------------------------------------------------------------------- /doc/doxygen-footer.html: -------------------------------------------------------------------------------- 1 |
2 |
libp11, Copyright (C) 2005 Olaf Kirch <okir@lst.de>OpenSC-Project.org Logo
3 | -------------------------------------------------------------------------------- /doc/opensc-logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenSC/openct/a4f3fcb91dcd78274dffb1b934e4a8c55dbb91a4/doc/opensc-logo.gif -------------------------------------------------------------------------------- /etc/Info.plist: -------------------------------------------------------------------------------- 1 | ifdManufacturerString 2 | OpenCT Project (www.opensc-project.org/openct/) 3 | ifdProductString 4 | PC/SC Lite IFD wrapper for OpenCT 5 | 6 | ifdCapabilities 7 | 0x00000000 8 | ifdProtocolSupport 9 | 0x00000001 10 | ifdVersionNumber 11 | 0x00000001 12 | 13 | ifdVendorID 14 | 15 | 0x0973 16 | 0x0529 17 | 0x0529 18 | 0x0529 19 | 0x0529 20 | 0x073d 21 | 0x04b9 22 | 0x04b9 23 | 0x096e 24 | 0x03f0 25 | 0x046a 26 | 0x04e6 27 | 0x04e6 28 | 0x04e6 29 | 0x04e6 30 | 0x04e6 31 | 0x04e6 32 | 0x073d 33 | 0x076b 34 | 0x076b 35 | 0x076b 36 | 0x076b 37 | 0x076b 38 | 0x0783 39 | 0x08e6 40 | 0x08e6 41 | 0x08e6 42 | 0x0b97 43 | 0x0b97 44 | 0x0bf8 45 | 0x0dc3 46 | 0x0a89 47 | 0x072f 48 | 0x072f 49 | 0x072f 50 | 0x072f 51 | 0x072f 52 | 0x072f 53 | 0x104f 54 | 0x0c4b 55 | 0x0a89 56 | 0x0a89 57 | 58 | 59 | ifdProductID 60 | 61 | 0x0001 62 | 0x050c 63 | 0x0514 64 | 0x0600 65 | 0x0700 66 | 0x0005 67 | 0x1202 68 | 0x1300 69 | 0x0005 70 | 0x1024 71 | 0x0010 72 | 0x5115 73 | 0x5116 74 | 0x5117 75 | 0x511d 76 | 0xE001 77 | 0xE003 78 | 0x0c00 79 | 0x1021 80 | 0x3021 81 | 0x5121 82 | 0x5321 83 | 0x6622 84 | 0x0003 85 | 0x3437 86 | 0x3438 87 | 0x4433 88 | 0x7762 89 | 0x7772 90 | 0x1006 91 | 0x1004 92 | 0x0030 93 | 0x0001 94 | 0x8009 95 | 0x9000 96 | 0x9006 97 | 0x9007 98 | 0x90d0 99 | 0x0004 100 | 0x0100 101 | 0x0020 102 | 0x0012 103 | 104 | 105 | ifdFriendlyName 106 | 107 | Axalto/Schlumberger/Gemalo egate token 108 | Aladdin eToken PRO 109 | Aladdin eToken PRO 110 | Aladdin eToken PRO 64 111 | Aladdin eToken PRO NG OTP 112 | Eutron CryptoIdendity 113 | Rainbow iKey 2000 114 | Rainbow iKey 3000 115 | G&D Starkey 100 116 | Generic CCID Reader 117 | Generic CCID Reader 118 | Generic CCID Reader 119 | Generic CCID Reader 120 | Generic CCID Reader 121 | Generic CCID Reader 122 | Generic CCID Reader 123 | Generic CCID Reader 124 | Generic CCID Reader 125 | Generic CCID Reader 126 | Generic CCID Reader 127 | Generic CCID Reader 128 | Generic CCID Reader 129 | Generic CCID Reader 130 | Generic CCID Reader 131 | Generic CCID Reader 132 | Generic CCID Reader 133 | Generic CCID Reader 134 | Generic CCID Reader 135 | Generic CCID Reader 136 | Generic CCID Reader 137 | Generic CCID Reader 138 | Generic CCID Reader 139 | Pertosmart Card Reader 140 | Pertosmart Card Reader 141 | Pertosmart Card Reader 142 | Pertosmart Card Reader 143 | Pertosmart Card Reader 144 | Pertosmart Card Reader 145 | WB Electronics Inifinty USB Ulimited 146 | Cyberjack Reader 147 | Aktiv Rutoken S 148 | Aktiv uaToken S 149 | 150 | -------------------------------------------------------------------------------- /etc/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = $(srcdir)/Makefile.in 2 | 3 | SUFFIXES = .in 4 | 5 | sources = openct.udev.in openct.udev.modalias.in openct.udev.compat openct_usb.mdev.in \ 6 | openct.conf.in openct.hald.in reader.conf.in \ 7 | init-script.in openct.hald.in openct_usb.mdev.in \ 8 | openct_usb.in openct_pcmcia.in openct_serial.in 9 | generated_data = openct.udev openct.udev.modalias openct_usb.mdev \ 10 | openct.conf openct.hald reader.conf 11 | noinst_generated_scripts = init-script openct.hald openct_usb.mdev 12 | udev_generated_scripts = openct_usb openct_pcmcia openct_serial 13 | 14 | CLEANFILES = $(generated_data) $(noinst_generated_scripts) $(udev_generated_scripts) 15 | 16 | nodist_noinst_SCRIPTS = $(noinst_generated_scripts) 17 | dist_noinst_DATA = Info.plist openct.fdi openct-policy.fdi openct-disable.fdi $(sources) 18 | nodist_noinst_DATA = $(generated_data) 19 | 20 | if ENABLE_UDEV 21 | nodist_udev_SCRIPTS = $(udev_generated_scripts) 22 | else 23 | nodist_noinst_SCRIPTS += $(udev_generated_scripts) 24 | endif 25 | 26 | if ENABLE_HOTPLUG 27 | hotplug_DATA = openct.usermap 28 | else 29 | dist_noinst_DATA += openct.usermap 30 | endif 31 | 32 | 33 | install-exec-hook: openct.conf 34 | $(MKDIR_P) "$(DESTDIR)$(sysconfdir)" 35 | if [ -f "$(DESTDIR)$(sysconfdir)/openct.conf" ]; then \ 36 | $(INSTALL_DATA) openct.conf "$(DESTDIR)$(sysconfdir)/openct.conf.new"; \ 37 | else \ 38 | $(INSTALL_DATA) openct.conf "$(DESTDIR)$(sysconfdir)/openct.conf"; \ 39 | fi 40 | 41 | .in: 42 | sed \ 43 | -e 's|@bindir[@]|$(bindir)|g' \ 44 | -e 's|@sbindir[@]|$(sbindir)|g' \ 45 | -e 's|@libdir[@]|$(libdir)|g' \ 46 | -e 's|@udevdir[@]|$(udevdir)|g' \ 47 | -e 's|@localstatedir[@]|$(localstatedir)|g' \ 48 | -e 's|@OPENCT_SOCKET_PATH[@]|@OPENCT_SOCKET_PATH@|g' \ 49 | -e 's|@ENABLE_NON_PRIVILEGED[@]|@ENABLE_NON_PRIVILEGED@|g' \ 50 | -e 's|@daemon_user[@]|@daemon_user@|g' \ 51 | -e 's|@daemon_groups[@]|@daemon_groups@|g' \ 52 | < "$<" > "$@" 53 | 54 | uninstall-hook: 55 | rm -f "$(DESTDIR)$(sysconfdir)/openct.conf" 56 | -------------------------------------------------------------------------------- /etc/init-script.in: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | ### BEGIN INIT INFO 4 | # Provides: openct 5 | # Required-Start: $syslog 6 | # Required-Stop: $syslog 7 | # Should-Start: $local_fs 8 | # Should-Stop: $local_fs 9 | # Default-Start: 2 3 4 5 10 | # Default-Stop: 0 1 6 11 | # Short-Description: smart card terminal framework 12 | # Description: Initialize the OpenCT smart card terminal 13 | # framework. 14 | ### END INIT INFO 15 | 16 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 17 | DAEMON=@sbindir@/openct-control 18 | STATUS_DIR="@OPENCT_SOCKET_PATH@" 19 | STATUS_FILE="$STATUS_DIR/status" 20 | NAME=OpenCT 21 | DESC="smart card terminal framework" 22 | 23 | test -x $DAEMON || exit 0 24 | 25 | # create the directory for our status and socket files, 26 | # if it does not exist. 27 | if ! test -e "$STATUS_DIR" 28 | then 29 | mkdir "$STATUS_DIR" 30 | 31 | # maybe you also want to set owner ship and permissions here. 32 | # this example would assign the directory to a group "scard" 33 | # and set permissions so only users in that group can access 34 | # smart card readers via openct. 35 | #chown root:scard "$STATUS_DIR" 36 | #chmod 0750 "$STATUS_DIR" 37 | fi 38 | 39 | set -e 40 | 41 | case "$1" in 42 | start) 43 | echo -n "Starting $DESC: $NAME" 44 | $DAEMON init 45 | echo "." 46 | ;; 47 | stop) 48 | echo -n "Stopping $DESC: $NAME " 49 | if [ -f $STATUS_FILE ]; then 50 | $DAEMON shutdown 51 | rm -f $STATUS_FILE 52 | fi 53 | echo "." 54 | ;; 55 | #reload) 56 | # 57 | # If the daemon can reload its config files on the fly 58 | # for example by sending it SIGHUP, do it here. 59 | # 60 | # If the daemon responds to changes in its config file 61 | # directly anyway, make this a do-nothing entry. 62 | # 63 | # echo -n "Reloading $DESC configuration..." 64 | # start-stop-daemon --stop --signal 1 --quiet --pidfile \ 65 | # @localstatedir@/run/$NAME.pid --exec $DAEMON 66 | # echo "done." 67 | #;; 68 | restart|force-reload) 69 | # 70 | # If the "reload" option is implemented, move the "force-reload" 71 | # option to the "reload" entry above. If not, "force-reload" is 72 | # just the same as "restart". 73 | # 74 | echo -n "Restarting $DESC: $NAME" 75 | if [ -f $STATUS_FILE ]; then 76 | $DAEMON shutdown 77 | rm -f $STATUS_FILE 78 | fi 79 | sleep 0.1 80 | $DAEMON init 81 | echo "." 82 | ;; 83 | *) 84 | N=/etc/init.d/$NAME 85 | # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2 86 | echo "Usage: $N {start|stop|restart|force-reload}" >&2 87 | exit 1 88 | ;; 89 | esac 90 | 91 | exit 0 92 | -------------------------------------------------------------------------------- /etc/openct-disable.fdi: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | hald-addon-openct 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /etc/openct-policy.fdi: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | hald-addon-openct 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /etc/openct.conf.in: -------------------------------------------------------------------------------- 1 | # Set debug level 2 | debug = 0; 3 | # 4 | # Enable hot plugging 5 | hotplug = yes; 6 | 7 | # 8 | # Path to ifdhandler 9 | ifdhandler { 10 | program = @sbindir@/ifdhandler; 11 | # 12 | # Safe to disable force_poll: 13 | # >=linux-2.6.27.14 14 | # >=linux-2.6.28.3 15 | # 16 | force_poll = 1; 17 | @ENABLE_NON_PRIVILEGED@ user = @daemon_user@; 18 | @ENABLE_NON_PRIVILEGED@ groups = { 19 | @ENABLE_NON_PRIVILEGED@ @daemon_groups@, 20 | @ENABLE_NON_PRIVILEGED@ }; 21 | }; 22 | 23 | # 24 | # Configuration for ifdproxy (if you use it) 25 | ifdproxy { 26 | # server-port = @OPENCT_SOCKET_PATH@/.ifdproxy, 27 | # device-port = :6666; 28 | }; 29 | 30 | # Configure static, non-hotplug aware readers here 31 | # 32 | # For a list of drivers try command 'ifdhandler -i', please 33 | # notice that not all drivers have serial device capability. 34 | 35 | #reader towitoko { 36 | # driver = towitoko; 37 | # device = serial:/dev/ttyS0; 38 | #}; 39 | 40 | #reader gempc { 41 | # driver = gempc; 42 | # device = serial:/dev/ttyS0; 43 | #}; 44 | 45 | #reader cm4000 { 46 | # driver = cm4000; 47 | # device = pcmcia:/dev/cmm0; 48 | #}; 49 | 50 | #reader cm4040 { 51 | # driver = ccid; 52 | # device = pcmcia_block:/dev/cmx0; 53 | #}; 54 | 55 | #reader pertosmart1030 { 56 | # driver = pertosmart1030; 57 | # device = serial:/dev/ttyS0; 58 | #}; 59 | 60 | # 61 | # Hotplug IDs 62 | driver egate { 63 | ids = { 64 | usb:0973/0001, 65 | }; 66 | }; 67 | 68 | driver ePass3000 { 69 | ids = { 70 | usb:096e/0401, 71 | }; 72 | }; 73 | 74 | driver etoken { 75 | ids = { 76 | usb:0529/050c, 77 | usb:0529/0514, 78 | }; 79 | }; 80 | driver etoken64 { 81 | ids = { 82 | usb:0529/0600, 83 | usb:0529/0700, 84 | }; 85 | }; 86 | driver eutron { 87 | ids = { 88 | usb:073d/0005, 89 | }; 90 | }; 91 | driver ikey2k { 92 | ids = { 93 | usb:04b9/1202, 94 | }; 95 | }; 96 | driver ikey3k { 97 | ids = { 98 | usb:04b9/1300, 99 | }; 100 | }; 101 | driver starkey { 102 | ids = { 103 | usb:096e/0005, 104 | }; 105 | }; 106 | driver cardman { 107 | ids = { 108 | # usb:076b/0596, # OMNIKEY CardMan 2020 109 | # usb:076b/1784, # OMNIKEY CardMan 6020 110 | # usb:08d4/0009, # Fujitsu Siemens SCR USB Reader 111 | }; 112 | }; 113 | driver ccid { 114 | ids = { 115 | usb:03f0/1024, # HP Keyboard with CCID reader 116 | usb:046a/0010, # Cherry smartboard G83-6744 117 | usb:04e6/5115, 118 | usb:04e6/5116, 119 | usb:04e6/5117, # SCM Micro token size reader 120 | usb:04e6/511d, # SCM Micro SCR3311 121 | usb:04e6/E001, 122 | usb:04e6/E003, 123 | usb:073d/0c00, # Eutron SimPocket (doesn't work yet) 124 | usb:076b/1021, # OmniKey CardMan 1021 125 | usb:076b/3021, 126 | usb:076b/5121, 127 | usb:076b/5321, # OmniKey CardMan 5321 128 | usb:076b/6622, # OmniKey CardMan 6121 129 | usb:0783/0003, 130 | usb:08e6/3437, # Gemplus 131 | usb:08e6/3438, # Gemplus GemPC Key SmartCard Reader 132 | usb:08e6/4433, # Gemplus 133 | usb:0b97/7762, # O2 Micro, Inc. Oz776 SmartCard Reader 134 | usb:0b97/7772, # O2 Micro, Inc. Oz776 SmartCard Reader 135 | usb:0bf8/1006, # fujitsu siemens 3.5" drive size reader 136 | usb:0dc3/1004, # Athena Smartcard Solutions, Inc. ASEKey 137 | usb:0a89/0030, # Aktiv Rutoken ECP 138 | }; 139 | }; 140 | driver pertosmart1030 { 141 | ids = { 142 | usb:072f/0001, 143 | usb:072f/8009, 144 | }; 145 | }; 146 | driver pertosmart1038 { 147 | ids = { 148 | usb:072f/9000, 149 | usb:072f/9006, # ACS CryptoMate Token 150 | usb:072f/9007, # ACS ACR 100 SIMFlash 151 | usb:072f/90d0, 152 | }; 153 | }; 154 | #driver wbeiuu { # driver not working yet 155 | # ids = { 156 | # usb:104f/0004, 157 | # }; 158 | #}; 159 | 160 | # Tested with USBID 0c4b:0100. These are red readers: one with LCD, 161 | # another one without. 162 | driver cyberjack { 163 | ids = { 164 | usb:0c4b/0100, 165 | }; 166 | }; 167 | driver rutoken { 168 | ids = { 169 | usb:0a89/0020, # Aktiv Rutoken S 170 | usb:0a89/0012, # Aktiv uaToken S 171 | }; 172 | }; 173 | -------------------------------------------------------------------------------- /etc/openct.fdi: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | true 9 | 10 | 11 | 12 | 13 | 14 | true 15 | 16 | 17 | 18 | 19 | 20 | true 21 | 22 | 23 | 24 | 25 | 26 | true 27 | 28 | 29 | 30 | 31 | 32 | true 33 | 34 | 35 | 36 | 37 | 38 | true 39 | 40 | 41 | 42 | 43 | 44 | true 45 | 46 | 47 | 48 | 49 | 50 | true 51 | 52 | 53 | 54 | 55 | 56 | true 57 | 58 | 59 | 60 | 61 | 62 | true 63 | 64 | 65 | 66 | 67 | 68 | true 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | 78 | 79 | 80 | true 81 | 82 | 83 | 84 | 85 | 86 | true 87 | 88 | 89 | 90 | 91 | 92 | true 93 | 94 | 95 | 96 | 97 | 98 | true 99 | 100 | 101 | 102 | 103 | 104 | true 105 | 106 | 107 | 108 | 109 | 110 | true 111 | 112 | 113 | 114 | 115 | true 116 | 117 | 118 | 119 | 120 | 121 | true 122 | 123 | 124 | 125 | 126 | 127 | true 128 | 129 | 130 | 131 | 132 | 133 | true 134 | 135 | 136 | 137 | smart_card_reader 138 | @info.parent:linux.device_file 139 | smart_card_reader 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /etc/openct.hald.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PRODUCT="`printf %x/%x/%x $HAL_PROP_USB_VENDOR_ID $HAL_PROP_USB_PRODUCT_ID \ 4 | $HAL_PROP_USB_DEVICE_REVISION_BCD`" 5 | 6 | # this script is run by root, so you can use it to modify 7 | # owner, group and permissions of the device file. 8 | # 9 | # NOTE: Minor race condidion. udev creates nodes with o+r. 10 | # 11 | # commented out for now, every administrator/distribution 12 | # should apply the security policy it prefers. 13 | # 14 | # usualy openct is run as root.root, thus no changes are 15 | # necessary (well, a chmod o-r would be good). but if 16 | # you choose to run openct as a different user or group. 17 | # you need to setup permissions here. 18 | # 19 | #chmod o-r $HAL_PROP_SMART_CARD_READER_DEVICE_FILE 20 | #chown @USER@:@GROUP@ $HAL_PROP_SMART_CARD_READER_DEVICE_FILE 21 | 22 | if test -e "$HAL_PROP_SMART_CARD_READER_DEVICE_FILE" 23 | then 24 | exec @sbindir@/openct-control attach usb:$PRODUCT usb $HAL_PROP_SMART_CARD_READER_DEVICE_FILE 25 | fi 26 | -------------------------------------------------------------------------------- /etc/openct.udev.compat: -------------------------------------------------------------------------------- 1 | 2 | # some distributions might not have a proper rule to set the name. 3 | # this is needed without USB_DEVICEFS the kernel doesn't tell us about 4 | # DEVICE. so we need to know the name of the device created by udev in 5 | # /dev/bus/usb. 6 | SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", \ 7 | NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0644" 8 | 9 | -------------------------------------------------------------------------------- /etc/openct.udev.in: -------------------------------------------------------------------------------- 1 | # udev rules file for openct 2 | 3 | # Update 2009-11-25 4 | # Thanks to Scott James Remnant and Martin Pitt for helping on irc 5 | # to figure out the new syntax / rules for udev. 6 | 7 | # COMPATIBILITY NOTES 8 | # new versions of udev want DRIVERS, older versions only support DRIVER 9 | # new versions of udev want SUBSYSTEMS, older versions only support BUS 10 | # 11 | # new combinations of udev and linux kernel do not create proper events 12 | # (or udev processes them "too fast" / race conditions) or similar. 13 | # as a result there is no way to get openct-control run when a usb smart 14 | # card reader is plugged in. restarting the init script will help as a 15 | # crude workaround. 16 | # 17 | SUBSYSTEM!="usb", GOTO="openct_usb_rules_end" 18 | ACTION!="add", GOTO="openct_usb_rules_end" 19 | 20 | # last file created by the kernel, if this is present everything should be 21 | # KERNEL=="[0-9]*:*", WAIT_FOR_ATTR="bInterfaceProtocol" 22 | # 2010-01-06 removed, as latest udev doesn't know WAIT_FOR_ATTR any more. 23 | 24 | # sleep for 100ms - the wait_for_sysfs might not be enough 25 | PROGRAM="/bin/sleep 0.1" 26 | 27 | # ccid 28 | ATTR{bInterfaceClass}=="0b", ATTR{bInterfaceSubClass}=="00", ATTR{bInterfaceProtocol}=="00", ATTRS{idVendor}=="?*" RUN+="@udevdir@/openct_usb /dev/$parent" 29 | 30 | # egate 31 | ATTR{idVendor}=="0973", ATTR{idProduct}=="0001", RUN+="@udevdir@/openct_usb /dev/$name" 32 | # eToken 33 | ATTR{idVendor}=="0529", ATTR{idProduct}=="050c", RUN+="@udevdir@/openct_usb /dev/$name" 34 | ATTR{idVendor}=="0529", ATTR{idProduct}=="0514", RUN+="@udevdir@/openct_usb /dev/$name" 35 | # eToken 64 36 | ATTR{idVendor}=="0529", ATTR{idProduct}=="0600", RUN+="@udevdir@/openct_usb /dev/$name" 37 | ATTR{idVendor}=="0529", ATTR{idProduct}=="0700", RUN+="@udevdir@/openct_usb /dev/$name" 38 | # eutron 39 | ATTR{idVendor}=="073d", ATTR{idProduct}=="0005", RUN+="@udevdir@/openct_usb /dev/$name" 40 | # ikey2k 41 | ATTR{idVendor}=="04b9", ATTR{idProduct}=="1200", RUN+="@udevdir@/openct_usb /dev/$name" 42 | # ikey3k 43 | ATTR{idVendor}=="04b9", ATTR{idProduct}=="1300", RUN+="@udevdir@/openct_usb /dev/$name" 44 | # starkey 45 | ATTR{idVendor}=="096e", ATTR{idProduct}=="0005", RUN+="@udevdir@/openct_usb /dev/$name" 46 | # cardman 47 | #ATTR{idVendor}=="076b", ATTR{idProduct}=="0596", RUN+="@udevdir@/openct_usb /dev/$name" 48 | #ATTR{idVendor}=="076b", ATTR{idProduct}=="1784", RUN+="@udevdir@/openct_usb /dev/$name" 49 | #ATTR{idVendor}=="08d4", ATTR{idProduct}=="0009", RUN+="@udevdir@/openct_usb /dev/$name" 50 | 51 | # spr 532 - ccid, but with wrong interface class (vendor) :( 52 | ATTR{idVendor}=="04e6", ATTR{idProduct}=="0003", RUN+="@udevdir@/openct_usb /dev/$name" 53 | ATTR{idVendor}=="04e6", ATTR{idProduct}=="E003", RUN+="@udevdir@/openct_usb /dev/$name" 54 | # pertosmart1030 55 | ATTR{idVendor}=="072f", ATTR{idProduct}=="0001", RUN+="@udevdir@/openct_usb /dev/$name" 56 | ATTR{idVendor}=="072f", ATTR{idProduct}=="8009", RUN+="@udevdir@/openct_usb /dev/$name" 57 | # pertosmart1038 58 | ATTR{idVendor}=="072f", ATTR{idProduct}=="9000", RUN+="@udevdir@/openct_usb /dev/$name" 59 | ATTR{idVendor}=="072f", ATTR{idProduct}=="9006", RUN+="@udevdir@/openct_usb /dev/$name" 60 | ATTR{idVendor}=="072f", ATTR{idProduct}=="9007", RUN+="@udevdir@/openct_usb /dev/$name" 61 | ATTR{idVendor}=="072f", ATTR{idProduct}=="90d0", RUN+="@udevdir@/openct_usb /dev/$name" 62 | # wbeiuu - driver not working yet. 63 | #ATTR{idVendor}=="104f", ATTR{idProduct}=="0004", RUN+="@udevdir@/openct_usb /dev/$name" 64 | # cyberjack 65 | ATTR{idVendor}=="0c4b", ATTR{idProduct}=="0100", RUN+="@udevdir@/openct_usb /dev/$name" 66 | # rutoken 67 | ATTR{idVendor}=="0a89", ATTR{idProduct}=="0020", RUN+="@udevdir@/openct_usb /dev/$name" 68 | ATTR{idVendor}=="0a89", ATTR{idProduct}=="0012", RUN+="@udevdir@/openct_usb /dev/$name" 69 | # ePass3000 70 | ATTR{idVendor}=="096e", ATTR{idProduct}=="0401", RUN+="@udevdir@/openct_usb /dev/$name" 71 | 72 | LABEL="openct_usb_rules_end" 73 | 74 | # udev pcmcia rules file for openct 75 | # 76 | SUBSYSTEMS!="pcmcia", GOTO="openct_pcmcia_rules_end" 77 | ACTION!="add", GOTO="openct_pcmcia_rules_end" 78 | 79 | # omnikey cardman 4040 80 | SUBSYSTEM=="cardman_4040", RUN+="@udevdir@/openct_pcmcia /dev/$name" 81 | 82 | # Gemplus PCMCIA Card 83 | DRIVERS=="serial_cs", ATTR{prod_id1}=="Gemplus", ATTR{prod_id2}=="SerialPort", ATTR{prod_id3}=="GemPC Card", RUN+="@udevdir@/openct_serial /dev/$name" 84 | 85 | LABEL="openct_pcmcia_rules_end" 86 | -------------------------------------------------------------------------------- /etc/openct.udev.modalias.in: -------------------------------------------------------------------------------- 1 | # udev rules file for openct 2 | # 3 | # COMPATIBILITY NOTES 4 | # new versions of udev want DRIVERS, older versions only support DRIVER 5 | # new versions of udev want SUBSYSTEMS, older versions only support BUS 6 | # 7 | # new combinations of udev and linux kernel do not create proper events 8 | # (or udev processes them "too fast" / race conditions) or similar. 9 | # as a result there is no way to get openct-control run when a usb smart 10 | # card reader is plugged in. restarting the init script will help as a 11 | # crude workaround. 12 | # 13 | SUBSYSTEM!="usb", GOTO="openct_usb_rules_end" 14 | ACTION!="add", GOTO="openct_usb_rules_end" 15 | 16 | # egate 17 | ENV{MODALIAS}=="usb:v0973p0001*", RUN+="@udevdir@/openct_usb" 18 | # eToken 19 | ENV{MODALIAS}=="usb:v0529p050C*", RUN+="@udevdir@/openct_usb" 20 | ENV{MODALIAS}=="usb:v0529p0514*", RUN+="@udevdir@/openct_usb" 21 | # eToken 64 22 | ENV{MODALIAS}=="usb:v0529p0600*", RUN+="@udevdir@/openct_usb" 23 | ENV{MODALIAS}=="usb:v0529p0700*", RUN+="@udevdir@/openct_usb" 24 | # eutron 25 | ENV{MODALIAS}=="usb:v073Dp0005*", RUN+="@udevdir@/openct_usb" 26 | # ikey2k 27 | ENV{MODALIAS}=="usb:v04B9p1200*", RUN+="@udevdir@/openct_usb" 28 | # ikey3k 29 | ENV{MODALIAS}=="usb:v04B9p1300*", RUN+="@udevdir@/openct_usb" 30 | # starkey 31 | ENV{MODALIAS}=="usb:v096Ep0005*", RUN+="@udevdir@/openct_usb" 32 | # cardman 33 | #ENV{MODALIAS}=="usb:v076Bp0596*", RUN+="@udevdir@/openct_usb" 34 | #ENV{MODALIAS}=="usb:v076Bp1784*", RUN+="@udevdir@/openct_usb" 35 | #ENV{MODALIAS}=="usb:v08D4p0009*", RUN+="@udevdir@/openct_usb" 36 | 37 | # ccid 38 | ENV{MODALIAS}=="usb:*ic0Bisc00*", RUN+="@udevdir@/openct_usb" 39 | 40 | # spr 532 - ccid, but with wrong interface class (vendor) :( 41 | ENV{MODALIAS}=="usb:v04E6p0003*", RUN+="@udevdir@/openct_usb" 42 | ENV{MODALIAS}=="usb:v04E6pE003*", RUN+="@udevdir@/openct_usb" 43 | # pertosmart1030 44 | ENV{MODALIAS}=="usb:v072Fp0001*", RUN+="@udevdir@/openct_usb" 45 | ENV{MODALIAS}=="usb:v072Fp8009*", RUN+="@udevdir@/openct_usb" 46 | # pertosmart1038 47 | ENV{MODALIAS}=="usb:v072Fp9000*", RUN+="@udevdir@/openct_usb" 48 | ENV{MODALIAS}=="usb:v072Fp9006*", RUN+="@udevdir@/openct_usb" 49 | ENV{MODALIAS}=="usb:v072Fp9007*", RUN+="@udevdir@/openct_usb" 50 | ENV{MODALIAS}=="usb:v072Fp90D0*", RUN+="@udevdir@/openct_usb" 51 | # wbeiuu - driver not working yet 52 | #ENV{MODALIAS}=="usb:v104Fp0004*", RUN+="@udevdir@/openct_usb" 53 | # Rutoken S 54 | ENV{MODALIAS}=="usb:v0a89p0020*", RUN+="@udevdir@/openct_usb" 55 | # ePass3000 56 | ENV{MODALIAS}=="usb:v096ep0401*", RUN+="@udevdir@/openct_usb" 57 | 58 | LABEL="openct_usb_rules_end" 59 | 60 | # udev pcmcia rules file for openct 61 | # 62 | SUBSYSTEMS!="pcmcia", GOTO="openct_pcmcia_rules_end" 63 | ACTION!="add", GOTO="openct_pcmcia_rules_end" 64 | 65 | # omnikey cardman 4040 66 | SUBSYSTEM=="cardman_4040", RUN+="@udevdir@/openct_pcmcia" 67 | 68 | # Gemplus PCMCIA Card 69 | DRIVERS=="serial_cs", SYSFS{prod_id1}=="Gemplus", SYSFS{prod_id2}=="SerialPort", SYSFS{prod_id3}=="GemPC Card", RUN+="@udevdir@/openct_serial" 70 | 71 | LABEL="openct_pcmcia_rules_end" 72 | -------------------------------------------------------------------------------- /etc/openct.usermap: -------------------------------------------------------------------------------- 1 | # note: this file is for the old linux hotplug mechanism without udev. 2 | # it is no longer properly maintained and not very much supported - I don't 3 | # have a machine left where I use it. All I can do is answer emails :( 4 | 5 | # module match_flags idVendor idProduct bcdDevice_lo bcdDevice_hi bDeviceClass bDeviceSubClass bDeviceProtocol bInterfaceClass bInterfaceSubClass bInterfaceProtocol driver_info 6 | # egate: 7 | openct 0x0003 0x0973 0x0001 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 8 | # 9 | # eToken 10 | openct 0x0003 0x0529 0x050c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 11 | openct 0x0003 0x0529 0x0514 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 12 | # eToken 64 / NG OTP 13 | openct 0x0003 0x0529 0x0600 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 14 | openct 0x0003 0x0529 0x0700 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 15 | # eutron 16 | openct 0x0003 0x073d 0x0005 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 17 | # ikey2k 18 | openct 0x0003 0x04b9 0x1200 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 19 | # ikey3k 20 | openct 0x0003 0x04b9 0x1300 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 21 | # starkey 22 | openct 0x0003 0x096e 0x0005 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 23 | # cardman 24 | #openct 0x0003 0x076b 0x0596 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 25 | #openct 0x0003 0x076b 0x1784 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 26 | #openct 0x0003 0x08d4 0x0009 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 27 | # ccid 28 | openct 0x0380 0x0000 0x0000 0x0000 0x0000 0x00 0x00 0x00 0x0b 0x00 0x00 0x00000000 29 | # spr 532 - ccid, but with wrong interface class (vendor) :( 30 | openct 0x0003 0x04e6 0x0003 0x0000 0x0000 0x00 0x00 0x00 0x0b 0x00 0x00 0x00000000 31 | openct 0x0003 0x04e6 0xe003 0x0000 0x0000 0x00 0x00 0x00 0x0b 0x00 0x00 0x00000000 32 | # pertosmart1030 33 | openct 0x0003 0x072f 0x0001 0x0000 0x0000 0x00 0x00 0x00 0x0b 0x00 0x00 0x00000000 34 | openct 0x0003 0x072f 0x8009 0x0000 0x0000 0x00 0x00 0x00 0x0b 0x00 0x00 0x00000000 35 | # pertosmart1038 36 | openct 0x0003 0x072f 0x9000 0x0000 0x0000 0x00 0x00 0x00 0x0b 0x00 0x00 0x00000000 37 | openct 0x0003 0x072f 0x9006 0x0000 0x0000 0x00 0x00 0x00 0x0b 0x00 0x00 0x00000000 38 | openct 0x0003 0x072f 0x9007 0x0000 0x0000 0x00 0x00 0x00 0x0b 0x00 0x00 0x00000000 39 | openct 0x0003 0x072f 0x90d0 0x0000 0x0000 0x00 0x00 0x00 0x0b 0x00 0x00 0x00000000 40 | # wbeiuu - driver not working yet 41 | #openct 0x0003 0x104f 0x0004 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 42 | # cyberjack 43 | openct 0x003 0x0c4b 0x0100 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 44 | # rutoken 45 | openct 0x0003 0x0a89 0x0020 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 46 | openct 0x0003 0x0a89 0x0012 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 47 | # ePass3000 48 | openct 0x0003 0x096e 0x0401 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 49 | -------------------------------------------------------------------------------- /etc/openct_pcmcia.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | test "$ACTION" = "add" || exit 0 4 | test -n "$DEVNAME" || exit 0 5 | test -e "@OPENCT_SOCKET_PATH@/status" || exit 0 6 | 7 | if [ -n "$DEVNAME" ] 8 | then 9 | @sbindir@/openct-control attach ccid pcmcia_block $DEVNAME 10 | exit 0 11 | fi 12 | -------------------------------------------------------------------------------- /etc/openct_serial.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | test "$ACTION" = "add" || exit 0 4 | test -n "$DEVNAME" || exit 0 5 | test -e "@OPENCT_SOCKET_PATH@/status" || exit 0 6 | 7 | if [ -n "$DEVNAME" ] 8 | then 9 | @sbindir@/openct-control attach ccid serial $DEVNAME 10 | exit 0 11 | fi 12 | -------------------------------------------------------------------------------- /etc/openct_usb.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # maybe udev passes the device name to us. 4 | if [ -n "$1" ]; then 5 | DEVNAME="$1" 6 | fi 7 | 8 | [ -n "$DEVPATH" ] || exit 0 9 | [ "$ACTION" = "add" ] || exit 0 10 | [ -e "@OPENCT_SOCKET_PATH@/status" ] || exit 0 11 | 12 | # try to get the device node from the parent device 13 | if [ -z "$DEVNAME" ]; then 14 | # 15 | # Guess udev info interface. 16 | # Newer udev uses udevadm 17 | # 18 | if which udevinfo > /dev/null 2>&1; then 19 | UDEVINFO="udevinfo" 20 | else 21 | UDEVINFO="udevadm info" 22 | fi 23 | DEVNAME=/dev/$($UDEVINFO --query=name --path=$(dirname $DEVPATH)) 24 | fi 25 | 26 | # if udev supplied a device node directly from the usb-device, we use it, 27 | # because it is guaranteed to exist at the time we run 28 | if [ -n "$DEVNAME" -a -e "$DEVNAME" ]; then 29 | DEVICE="$DEVNAME" 30 | fi 31 | 32 | [ -n "$DEVICE" ] || exit 0 33 | 34 | if [ -z "$PRODUCT" -a -n "$MODALIAS" ]; then 35 | PRODUCT=$(echo $MODALIAS | sed -e 's/usb:v\(....\)p\(....\)d\(....\).*/\1\/\2\/\3/g' |tr A-F a-f) 36 | fi 37 | 38 | if [ -z "$PRODUCT" ]; then 39 | V=$(cat /sys$(dirname $DEVPATH)/idVendor | sed -e 's/^0*//') 40 | P=$(cat /sys$(dirname $DEVPATH)/idProduct | sed -e 's/^0*//') 41 | D=$(cat /sys$(dirname $DEVPATH)/bcdDevice | sed -e 's/^0*//') 42 | PRODUCT="$V/$P/$D" 43 | fi 44 | 45 | [ -n "$PRODUCT" ] || exit 0 46 | 47 | # we may neeed to wait for the device node, when usbfs is used 48 | for A in "0 1 2 3 4 5 6 7 8 9"; do 49 | if [ -e "$DEVICE" ]; then 50 | @sbindir@/openct-control attach usb:$PRODUCT usb $DEVICE 51 | exit 0 52 | fi 53 | sleep 0.1 54 | done 55 | 56 | echo "$0 waited for $DEVICE but it did not appear." | logger -p daemon.error 57 | exit 0 58 | -------------------------------------------------------------------------------- /etc/openct_usb.mdev.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copy to /lib/mdev/openct_usb 5 | # Put the following in /etc/mdev.conf: 6 | # .* 0:0 0660 @/lib/mdev/openct_usb 7 | # For some strange reason "usb.*" does not catch the event. 8 | # 9 | [ -n "${DEVPATH}" ] || exit 0 10 | [ "${ACTION}" = "add" ] || exit 0 11 | [ "${DEVTYPE}" = "usb_device" ] || exit 0 12 | 13 | DEVICE="/dev/bus/usb/${BUSNUM}/${DEVNUM}" 14 | 15 | if ! [ -e "${DEVICE}" ]; then 16 | mkdir -p "$(dirname "${DEVICE}")" 17 | mknod "${DEVICE}" c ${MAJOR} ${MINOR} 18 | fi 19 | 20 | [ -e "@OPENCT_SOCKET_PATH@/status" ] || exit 0 21 | 22 | # Don't know why... 23 | sleep 1 24 | 25 | @sbindir@/openct-control attach "usb:${PRODUCT}" usb "${DEVICE}" 26 | -------------------------------------------------------------------------------- /etc/reader.conf.in: -------------------------------------------------------------------------------- 1 | # OpenCT configuration file for pcsc-lite 2 | # http://www.opensc.org/openct/ 3 | 4 | FRIENDLYNAME "OpenCT" 5 | DEVICENAME /dev/null 6 | LIBPATH @libdir@/openct-ifd.so 7 | CHANNELID 0 8 | 9 | # End of file 10 | -------------------------------------------------------------------------------- /macos/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = $(srcdir)/Makefile.in 2 | 3 | dist_noinst_SCRIPTS = libtool-bundle 4 | -------------------------------------------------------------------------------- /macos/libtool-bundle: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # A shell script to create MacOS X bundles 3 | # from files created by GNU libtool. 4 | # Incomplete, but works. 5 | # 6 | # $Id$ 7 | # 8 | # 9 | 10 | set -e 11 | verbose=0 12 | 13 | verbose_msg () 14 | { 15 | if [ $verbose -ne 0 ]; then 16 | echo "libtool-bundle: $@" 17 | fi 18 | } 19 | 20 | error_msg () 21 | { 22 | echo 1>&2 "libtool-bundle: $@" 23 | } 24 | 25 | usage () 26 | { 27 | error_msg "Usage: $0 [-e extra XML data] [Mach-O bundle file] [destination directory] " 28 | exit 1 29 | } 30 | 31 | case $1 in 32 | -e) shift; if [ "$1" ]; then extradata=$1; shift; else usage; fi; ;; 33 | esac 34 | 35 | [ $# -le 1 -o $# -ge 4 ] && usage 36 | 37 | sofile=$1 38 | [ ! -f $sofile ] && error_msg "Not a file or file not found: $sofile" && exit 1 39 | case "$sofile" in 40 | *.so*) 41 | # Assume it's ok 42 | ;; 43 | *) 44 | error_msg "Invalid bundle: $sofile" 45 | exit 1 46 | ;; 47 | esac 48 | 49 | destdir=$2 50 | [ ! -d $destdir -o ! -w $destdir ] && error_msg "Not a directory or no write access: $destdir" && exit 1 51 | 52 | name="$sofile" 53 | [ $# -eq 3 ] && name=$3 54 | name=`echo $name | sed -e "s@.*/@@" -e "s@\.so.*@@"` 55 | root="$destdir/${name}.bundle" 56 | 57 | verbose_msg "sofile: $sofile" 58 | verbose_msg "destdir: $destdir" 59 | verbose_msg "name: $name" 60 | verbose_msg "root: $root" 61 | 62 | arch=`uname` 63 | [ x$arch = xDarwin ] && arch=MacOS 64 | type="BNDL" 65 | creator="????" 66 | 67 | # Overwrite existing bundle 68 | [ -d "$root" ] && rm -rf "$root" 69 | 70 | mkdir -p "$root"/Contents/$arch 71 | cp "$sofile" "$root"/Contents/$arch/ 72 | echo "$type$creator" > "$root"/Contents/PkgInfo 73 | 74 | create_info_plist () 75 | { 76 | echo "" 77 | echo "" 78 | echo "" 79 | echo "" 80 | echo " CFBundleDevelopmentRegion" 81 | echo " English" 82 | echo " CFBundleExecutable" 83 | echo " `basename \"$sofile\"`" 84 | echo " CFBundleInfoDictionaryVersion" 85 | echo " 6.0" 86 | echo " CFBundleName" 87 | echo " $name" 88 | echo " CFBundlePackageType" 89 | echo " $type" 90 | echo " CFBundleSignature" 91 | echo " $creator" 92 | echo " CFBundleVersion" 93 | echo " 0.0.1d1" 94 | if [ "$extradata" ]; then 95 | echo "" 96 | [ -f "$extradata" ]; cat $extradata 97 | fi 98 | echo "" 99 | echo "" 100 | } 101 | 102 | create_info_plist > "$root"/Contents/Info.plist 103 | 104 | echo "Installed $sofile as $root" 105 | -------------------------------------------------------------------------------- /solaris/Makefile.client: -------------------------------------------------------------------------------- 1 | PACKAGE=OSCopenct 2 | PACKAGE_NAME=openct 3 | CLASSES=none 4 | CATEGORY=drivers 5 | VENDOR=OSC 6 | EMAIL=william@wanders.org 7 | DATE=date 8 | PSTAMP=$(DATE:sh) 9 | VERSION=SVN 10 | PWD=pwd 11 | CONFIGURE_PREFIX=$(PWD:sh)/.. 12 | CONFIGURE=${CONFIGURE_PREFIX}/configure 13 | CONFIGURE_ARGS=--prefix=/usr --sysconfdir=/etc/openct --enable-sunrayclient 14 | CONFIG_GUESS=${CONFIGURE_PREFIX}/config.guess 15 | UNAME_ARCH=/sbin/uname -p 16 | PLATFORM = $(CONFIG_GUESS:sh) 17 | ARCH = $(UNAME_ARCH:sh) 18 | 19 | build: 20 | @echo "Setup platform specific build directory ${PLATFORM}" 21 | mkdir -p build-${PLATFORM} 22 | ( cd build-${PLATFORM}; CC=cc ${CONFIGURE} ${CONFIGURE_ARGS}; make ) 23 | 24 | dist: 25 | @echo "Setup platform specific dist directory dist-${PLATFORM}" 26 | mkdir -p dist-${PLATFORM} 27 | @echo "Performing Installing in dist directory" 28 | ( cd build-${PLATFORM}; make DESTDIR=`pwd`/../dist-${PLATFORM} install ) 29 | 30 | package: 31 | @echo "Setup package meta files" 32 | -rm proto checkinstall pkginfo 33 | -sed "s|@ARCH@|${ARCH}|" checkinstall 34 | -( echo "PKG=\"${PACKAGE}\""; \ 35 | echo "NAME=\"${PACKAGE_NAME}\""; \ 36 | echo "VERSION=\"${VERSION}\""; \ 37 | echo "ARCH=\"${ARCH}\""; \ 38 | echo "CLASSES=\"${CLASSES}\""; \ 39 | echo "CATEGORY=\"${CATEGORY}\""; \ 40 | echo "VENDOR=\"${VENDOR}\""; \ 41 | echo "PSTAMP=\"${PSTAMP}\""; \ 42 | echo "EMAIL=\"${EMAIL}\""; \ 43 | echo "ISTATES=\"S s 1 2 3\""; \ 44 | echo "RSTATES=\"S s 1 2 3\""; \ 45 | echo "BASEDIR=\"/\"" ) >pkginfo 46 | @echo "Setup package distribution" 47 | mkdir -p dist-${PLATFORM}/etc/openct 48 | -cp openct.conf-dist dist-${PLATFORM}/etc/openct/openct.conf 49 | -( pkgproto dist-${PLATFORM}= | sed -e "s|$(LOGNAME) other$$|root bin|" | egrep -v "(s|d) none (/|/etc|/var|/usr|/usr/local) "; \ 50 | echo "i checkinstall=checkinstall"; \ 51 | echo "i pkginfo=pkginfo" ) >proto 52 | @echo "Creating package" 53 | -pkgmk -o -r . -d . -f proto 54 | -pkgtrans -s . ${PACKAGE_NAME}-${VERSION}-${PLATFORM}.pkg ${PACKAGE} 55 | 56 | clean: 57 | rm -rf build-${PLATFORM} 58 | rm -rf dist-${PLATFORM} 59 | rm -rf ${PACKAGE} 60 | rm -f proto checkinstall pkginfo 61 | 62 | veryclean: clean 63 | rm -f ${PACKAGE_NAME}-${VERSION}-${PLATFORM}.pkg 64 | -------------------------------------------------------------------------------- /solaris/Makefile.server: -------------------------------------------------------------------------------- 1 | PACKAGE=OSCutopenct 2 | PACKAGE_NAME=utopenct 3 | CLASSES=none 4 | CATEGORY=drivers 5 | VENDOR=OSC 6 | EMAIL=william@wanders.org 7 | DATE=date 8 | PSTAMP=$(DATE:sh) 9 | VERSION=SVN 10 | PWD=pwd 11 | CONFIGURE_PREFIX=$(PWD:sh)/.. 12 | CONFIGURE=${CONFIGURE_PREFIX}/configure 13 | CONFIGURE_ARGS=--prefix=/opt/SUNWut --sysconfdir=/etc/opt/SUNWut/openct --enable-sunray 14 | CONFIG_GUESS=${CONFIGURE_PREFIX}/config.guess 15 | UNAME_ARCH=/sbin/uname -p 16 | PLATFORM = $(CONFIG_GUESS:sh) 17 | ARCH = $(UNAME_ARCH:sh) 18 | 19 | build: 20 | @echo "Setup platform specific build directory ${PLATFORM}" 21 | mkdir -p build-${PLATFORM} 22 | ( cd build-${PLATFORM}; CC=cc ${CONFIGURE} ${CONFIGURE_ARGS}; make ) 23 | 24 | dist: 25 | @echo "Setup platform specific dist directory dist-${PLATFORM}" 26 | mkdir -p dist-${PLATFORM} 27 | @echo "Performing Installing in dist directory" 28 | ( cd build-${PLATFORM}; make DESTDIR=`pwd`/../dist-${PLATFORM} install ) 29 | 30 | package: 31 | @echo "Setup package meta files" 32 | -rm proto checkinstall pkginfo 33 | -sed "s|@ARCH@|${ARCH}|" checkinstall 34 | -( echo "PKG=\"${PACKAGE}\""; \ 35 | echo "NAME=\"${PACKAGE_NAME}\""; \ 36 | echo "VERSION=\"${VERSION}\""; \ 37 | echo "ARCH=\"${ARCH}\""; \ 38 | echo "CLASSES=\"${CLASSES}\""; \ 39 | echo "CATEGORY=\"${CATEGORY}\""; \ 40 | echo "VENDOR=\"${VENDOR}\""; \ 41 | echo "PSTAMP=\"${PSTAMP}\""; \ 42 | echo "EMAIL=\"${EMAIL}\""; \ 43 | echo "ISTATES=\"S s 1 2 3\""; \ 44 | echo "RSTATES=\"S s 1 2 3\""; \ 45 | echo "BASEDIR=\"/\"" ) >pkginfo 46 | @echo "Setup package distribution" 47 | mkdir -p dist-${PLATFORM}/etc/opt/SUNWut/openct 48 | -cp openct.conf-dist dist-${PLATFORM}/etc/opt/SUNWut/openct/openct.conf 49 | -( pkgproto dist-${PLATFORM}= | sed -e "s|$(LOGNAME) other$$|root bin|" | egrep -v "(s|d) none (/|/etc|/var|/usr|/usr/local) "; \ 50 | echo "i checkinstall=checkinstall"; \ 51 | echo "i pkginfo=pkginfo" ) >proto 52 | @echo "Creating package" 53 | -pkgmk -o -r . -d . -f proto 54 | -pkgtrans -s . ${PACKAGE_NAME}-${VERSION}-${PLATFORM}.pkg ${PACKAGE} 55 | 56 | clean: 57 | rm -rf build-${PLATFORM} 58 | rm -rf dist-${PLATFORM} 59 | rm -rf ${PACKAGE} 60 | rm -f proto checkinstall pkginfo 61 | 62 | veryclean: clean 63 | rm -f ${PACKAGE_NAME}-${VERSION}-${PLATFORM}.pkg 64 | -------------------------------------------------------------------------------- /solaris/README: -------------------------------------------------------------------------------- 1 | Creating an installable package for Solaris Sunray (SRSS 3.1) 2 | ============================================================= 3 | 4 | The files in this directory are an attempt to ease 5 | the building of openct packages for Solaris running 6 | as Sunray Server. 7 | 8 | The basic steps to create Solaris packages are: 9 | # make -f Makefile.server build 10 | # make -f Makefile.server dist 11 | # make -f Makefile.server package 12 | # make -f Makefile.client build 13 | # make -f Makefile.client dist 14 | # make -f Makefile.client package 15 | 16 | NOTE: If using the GNU compiler adjust the Makefile 17 | 18 | TODO: 19 | 20 | Start/stop utopenct service for active Sunrays. 21 | -------------------------------------------------------------------------------- /solaris/checkinstall.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | expected_platform="@ARCH@" 4 | platform=`uname -p` 5 | if [ ${platform} != ${expected_platform} ]; then 6 | echo "This package must be installed on ${expected_platform}" 7 | exit 1 8 | fi 9 | exit 0 10 | -------------------------------------------------------------------------------- /solaris/devices-openct-fabric.xml-dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 26 | 27 | 28 | 36 | 37 | 42 | 43 | 48 | 49 | 50 | 52 | 53 | 54 | 55 | 56 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /solaris/openct-fabric-dist: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | # 3 | # Copyright 2005 William Wanders. All rights reserved. 4 | # Use is subject to license terms. 5 | # 6 | # ident "@(#)openct-fabric 1.1 04/08/31 SMI" 7 | # 8 | # This script is used initialize and shutdown the OpenCT fabric 9 | # 10 | 11 | case "$1" in 12 | 'start') 13 | # Create directory for OpenCT fabric 14 | if [ ! -d /var/run/openct ] 15 | then 16 | mkdir -p /var/run/openct 17 | fi 18 | 19 | # Startup the OpenCT fabric 20 | if [ ! -f /var/run/openct/status ] 21 | then 22 | /usr/sbin/openct-control init 23 | fi 24 | 25 | # Add sysevent handler for hotplug support 26 | if syseventadm list \ 27 | -v SUNW -p ddi -c EC_devfs -s ESC_devfs_devi_add \ 28 | /usr/sbin/openct-hotplug '${di.path}' >/dev/null 29 | then 30 | echo "system eventhandler already added" 31 | else 32 | syseventadm add \ 33 | -v SUNW -p ddi -c EC_devfs -s ESC_devfs_devi_add \ 34 | /usr/sbin/openct-hotplug '${di.path}' 35 | fi 36 | ;; 37 | 'stop') 38 | # Remove sysevent handler for hotplug support 39 | if syseventadm list \ 40 | -v SUNW -p ddi -c EC_devfs -s ESC_devfs_devi_add \ 41 | /usr/sbin/openct-hotplug '${di.path}' >/dev/null 42 | then 43 | syseventadm remove \ 44 | -v SUNW -p ddi -c EC_devfs -s ESC_devfs_devi_add \ 45 | /usr/sbin/openct-hotplug '${di.path}' 46 | fi 47 | 48 | # Shutdown the OpenCT fabric 49 | if [ -f /var/run/openct/status ] 50 | then 51 | /usr/sbin/openct-control shutdown 52 | fi 53 | 54 | # Cleanup the OpenCT fabric directory 55 | if [ -d /var/run/openct ] 56 | then 57 | rm -rf /var/run/openct 58 | fi 59 | ;; 60 | 'status') 61 | /usr/sbin/openct-control status 62 | ;; 63 | *) 64 | echo "Usage: $0 { start | stop | status}" 65 | exit 1 66 | ;; 67 | esac 68 | 69 | exit $? 70 | -------------------------------------------------------------------------------- /solaris/openct-hotplug-dist: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # USB Hotplug script for OpenCT on Solaris 4 | # 5 | # This script should be run by sysevent daemon (sysevent[conf]d). 6 | # 7 | # This can be configured by issuing the followin comand as "root". 8 | # 9 | # syseventadm add -v SUNW -p ddi -c EC_devfs -s ESC_devfs_devi_add \ 10 | # /usr/sbin/openct-hotplug '${di.path}' 11 | # 12 | # The script will search for the applicable /dev link file for 13 | # the given device. If such link is found it means that the 14 | # device is bound in the system through the ugen device driver 15 | # and should be accessable by OpenCT. An openct-control command 16 | # is then issued to attach the device. 17 | # 18 | OPENCT_CONTROL=/usr/sbin/openct-control 19 | DEVICE=$1 20 | 21 | for CNTRL0 in `ls /devices$DEVICE:[0-9a-f]*.[0-9a-f]*.cntrl0 2>/dev/null` 22 | do 23 | #echo "CNTRL0=$CNTRL0" 24 | VENDOR_PRODUCT=`echo $CNTRL0 | sed "s|/devices$DEVICE:\([0-9a-f]*\.[0-9a-f]*\).cntrl0|\1|"` 25 | #echo "VENDOR_PRODUCT=$VENDOR_PRODUCT" 26 | for CNTRL0_INSTANCE in `ls /dev/usb/$VENDOR_PRODUCT/*/cntrl0 2>/dev/null` 27 | do 28 | #echo "CNTRL0_INSTANCE=$CNTRL0_INSTANCE" 29 | if `ls -l "$CNTRL0_INSTANCE" | grep "$DEVICE" >/dev/null` 30 | then 31 | #echo "$CNTRL0_INSTANCE points to /pci@1f,0/pci@5/usb@0,1/device@2" 32 | VENDOR=`echo $VENDOR_PRODUCT | sed "s|\([0-9a-f]*\)\.\([0-9a-f]*\)|\1|"` 33 | PRODUCT=`echo $VENDOR_PRODUCT | sed "s|\([0-9a-f]*\)\.\([0-9a-f]*\)|\2|"` 34 | #echo "VENDOR=$VENDOR" 35 | #echo "PRODUCT=$PRODUCT" 36 | ID_INSTANCE=`printf "usb:%04x/%04x" 0x$VENDOR 0x$PRODUCT` 37 | logger -i -p local0.notice -t openct-hotplug "$OPENCT_CONTROL attach $CNTRL0_INSTANCE $ID_INSTANCE" 38 | $OPENCT_CONTROL attach $CNTRL0_INSTANCE $ID_INSTANCE 39 | fi 40 | done 41 | done 42 | exit 0 43 | -------------------------------------------------------------------------------- /solaris/openct.conf-dist: -------------------------------------------------------------------------------- 1 | # Set debug level 2 | debug = 0; 3 | # 4 | # Enable hot plugging 5 | hotplug = yes; 6 | # 7 | # Path to ifdhandler 8 | ifdhandler = /opt/SUNWut/sbin/ifdhandler; 9 | 10 | # 11 | # Configuration for ifdproxy (if you use it) 12 | ifdproxy { 13 | # server-port = /var/run/openct/.ifdproxy, 14 | # device-port = :6666; 15 | }; 16 | 17 | # Configure static, non-hotplug aware readers here 18 | # 19 | # For a list of drivers try command 'ifdhandler -i', please 20 | # notice that not all drivers have serial device capability. 21 | 22 | #reader towitoko { 23 | # driver = towitoko; 24 | # device = serial:/dev/ttyS0; 25 | #}; 26 | 27 | # 28 | # Hotplug IDs 29 | driver egate { 30 | ids = { 31 | usb:0973/0001, 32 | }; 33 | }; 34 | driver etoken { 35 | ids = { 36 | usb:0529/050c, 37 | usb:0529/0514, 38 | }; 39 | }; 40 | driver eutron { 41 | ids = { 42 | usb:073d/0005, 43 | }; 44 | }; 45 | driver ikey2k { 46 | ids = { 47 | usb:04b9/1202, 48 | }; 49 | }; 50 | driver ikey3k { 51 | ids = { 52 | usb:04b9/1300, 53 | }; 54 | }; 55 | driver cardman { 56 | ids = { 57 | usb:076b/0596, # OMNIKEY CardMan 2020 58 | usb:076b/1784, # OMNIKEY CardMan 6020 59 | usb:08d4/0009, # Fujitsu Siemens SCR USB Reader 60 | }; 61 | }; 62 | driver ccid { 63 | ids = { 64 | usb:08e6/3437, 65 | usb:08e6/3438, 66 | usb:08e6/4433, 67 | usb:04e6/5115, 68 | usb:04e6/E001, 69 | usb:04e6/E003, 70 | usb:076b/3021, 71 | usb:0783/0003, 72 | }; 73 | }; 74 | 75 | -------------------------------------------------------------------------------- /solaris/pkginfo.in: -------------------------------------------------------------------------------- 1 | PKG="OSCopenct" 2 | NAME="openct" 3 | VERSION="@VERSION@" 4 | ARCH="@ARCH@" 5 | CLASSES="none" 6 | CATEGORY="drivers" 7 | VENDOR="OSC" 8 | PSTAMP="26thFeb2005" 9 | EMAIL="william@wanders.org" 10 | ISTATES="S s 1 2 3" 11 | RSTATES="S s 1 2 3" 12 | BASEDIR="/" 13 | -------------------------------------------------------------------------------- /solaris/postinstall: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | svccfg import /var/svc/manifest/system/device/devices-openct-fabric.xml 4 | exit 0 5 | -------------------------------------------------------------------------------- /solaris/preremove: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | svcadm disable openct-fabric 4 | svccfg delete openct-fabric 5 | exit 0 6 | -------------------------------------------------------------------------------- /solaris/proto: -------------------------------------------------------------------------------- 1 | d none usr 0755 root sys 2 | d none usr/include 0755 root bin 3 | d none usr/include/openct 0755 root bin 4 | f none usr/include/openct/apdu.h 0644 root bin 5 | f none usr/include/openct/buffer.h 0644 root bin 6 | f none usr/include/openct/conf.h 0644 root bin 7 | f none usr/include/openct/device.h 0644 root bin 8 | f none usr/include/openct/driver.h 0644 root bin 9 | f none usr/include/openct/error.h 0644 root bin 10 | f none usr/include/openct/ifd.h 0644 root bin 11 | f none usr/include/openct/logging.h 0644 root bin 12 | f none usr/include/openct/openct.h 0644 root bin 13 | f none usr/include/openct/protocol.h 0644 root bin 14 | f none usr/include/openct/server.h 0644 root bin 15 | f none usr/include/openct/socket.h 0644 root bin 16 | f none usr/include/openct/tlv.h 0644 root bin 17 | f none usr/include/openct/types.h 0644 root bin 18 | f none usr/include/openct/ctapi.h 0644 root bin 19 | d none usr/lib 0755 root bin 20 | s none usr/lib/libopenct.so.0=libopenct.so.0.0.2 21 | f none usr/lib/libopenct.so.0.0.2 0755 root bin 22 | s none usr/lib/libopenct.so=libopenct.so.0.0.2 23 | d none usr/lib/pkgconfig 0755 root other 24 | f none usr/lib/pkgconfig/libopenct.pc 0644 root other 25 | f none usr/lib/libopenct.la 0755 root bin 26 | f none usr/lib/libopenct.a 0644 root bin 27 | s none usr/lib/libifd.so.0=libifd.so.0.0.2 28 | f none usr/lib/libifd.so.0.0.2 0755 root bin 29 | s none usr/lib/libifd.so=libifd.so.0.0.2 30 | f none usr/lib/libifd.la 0755 root bin 31 | f none usr/lib/libifd.a 0644 root bin 32 | f none usr/lib/libopenctapi.so 0755 root bin 33 | f none usr/lib/libopenctapi.la 0755 root bin 34 | f none usr/lib/libopenctapi.a 0644 root bin 35 | f none usr/lib/openct-ifd.so 0755 root bin 36 | f none usr/lib/openct-ifd.la 0755 root bin 37 | f none usr/lib/openct-ifd.a 0644 root bin 38 | d none usr/lib/openct-ifd.bundle 0755 root bin 39 | d none usr/lib/openct-ifd.bundle/Contents 0755 root bin 40 | d none usr/lib/openct-ifd.bundle/Contents/SunOS 0755 root bin 41 | f none usr/lib/openct-ifd.bundle/Contents/SunOS/openct-ifd 0755 root bin 42 | f none usr/lib/openct-ifd.bundle/Contents/PkgInfo 0644 root bin 43 | f none usr/lib/openct-ifd.bundle/Contents/Info.plist 0644 root bin 44 | d none usr/sbin 0755 root bin 45 | f none usr/sbin/ifdhandler 0755 root bin 46 | f none usr/sbin/ifdproxy 0755 root bin 47 | f none usr/sbin/openct-control 0755 root bin 48 | f none usr/sbin/openct-hotplug 0755 root bin 49 | d none usr/bin 0755 root bin 50 | f none usr/bin/openct-tool 0755 root bin 51 | d none etc 0755 root sys 52 | d none etc/openct 0755 root sys 53 | f none etc/openct/openct.conf 0644 root sys 54 | d none lib 0755 root bin 55 | d none lib/svc 0755 root bin 56 | d none lib/svc/method 0755 root bin 57 | f none lib/svc/method/openct-fabric 0755 root bin 58 | d none var 0755 root sys 59 | d none var/svc 0755 root sys 60 | d none var/svc/manifest 0755 root sys 61 | d none var/svc/manifest/system 0755 root sys 62 | d none var/svc/manifest/system/device 0755 root sys 63 | f none var/svc/manifest/system/device/devices-openct-fabric.xml 0644 root sys 64 | i checkinstall=checkinstall 65 | i postinstall=postinstall 66 | i preremove=preremove 67 | i pkginfo=pkginfo 68 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = $(srcdir)/Makefile.in 2 | 3 | # Order IS important 4 | SUBDIRS = include ct ifd tools ctapi pcsc 5 | -------------------------------------------------------------------------------- /src/ct/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = $(srcdir)/Makefile.in 2 | 3 | lib_LTLIBRARIES = libopenct.la 4 | pkgconfig_DATA = libopenct.pc 5 | 6 | libopenct_la_SOURCES = \ 7 | buffer.c client.c error.c mainloop.c path.c \ 8 | socket.c status.c tlv.c 9 | libopenct_la_CFLAGS = $(AM_CFLAGS) \ 10 | -I$(top_srcdir)/src/include \ 11 | -I$(top_builddir)/src/include 12 | libopenct_la_LDFLAGS = \ 13 | -version-info @OPENCT_LT_CURRENT@:@OPENCT_LT_REVISION@:@OPENCT_LT_AGE@ \ 14 | -no-undefined 15 | -------------------------------------------------------------------------------- /src/ct/buffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Buffer handling functions 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #ifdef HAVE_CONFIG_H 8 | #include 9 | #endif 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | void ct_buf_init(ct_buf_t * bp, void *mem, size_t len) 16 | { 17 | memset(bp, 0, sizeof(*bp)); 18 | bp->base = (unsigned char *)mem; 19 | bp->size = len; 20 | } 21 | 22 | void ct_buf_set(ct_buf_t * bp, void *mem, size_t len) 23 | { 24 | ct_buf_init(bp, mem, len); 25 | bp->tail = len; 26 | } 27 | 28 | void ct_buf_clear(ct_buf_t * bp) 29 | { 30 | bp->head = bp->tail = 0; 31 | } 32 | 33 | int ct_buf_get(ct_buf_t * bp, void *mem, size_t len) 34 | { 35 | if (len > bp->tail - bp->head) 36 | return -1; 37 | if (mem) 38 | memcpy(mem, bp->base + bp->head, len); 39 | bp->head += len; 40 | return len; 41 | } 42 | 43 | int ct_buf_gets(ct_buf_t * bp, char *buffer, size_t size) 44 | { 45 | unsigned int n, avail; 46 | unsigned char *s; 47 | 48 | size -= 1; /* room for NUL byte */ 49 | 50 | /* Limit string to what we have */ 51 | avail = bp->tail - bp->head; 52 | if (size > avail) 53 | size = avail; 54 | 55 | /* Look for newline */ 56 | s = bp->base + bp->head; 57 | for (n = 0; n < size && s[n] != '\n'; n++) ; 58 | 59 | /* Copy string (excluding newline) */ 60 | memcpy(buffer, s, n); 61 | buffer[n] = '\0'; 62 | 63 | /* And eat any characters that weren't copied 64 | * (including the newline) 65 | */ 66 | while (n < avail && s[n++] != '\n') ; 67 | 68 | bp->head += n; 69 | return 0; 70 | } 71 | 72 | int ct_buf_put(ct_buf_t * bp, const void *mem, size_t len) 73 | { 74 | if (len > bp->size - bp->tail) 75 | ct_buf_compact(bp); 76 | if (len > bp->size - bp->tail) { 77 | bp->overrun = 1; 78 | return -1; 79 | } 80 | if (mem) 81 | memcpy(bp->base + bp->tail, mem, len); 82 | bp->tail += len; 83 | return len; 84 | } 85 | 86 | int ct_buf_push(ct_buf_t * bp, const void *mem, size_t len) 87 | { 88 | if (bp->head < len) 89 | return -1; 90 | bp->head -= len; 91 | if (mem) 92 | memcpy(bp->base + bp->head, mem, len); 93 | return len; 94 | } 95 | 96 | int ct_buf_putc(ct_buf_t * bp, int byte) 97 | { 98 | unsigned char c = byte; 99 | 100 | return ct_buf_put(bp, &c, 1); 101 | } 102 | 103 | int ct_buf_puts(ct_buf_t * bp, const char *string) 104 | { 105 | return ct_buf_put(bp, string, strlen(string)); 106 | } 107 | 108 | unsigned int ct_buf_avail(ct_buf_t * bp) 109 | { 110 | return bp->tail - bp->head; 111 | } 112 | 113 | unsigned int ct_buf_tailroom(ct_buf_t * bp) 114 | { 115 | return bp->size - bp->tail; 116 | } 117 | 118 | unsigned int ct_buf_size(ct_buf_t * bp) 119 | { 120 | return bp->size; 121 | } 122 | 123 | void *ct_buf_head(ct_buf_t * bp) 124 | { 125 | return bp->base + bp->head; 126 | } 127 | 128 | void *ct_buf_tail(ct_buf_t * bp) 129 | { 130 | return bp->base + bp->tail; 131 | } 132 | 133 | int ct_buf_read(ct_buf_t * bp, int fd) 134 | { 135 | unsigned int count; 136 | int n; 137 | 138 | ct_buf_compact(bp); 139 | 140 | count = bp->size - bp->tail; 141 | if ((n = read(fd, bp->base + bp->tail, count)) < 0) 142 | return -1; 143 | bp->tail += n; 144 | return 0; 145 | } 146 | 147 | void ct_buf_compact(ct_buf_t * bp) 148 | { 149 | unsigned int count; 150 | 151 | if (bp->head == 0) 152 | return; 153 | 154 | count = bp->tail - bp->head; 155 | memmove(bp->base, bp->base + bp->head, count); 156 | bp->tail -= bp->head; 157 | bp->head = 0; 158 | } 159 | 160 | int ct_buf_overrun(ct_buf_t * bp) 161 | { 162 | return bp->overrun; 163 | } 164 | -------------------------------------------------------------------------------- /src/ct/error.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Error handling 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #ifdef HAVE_CONFIG_H 8 | #include 9 | #endif 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | enum { 18 | DST_STDERR, 19 | DST_SYSLOG 20 | }; 21 | 22 | static int log_open = 0; 23 | static int log_dest = DST_STDERR; 24 | 25 | static void ct_log_init(void) 26 | { 27 | if (!log_open) { 28 | openlog("ifdhandler", LOG_PID, LOG_DAEMON); 29 | log_open = 1; 30 | } 31 | } 32 | 33 | void ct_log_destination(const char *dest) 34 | { 35 | ct_log_init(); 36 | if (!strcmp(dest, "@stderr")) { 37 | log_dest = DST_STDERR; 38 | } else if (!strcmp(dest, "@syslog")) { 39 | log_dest = DST_SYSLOG; 40 | } else { 41 | log_dest = DST_STDERR; 42 | ct_error("log destination %s not implemented yet", dest); 43 | } 44 | } 45 | 46 | void ct_error(const char *fmt, ...) 47 | { 48 | va_list ap; 49 | int n; 50 | 51 | va_start(ap, fmt); 52 | if (log_dest == DST_STDERR) { 53 | fprintf(stderr, "Error: "); 54 | vfprintf(stderr, fmt, ap); 55 | if (!(n = strlen(fmt)) || fmt[n - 1] != '\n') 56 | fprintf(stderr, "\n"); 57 | } else { 58 | vsyslog(LOG_WARNING, fmt, ap); 59 | } 60 | va_end(ap); 61 | } 62 | 63 | void ct_debug(const char *fmt, ...) 64 | { 65 | va_list ap; 66 | 67 | va_start(ap, fmt); 68 | if (log_dest == DST_STDERR) { 69 | fprintf(stderr, "Debug: "); 70 | vfprintf(stderr, fmt, ap); 71 | fprintf(stderr, "\n"); 72 | } else { 73 | vsyslog(LOG_DEBUG, fmt, ap); 74 | } 75 | va_end(ap); 76 | } 77 | 78 | const char *ct_hexdump(const void *data, size_t len) 79 | { 80 | static char string[1024]; 81 | unsigned char *d = (unsigned char *)data; 82 | unsigned int i, left; 83 | 84 | string[0] = '\0'; 85 | left = sizeof(string); 86 | for (i = 0; len--; i += 3) { 87 | if (i >= sizeof(string) - 4) 88 | break; 89 | snprintf(string + i, 4, " %02x", *d++); 90 | } 91 | return string; 92 | } 93 | 94 | #define DIM(v) (sizeof(v)/(sizeof((v)[0]))) 95 | 96 | const char *ct_strerror(int rc) 97 | { 98 | const char *proto_errors[] = { 99 | "Invalid message", 100 | "Invalid command", 101 | "Missing argument", 102 | "Not connected to IFD handler", 103 | }; 104 | const int proto_base = -IFD_ERROR_INVALID_MSG; 105 | const char *gen_errors[] = { 106 | "Success", 107 | "Generic error", 108 | "Command timed out", 109 | "Invalid slot", 110 | "Operation not supported", 111 | "Communication error", 112 | "No card present", 113 | "Reader already locked", 114 | "Reader not locked", 115 | "Invalid argument", 116 | "Out of memory", 117 | "Buffer too small", 118 | "Timeout on user input", 119 | "Operation aborted by user", 120 | "PIN mismatch", 121 | "Unable to reset card", 122 | "Device cannot perform requested operation", 123 | "Device was disconnected", 124 | "Card returned invalid ATR", 125 | }; 126 | const int gen_base = -IFD_SUCCESS; 127 | const char *proxy_errors[] = { 128 | "Device already claimed", 129 | "Device busy", 130 | "Device not known", 131 | }; 132 | const int proxy_base = -IFD_ERROR_ALREADY_CLAIMED; 133 | const char **errors = NULL, *msg = NULL; 134 | int count = 0, err_base = 0, error = rc; 135 | static char message[64]; 136 | 137 | if (error < 0) 138 | error = -error; 139 | if (error >= proto_base) { 140 | errors = proto_errors; 141 | count = DIM(proto_errors); 142 | err_base = proto_base; 143 | } else if (error >= gen_base) { 144 | errors = gen_errors; 145 | count = DIM(gen_errors); 146 | err_base = gen_base; 147 | } else if (error >= proxy_base) { 148 | errors = proxy_errors; 149 | count = DIM(proxy_errors); 150 | err_base = proxy_base; 151 | } 152 | error -= err_base; 153 | if (error >= count || count == 0) { 154 | msg = message; 155 | snprintf(message, sizeof(message), 156 | "Unknown OpenCT error %d", -rc); 157 | } else { 158 | msg = errors[error]; 159 | } 160 | return msg; 161 | } 162 | -------------------------------------------------------------------------------- /src/ct/libopenct.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libopenct 7 | Description: libopenct 8 | Version: @VERSION@ 9 | Libs: -L${libdir} -lopenct 10 | Cflags: -I${includedir} 11 | 12 | -------------------------------------------------------------------------------- /src/ct/mainloop.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Resource manager daemon - main loop 3 | * 4 | * Copyright (C) 2003 Olaf Kirch 5 | */ 6 | 7 | #ifdef HAVE_CONFIG_H 8 | #include 9 | #endif 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #define IFD_MAX_SOCKETS 256 24 | 25 | static ct_socket_t sock_head; 26 | static int leave_mainloop; 27 | 28 | void ct_mainloop_add_socket(ct_socket_t * sock) 29 | { 30 | if (sock) 31 | ct_socket_link(&sock_head, sock); 32 | } 33 | 34 | /* 35 | * Main loop 36 | */ 37 | void ct_mainloop(void) 38 | { 39 | leave_mainloop = 0; 40 | while (!leave_mainloop) { 41 | struct pollfd pfd[IFD_MAX_SOCKETS + 1]; 42 | ct_socket_t *poll_socket[IFD_MAX_SOCKETS]; 43 | ct_socket_t *sock, *next; 44 | unsigned int nsockets = 0, npoll = 0; 45 | unsigned int n = 0, listening; 46 | int have_driver_with_poll = 0; 47 | int rc; 48 | 49 | /* Zap poll structure */ 50 | memset(pfd, 0, sizeof(pfd)); 51 | 52 | /* Count active sockets, and decide whether to 53 | * accept additional connections or not. */ 54 | for (sock = sock_head.next; sock; sock = next) { 55 | next = sock->next; 56 | /* Kill any dead or excess sockets */ 57 | if (sock->fd < 0 || nsockets == IFD_MAX_SOCKETS) { 58 | ct_socket_free(sock); 59 | } else { 60 | nsockets++; 61 | } 62 | } 63 | listening = (nsockets < IFD_MAX_SOCKETS) ? POLLIN : 0; 64 | 65 | /* Now loop over all sockets and set up the poll structs */ 66 | for (sock = sock_head.next; sock; sock = sock->next) { 67 | poll_socket[npoll] = sock; 68 | if (sock->poll) { 69 | have_driver_with_poll = 1; 70 | if (sock->poll(sock, &pfd[npoll]) == 1) 71 | npoll++; 72 | } else { 73 | if (sock->listener) 74 | sock->events = listening; 75 | 76 | pfd[npoll].fd = sock->fd; 77 | pfd[npoll].events = sock->events; 78 | npoll++; 79 | } 80 | } 81 | 82 | if (npoll == 0) 83 | break; 84 | 85 | rc = poll(pfd, npoll, have_driver_with_poll ? 1000 : -1); 86 | if (rc < 0) { 87 | if (errno == EINTR) 88 | continue; 89 | ct_error("poll: %m"); 90 | break; 91 | } 92 | 93 | for (n = 0; n < npoll; n++) { 94 | sock = poll_socket[n]; 95 | if (sock->poll) { 96 | if (sock->poll(sock, &pfd[n]) < 0) { 97 | ct_socket_free(sock); 98 | continue; 99 | } 100 | continue; 101 | } 102 | 103 | if (pfd[n].revents & POLLERR) { 104 | if (sock->error(sock) < 0) { 105 | ct_socket_free(sock); 106 | continue; 107 | } 108 | } 109 | if (pfd[n].revents & POLLOUT) { 110 | if (sock->send(sock) < 0) { 111 | ct_socket_free(sock); 112 | continue; 113 | } 114 | } 115 | if (pfd[n].revents & POLLIN) { 116 | if ((rc = sock->recv(sock)) < 0) { 117 | ct_socket_free(sock); 118 | continue; 119 | } 120 | } 121 | } 122 | } 123 | } 124 | 125 | void ct_mainloop_leave(void) 126 | { 127 | leave_mainloop = 1; 128 | } 129 | -------------------------------------------------------------------------------- /src/ct/path.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Path handling routines 3 | * 4 | * Copyright (C) 2006, Andreas Jellinghaus 5 | */ 6 | 7 | #ifdef HAVE_CONFIG_H 8 | #include 9 | #endif 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | /* 16 | * Format path 17 | */ 18 | int ct_format_path(char *path, const size_t pathlen, const char *file) 19 | { 20 | int rc; 21 | 22 | if (!file) 23 | return 0; 24 | 25 | #if defined (sunray) || defined (sunrayclient) 26 | { 27 | if (getenv("UTDEVROOT")) 28 | rc = snprintf(path, pathlen, 29 | "%s/openct/%s", getenv("UTDEVROOT"), 30 | file); 31 | else if (getenv("OPENCT_SOCKETDIR")) 32 | rc = snprintf(path, pathlen, 33 | "%s/%s", getenv("OPENCT_SOCKETDIR"), 34 | file); 35 | else 36 | rc = snprintf(path, pathlen, 37 | "%s/%s", OPENCT_SOCKET_PATH, file); 38 | } 39 | #else 40 | if (getenv("OPENCT_SOCKETDIR")) { 41 | rc = snprintf(path, pathlen, 42 | "%s/%s", getenv("OPENCT_SOCKETDIR"), file); 43 | } else { 44 | rc = snprintf(path, pathlen, "%s/%s", OPENCT_SOCKET_PATH, file); 45 | } 46 | #endif 47 | if (rc < 0) { 48 | /* hmm. error handling? */ 49 | return 0; 50 | 51 | } 52 | if (rc >= pathlen) { 53 | /* truncated */ 54 | return 0; 55 | } 56 | 57 | return 1; 58 | } 59 | -------------------------------------------------------------------------------- /src/ct/status.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Shared status file for OpenCT readers 3 | * 4 | * Copyright (C) 2003 Olaf Kirch 5 | */ 6 | 7 | #ifdef HAVE_CONFIG_H 8 | #include 9 | #endif 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | static int ct_status_lock(void); 29 | static void ct_status_unlock(void); 30 | 31 | static void *ct_map_status(int flags, size_t * size) 32 | { 33 | struct stat stb; 34 | int fd, prot; 35 | void *addr = NULL; 36 | char status_path[PATH_MAX]; 37 | 38 | if (!ct_format_path(status_path, PATH_MAX, "status")) { 39 | return NULL; 40 | } 41 | 42 | if ((fd = open(status_path, flags)) < 0) { 43 | ct_error("can't open %s: %s", status_path, strerror(errno)); 44 | return NULL; 45 | } 46 | 47 | if (fstat(fd, &stb) < 0) { 48 | ct_error("unable to stat %s: %m", status_path); 49 | goto done; 50 | } 51 | *size = stb.st_size; 52 | 53 | prot = PROT_READ; 54 | if ((flags & O_ACCMODE) == O_RDWR) 55 | prot |= PROT_WRITE; 56 | 57 | addr = mmap(NULL, *size, prot, MAP_SHARED, fd, 0); 58 | if (addr == MAP_FAILED) { 59 | addr = NULL; 60 | } 61 | 62 | done:close(fd); 63 | return addr; 64 | } 65 | 66 | int ct_status_destroy(void) 67 | { 68 | char status_path[PATH_MAX]; 69 | 70 | if (!ct_format_path(status_path, PATH_MAX, "status")) { 71 | return -1; 72 | } 73 | 74 | return unlink(status_path); 75 | } 76 | 77 | int ct_status_clear(unsigned int count, const char *owner) 78 | { 79 | int fd = -1; 80 | char status_path[PATH_MAX]; 81 | 82 | if (!ct_format_path(status_path, PATH_MAX, "status")) { 83 | return -1; 84 | } 85 | 86 | unlink(status_path); 87 | if ((fd = open(status_path, O_RDWR | O_CREAT, 0644)) < 0 88 | || ftruncate(fd, count * sizeof(ct_info_t)) < 0 89 | || fchmod(fd, 0644) < 0) { 90 | ct_error("cannot create %s: %m", status_path); 91 | goto error; 92 | } 93 | 94 | if (owner != NULL) { 95 | struct passwd *p = getpwnam(owner); 96 | 97 | if (p == NULL) { 98 | ct_error("cannot parse user %s", owner); 99 | goto error; 100 | } 101 | 102 | if (fchown(fd, p->pw_uid, -1) == -1) { 103 | ct_error("cannot chown %s to %s: %m", status_path, owner); 104 | goto error; 105 | } 106 | } 107 | 108 | return 0; 109 | 110 | error: 111 | 112 | unlink(status_path); 113 | if (fd >= 0) 114 | close(fd); 115 | return -1; 116 | } 117 | 118 | int ct_status(const ct_info_t ** result) 119 | { 120 | static const ct_info_t *reader_status; 121 | static unsigned int num_status; 122 | 123 | if (reader_status == NULL) { 124 | size_t size; 125 | 126 | reader_status = (ct_info_t *) ct_map_status(O_RDONLY, &size); 127 | if (reader_status == NULL) 128 | return -1; 129 | num_status = size / sizeof(ct_info_t); 130 | } 131 | 132 | *result = reader_status; 133 | return num_status; 134 | } 135 | 136 | ct_info_t *ct_status_alloc_slot(int *num) 137 | { 138 | ct_info_t *info; 139 | size_t size; 140 | unsigned int n, max; 141 | 142 | info = (ct_info_t *) ct_map_status(O_RDWR, &size); 143 | if (info == NULL) 144 | return NULL; 145 | 146 | max = size / sizeof(ct_info_t); 147 | if (*num == -1) { 148 | sigset_t sigset; 149 | 150 | /* Block all signals while holding the lock */ 151 | sigfillset(&sigset); 152 | sigprocmask(SIG_SETMASK, &sigset, &sigset); 153 | 154 | /* Lock the status file against concurrent access */ 155 | ct_status_lock(); 156 | 157 | /* find a free slot */ 158 | for (n = 0; n < max; n++, info) { 159 | if (info[n].ct_pid == 0 160 | || (kill(info[n].ct_pid, 0) < 0 161 | && errno == ESRCH)) { 162 | *num = n; 163 | break; 164 | } 165 | } 166 | 167 | /* Done, unlock the file again */ 168 | ct_status_unlock(); 169 | 170 | /* unblock signals */ 171 | sigprocmask(SIG_SETMASK, &sigset, NULL); 172 | } else if (*num >= max) { 173 | munmap((void *)info, size); 174 | return NULL; 175 | } 176 | 177 | memset(&info[*num], 0, sizeof(ct_info_t)); 178 | info[*num].ct_pid = getpid(); 179 | 180 | msync((void *)info, size, MS_SYNC); 181 | return info + *num; 182 | } 183 | 184 | #define ALIGN(x, size) (((caddr_t) (x)) - ((unsigned long) (x) % (size))) 185 | int ct_status_update(ct_info_t * status) 186 | { 187 | size_t size; 188 | caddr_t page; 189 | 190 | /* get the page this piece of data is sitting on */ 191 | size = getpagesize(); 192 | page = ALIGN(status, size); 193 | 194 | /* flush two pages if data spans two pages */ 195 | if (page != ALIGN(status + 1, size)) 196 | size <<= 1; 197 | 198 | if (msync(page, size, MS_SYNC) < 0) { 199 | ct_error("msync: %m"); 200 | return -1; 201 | } 202 | 203 | return 0; 204 | } 205 | 206 | /* 207 | * Lock file handling 208 | */ 209 | static int ct_status_lock(void) 210 | { 211 | int fd, retries = 10; 212 | int ret = -1; 213 | char status_lock_path[PATH_MAX]; 214 | char status_temp_path[PATH_MAX]; 215 | 216 | if (!ct_format_path(status_lock_path, PATH_MAX, "status.lock")) { 217 | return -1; 218 | } 219 | 220 | snprintf(status_temp_path, PATH_MAX, 221 | "%s.%u", status_lock_path, (unsigned int)getpid()); 222 | 223 | if ((fd = open(status_temp_path, O_CREAT | O_RDWR, 0600)) < 0) 224 | return -1; 225 | 226 | while (retries--) { 227 | if (link(status_temp_path, status_lock_path) >= 0) { 228 | ret = 0; 229 | break; 230 | } 231 | } 232 | 233 | close(fd); 234 | unlink(status_temp_path); 235 | return ret; 236 | } 237 | 238 | static void ct_status_unlock(void) 239 | { 240 | char status_lock_path[PATH_MAX]; 241 | 242 | if (!ct_format_path(status_lock_path, PATH_MAX, "status.lock")) { 243 | return; 244 | } 245 | 246 | unlink(status_lock_path); 247 | } 248 | -------------------------------------------------------------------------------- /src/ct/tlv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * TLV handling routines 3 | * 4 | * Copyright (C) 2003 Olaf Kirch 5 | */ 6 | 7 | #ifdef HAVE_CONFIG_H 8 | #include 9 | #endif 10 | #ifdef HAVE_GETOPT_H 11 | #include 12 | #endif 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | /* 22 | * Parse TLV data 23 | */ 24 | int ct_tlv_parse(ct_tlv_parser_t * parser, ct_buf_t * bp) 25 | { 26 | unsigned int avail, len; 27 | unsigned char *p, tag; 28 | 29 | /* Code below relies on it */ 30 | assert(((ifd_tag_t) - 1) == 255); 31 | 32 | while ((avail = ct_buf_avail(bp)) != 0) { 33 | unsigned int header = 2; 34 | 35 | if (avail < 2) 36 | return -1; 37 | 38 | p = (unsigned char *)ct_buf_head(bp); 39 | tag = p[0]; 40 | len = p[1]; 41 | 42 | if (tag & __CT_TAG_LARGE) { 43 | parser->use_large_tags = 1; 44 | tag &= ~__CT_TAG_LARGE; 45 | if (avail < 3) 46 | return -1; 47 | len = (len << 8) | p[header++]; 48 | } 49 | 50 | if (len == 0 || header + len > avail) 51 | return -1; 52 | 53 | parser->val[tag] = p + header; 54 | parser->len[tag] = len; 55 | 56 | ct_buf_get(bp, NULL, header + len); 57 | } 58 | 59 | return 0; 60 | } 61 | 62 | /* 63 | * Extract TLV encoded items as strings, integers, etc. 64 | */ 65 | int ct_tlv_get_string(ct_tlv_parser_t * parser, ifd_tag_t tag, char *buf, 66 | size_t size) 67 | { 68 | unsigned char *p; 69 | unsigned int len; 70 | 71 | if (!(p = parser->val[tag])) 72 | return 0; 73 | 74 | len = parser->len[tag]; 75 | if (len > size - 1) 76 | len = size - 1; 77 | strncpy(buf, (const char *)p, len); 78 | buf[len] = '\0'; 79 | return 1; 80 | } 81 | 82 | int ct_tlv_get_int(ct_tlv_parser_t * parser, ifd_tag_t tag, unsigned int *value) 83 | { 84 | unsigned char *p; 85 | unsigned int len; 86 | 87 | *value = 0; 88 | if (!(p = parser->val[tag])) 89 | return 0; 90 | 91 | len = parser->len[tag]; 92 | while (len--) { 93 | *value <<= 8; 94 | *value |= *p++; 95 | } 96 | 97 | return 1; 98 | } 99 | 100 | int ct_tlv_get_opaque(ct_tlv_parser_t * parser, ifd_tag_t tag, 101 | unsigned char **data, size_t * lenp) 102 | { 103 | unsigned char *p; 104 | 105 | *data = NULL; 106 | *lenp = 0; 107 | 108 | if (!(p = parser->val[tag])) 109 | return 0; 110 | *lenp = parser->len[tag]; 111 | *data = p; 112 | return 1; 113 | } 114 | 115 | int ct_tlv_get_bytes(ct_tlv_parser_t * parser, ifd_tag_t tag, void *buf, 116 | size_t size) 117 | { 118 | unsigned char *p; 119 | unsigned int len; 120 | 121 | if (!(p = parser->val[tag])) 122 | return 0; 123 | len = parser->len[tag]; 124 | if (len > size) 125 | len = size; 126 | memcpy(buf, p, len); 127 | return len; 128 | } 129 | 130 | /* 131 | * Initialize a TLV data builder 132 | */ 133 | void ct_tlv_builder_init(ct_tlv_builder_t * builder, ct_buf_t * bp, 134 | int large_tags) 135 | { 136 | memset(builder, 0, sizeof(*builder)); 137 | builder->use_large_tags = large_tags; 138 | builder->buf = bp; 139 | } 140 | 141 | /* 142 | * TLV encode objects 143 | */ 144 | void ct_tlv_put_int(ct_tlv_builder_t * builder, ifd_tag_t tag, 145 | unsigned int value) 146 | { 147 | int n; 148 | 149 | if (builder->error) 150 | return; 151 | ct_tlv_put_tag(builder, tag); 152 | for (n = 0; (value >> (n + 8)) != 0; n += 8) ; 153 | do { 154 | ct_tlv_add_byte(builder, value >> n); 155 | n -= 8; 156 | } while (n >= 0); 157 | 158 | builder->lenp = NULL; 159 | } 160 | 161 | void ct_tlv_put_string(ct_tlv_builder_t * builder, ifd_tag_t tag, 162 | const char *string) 163 | { 164 | if (builder->error) 165 | return; 166 | 167 | ct_tlv_put_tag(builder, tag); 168 | ct_tlv_add_bytes(builder, (const unsigned char *)string, 169 | strlen(string)); 170 | 171 | builder->lenp = NULL; 172 | } 173 | 174 | void ct_tlv_put_opaque(ct_tlv_builder_t * builder, ifd_tag_t tag, 175 | const unsigned char *data, size_t len) 176 | { 177 | if (builder->error) 178 | return; 179 | 180 | ct_tlv_put_tag(builder, tag); 181 | ct_tlv_add_bytes(builder, data, len); 182 | 183 | builder->lenp = NULL; 184 | } 185 | 186 | void ct_tlv_put_tag(ct_tlv_builder_t * builder, ifd_tag_t tag) 187 | { 188 | ct_buf_t *bp = builder->buf; 189 | 190 | if (builder->error < 0) 191 | return; 192 | if (builder->use_large_tags) 193 | tag |= __CT_TAG_LARGE; 194 | if (ct_buf_putc(bp, tag) < 0) 195 | goto err; 196 | builder->len = 0; 197 | builder->lenp = (unsigned char *)ct_buf_tail(bp); 198 | if (ct_buf_putc(bp, 0) < 0 199 | || (builder->use_large_tags && ct_buf_putc(bp, 0) < 0)) 200 | goto err; 201 | return; 202 | 203 | err:builder->error = -1; 204 | } 205 | 206 | void ct_tlv_add_byte(ct_tlv_builder_t * builder, unsigned char byte) 207 | { 208 | ct_tlv_add_bytes(builder, &byte, 1); 209 | } 210 | 211 | void ct_tlv_add_bytes(ct_tlv_builder_t * builder, const unsigned char *data, 212 | size_t num) 213 | { 214 | ct_buf_t *bp = builder->buf; 215 | 216 | if (builder->error < 0) 217 | return; 218 | 219 | if (!builder->lenp) 220 | goto error; 221 | 222 | builder->len += num; 223 | if (ct_buf_put(bp, data, num) < 0) 224 | goto error; 225 | 226 | if (builder->use_large_tags) { 227 | if (builder->len > 65535) 228 | goto error; 229 | builder->lenp[0] = builder->len >> 8; 230 | builder->lenp[1] = builder->len; 231 | } else { 232 | if (builder->len > 266) 233 | goto error; 234 | builder->lenp[0] = builder->len; 235 | } 236 | return; 237 | 238 | error: 239 | builder->error = -1; 240 | return; 241 | } 242 | -------------------------------------------------------------------------------- /src/ctapi/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = $(srcdir)/Makefile.in 2 | 3 | openctinclude_HEADERS = ctapi.h 4 | lib_LTLIBRARIES = libopenctapi.la 5 | 6 | libopenctapi_la_SOURCES = ctapi.c ctapi.h 7 | libopenctapi_la_LIBADD = $(top_builddir)/src/ct/libopenct.la 8 | libopenctapi_la_CFLAGS = $(AM_CFLAGS) \ 9 | -I$(top_srcdir)/src/include \ 10 | -I$(top_builddir)/src/include 11 | libopenctapi_la_LDFLAGS = -avoid-version -no-undefined -module -shared 12 | -------------------------------------------------------------------------------- /src/ctapi/ctapi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Defines CT-API functions and returns 3 | * 4 | * Copyright (C) 1998, David Corcoran 5 | */ 6 | 7 | #ifndef OPENCT_CTAPI_H 8 | #define OPENCT_CTAPI_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #define MAX_APDULEN 1040 15 | 16 | char CT_init(unsigned short Ctn, /* Terminal Number */ 17 | unsigned short pn /* Port Number */ 18 | ); 19 | 20 | char CT_close(unsigned short Ctn /* Terminal Number */ 21 | ); 22 | 23 | char CT_data(unsigned short ctn, /* Terminal Number */ 24 | unsigned char *dad, /* Destination */ 25 | unsigned char *sad, /* Source */ 26 | unsigned short lc, /* Length of command */ 27 | unsigned char *cmd, /* Command/Data Buffer */ 28 | unsigned short *lr, /* Length of Response */ 29 | unsigned char *rsp /* Response */ 30 | ); 31 | 32 | #define OK 0 /* Success */ 33 | #define ERR_INVALID -1 /* Invalid Data */ 34 | #define ERR_CT -8 /* CT Error */ 35 | #define ERR_TRANS -10 /* Transmission Error */ 36 | #define ERR_MEMORY -11 /* Memory Allocate Error */ 37 | #define ERR_HOST -127 /* Abort by Host/OS */ 38 | #define ERR_HTSI -128 /* HTSI Error */ 39 | 40 | enum { 41 | CTAPI_DAD_ICC1 = 0, 42 | CTAPI_DAD_CT = 1, 43 | CTAPI_DAD_HOST = 2, 44 | CTAPI_DAD_ICC2 = 3 45 | }; 46 | 47 | /* 48 | * CT-BCS commands 49 | */ 50 | #define CTBCS_CLA 0x20 51 | #define CTBCS_CLA_2 0x80 52 | #define CTBCS_INS_RESET 0x11 53 | #define CTBCS_INS_REQUEST_ICC 0x12 54 | #define CTBCS_INS_STATUS 0x13 55 | #define CTBCS_INS_EJECT_ICC 0x15 56 | #define CTBCS_INS_INPUT 0x16 57 | #define CTBCS_INS_OUTPUT 0x17 58 | #define CTBCS_INS_PERFORM_VERIFICATION 0x18 59 | #define CTBCS_INS_MODIFY_VERIFICATION 0x19 60 | #define CTBCS_INS_SET_INTERFACE_PARAM 0x60 61 | 62 | /* 63 | * CT-BCS functional units (P1 byte) 64 | */ 65 | #define CTBCS_UNIT_CT 0x00 66 | #define CTBCS_UNIT_INTERFACE1 0x01 67 | #define CTBCS_UNIT_INTERFACE2 0x02 68 | #define CTBCS_UNIT_DISPLAY 0x40 69 | #define CTBCS_UNIT_KEYPAD 0x50 70 | 71 | /* 72 | * P2 parameter for Reset CT: data to be returned 73 | */ 74 | #define CTBCS_P2_RESET_NO_RESP 0x00 /* Return no data */ 75 | #define CTBCS_P2_RESET_GET_ATR 0x01 /* Return complete ATR */ 76 | #define CTBCS_P2_RESET_GET_HIST 0x02 /* Return historical bytes */ 77 | 78 | /* 79 | * P2 parameter for Request ICC: data to be returned 80 | */ 81 | #define CTBCS_P2_REQUEST_NO_RESP 0x00 /* Return no data */ 82 | #define CTBCS_P2_REQUEST_GET_ATR 0x01 /* Return complete ATR */ 83 | #define CTBCS_P2_REQUEST_GET_HIST 0x02 /* Return historical bytes */ 84 | 85 | /* 86 | * P2 parameter for Get status: TAG of data object to return 87 | */ 88 | #define CTBCS_P2_STATUS_MANUFACTURER 0x46 /* Return manufacturer DO */ 89 | #define CTBCS_P2_STATUS_ICC 0x80 /* Return ICC DO */ 90 | 91 | /* 92 | * P2 parameter for Input 93 | */ 94 | #define CTBCS_P2_INPUT_ECHO 0x01 /* Echo input on display */ 95 | #define CTBCS_P2_INPUT_ASTERISKS 0x02 /* Echo input as asterisks */ 96 | 97 | /* 98 | * Tags for paramaters to input, output et al. 99 | */ 100 | #define CTBCS_TAG_PROMPT 0x50 101 | #define CTBCS_TAG_VERIFY_CMD 0x52 102 | #define CTBCS_TAG_TIMEOUT 0x80 103 | #define CTBCS_TAG_TPP 0x22 104 | #define CTBCS_TAG_TPC 0x45 105 | 106 | /* 107 | * PIN command control flags 108 | */ 109 | #define CTBCS_PIN_CONTROL_LEN_SHIFT 4 110 | #define CTBCS_PIN_CONTROL_LEN_MASK 0x0F 111 | #define CTBCS_PIN_CONTROL_ENCODE_ASCII 0x01 112 | 113 | /* 114 | * Status words returned by CTBCS 115 | */ 116 | 117 | #define CTBCS_SW_BAD_LENGTH 0x6700 118 | #define CTBCS_SW_BAD_COMMAND 0x6900 119 | #define CTBCS_SW_NOT_EXECUTABLE 0x6985 120 | #define CTBCS_SW_BAD_PARAMS 0x6a00 121 | #define CTBCS_SW_NOT_SUPPORTED 0x6a80 122 | #define CTBCS_SW_INVALID_TLV 0x6a85 123 | #define CTBCS_SW_BAD_LE 0x6c00 124 | #define CTBCS_SW_BAD_INS 0x6d00 125 | #define CTBCS_SW_BAD_CLASS 0x6e00 126 | #define CTBCS_SW_BAD_ICC 0x6f00 127 | #define CTBCS_SW_SUCCESS 0x9000 128 | 129 | /* 130 | * Data returned by Get Status command 131 | */ 132 | #define CTBCS_DATA_STATUS_NOCARD 0x00 /* No card present */ 133 | #define CTBCS_DATA_STATUS_CARD 0x01 /* Card present */ 134 | #define CTBCS_DATA_STATUS_CARD_CONNECT 0x05 /* Card present */ 135 | 136 | #ifdef __cplusplus 137 | } 138 | #endif 139 | #endif /* OPENCT_CTAPI_H */ 140 | -------------------------------------------------------------------------------- /src/ifd/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = $(srcdir)/Makefile.in 2 | 3 | noinst_LTLIBRARIES = libifd.la 4 | sbin_PROGRAMS = ifdhandler ifdproxy 5 | noinst_HEADERS = atr.h ctbcs.h ifdhandler.h internal.h ria.h usb-descriptors.h 6 | 7 | libifd_la_SOURCES = \ 8 | apdu.c atr.c checksum.c conf.c ctbcs.c device.c driver.c \ 9 | init.c locks.c manager.c modules.c pcmcia.c pcmcia-block.c process.c protocol.c \ 10 | reader.c serial.c usb.c usb-descriptors.c utils.c \ 11 | \ 12 | ifd-acr30u.c ifd-cardman.c ifd-ccid.c ifd-cm4000.c ifd-egate.c \ 13 | ifd-etoken.c ifd-etoken64.c ifd-eutron.c ifd-gempc.c ifd-ikey2k.c \ 14 | ifd-ikey3k.c ifd-kaan.c ifd-pertosmart1030.c ifd-pertosmart1038.c \ 15 | ifd-smartboard.c ifd-smph.c ifd-starkey.c ifd-towitoko.c cardman.h \ 16 | ifd-cyberjack.c ifd-rutoken.c ifd-epass3k.c \ 17 | \ 18 | proto-gbp.c proto-sync.c proto-t0.c proto-t1.c \ 19 | proto-trans.c proto-escape.c \ 20 | \ 21 | sys-sunray.c sys-solaris.c sys-bsd.c sys-linux.c sys-null.c sys-osx.c \ 22 | \ 23 | ria.c 24 | # new driver not working yet: ifd-wbeiuu.c 25 | libifd_la_LIBADD = $(top_builddir)/src/ct/libopenct.la $(LTLIB_LIBS) $(OPTIONAL_LIBUSB_LIBS) 26 | libifd_la_CFLAGS = $(AM_CFLAGS) \ 27 | -I$(top_srcdir)/src/include \ 28 | -I$(top_builddir)/src/include \ 29 | $(OPTIONAL_PCSC_CFLAGS) $(OPTIONAL_LIBUSB_CFLAGS) $(LTLIB_CFLAGS) 30 | 31 | ifdhandler_SOURCES = ifdhandler.c 32 | ifdhandler_LDADD = libifd.la 33 | ifdhandler_CFLAGS = $(AM_CFLAGS) \ 34 | -I$(top_srcdir)/src/include \ 35 | -I$(top_builddir)/src/include 36 | 37 | ifdproxy_SOURCES = ifdproxy.c ria-device.c ria-server.c 38 | ifdproxy_LDADD = libifd.la 39 | ifdproxy_CFLAGS = $(AM_CFLAGS) \ 40 | -I$(top_srcdir)/src/include \ 41 | -I$(top_builddir)/src/include 42 | -------------------------------------------------------------------------------- /src/ifd/apdu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * APDU handling 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #include "internal.h" 8 | #include 9 | 10 | /* 11 | * Check the APDU type and length 12 | */ 13 | static int __ifd_apdu_check(const void *sbuf, size_t len, ifd_iso_apdu_t * iso) 14 | { 15 | unsigned char *data = (unsigned char *)sbuf; 16 | unsigned int b; 17 | 18 | memset(iso, 0, sizeof(*iso)); 19 | if (len < 5) { 20 | iso->cse = IFD_APDU_CASE_1; 21 | return 0; 22 | } 23 | 24 | b = data[4]; 25 | len -= 5; 26 | 27 | /* APDU + Le */ 28 | if (len == 0) { 29 | iso->cse = IFD_APDU_CASE_2S; 30 | iso->le = b ? b : 256; 31 | return 0; 32 | } 33 | 34 | data += 5; 35 | if (b == 0) 36 | b = 256; 37 | 38 | iso->lc = b; 39 | iso->len = len; 40 | iso->data = data; 41 | 42 | /* APDU + Lc + data */ 43 | if (len == b) { 44 | iso->cse = IFD_APDU_CASE_3S; 45 | return 0; 46 | } 47 | 48 | /* APDU + Lc + data + Le */ 49 | if (len == b + 1) { 50 | iso->cse = IFD_APDU_CASE_4S; 51 | iso->le = data[b] ? data[b] : 256; 52 | iso->len--; 53 | return 0; 54 | } 55 | 56 | return -1; 57 | } 58 | 59 | int ifd_apdu_case(const void *buf, size_t len) 60 | { 61 | ifd_iso_apdu_t iso; 62 | 63 | if (__ifd_apdu_check(buf, len, &iso) < 0) 64 | return -1; 65 | return iso.cse; 66 | } 67 | 68 | /* 69 | * Convert internal APDU type to an ISO-7816-4 APDU 70 | */ 71 | int ifd_iso_apdu_parse(const void *data, size_t len, ifd_iso_apdu_t * iso) 72 | { 73 | unsigned char *p; 74 | 75 | if (len < 4) 76 | return -1; 77 | 78 | if (__ifd_apdu_check(data, len, iso) < 0) 79 | return -1; 80 | 81 | p = (unsigned char *)data; 82 | iso->cla = *p++; 83 | iso->ins = *p++; 84 | iso->p1 = *p++; 85 | iso->p2 = *p++; 86 | 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /src/ifd/atr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ATR parsing functions 3 | * 4 | * Copyright (C) 2004, Olaf Kirch 5 | */ 6 | 7 | #include "internal.h" 8 | #include 9 | #include "atr.h" 10 | 11 | int ifd_atr_parse(ifd_atr_info_t * info, const unsigned char *atr, size_t len) 12 | { 13 | unsigned int m, n, k; 14 | 15 | ifd_debug(1, "atr=%s", ct_hexdump(atr, len)); 16 | 17 | /* Initialize the atr_info struct */ 18 | memset(info, 0, sizeof(*info)); 19 | info->default_protocol = -1; 20 | for (n = 0; n < 3; n++) { 21 | info->TA[n] = -1; 22 | info->TB[n] = -1; 23 | info->TC[n] = -1; 24 | } 25 | 26 | if (len < 2 + (atr[1] & 0x0f)) 27 | return IFD_ERROR_INVALID_ATR; 28 | 29 | /* Ignore hysterical bytes */ 30 | len -= atr[1] & 0x0f; 31 | 32 | for (m = 0, n = 2; n < len; m++) { 33 | unsigned int TDi; 34 | 35 | /* TA1, TA2, TA3, TA4 are legal, TA5 wouldn't be */ 36 | if (m > 3) 37 | return IFD_ERROR_INVALID_ATR; 38 | 39 | TDi = atr[n - 1]; 40 | if (n != 2) { 41 | int prot; 42 | 43 | prot = TDi & 0x0f; 44 | if (info->default_protocol < 0) 45 | info->default_protocol = prot; 46 | info->supported_protocols |= (1 << prot); 47 | } 48 | 49 | k = ifd_count_bits(TDi & 0xF0); 50 | if (k == 0 || n + k > len) 51 | return IFD_ERROR_INVALID_ATR; 52 | if (TDi & 0x10) 53 | info->TA[m] = atr[n++]; 54 | if (TDi & 0x20) 55 | info->TB[m] = atr[n++]; 56 | if (TDi & 0x40) 57 | info->TC[m] = atr[n++]; 58 | if (!(TDi & 0x80)) { 59 | /* If the ATR indicates we support anything 60 | * in addition to T=0, there'll be a TCK byte 61 | * at the end of the string. 62 | * For now, simply chop it off. Later we may 63 | * want to verify it. 64 | */ 65 | if (info->supported_protocols & ~0x1) 66 | len--; 67 | if (n < len) 68 | return IFD_ERROR_INVALID_ATR; 69 | break; 70 | } 71 | n++; 72 | } 73 | 74 | /* ATR didn't list any supported protocols, so 75 | * we default to T=0 */ 76 | if (info->supported_protocols == 0) { 77 | info->supported_protocols = 0x01; 78 | info->default_protocol = IFD_PROTOCOL_T0; 79 | } 80 | 81 | ifd_debug(1, "supported protocols=0x%x, default protocol=%d", 82 | info->supported_protocols, info->default_protocol); 83 | return 0; 84 | } 85 | 86 | /* 87 | * Given the ATR info and a selected protocol, build the PTS 88 | * string. 89 | */ 90 | int ifd_build_pts(const ifd_atr_info_t * info, int protocol, unsigned char *buf, 91 | size_t len) 92 | { 93 | unsigned char ptsbuf[7], pck; 94 | size_t n, ptslen = 0; 95 | 96 | /* IFD_PROTOCOL_Tn is just n, so we take it easy here */ 97 | if (!(info->supported_protocols & (1 << protocol))) { 98 | ct_error("Protocol not supported by card (according to ATR)"); 99 | return IFD_ERROR_NOT_SUPPORTED; 100 | } 101 | 102 | ptsbuf[ptslen++] = 0xFF; 103 | ptsbuf[ptslen++] = protocol; 104 | if (info->TA[0] != -1) { 105 | ptsbuf[ptslen++] = info->TA[0]; 106 | ptsbuf[1] |= 0x10; 107 | } 108 | if (info->TC[0] == 255) { 109 | ptsbuf[ptslen++] = 1; 110 | ptsbuf[1] |= 0x20; 111 | } 112 | 113 | for (n = 0, pck = 0; n < ptslen; n++) 114 | pck ^= ptsbuf[n]; 115 | ptsbuf[ptslen++] = pck; 116 | 117 | if (ptslen > len) 118 | return IFD_ERROR_BUFFER_TOO_SMALL; 119 | 120 | memcpy(buf, ptsbuf, ptslen); 121 | return ptslen; 122 | } 123 | 124 | /* validate a PTS response according to ISO7816-3 */ 125 | int 126 | ifd_verify_pts(ifd_atr_info_t * info, 127 | int protocol, const unsigned char *buf, size_t len) 128 | { 129 | int n, i; 130 | int ptsr[3]; 131 | int pck; 132 | 133 | if (len < 3) 134 | return IFD_ERROR_BUFFER_TOO_SMALL; 135 | 136 | if (buf[0] != 0xFF) 137 | return IFD_ERROR_INCOMPATIBLE_DEVICE; /* not a pts response */ 138 | 139 | for (n = 0, pck = 0; n < len; n++) 140 | pck ^= buf[n]; 141 | 142 | if (pck) 143 | return IFD_ERROR_COMM_ERROR; 144 | for (i = 0; i < 3; i++) 145 | ptsr[i] = -1; 146 | for (i = 0, n = 2; i < 3 && n < len - 1; i++) { 147 | if (buf[1] & 1 << (i + 4)) 148 | ptsr[i] = buf[n++]; 149 | } 150 | if (n < len - 1) /* extra bytes in response */ 151 | return IFD_ERROR_INCOMPATIBLE_DEVICE; 152 | if (info->TA[0] != -1 && ptsr[0] != info->TA[0]) 153 | info->TA[0] = -1; 154 | if (info->TC[0] == 255 && (ptsr[1] == -1 || (ptsr[1] & 1) == 0)) 155 | return IFD_ERROR_INCOMPATIBLE_DEVICE; 156 | return 0; 157 | } 158 | 159 | int ifd_pts_complete(const unsigned char *pts, size_t len) 160 | { 161 | unsigned int j = 2; 162 | 163 | if (j > len) 164 | return 0; 165 | j = +ifd_count_bits(pts[1] & 0x70); 166 | j++; 167 | if (j > len) 168 | return 0; 169 | return 1; 170 | } 171 | -------------------------------------------------------------------------------- /src/ifd/atr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ATR type definitions 3 | * 4 | * Copyright (C) 2004, Olaf Kirch 5 | */ 6 | 7 | #ifndef OPENCT_ATR_H 8 | #define OPENCT_ATR_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | typedef struct ifd_atr_info { 15 | /* The following contain -1 if the field wasn't present */ 16 | int TA[4]; 17 | int TB[4]; 18 | int TC[4]; 19 | unsigned int supported_protocols; 20 | int default_protocol; 21 | } ifd_atr_info_t; 22 | 23 | extern int ifd_atr_parse(ifd_atr_info_t *, const unsigned char *, 24 | size_t); 25 | extern int ifd_build_pts(const ifd_atr_info_t *, int, unsigned char *, 26 | size_t); 27 | extern int ifd_verify_pts(ifd_atr_info_t *, int, 28 | const unsigned char *, size_t); 29 | extern int ifd_pts_complete(const unsigned char *pts, size_t len); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | #endif /* OPENCT_ATR_H */ 35 | -------------------------------------------------------------------------------- /src/ifd/cardman.h: -------------------------------------------------------------------------------- 1 | #ifndef _CARDMAN_H_ 2 | #define _CARDMAN_H_ 3 | 4 | #define MAX_ATR 33 5 | 6 | #define CM2020_MAX_DEV 16 7 | #define CM4000_MAX_DEV 4 8 | 9 | typedef struct atreq { 10 | int atr_len; 11 | unsigned char atr[64]; 12 | int power_act; 13 | unsigned char bIFSD; 14 | unsigned char bIFSC; 15 | } atreq_t; 16 | 17 | typedef struct ptsreq { 18 | unsigned long protocol; /*T=0: 2^0, T=1: 2^1 */ 19 | unsigned char flags; 20 | unsigned char pts1; 21 | unsigned char pts2; 22 | unsigned char pts3; 23 | } ptsreq_t; 24 | 25 | #define CM_IOC_MAGIC 'c' 26 | #define CM_IOC_MAXNR 255 27 | 28 | #define CM_IOCGSTATUS _IOR (CM_IOC_MAGIC, 0, unsigned char *) 29 | #define CM_IOCGATR _IOWR(CM_IOC_MAGIC, 1, atreq_t *) 30 | #define CM_IOCSPTS _IOW (CM_IOC_MAGIC, 2, ptsreq_t *) 31 | #define CM_IOCSRDR _IO (CM_IOC_MAGIC, 3) 32 | #define CM_IOCARDOFF _IO (CM_IOC_MAGIC, 4) 33 | 34 | #define CM_IOSDBGLVL _IOW(CM_IOC_MAGIC, 250, int*) 35 | 36 | /* card and device states */ 37 | #define CM_CARD_INSERTED 0x01 38 | #define CM_CARD_POWERED 0x02 39 | #define CM_ATR_PRESENT 0x04 40 | #define CM_ATR_VALID 0x08 41 | #define CM_STATE_VALID 0x0f 42 | /* extra info only from CM4000 */ 43 | #define CM_NO_READER 0x10 44 | #define CM_BAD_CARD 0x20 45 | 46 | #ifdef __KERNEL__ 47 | 48 | /* USB can have 16 readers, while PCMCIA is allowed 4 slots */ 49 | 50 | #define CM4000_MAX_DEV 4 51 | 52 | #ifdef __CM2020__ 53 | 54 | #define MODULE_NAME "cardman_usb" 55 | 56 | #define CM2020_MAX_DEV 16 57 | #define CM2020_MINOR 224 58 | 59 | #define CM2020_REQT_WRITE 0x42 60 | #define CM2020_REQT_READ 0xc2 61 | 62 | #define CM2020_MODE_1 0x01 63 | #define CM2020_MODE_2 0x02 64 | #define CM2020_MODE_3 0x03 65 | #define CM2020_MODE_4 0x08 66 | #define CM2020_CARD_ON 0x10 67 | #define CM2020_CARD_OFF 0x11 68 | #define CM2020_GET_STATUS 0x20 69 | #define CM2020_STATUS_MASK 0xc0 70 | #define CM2020_STATUS_NO_CARD 0x00 71 | #define CM2020_STATUS_NOT_POWERD 0x40 72 | #define CM2020_STATUS_POWERD 0xc0 73 | #define CM2020_SET_PARAMETER 0x30 74 | 75 | #define CM2020_CARDON_COLD 0x00 76 | #define CM2020_CARDON_WARM 0x01 77 | 78 | #define CM2020_FREQUENCY_3_72MHZ 0x00 79 | #define CM2020_FREQUENCY_5_12MHZ 0x10 80 | 81 | #define CM2020_BAUDRATE_115200 0x0C 82 | #define CM2020_BAUDRATE_76800 0x08 83 | #define CM2020_BAUDRATE_57600 0x06 84 | #define CM2020_BAUDRATE_38400 0x04 85 | #define CM2020_BAUDRATE_28800 0x03 86 | #define CM2020_BAUDRATE_19200 0x02 87 | #define CM2020_BAUDRATE_9600 0x01 88 | 89 | #define CM2020_ODD_PARITY 0x80 90 | 91 | #define CM2020_CARD_ASYNC 0x00 92 | 93 | enum { 94 | CB_NOP, 95 | CB_SET_PARAMETER, 96 | CB_READ_STATUS, 97 | CB_READ_ATR, 98 | CB_WRITE_PTS, 99 | CB_READ_PTS, 100 | CB_WRITE_T1, 101 | CB_PROG_T1, 102 | CB_READ_T1, 103 | CB_WRITE_T0, 104 | CB_WRITE_T0_SW1SW2, 105 | CB_READ_T0, 106 | CB_READ_T0_DATA, 107 | CB_CARD_OFF, 108 | CB_T1MODE2 109 | }; 110 | 111 | #define TIMEOUT_LEN 60000 112 | #define MAX_RBUF 512 113 | 114 | typedef struct usb_cardman { 115 | 116 | struct usb_device *dev; 117 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 118 | struct usb_interface *interface; /* the interface for this device */ 119 | #endif 120 | struct task_struct *owner; 121 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) 122 | struct usb_ctrlrequest *dr; 123 | #else 124 | devrequest *dr; 125 | #endif 126 | struct urb *irq, *ctrl, *rctl; 127 | unsigned char *ibuf, *cbuf, *rcbuf; 128 | wait_queue_head_t waitq; 129 | 130 | unsigned char atr[MAX_ATR]; 131 | unsigned char atr_csum; 132 | unsigned char atr_len; 133 | unsigned char bIFSD, bIFSC; 134 | unsigned char ta1; /* TA(1) specifies Fi over b8 to b5, Di over b4 to b1 */ 135 | unsigned char pts[4]; 136 | 137 | unsigned char rbuf[MAX_RBUF]; 138 | short rlen; 139 | 140 | int t1_reply_len; 141 | 142 | /* length of a T=0 packet, excl. the header length */ 143 | unsigned char t0_data_len; 144 | 145 | /* relative data offset as we proceed through the packet */ 146 | unsigned char t0_data_off; 147 | 148 | /* byte 2 of the T=0 header (INS from CLA INS ADR...) */ 149 | unsigned char t0_ins; 150 | 151 | /* length of T=0 reply we expcet. 2 for a WriteT0, else 152 | * ReadT0 length + 2 (Sw1 Sw2) 153 | */ 154 | unsigned short t0_expected_reply_len; 155 | 156 | int bInterval; 157 | unsigned char ctrlendp; 158 | unsigned char intendp; 159 | unsigned char card_state; 160 | int flags; 161 | int op; 162 | unsigned char proto; 163 | int ttl, ttl_hi, /* CWT */ 164 | bwt, /* BWT */ 165 | ptsttl; /* PTS retry */ 166 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 167 | int open; 168 | int present; 169 | struct semaphore sem; 170 | int minor; 171 | #endif 172 | } usb_cardman_t; 173 | #endif /* __CM2020__ */ 174 | 175 | #ifdef __CM4000__ 176 | 177 | #define DEVICE_NAME "cmm" 178 | #define MODULE_NAME "cardman_cs" 179 | 180 | /* unofficial CM4000 ioctl */ 181 | #define CM4000_IOCMONITOR _IO (CM_IOC_MAGIC, 251) 182 | #define CM4000_IOCDUMPATR _IO (CM_IOC_MAGIC, 252) 183 | #define CM4000_IOCDECUSECOUNT _IO (CM_IOC_MAGIC, 253) 184 | #define CM4000_IOCPOWERON _IO (CM_IOC_MAGIC, 254) 185 | #define CM4000_IOCGIOADDR _IOW(CM_IOC_MAGIC, 255, int*) 186 | 187 | #endif /* __CM4000__ */ 188 | 189 | #endif /* __KERNEL__ */ 190 | #endif /* _CARDMAN_H_ */ 191 | -------------------------------------------------------------------------------- /src/ifd/checksum.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Checksum handling 3 | * 4 | * Copyright Matthias Bruestle 1999-2002 5 | * For licensing, see the file LICENCE 6 | */ 7 | 8 | #include "internal.h" 9 | 10 | #define min( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) 11 | 12 | /* ISO STD 3309 */ 13 | /* From: medin@catbyte.b30.ingr.com (Dave Medin) 14 | * Subject: CCITT checksums 15 | * Newsgroups: sci.electronics 16 | * Date: Mon, 7 Dec 1992 17:33:39 GMT 17 | */ 18 | 19 | /* Correct Table? */ 20 | 21 | static unsigned short crctab[256] = { 22 | 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 23 | 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 24 | 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 25 | 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 26 | 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 27 | 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 28 | 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 29 | 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 30 | 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 31 | 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 32 | 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 33 | 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 34 | 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 35 | 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 36 | 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 37 | 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 38 | 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 39 | 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 40 | 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 41 | 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 42 | 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 43 | 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 44 | 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 45 | 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 46 | 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 47 | 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 48 | 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 49 | 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 50 | 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 51 | 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 52 | 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 53 | 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 54 | }; 55 | 56 | /* 57 | * Returns LRC of data. 58 | */ 59 | unsigned int csum_lrc_compute(const uint8_t * in, size_t len, unsigned char *rc) 60 | { 61 | unsigned char lrc = 0; 62 | 63 | while (len--) 64 | lrc ^= *in++; 65 | 66 | if (rc) 67 | *rc = lrc; 68 | return 1; 69 | } 70 | 71 | /* 72 | * Compute CRC of data. 73 | */ 74 | unsigned int 75 | csum_crc_compute(const uint8_t * data, size_t len, unsigned char *rc) 76 | { 77 | unsigned short v = 0xFFFF; 78 | 79 | while (len--) { 80 | v = ((v >> 8) & 0xFF) ^ crctab[(v ^ *data++) & 0xFF]; 81 | } 82 | 83 | if (rc) { 84 | rc[0] = (v >> 8) & 0xFF; 85 | rc[1] = v & 0xFF; 86 | } 87 | 88 | return 2; 89 | } 90 | -------------------------------------------------------------------------------- /src/ifd/ctbcs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Build Extended CTBCS APDUs for those readers that 3 | * support them (such as Kobil Kaan). 4 | * 5 | * Copyright (C) 2003, Olaf Kirch 6 | */ 7 | 8 | #include "internal.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "ctbcs.h" 14 | 15 | /* 16 | * Start building CTBCS apdu 17 | */ 18 | void ctbcs_begin(ct_buf_t * bp, unsigned int ins, unsigned int p1, 19 | unsigned int p2) 20 | { 21 | ct_buf_putc(bp, 0x20); 22 | ct_buf_putc(bp, ins); 23 | ct_buf_putc(bp, p1); 24 | ct_buf_putc(bp, p2); 25 | ct_buf_putc(bp, 0); 26 | } 27 | 28 | /* 29 | * Finish CTBCS apdu 30 | */ 31 | int ctbcs_finish(ct_buf_t * bp) 32 | { 33 | unsigned int len; 34 | 35 | if (ct_buf_overrun(bp)) 36 | return IFD_ERROR_BUFFER_TOO_SMALL; 37 | 38 | len = ct_buf_avail(bp); 39 | bp->base[4] = len - 5; /* lc */ 40 | return len; 41 | } 42 | 43 | /* 44 | * Output a string to the display 45 | */ 46 | int ctbcs_build_output(unsigned char *cmd, size_t size, const char *message) 47 | { 48 | ct_buf_t buf; 49 | 50 | if (message == NULL) 51 | return IFD_ERROR_INVALID_ARG; 52 | 53 | ct_buf_init(&buf, cmd, size); 54 | ctbcs_begin(&buf, 0x17, 0x40, 0x00); 55 | ctbcs_add_message(&buf, message); 56 | return ctbcs_finish(&buf); 57 | } 58 | 59 | /* 60 | * Generic Verify APDU 61 | */ 62 | static int ctbcs_build_verify_apdu(unsigned char *cmd, size_t size, 63 | unsigned char ins, unsigned char p1, 64 | const char *prompt, unsigned int timeout, 65 | const unsigned char *data, size_t data_len) 66 | { 67 | ct_buf_t buf; 68 | 69 | if (!data || !data_len) 70 | return IFD_ERROR_INVALID_ARG; 71 | 72 | if (prompt == NULL) 73 | return IFD_ERROR_INVALID_ARG; 74 | ct_buf_init(&buf, cmd, size); 75 | ctbcs_begin(&buf, ins, p1, 0x00); 76 | 77 | ctbcs_add_timeout(&buf, timeout); 78 | ctbcs_add_message(&buf, prompt); 79 | 80 | ct_buf_putc(&buf, 0x52); 81 | ct_buf_putc(&buf, data_len); 82 | ct_buf_put(&buf, data, data_len); 83 | if (ct_buf_overrun(&buf)) 84 | return IFD_ERROR_BUFFER_TOO_SMALL; 85 | 86 | cmd[4] = ct_buf_avail(&buf) - 5; /* lc */ 87 | return ct_buf_avail(&buf); 88 | } 89 | 90 | /* 91 | * Build Perform Verify APDU 92 | */ 93 | int ctbcs_build_perform_verify_apdu(unsigned char *cmd, size_t size, 94 | unsigned int p1, const char *prompt, 95 | unsigned int timeout, 96 | const unsigned char *data, size_t data_len) 97 | { 98 | return ctbcs_build_verify_apdu(cmd, size, 0x18, p1, 99 | prompt, timeout, data, data_len); 100 | } 101 | 102 | /* 103 | * Build Modify Verify APDU 104 | */ 105 | int ctbcs_build_modify_verify_apdu(unsigned char *cmd, size_t size, 106 | unsigned int p1, const char *prompt, 107 | unsigned int timeout, 108 | const unsigned char *data, size_t data_len) 109 | { 110 | return ctbcs_build_verify_apdu(cmd, size, 0x19, p1, 111 | prompt, timeout, data, data_len); 112 | } 113 | 114 | /* 115 | * Helper function add message/timeout arguments to command 116 | * buffer 117 | */ 118 | int ctbcs_add_timeout(ct_buf_t * bp, unsigned int timeout) 119 | { 120 | if (!timeout) 121 | return 0; 122 | ct_buf_putc(bp, 0x80); 123 | ct_buf_putc(bp, 1); 124 | ct_buf_putc(bp, timeout); 125 | return ct_buf_avail(bp); 126 | } 127 | 128 | int ctbcs_add_message(ct_buf_t * bp, const char *message) 129 | { 130 | int n; 131 | 132 | if (!message || !strcmp(message, "@")) 133 | return 0; 134 | 135 | if ((n = strlen(message)) > 32) 136 | n = 32; 137 | 138 | ct_buf_putc(bp, 0x50); 139 | ct_buf_putc(bp, n); 140 | ct_buf_put(bp, message, n); 141 | 142 | return ct_buf_avail(bp); 143 | } 144 | -------------------------------------------------------------------------------- /src/ifd/ctbcs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Build Extended CTBCS APDUs for those readers that 3 | * support them (such as Kobil Kaan). 4 | * 5 | * Copyright (C) 2003, Olaf Kirch 6 | */ 7 | 8 | #ifndef IFD_CTBCS_H 9 | #define IFD_CTBCS_H 10 | 11 | extern int ctbcs_build_output(unsigned char *cmd, size_t size, 12 | const char *message); 13 | extern int ctbcs_build_perform_verify_apdu(unsigned char *cmd, size_t size, 14 | unsigned int slot, 15 | const char *prompt, 16 | unsigned int timeout, 17 | const unsigned char *data, 18 | size_t data_len); 19 | extern int ctbcs_build_modify_verify_apdu(unsigned char *cmd, size_t size, 20 | unsigned int dest, const char *prompt, 21 | unsigned int timeout, 22 | const unsigned char *data, 23 | size_t data_len); 24 | 25 | extern void ctbcs_begin(ct_buf_t *, unsigned int, unsigned int, unsigned int); 26 | extern int ctbcs_finish(ct_buf_t *); 27 | extern int ctbcs_add_message(ct_buf_t *, const char *); 28 | extern int ctbcs_add_timeout(ct_buf_t *, unsigned int); 29 | 30 | #endif /* IFD_CTBCS_H */ 31 | -------------------------------------------------------------------------------- /src/ifd/device.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Generic IFD device layer 3 | * 4 | * Copyright (C) 2003 Olaf Kirch 5 | */ 6 | 7 | #include "internal.h" 8 | #include 9 | #include 10 | 11 | /* 12 | * Open a device given the name 13 | */ 14 | ifd_device_t *ifd_device_open(const char *name) 15 | { 16 | if (name == NULL) { 17 | ct_error("Null device"); 18 | return NULL; 19 | } 20 | 21 | if (!strncmp(name, "serial:", 7)) 22 | return ifd_open_serial(name + 7); 23 | if (!strncmp(name, "usb:", 4)) 24 | return ifd_open_usb(name + 4); 25 | if (!strncmp(name, "remote:", 7)) 26 | return ifd_open_remote(name + 7); 27 | if (!strncmp(name, "pcmcia:", 7)) 28 | return ifd_open_pcmcia(name + 7); 29 | if (!strncmp(name, "pcmcia_block:", 13)) 30 | return ifd_open_pcmcia_block(name + 13); 31 | 32 | ct_error("Unknown device type \"%s\"", name); 33 | return NULL; 34 | } 35 | 36 | /* 37 | * Create a new device struct 38 | * This is an internal function called by the different device 39 | * type handlers (serial, usb, etc) 40 | */ 41 | ifd_device_t *ifd_device_new(const char *name, struct ifd_device_ops * ops, 42 | size_t size) 43 | { 44 | ifd_device_t *dev; 45 | 46 | dev = (ifd_device_t *) calloc(1, size); 47 | if (!dev) { 48 | ct_error("out of memory"); 49 | return NULL; 50 | } 51 | dev->name = strdup(name); 52 | dev->ops = ops; 53 | 54 | return dev; 55 | } 56 | 57 | /* 58 | * Destroy a device handle 59 | */ 60 | void ifd_device_free(ifd_device_t * dev) 61 | { 62 | if (dev->name) 63 | free(dev->name); 64 | memset(dev, 0, sizeof(*dev)); 65 | free(dev); 66 | } 67 | 68 | /* 69 | * Miscellaneous device operations. These functions 70 | * just do a consistency check on the handle, and route 71 | * the call to the appropriate member function 72 | */ 73 | int ifd_device_type(ifd_device_t * dev) 74 | { 75 | return dev->type; 76 | } 77 | 78 | int ifd_device_reset(ifd_device_t * dev) 79 | { 80 | if (!dev || !dev->ops || !dev->ops->reset) 81 | return IFD_ERROR_NOT_SUPPORTED; 82 | return dev->ops->reset(dev); 83 | } 84 | 85 | void ifd_device_set_hotplug(ifd_device_t * dev, int hotplug) 86 | { 87 | if (hotplug) 88 | dev->hotplug = 1; 89 | } 90 | 91 | int ifd_device_set_parameters(ifd_device_t * dev, 92 | const ifd_device_params_t * parms) 93 | { 94 | if (!dev || !dev->ops || !dev->ops->set_params) 95 | return IFD_ERROR_NOT_SUPPORTED; 96 | return dev->ops->set_params(dev, parms); 97 | } 98 | 99 | int ifd_device_get_parameters(ifd_device_t * dev, ifd_device_params_t * parms) 100 | { 101 | if (!dev || !dev->ops || !dev->ops->get_params) 102 | return IFD_ERROR_NOT_SUPPORTED; 103 | return dev->ops->get_params(dev, parms); 104 | } 105 | 106 | void ifd_device_flush(ifd_device_t * dev) 107 | { 108 | if (!dev || !dev->ops || !dev->ops->flush) 109 | return; 110 | dev->ops->flush(dev); 111 | } 112 | 113 | void ifd_device_send_break(ifd_device_t * dev, unsigned int usec) 114 | { 115 | if (!dev || !dev->ops || !dev->ops->send_break) 116 | return; 117 | dev->ops->send_break(dev, usec); 118 | } 119 | 120 | int ifd_device_send(ifd_device_t * dev, const unsigned char *data, size_t len) 121 | { 122 | if (!dev || !dev->ops || !dev->ops->send) 123 | return IFD_ERROR_NOT_SUPPORTED; 124 | return dev->ops->send(dev, data, len); 125 | } 126 | 127 | int ifd_device_control(ifd_device_t * dev, void *cmsg, size_t len) 128 | { 129 | if (!dev || !dev->ops || !dev->ops->control) 130 | return IFD_ERROR_NOT_SUPPORTED; 131 | return dev->ops->control(dev, cmsg, len); 132 | } 133 | 134 | int ifd_device_recv(ifd_device_t * dev, unsigned char *data, size_t len, 135 | long timeout) 136 | { 137 | if (timeout < 0) 138 | timeout = dev->timeout; 139 | 140 | if (!dev || !dev->ops || !dev->ops->recv) 141 | return IFD_ERROR_NOT_SUPPORTED; 142 | return dev->ops->recv(dev, data, len, timeout); 143 | } 144 | 145 | int ifd_device_transceive(ifd_device_t * dev, const void *sbuf, size_t slen, 146 | void *rbuf, size_t rlen, long timeout) 147 | { 148 | int rc; 149 | 150 | if (timeout < 0) 151 | timeout = dev->timeout; 152 | 153 | if (!dev || !dev->ops) 154 | return -1; 155 | if (dev->ops->transceive) 156 | return dev->ops->transceive(dev, 157 | sbuf, slen, rbuf, rlen, timeout); 158 | 159 | /* Fall back to send/recv */ 160 | ifd_device_flush(dev); 161 | if ((rc = ifd_device_send(dev, (const unsigned char *)sbuf, slen)) < 0) 162 | return rc; 163 | return ifd_device_recv(dev, (unsigned char *)rbuf, rlen, timeout); 164 | } 165 | 166 | int ifd_device_poll_presence(ifd_device_t * dev, struct pollfd *pfd) 167 | { 168 | if (!dev || !dev->ops || !dev->ops->poll_presence) 169 | return 1; 170 | return dev->ops->poll_presence(dev, pfd); 171 | } 172 | 173 | int ifd_device_get_eventfd(ifd_device_t * dev, short *events) 174 | { 175 | if (!dev || !dev->ops) 176 | return -1; 177 | if (!dev->ops->get_eventfd) 178 | return -1; 179 | return dev->ops->get_eventfd(dev, events); 180 | } 181 | 182 | void ifd_device_close(ifd_device_t * dev) 183 | { 184 | if (!dev) 185 | return; 186 | if (dev->ops && dev->ops->close) 187 | dev->ops->close(dev); 188 | ifd_device_free(dev); 189 | } 190 | 191 | /* 192 | * Device ID handling 193 | */ 194 | int ifd_device_id_parse(const char *str, ifd_devid_t * id) 195 | { 196 | unsigned int n; 197 | 198 | id->type = IFD_DEVICE_TYPE_OTHER; 199 | 200 | n = strcspn(str, ":"); 201 | if (str[n] == ':') { 202 | if (!strncmp(str, "usb", n)) 203 | id->type = IFD_DEVICE_TYPE_USB; 204 | else if (!strncmp(str, "pcmcia", n)) 205 | id->type = IFD_DEVICE_TYPE_PCMCIA; 206 | else 207 | return -1; 208 | str += n + 1; 209 | } 210 | 211 | for (n = 0; *str && n < IFD_MAX_DEVID_PARTS; n++) { 212 | id->val[n] = strtoul(str, (char **)&str, 16); 213 | if (*str == '/') 214 | str++; 215 | } 216 | 217 | if (*str || n == 0) 218 | return -1; 219 | id->num = n; 220 | return 0; 221 | } 222 | 223 | int ifd_device_id_match(const ifd_devid_t * match, const ifd_devid_t * id) 224 | { 225 | if (id->type != match->type 226 | || id->num < match->num 227 | || memcmp(id->val, match->val, match->num * sizeof(id->val[0]))) 228 | return 0; 229 | return 1; 230 | } 231 | -------------------------------------------------------------------------------- /src/ifd/driver.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * Generic driver functions. 4 | * 5 | * Copyright (C) 2003, Olaf Kirch 6 | */ 7 | 8 | #include "internal.h" 9 | #include 10 | #include 11 | 12 | struct ifd_driver_info { 13 | struct ifd_driver_info *next; 14 | 15 | ifd_driver_t driver; 16 | 17 | unsigned int nids; 18 | ifd_devid_t *id; 19 | }; 20 | 21 | static struct ifd_driver_info *list; 22 | 23 | /* 24 | * Find registered driver by name 25 | */ 26 | static struct ifd_driver_info *find_by_name(const char *name, int create) 27 | { 28 | struct ifd_driver_info *ip; 29 | 30 | for (ip = list; ip; ip = ip->next) { 31 | if (!strcmp(ip->driver.name, name)) 32 | return ip; 33 | } 34 | 35 | if (!create) 36 | return NULL; 37 | 38 | ip = (struct ifd_driver_info *)calloc(1, sizeof(*ip)); 39 | if (!ip) { 40 | ct_error("out of memory"); 41 | return NULL; 42 | } 43 | ip->driver.name = strdup(name); 44 | ip->next = list; 45 | list = ip; 46 | 47 | return ip; 48 | } 49 | 50 | /** 51 | * Register a driver. 52 | * 53 | * @param name Driver name. 54 | * @param ops Driver operations. 55 | */ 56 | void ifd_driver_register(const char *name, struct ifd_driver_ops *ops) 57 | { 58 | struct ifd_driver_info *ip; 59 | 60 | ip = find_by_name(name, 1); 61 | if (ip->driver.ops == NULL) 62 | ip->driver.ops = ops; 63 | } 64 | 65 | /** 66 | * Add a device ID to a driver. 67 | * 68 | * @param id Device ID. 69 | * @param name Driver name. 70 | * 71 | * Device which support plug-and-play can be mapped to drivers based on the 72 | * device ID. This function adds a device ID to a driver, so that the driver 73 | * can be looked-up at device detection time. The driver doesn't have to be 74 | * registered before calling this function. 75 | * 76 | * Device IDs start with the device type followed by a semi-colon and by a 77 | * device type specific ID. The following device types are supported: 78 | * 79 | * @li USB usb:vendor_id/device_id 80 | * 81 | * @return Error code <0 if failure. 82 | */ 83 | int ifd_driver_add_id(const char *id, const char *name) 84 | { 85 | struct ifd_driver_info *ip; 86 | 87 | ifd_debug(3, "ifd_driver_add_id(%s, %s)", id, name); 88 | ip = find_by_name(name, 1); 89 | if (!ip) 90 | return -1; 91 | 92 | ip->id = (ifd_devid_t *) realloc(ip->id, 93 | (ip->nids + 1) * sizeof(ifd_devid_t)); 94 | if (!ip->id) { 95 | ct_error("out of memory"); 96 | return IFD_ERROR_NO_MEMORY; 97 | } 98 | if (ifd_device_id_parse(id, &ip->id[ip->nids]) >= 0) 99 | ip->nids++; 100 | 101 | return 0; 102 | } 103 | 104 | /** 105 | * Get the driver name for a given device ID. 106 | * 107 | * @param id Device ID. 108 | * 109 | * @sa ifd_driver_add_id 110 | * @return Driver name or NULL if no driver is found. 111 | */ 112 | const char *ifd_driver_for_id(ifd_devid_t * id) 113 | { 114 | struct ifd_driver_info *ip; 115 | unsigned int n; 116 | 117 | for (ip = list; ip; ip = ip->next) { 118 | for (n = 0; n < ip->nids; n++) { 119 | if (ifd_device_id_match(&ip->id[n], id)) 120 | return ip->driver.name; 121 | } 122 | } 123 | 124 | return NULL; 125 | } 126 | 127 | /** 128 | * Lookup a driver by name. 129 | * 130 | * @param name Driver name. 131 | * 132 | * If the configuration parameter @a autoload is set, OpenCT will try to load 133 | * an external module for the requested driver. 134 | * 135 | * @return Pointer the the driver structure, or NULL if no driver is found. 136 | */ 137 | const ifd_driver_t *ifd_driver_get(const char *name) 138 | { 139 | struct ifd_driver_info *ip; 140 | int retries = 2; 141 | 142 | while (retries--) { 143 | ip = find_by_name(name, ct_config.autoload); 144 | if (ip == NULL) 145 | break; 146 | if (ip->driver.ops != NULL) 147 | return &ip->driver; 148 | if (!ct_config.autoload || ifd_load_module("driver", name) < 0) 149 | break; 150 | } 151 | 152 | return NULL; 153 | } 154 | 155 | /** 156 | * Get a list of registered drivers. 157 | * 158 | * @param names Name array. 159 | * @param max Size of the name array. 160 | * 161 | * This function fills the array pointed by @a names with pointers to the 162 | * driver names. At most @a max entries are returned. The names must @b not 163 | * be freed by the caller. 164 | * 165 | * @return Number of driver names. 166 | */ 167 | unsigned int ifd_drivers_list(const char **names, size_t max) 168 | { 169 | struct ifd_driver_info *ip; 170 | unsigned int n; 171 | 172 | for (ip = list, n = 0; ip && n < max; ip = ip->next, n++) { 173 | names[n] = ip->driver.name; 174 | } 175 | return n; 176 | } 177 | -------------------------------------------------------------------------------- /src/ifd/ifd-cm4000.c: -------------------------------------------------------------------------------- 1 | /* 2 | * OMNIKEY CardMan Mobile PCMCIA 4000 Driver 3 | * 4 | * This driver is not yet complete, but at least it 5 | * spits out the ATR already. 6 | * 7 | * Copyright (C) 2005, Harald Welte 8 | * 9 | * Based on information from the cm4000 driver by Omnikey AG. 10 | */ 11 | 12 | /* only available on linux */ 13 | #ifdef linux 14 | 15 | #include "internal.h" 16 | #include "cardman.h" 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | /* 24 | * Initialize the device 25 | */ 26 | static int cm_open(ifd_reader_t * reader, const char *device_name) 27 | { 28 | ifd_device_t *dev; 29 | ifd_device_params_t params; 30 | 31 | reader->name = "OMNIKEY CardMan 4000"; 32 | reader->nslots = 1; 33 | if (!(dev = ifd_device_open(device_name))) 34 | return -1; 35 | if (ifd_device_type(dev) != IFD_DEVICE_TYPE_PCMCIA) { 36 | ct_error("cm4000: device %s is not a PCMCIA device", 37 | device_name); 38 | ifd_device_close(dev); 39 | return -1; 40 | } 41 | 42 | reader->driver_data = NULL; 43 | reader->device = dev; 44 | dev->timeout = 2000; 45 | 46 | params = dev->settings; 47 | params.usb.interface = 0; 48 | if (ifd_device_set_parameters(dev, ¶ms) < 0) { 49 | ct_error("cm4000: setting parameters failed", device_name); 50 | ifd_device_close(dev); 51 | return -1; 52 | } 53 | 54 | return 0; 55 | } 56 | 57 | /* 58 | * Power up the card slot 59 | */ 60 | static int cm_activate(ifd_reader_t * reader) 61 | { 62 | ifd_debug(1, "called."); 63 | return 0; 64 | } 65 | 66 | static int cm_deactivate(ifd_reader_t * reader) 67 | { 68 | ifd_debug(1, "called."); 69 | return 0; 70 | } 71 | 72 | /* 73 | * Card status 74 | */ 75 | static int cm_card_status(ifd_reader_t * reader, int slot, int *status) 76 | { 77 | ifd_device_t *dev = reader->device; 78 | unsigned int cm_status = 0; 79 | int rc; 80 | 81 | *status = 0; 82 | 83 | ifd_debug(1, "called."); 84 | rc = ioctl(dev->fd, CM_IOCGSTATUS, &cm_status); 85 | if (rc != 0) { 86 | ifd_debug(1, "error during ioctl(CM_IOCGSTATUS): %d=%s", 87 | rc, strerror(errno)); 88 | return -1; 89 | } 90 | 91 | if (cm_status & CM_ATR_PRESENT) 92 | *status = IFD_CARD_PRESENT; 93 | 94 | /* Hardware doesn't tell us about status change */ 95 | 96 | ifd_debug(1, "card %spresent", *status ? "" : "not "); 97 | return 0; 98 | } 99 | 100 | /* 101 | * Reset 102 | */ 103 | static int cm_card_reset(ifd_reader_t * reader, int slot, void *atr, 104 | size_t size) 105 | { 106 | ifd_device_t *dev = reader->device; 107 | struct atreq cmatr; 108 | int len; 109 | 110 | ioctl(dev->fd, 0x6304, 1); 111 | /* propriatary driver doesn't check return value here, too */ 112 | 113 | /* CM_IOCGATR */ 114 | if (ioctl(dev->fd, CM_IOCGATR, &cmatr) != 0) { 115 | ifd_debug(1, "error during ioctl(CM_IOCGATR)\n"); 116 | return -1; 117 | } 118 | 119 | if (cmatr.atr_len == -1) { 120 | ifd_debug(1, "atr_len == -1\n"); 121 | return -1; 122 | } 123 | 124 | len = cmatr.atr_len; 125 | if ((size_t) len > size) 126 | len = size; 127 | 128 | memcpy(atr, &cmatr.atr, len); 129 | 130 | return len; 131 | } 132 | 133 | static int cm_send(ifd_reader_t * reader, unsigned int dad, 134 | const unsigned char *buffer, size_t len) 135 | { 136 | ifd_device_t *dev = reader->device; 137 | 138 | return write(dev->fd, buffer, len); 139 | } 140 | 141 | static int cm_recv(ifd_reader_t * reader, unsigned int dad, 142 | unsigned char *buffer, size_t len, long timeout) 143 | { 144 | ifd_device_t *dev = reader->device; 145 | 146 | return read(dev->fd, buffer, len); 147 | } 148 | 149 | /* 150 | * Driver operations 151 | */ 152 | static struct ifd_driver_ops cm4000_driver; 153 | 154 | /* 155 | * Initialize this module 156 | */ 157 | void ifd_cm4000_register(void) 158 | { 159 | cm4000_driver.open = cm_open; 160 | cm4000_driver.activate = cm_activate; 161 | cm4000_driver.deactivate = cm_deactivate; 162 | cm4000_driver.card_reset = cm_card_reset; 163 | cm4000_driver.card_status = cm_card_status; 164 | cm4000_driver.send = cm_send; 165 | cm4000_driver.recv = cm_recv; 166 | 167 | ifd_driver_register("cm4000", &cm4000_driver); 168 | } 169 | 170 | #else 171 | 172 | /* 173 | * Initialize this module 174 | */ 175 | void ifd_cm4000_register(void) 176 | { 177 | } 178 | 179 | #endif 180 | -------------------------------------------------------------------------------- /src/ifd/ifd-etoken.c: -------------------------------------------------------------------------------- 1 | /* 2 | * eToken driver 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | * 6 | * Based on information from the etoken driver by 7 | * Andreas Jellinghaus . 8 | */ 9 | 10 | #include "internal.h" 11 | #include 12 | #include 13 | 14 | #define ET_TIMEOUT 1000 15 | 16 | static int et_magic(ifd_device_t *); 17 | 18 | /* 19 | * Initialize the device 20 | */ 21 | static int et_open(ifd_reader_t * reader, const char *device_name) 22 | { 23 | ifd_device_t *dev; 24 | ifd_device_params_t params; 25 | 26 | reader->name = "Aladdin eToken PRO"; 27 | reader->nslots = 1; 28 | if (!(dev = ifd_device_open(device_name))) 29 | return -1; 30 | if (ifd_device_type(dev) != IFD_DEVICE_TYPE_USB) { 31 | ct_error("etoken: device %s is not a USB device", device_name); 32 | ifd_device_close(dev); 33 | return -1; 34 | } 35 | 36 | params = dev->settings; 37 | params.usb.interface = 0; 38 | if (ifd_device_set_parameters(dev, ¶ms) < 0) { 39 | ct_error("etoken: setting parameters failed", device_name); 40 | ifd_device_close(dev); 41 | return -1; 42 | } 43 | 44 | reader->device = dev; 45 | 46 | return 0; 47 | } 48 | 49 | /* Some magic incantations copied from Andreas 50 | * Jellinghaus' eToken driver 51 | * */ 52 | static int et_magic(ifd_device_t * dev) 53 | { 54 | unsigned char cookie[] = { 0x00, 0x00, 0x01, 0x00, 0x88, 0x13 }; 55 | unsigned char buffer[256]; 56 | 57 | if (ifd_usb_control(dev, 0x40, 0x03, 0, 0, NULL, 0, -1) < 0 58 | || ifd_usb_control(dev, 0xc0, 0x83, 0, 0, buffer, 13, -1) != 13 59 | || ifd_usb_control(dev, 0x40, 0x02, 0, 0, cookie, sizeof(cookie), 60 | -1) < 0 61 | || ifd_usb_control(dev, 0xc0, 0x82, 0, 0, buffer, 1, -1) != 1 62 | || buffer[0] != 0) 63 | return -1; 64 | 65 | return 0; 66 | } 67 | 68 | /* 69 | * Power up the reader 70 | */ 71 | static int et_activate(ifd_reader_t * reader) 72 | { 73 | return 0; 74 | } 75 | 76 | static int et_deactivate(ifd_reader_t * reader) 77 | { 78 | return -1; 79 | } 80 | 81 | /* 82 | * Card status - always present 83 | */ 84 | static int et_card_status(ifd_reader_t * reader, int slot, int *status) 85 | { 86 | *status = IFD_CARD_PRESENT; 87 | return 0; 88 | } 89 | 90 | /* 91 | * Reset - nothing to be done? 92 | * We should do something to make it come back with all state zapped 93 | */ 94 | static int et_card_reset(ifd_reader_t * reader, int slot, void *atr, 95 | size_t size) 96 | { 97 | ifd_device_t *dev = reader->device; 98 | unsigned char buffer[256]; 99 | int rc, n, atrlen; 100 | 101 | /* Request the ATR */ 102 | rc = ifd_usb_control(dev, 0x40, 0x01, 0, 0, NULL, 0, ET_TIMEOUT); 103 | if (rc < 0) 104 | goto failed; 105 | 106 | /* Receive the ATR */ 107 | rc = ifd_usb_control(dev, 0xc0, 0x81, 0, 0, buffer, 0x23, ET_TIMEOUT); 108 | if (rc <= 0) 109 | goto failed; 110 | 111 | n = buffer[0]; 112 | if (n + 1 > rc) 113 | goto failed; 114 | if (n > IFD_MAX_ATR_LEN) 115 | goto failed; 116 | 117 | if (n > size) 118 | n = size; 119 | atrlen = n; 120 | memcpy(atr, buffer + 1, atrlen); 121 | 122 | if (et_magic(dev) < 0) 123 | goto failed; 124 | return atrlen; 125 | 126 | failed: 127 | ct_error("etoken: failed to activate token"); 128 | return -1; 129 | } 130 | 131 | /* 132 | * Send/receive routines 133 | */ 134 | static int et_send(ifd_reader_t * reader, unsigned int dad, 135 | const unsigned char *buffer, size_t len) 136 | { 137 | return ifd_usb_control(reader->device, 0x40, 0x06, 0, 0, 138 | (void *)buffer, len, -1); 139 | } 140 | 141 | static int et_recv(ifd_reader_t * reader, unsigned int dad, 142 | unsigned char *buffer, size_t len, long timeout) 143 | { 144 | return ifd_usb_control(reader->device, 0xc0, 0x86, 0, 0, 145 | buffer, len, timeout); 146 | } 147 | 148 | static int et_get_eventfd(ifd_reader_t * reader, short *events) 149 | { 150 | ifd_debug(1, "called."); 151 | 152 | return ifd_device_get_eventfd(reader->device, events); 153 | } 154 | 155 | static int et_event(ifd_reader_t * reader, int *status, size_t status_size) 156 | { 157 | (void)reader; 158 | (void)status; 159 | (void)status_size; 160 | 161 | ifd_debug(1, "called."); 162 | 163 | return 0; 164 | } 165 | 166 | static int et_error(ifd_reader_t * reader) 167 | { 168 | (void)reader; 169 | 170 | ifd_debug(1, "called."); 171 | 172 | return IFD_ERROR_DEVICE_DISCONNECTED; 173 | } 174 | 175 | /* 176 | * Driver operations 177 | */ 178 | static struct ifd_driver_ops etoken_driver; 179 | 180 | /* 181 | * Initialize this module 182 | */ 183 | void ifd_etoken_register(void) 184 | { 185 | etoken_driver.open = et_open; 186 | etoken_driver.activate = et_activate; 187 | etoken_driver.deactivate = et_deactivate; 188 | etoken_driver.card_status = et_card_status; 189 | etoken_driver.card_reset = et_card_reset; 190 | etoken_driver.send = et_send; 191 | etoken_driver.recv = et_recv; 192 | etoken_driver.get_eventfd = et_get_eventfd; 193 | etoken_driver.event = et_event; 194 | etoken_driver.error = et_error; 195 | 196 | ifd_driver_register("etoken", &etoken_driver); 197 | } 198 | -------------------------------------------------------------------------------- /src/ifd/ifd-etoken64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * eToken 64 driver 3 | * 4 | * Copyright (C) 2005, Olaf Kirch 5 | * Copyright (C) 2005, Andreas Jellinghaus . 6 | */ 7 | 8 | #include "internal.h" 9 | #include 10 | #include 11 | 12 | #define ET64_TIMEOUT 1000 13 | 14 | /* 15 | * Initialize the device 16 | */ 17 | static int et64_open(ifd_reader_t * reader, const char *device_name) 18 | { 19 | ifd_device_t *dev; 20 | ifd_device_params_t params; 21 | 22 | reader->name = "Aladdin eToken PRO 64k"; 23 | reader->nslots = 1; 24 | if (!(dev = ifd_device_open(device_name))) 25 | return -1; 26 | if (ifd_device_type(dev) != IFD_DEVICE_TYPE_USB) { 27 | ct_error("etoken64: device %s is not a USB device", 28 | device_name); 29 | ifd_device_close(dev); 30 | return -1; 31 | } 32 | 33 | params = dev->settings; 34 | params.usb.interface = 0; 35 | if (ifd_device_set_parameters(dev, ¶ms) < 0) { 36 | ct_error("etoken64: setting parameters failed", device_name); 37 | ifd_device_close(dev); 38 | return -1; 39 | } 40 | 41 | reader->device = dev; 42 | 43 | return 0; 44 | } 45 | 46 | /* 47 | * Power up the reader 48 | */ 49 | static int et64_activate(ifd_reader_t * reader) 50 | { 51 | return 0; 52 | } 53 | 54 | static int et64_deactivate(ifd_reader_t * reader) 55 | { 56 | return -1; 57 | } 58 | 59 | /* 60 | * Card status - always present 61 | */ 62 | static int et64_card_status(ifd_reader_t * reader, int slot, int *status) 63 | { 64 | *status = IFD_CARD_PRESENT; 65 | return 0; 66 | } 67 | 68 | /* 69 | * Reset - nothing to be done? 70 | * We should do something to make it come back with all state zapped 71 | */ 72 | static int et64_card_reset(ifd_reader_t * reader, int slot, void *atr, 73 | size_t size) 74 | { 75 | ifd_device_t *dev = reader->device; 76 | unsigned char buffer[256]; 77 | int rc, n, atrlen; 78 | 79 | /* Request the ATR */ 80 | rc = ifd_usb_control(dev, 0x40, 0x01, 0, 0, NULL, 0, ET64_TIMEOUT); 81 | if (rc < 0) 82 | goto failed; 83 | 84 | /* Receive the ATR */ 85 | rc = ifd_usb_control(dev, 0xc0, 0x81, 0, 0, buffer, 0x23, ET64_TIMEOUT); 86 | if (rc <= 0) 87 | goto failed; 88 | 89 | n = buffer[0]; 90 | if (n + 1 > rc) 91 | goto failed; 92 | if (n > IFD_MAX_ATR_LEN) 93 | goto failed; 94 | 95 | if (n > size) 96 | n = size; 97 | atrlen = n; 98 | memcpy(atr, buffer + 1, atrlen); 99 | 100 | if (ifd_usb_control(dev, 0x40, 0x08, 0, 0, NULL, 0, -1) < 0 101 | || ifd_usb_control(dev, 0xc0, 0x88, 0, 0, buffer, 02, -1) != 02 102 | || ifd_usb_control(dev, 0x40, 0x03, 0, 0, NULL, 0, -1) < 0 103 | || ifd_usb_control(dev, 0xc0, 0x83, 0, 0, buffer, 1, -1) != 1 104 | || buffer[0] != 0) 105 | goto failed; 106 | 107 | return atrlen; 108 | 109 | failed: 110 | ct_error("etoken64: failed to activate token"); 111 | return -1; 112 | } 113 | 114 | /* 115 | * Send/receive routines 116 | */ 117 | static int et64_send(ifd_reader_t * reader, unsigned int dad, 118 | const unsigned char *buffer, size_t len) 119 | { 120 | return ifd_usb_control(reader->device, 0x40, 0x06, 0, 0, 121 | (void *)buffer, len, -1); 122 | } 123 | 124 | static int et64_recv(ifd_reader_t * reader, unsigned int dad, 125 | unsigned char *buffer, size_t len, long timeout) 126 | { 127 | return ifd_usb_control(reader->device, 0xc0, 0x86, 0, 0, 128 | buffer, len, timeout); 129 | } 130 | 131 | static int et64_get_eventfd(ifd_reader_t * reader, short *events) 132 | { 133 | ifd_debug(1, "called."); 134 | 135 | return ifd_device_get_eventfd(reader->device, events); 136 | } 137 | 138 | static int et64_event(ifd_reader_t * reader, int *status, size_t status_size) 139 | { 140 | (void)reader; 141 | (void)status; 142 | (void)status_size; 143 | 144 | ifd_debug(1, "called."); 145 | 146 | return 0; 147 | } 148 | 149 | static int et64_error(ifd_reader_t * reader) 150 | { 151 | (void)reader; 152 | 153 | ifd_debug(1, "called."); 154 | 155 | return IFD_ERROR_DEVICE_DISCONNECTED; 156 | } 157 | 158 | /* 159 | * Driver operations 160 | */ 161 | static struct ifd_driver_ops etoken64_driver; 162 | 163 | /* 164 | * Initialize this module 165 | */ 166 | void ifd_etoken64_register(void) 167 | { 168 | etoken64_driver.open = et64_open; 169 | etoken64_driver.activate = et64_activate; 170 | etoken64_driver.deactivate = et64_deactivate; 171 | etoken64_driver.card_status = et64_card_status; 172 | etoken64_driver.card_reset = et64_card_reset; 173 | etoken64_driver.send = et64_send; 174 | etoken64_driver.recv = et64_recv; 175 | etoken64_driver.get_eventfd = et64_get_eventfd; 176 | etoken64_driver.event = et64_event; 177 | etoken64_driver.error = et64_error; 178 | 179 | ifd_driver_register("etoken64", &etoken64_driver); 180 | } 181 | -------------------------------------------------------------------------------- /src/ifd/ifd-ikey2k.c: -------------------------------------------------------------------------------- 1 | /* 2 | * driver for Rainbow iKey 2032 devices 3 | * 4 | * Copyright (C) 2003, Andreas Jellinghaus 5 | * Copyright (C) 2003, Olaf Kirch 6 | */ 7 | 8 | #include "internal.h" 9 | #include 10 | #include 11 | 12 | /* 13 | * Initialize the device 14 | */ 15 | static int ikey2k_open(ifd_reader_t * reader, const char *device_name) 16 | { 17 | ifd_device_t *dev; 18 | ifd_device_params_t params; 19 | 20 | reader->name = "Rainbow iKey 2032"; 21 | reader->nslots = 1; 22 | if (!(dev = ifd_device_open(device_name))) 23 | return -1; 24 | if (ifd_device_type(dev) != IFD_DEVICE_TYPE_USB) { 25 | ct_error("ikey2k: device %s is not a USB device", device_name); 26 | ifd_device_close(dev); 27 | return -1; 28 | } 29 | 30 | params = dev->settings; 31 | params.usb.interface = 0; 32 | if (ifd_device_set_parameters(dev, ¶ms) < 0) { 33 | ct_error("ikey2k: setting parameters failed", device_name); 34 | ifd_device_close(dev); 35 | return -1; 36 | } 37 | 38 | reader->device = dev; 39 | 40 | return 0; 41 | } 42 | 43 | /* 44 | * Power up the reader 45 | */ 46 | static int ikey2k_activate(ifd_reader_t * reader) 47 | { 48 | return 0; 49 | } 50 | 51 | static int ikey2k_deactivate(ifd_reader_t * reader) 52 | { 53 | return -1; 54 | } 55 | 56 | /* 57 | * Card status - always present 58 | */ 59 | static int ikey2k_card_status(ifd_reader_t * reader, int slot, int *status) 60 | { 61 | *status = IFD_CARD_PRESENT; 62 | return 0; 63 | } 64 | 65 | /* 66 | * Reset - nothing to be done? 67 | * We should do something to make it come back with all state zapped 68 | */ 69 | static int ikey2k_card_reset(ifd_reader_t * reader, int slot, void *atr, 70 | size_t size) 71 | { 72 | ifd_device_t *dev = reader->device; 73 | unsigned char buffer[256]; 74 | int rc, atrlen; 75 | 76 | static unsigned char expect5[] = 77 | { 0x0d, 0x63, 0x00, 0x00, 0x2d, 0x2d, 0xc0, 0x80, 78 | 0x80, 0x60, 0x80, 0x01, 0x19 79 | }; 80 | 81 | if (ifd_usb_control(dev, 0xc1, 0x00, 0, 0, buffer, 0x40, -1) != 13) 82 | goto failed; 83 | 84 | /* we've seen values of 0x03, 0x05 and 0x06 in position 3, and 85 | * since we don't know what they mean, we mask them here. */ 86 | buffer[3] &= 0xF0; 87 | 88 | if (memcmp(buffer, expect5, sizeof(expect5)) != 0 89 | || ifd_usb_control(dev, 0x41, 0x16, 0, 0, buffer, 00, -1) != 0 90 | || ifd_usb_control(dev, 0xc1, 0x01, 0, 0, buffer, 02, -1) != 1 91 | || buffer[0] != 00) 92 | goto failed; 93 | 94 | rc = ifd_usb_control(dev, 0x41, 0x16, 0x1901, 0, buffer, 0, 1000); 95 | if (rc < 0) 96 | goto failed; 97 | 98 | rc = ifd_usb_control(dev, 0xc1, 0x01, 0, 0, buffer, 0x19, 1000); 99 | if (rc != 25) 100 | goto failed; 101 | 102 | rc = ifd_usb_control(dev, 0x41, 0x16, 0, 0, buffer, 0x0, 1000); 103 | if (rc != 0) 104 | goto failed; 105 | 106 | rc = ifd_usb_control(dev, 0xc1, 0x01, 0, 0, buffer, 0x02, 1000); 107 | if (rc != 1 || buffer[0] != 0) 108 | goto failed; 109 | 110 | rc = ifd_usb_control(dev, 0x41, 0x16, 0, 0, buffer, 0x0, 1000); 111 | if (rc != 0) 112 | goto failed; 113 | 114 | rc = ifd_usb_control(dev, 0xc1, 0x01, 0, 0, buffer, 0x20, 1000); 115 | if (rc != 1 || buffer[0] != 0) 116 | goto failed; 117 | 118 | rc = ifd_usb_control(dev, 0x41, 0x16, 0x1901, 0, buffer, 0, 1000); 119 | if (rc < 0) 120 | goto failed; 121 | 122 | rc = ifd_usb_control(dev, 0xc1, 0x01, 0, 0, buffer, 0x19, 1000); 123 | if (rc != 25) 124 | goto failed; 125 | 126 | /* yes, this is _currently_ dead code, as IFD_MAX_ATR_LEN 127 | * is higher than 25 ... */ 128 | if (rc > IFD_MAX_ATR_LEN) 129 | goto failed; 130 | 131 | atrlen = rc; 132 | memcpy(atr, buffer, atrlen); 133 | 134 | return atrlen; 135 | 136 | failed: 137 | ct_error("ikey2k: failed to activate token"); 138 | return -1; 139 | } 140 | 141 | /* 142 | * Select a protocol. We override this function to be able to set the T=1 IFSC 143 | */ 144 | static int ikey2k_set_protocol(ifd_reader_t * reader, int nslot, int proto) 145 | { 146 | ifd_slot_t *slot = &reader->slot[nslot]; 147 | int r; 148 | 149 | if (!(slot->proto = ifd_protocol_new(proto, reader, slot->dad))) 150 | return -1; 151 | 152 | if (proto == IFD_PROTOCOL_T1) { 153 | r = ifd_protocol_set_parameter(slot->proto, 154 | IFD_PROTOCOL_T1_IFSC, 256); 155 | if (r < 0) 156 | return r; 157 | } 158 | 159 | return 0; 160 | } 161 | 162 | /* 163 | * Send/receive routines 164 | */ 165 | static int ikey2k_send(ifd_reader_t * reader, unsigned int dad, 166 | const unsigned char *buffer, size_t len) 167 | { 168 | int value, idx; 169 | value = buffer[1] << 8 | buffer[0]; 170 | idx = buffer[3] << 8 | buffer[2]; 171 | 172 | return ifd_usb_control(reader->device, 0x41, 0x17, value, idx, 173 | (void *)&buffer[4], len - 4, -1); 174 | } 175 | 176 | static int ikey2k_recv(ifd_reader_t * reader, unsigned int dad, 177 | unsigned char *buffer, size_t len, long timeout) 178 | { 179 | return ifd_usb_control(reader->device, 0xc1, 0x01, 0, 0, 180 | buffer, 255, timeout); 181 | } 182 | 183 | /* 184 | * Driver operations 185 | */ 186 | static struct ifd_driver_ops ikey2k_driver; 187 | 188 | /* 189 | * Initialize this module 190 | */ 191 | void ifd_ikey2k_register(void) 192 | { 193 | ikey2k_driver.open = ikey2k_open; 194 | ikey2k_driver.activate = ikey2k_activate; 195 | ikey2k_driver.deactivate = ikey2k_deactivate; 196 | ikey2k_driver.card_status = ikey2k_card_status; 197 | ikey2k_driver.card_reset = ikey2k_card_reset; 198 | ikey2k_driver.set_protocol = ikey2k_set_protocol; 199 | ikey2k_driver.send = ikey2k_send; 200 | ikey2k_driver.recv = ikey2k_recv; 201 | 202 | ifd_driver_register("ikey2k", &ikey2k_driver); 203 | } 204 | -------------------------------------------------------------------------------- /src/ifd/ifd-ikey3k.c: -------------------------------------------------------------------------------- 1 | /* 2 | * driver for Rainbow iKey 3000 devices 3 | * 4 | * Copyright (C) 2003, Andreas Jellinghaus 5 | * Copyright (C) 2003, Olaf Kirch 6 | */ 7 | 8 | #include "internal.h" 9 | #include 10 | #include 11 | 12 | /* 13 | * Initialize the device 14 | */ 15 | static int ikey3k_open(ifd_reader_t * reader, const char *device_name) 16 | { 17 | ifd_device_t *dev; 18 | ifd_device_params_t params; 19 | 20 | reader->name = "Rainbow iKey 3000"; 21 | reader->nslots = 1; 22 | if (!(dev = ifd_device_open(device_name))) 23 | return -1; 24 | if (ifd_device_type(dev) != IFD_DEVICE_TYPE_USB) { 25 | ct_error("ikey3k: device %s is not a USB device", device_name); 26 | ifd_device_close(dev); 27 | return -1; 28 | } 29 | 30 | params = dev->settings; 31 | params.usb.interface = 0; 32 | if (ifd_device_set_parameters(dev, ¶ms) < 0) { 33 | ct_error("ikey3k: setting parameters failed", device_name); 34 | ifd_device_close(dev); 35 | return -1; 36 | } 37 | 38 | reader->device = dev; 39 | 40 | return 0; 41 | } 42 | 43 | /* 44 | * Power up the reader 45 | */ 46 | static int ikey3k_activate(ifd_reader_t * reader) 47 | { 48 | return 0; 49 | } 50 | 51 | static int ikey3k_deactivate(ifd_reader_t * reader) 52 | { 53 | return -1; 54 | } 55 | 56 | /* 57 | * Card status - always present 58 | */ 59 | static int ikey3k_card_status(ifd_reader_t * reader, int slot, int *status) 60 | { 61 | *status = IFD_CARD_PRESENT; 62 | return 0; 63 | } 64 | 65 | /* 66 | * Reset - nothing to be done? 67 | * We should do something to make it come back with all state zapped 68 | */ 69 | static int ikey3k_card_reset(ifd_reader_t * reader, int slot, void *atr, 70 | size_t size) 71 | { 72 | ifd_device_t *dev = reader->device; 73 | unsigned char buffer[256]; 74 | int rc, n, atrlen; 75 | 76 | unsigned char expect5[] = 77 | { 0x0a, 0x61, 0x00, 0x07, 0x2d, 0x2d, 0xc0, 0x80, 0x80, 0x60 }; 78 | unsigned char expect11[] = { 0xff, 0x11, 0x11, 0xff }; 79 | 80 | if (ifd_usb_control(dev, 0xc1, 0x00, 0, 0, buffer, 0x40, -1) != 10 81 | || memcmp(buffer, expect5, sizeof(expect5)) != 0 82 | || ifd_usb_control(dev, 0x41, 0x16, 0, 0, buffer, 00, -1) != 0 83 | || ifd_usb_control(dev, 0xc1, 0x01, 0, 0, buffer, 02, -1) != 1 84 | || buffer[0] != 00) 85 | goto failed; 86 | 87 | rc = ifd_usb_control(dev, 0x41, 0x16, 0x2005, 0, buffer, 0, 1000); 88 | if (rc < 0) 89 | goto failed; 90 | 91 | rc = ifd_usb_control(dev, 0xc1, 0x01, 0, 0, buffer, 0x20, 1000); 92 | if (rc <= 0) 93 | goto failed; 94 | 95 | n = buffer[0]; 96 | if (n + 1 > rc) 97 | goto failed; 98 | if (n > IFD_MAX_ATR_LEN) 99 | goto failed; 100 | 101 | if (n > size) 102 | n = size; 103 | atrlen = n; 104 | memcpy(atr, buffer + 1, atrlen); 105 | 106 | if (ifd_usb_control(dev, 0x41, 0x16, 0x0002, 0, buffer, 0, -1) != 0 107 | || ifd_usb_control(dev, 0xc1, 0x01, 0, 0, buffer, 04, -1) != 4 108 | || memcmp(buffer, expect11, sizeof(expect11)) != 0) 109 | goto failed; 110 | 111 | return atrlen; 112 | 113 | failed: 114 | ct_error("ikey3k: failed to activate token"); 115 | return -1; 116 | } 117 | 118 | /* 119 | * Select a protocol. We override this function to be able to set the T=1 IFSC 120 | */ 121 | static int ikey3k_set_protocol(ifd_reader_t * reader, int nslot, int proto) 122 | { 123 | ifd_slot_t *slot = &reader->slot[nslot]; 124 | int r; 125 | 126 | if (!(slot->proto = ifd_protocol_new(proto, reader, slot->dad))) 127 | return -1; 128 | 129 | if (proto == IFD_PROTOCOL_T1) { 130 | r = ifd_protocol_set_parameter(slot->proto, 131 | IFD_PROTOCOL_T1_IFSC, 256); 132 | if (r < 0) 133 | return r; 134 | } 135 | 136 | return 0; 137 | } 138 | 139 | /* 140 | * Send/receive routines 141 | */ 142 | static int ikey3k_send(ifd_reader_t * reader, unsigned int dad, 143 | const unsigned char *buffer, size_t len) 144 | { 145 | int value, idx; 146 | value = buffer[1] << 8 | buffer[0]; 147 | idx = buffer[3] << 8 | buffer[2]; 148 | 149 | return ifd_usb_control(reader->device, 0x41, 0x17, value, idx, 150 | (void *)&buffer[4], len - 4, -1); 151 | } 152 | 153 | static int ikey3k_recv(ifd_reader_t * reader, unsigned int dad, 154 | unsigned char *buffer, size_t len, long timeout) 155 | { 156 | return ifd_usb_control(reader->device, 0xc1, 0x01, 0, 0, 157 | buffer, 255, timeout); 158 | } 159 | 160 | /* 161 | * Driver operations 162 | */ 163 | static struct ifd_driver_ops ikey3k_driver; 164 | 165 | /* 166 | * Initialize this module 167 | */ 168 | void ifd_ikey3k_register(void) 169 | { 170 | ikey3k_driver.open = ikey3k_open; 171 | ikey3k_driver.activate = ikey3k_activate; 172 | ikey3k_driver.deactivate = ikey3k_deactivate; 173 | ikey3k_driver.card_status = ikey3k_card_status; 174 | ikey3k_driver.card_reset = ikey3k_card_reset; 175 | ikey3k_driver.set_protocol = ikey3k_set_protocol; 176 | ikey3k_driver.send = ikey3k_send; 177 | ikey3k_driver.recv = ikey3k_recv; 178 | 179 | ifd_driver_register("ikey3k", &ikey3k_driver); 180 | } 181 | -------------------------------------------------------------------------------- /src/ifd/ifd-starkey.c: -------------------------------------------------------------------------------- 1 | /* 2 | * starkey driver 3 | * 4 | * Copyright (C) 2005, Andreas Jellinghaus 5 | */ 6 | 7 | #include "internal.h" 8 | #include 9 | #include 10 | 11 | #define STARKEY_TIMEOUT 100000 12 | 13 | /* 14 | * Initialize the device 15 | */ 16 | static int starkey_open(ifd_reader_t * reader, const char *device_name) 17 | { 18 | ifd_device_t *dev; 19 | ifd_device_params_t params; 20 | 21 | reader->name = "G&D Starkey 100"; 22 | reader->nslots = 1; 23 | if (!(dev = ifd_device_open(device_name))) 24 | return -1; 25 | if (ifd_device_type(dev) != IFD_DEVICE_TYPE_USB) { 26 | ct_error("starkey: device %s is not a USB device", device_name); 27 | ifd_device_close(dev); 28 | return -1; 29 | } 30 | 31 | params = dev->settings; 32 | params.usb.interface = 0; 33 | if (ifd_device_set_parameters(dev, ¶ms) < 0) { 34 | ct_error("starkey: setting parameters failed", device_name); 35 | ifd_device_close(dev); 36 | return -1; 37 | } 38 | 39 | reader->device = dev; 40 | 41 | return 0; 42 | } 43 | 44 | /* 45 | * Power up the reader 46 | */ 47 | static int starkey_activate(ifd_reader_t * reader) 48 | { 49 | return 0; 50 | } 51 | 52 | static int starkey_deactivate(ifd_reader_t * reader) 53 | { 54 | return -1; 55 | } 56 | 57 | /* 58 | * Card status - always present 59 | */ 60 | static int starkey_card_status(ifd_reader_t * reader, int slot, int *status) 61 | { 62 | *status = IFD_CARD_PRESENT; 63 | return 0; 64 | } 65 | 66 | /* 67 | * Reset - nothing to be done? 68 | * We should do something to make it come back with all state zapped 69 | */ 70 | static int starkey_card_reset(ifd_reader_t * reader, int slot, void *atr, 71 | size_t size) 72 | { 73 | ifd_device_t *dev = reader->device; 74 | unsigned char buffer[32]; 75 | int rc, atrlen; 76 | ifd_usb_capture_t *cap; 77 | 78 | rc = ifd_usb_begin_capture(dev, 79 | IFD_USB_URB_TYPE_INTERRUPT, 0x81, 80 | sizeof(buffer), &cap); 81 | if (rc < 0) 82 | return rc; 83 | 84 | rc = ifd_usb_capture(dev, cap, buffer, sizeof(buffer), STARKEY_TIMEOUT); 85 | 86 | if (rc <= 0) { 87 | ct_error("starkey: failed to activate token"); 88 | return -1; 89 | } 90 | 91 | memcpy(atr, buffer, rc); 92 | atrlen = rc; 93 | return atrlen; 94 | } 95 | 96 | /* 97 | * Send/receive routines 98 | */ 99 | static int starkey_send(ifd_reader_t * reader, unsigned int dad, 100 | const unsigned char *buffer, size_t len) 101 | { 102 | return ifd_usb_control(reader->device, 0x40, 0x06, 0, 0, 103 | (void *)buffer, len, -1); 104 | } 105 | 106 | static int starkey_recv(ifd_reader_t * reader, unsigned int dad, 107 | unsigned char *buffer, size_t len, long timeout) 108 | { 109 | return ifd_usb_control(reader->device, 0xc0, 0x86, 0, 0, 110 | buffer, len, timeout); 111 | } 112 | 113 | /* 114 | * Driver operations 115 | */ 116 | static struct ifd_driver_ops starkey_driver; 117 | 118 | /* 119 | * Initialize this module 120 | */ 121 | void ifd_starkey_register(void) 122 | { 123 | starkey_driver.open = starkey_open; 124 | starkey_driver.activate = starkey_activate; 125 | starkey_driver.deactivate = starkey_deactivate; 126 | starkey_driver.card_status = starkey_card_status; 127 | starkey_driver.card_reset = starkey_card_reset; 128 | starkey_driver.send = starkey_send; 129 | starkey_driver.recv = starkey_recv; 130 | 131 | ifd_driver_register("starkey", &starkey_driver); 132 | } 133 | -------------------------------------------------------------------------------- /src/ifd/ifdhandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Internal ifdhandler functions 3 | * 4 | * Copyright (C) 2003 Olaf Kirch 5 | */ 6 | 7 | #ifndef IFD_IFDHANDLER_H 8 | #define IFD_IFDHANDLER_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | extern int ifdhandler_process(ct_socket_t *, ifd_reader_t *, 15 | ct_buf_t *, ct_buf_t *); 16 | extern int ifdhandler_lock(ct_socket_t *, int, int, ct_lock_handle *); 17 | extern int ifdhandler_check_lock(ct_socket_t *, int, int); 18 | extern int ifdhandler_unlock(ct_socket_t *, int, ct_lock_handle); 19 | extern void ifdhandler_unlock_all(ct_socket_t *); 20 | 21 | #endif /* IFD_IFDHANDLER_H */ 22 | -------------------------------------------------------------------------------- /src/ifd/init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Initialize the library 3 | * 4 | * Copyright (C) 2003 Olaf Kirch 5 | */ 6 | 7 | #include "internal.h" 8 | #include 9 | #include 10 | 11 | static int configure_driver(ifd_conf_node_t * cf); 12 | 13 | int ifd_init(void) 14 | { 15 | unsigned int ival; 16 | char *sval; 17 | ifd_conf_node_t **nodes; 18 | int i, n; 19 | 20 | /* initialize ltdl */ 21 | i = lt_dlinit(); 22 | if (i != 0) 23 | ct_error("lt_dlinit returned %d", i); 24 | 25 | /* Register built-in drivers */ 26 | ifd_acr30u_register(); 27 | ifd_cardman_register(); 28 | ifd_cm4000_register(); 29 | ifd_egate_register(); 30 | ifd_epass3k_register(); 31 | ifd_etoken_register(); 32 | ifd_etoken64_register(); 33 | ifd_eutron_register(); 34 | ifd_gempc_register(); 35 | ifd_ikey2k_register(); 36 | ifd_ikey3k_register(); 37 | ifd_kaan_register(); 38 | ifd_pertosmart_ac1030_register(); 39 | ifd_pertosmart_ac1038_register(); 40 | ifd_smartboard_register(); 41 | ifd_smph_register(); 42 | ifd_starkey_register(); 43 | ifd_towitoko_register(); 44 | ifd_rutoken_register(); 45 | /* ifd_wbeiuu_register(); driver not working yet */ 46 | ifd_cyberjack_register(); 47 | /* ccid last */ 48 | ifd_ccid_register(); 49 | 50 | /* Register all builtin protocols */ 51 | ifd_protocol_register(&ifd_protocol_t0); 52 | ifd_protocol_register(&ifd_protocol_t1); 53 | ifd_protocol_register(&ifd_protocol_gbp); 54 | ifd_protocol_register(&ifd_protocol_trans); 55 | ifd_protocol_register(&ifd_protocol_i2c_short); 56 | ifd_protocol_register(&ifd_protocol_i2c_long); 57 | ifd_protocol_register(&ifd_protocol_2wire); 58 | ifd_protocol_register(&ifd_protocol_3wire); 59 | ifd_protocol_register(&ifd_protocol_eurochip); 60 | ifd_protocol_register(&ifd_protocol_esc); 61 | 62 | if (ifd_conf_get_integer("debug", &ival) >= 0 && ival > ct_config.debug) 63 | ct_config.debug = ival; 64 | 65 | if (ifd_conf_get_string("ifdhandler.program", &sval) >= 0) 66 | ct_config.ifdhandler = sval; 67 | 68 | /* Register all driver information (use hotplug ids) */ 69 | n = ifd_conf_get_nodes("driver", NULL, 0); 70 | if (n >= 0) { 71 | nodes = (ifd_conf_node_t **) calloc(n, sizeof(*nodes)); 72 | if (!nodes) { 73 | ct_error("out of memory"); 74 | return 1; 75 | } 76 | n = ifd_conf_get_nodes("driver", nodes, n); 77 | for (i = 0; i < n; i++) { 78 | if (configure_driver(nodes[i])) { 79 | free(nodes); 80 | return 1; 81 | } 82 | } 83 | free(nodes); 84 | } 85 | return 0; 86 | } 87 | 88 | /* 89 | * Configure a reader driver 90 | */ 91 | static int configure_driver(ifd_conf_node_t * cf) 92 | { 93 | const char *driver; 94 | char **ids; 95 | int j, n; 96 | 97 | if (!(driver = cf->value)) 98 | return 1; 99 | if ((n = ifd_conf_node_get_string_list(cf, "ids", NULL, 0)) >= 0) { 100 | ids = (char **)calloc(n, sizeof(char *)); 101 | if (!ids) { 102 | ct_error("out of memory"); 103 | return 1; 104 | } 105 | n = ifd_conf_node_get_string_list(cf, "ids", ids, n); 106 | for (j = 0; j < n; j++) 107 | ifd_driver_add_id(ids[j], driver); 108 | free(ids); 109 | } 110 | return 0; 111 | } 112 | -------------------------------------------------------------------------------- /src/ifd/locks.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Locking functions - these are somewhat simplified 3 | * by the fact that we have one manager process per reader, 4 | * so we don't have to worry about different readers here, 5 | * just different slots. 6 | * 7 | * Copyright (C) 2003 Olaf Kirch 8 | * 9 | * FIXME - prevent denial of service from clients allocating 10 | * huge numbers of locks. There should be a maximum of one shared 11 | * and one exclusive lock per client. 12 | */ 13 | 14 | #include "internal.h" 15 | #include 16 | #include "ifdhandler.h" 17 | 18 | typedef struct ct_lock { 19 | struct ct_lock *next; 20 | unsigned int slot; 21 | uid_t uid; 22 | ct_lock_handle handle; 23 | ct_socket_t *owner; 24 | int exclusive; 25 | } ct_lock_t; 26 | 27 | static ct_lock_t *locks; 28 | static unsigned int lock_handle = 0; 29 | 30 | /* 31 | * Try to establish a lock 32 | */ 33 | int ifdhandler_lock(ct_socket_t * sock, int slot, int type, 34 | ct_lock_handle * res) 35 | { 36 | ct_lock_t *l; 37 | int rc; 38 | 39 | /* See if we have a locking conflict */ 40 | if ((rc = ifdhandler_check_lock(sock, slot, type)) < 0) 41 | return rc; 42 | 43 | /* No conflict - grant lock and record this fact */ 44 | l = (ct_lock_t *) calloc(1, sizeof(*l)); 45 | if (!l) { 46 | ct_error("out of memory"); 47 | return IFD_ERROR_NO_MEMORY; 48 | } 49 | l->exclusive = (type == IFD_LOCK_EXCLUSIVE); 50 | l->uid = sock->client_uid; 51 | l->handle = lock_handle++; 52 | l->owner = sock; 53 | l->slot = slot; 54 | 55 | l->next = locks; 56 | locks = l; 57 | 58 | ifd_debug(1, "granted %s lock %u for slot %u by uid=%u", 59 | l->exclusive ? "excl" : "shared", l->handle, l->slot, l->uid); 60 | 61 | *res = l->handle; 62 | return 0; 63 | } 64 | 65 | /* 66 | * Check if a slot is locked by someone else 67 | */ 68 | int ifdhandler_check_lock(ct_socket_t * sock, int slot, int type) 69 | { 70 | ct_lock_t *l; 71 | 72 | for (l = locks; l; l = l->next) { 73 | if (l->slot != slot) 74 | continue; 75 | 76 | if (l->owner == sock) 77 | continue; 78 | 79 | if (l->exclusive 80 | || type == IFD_LOCK_EXCLUSIVE || l->uid != sock->client_uid) 81 | return IFD_ERROR_LOCKED; 82 | } 83 | 84 | return 0; 85 | } 86 | 87 | /* 88 | * Release a lock 89 | */ 90 | int ifdhandler_unlock(ct_socket_t * sock, int slot, ct_lock_handle handle) 91 | { 92 | ct_lock_t *l, **lp; 93 | 94 | for (lp = &locks; (l = *lp) != NULL; lp = &l->next) { 95 | if (l->owner == sock && l->slot == slot && l->handle == handle) { 96 | ifd_debug(1, 97 | "released %s lock %u for slot %u by uid=%u", 98 | l->exclusive ? "excl" : "shared", 99 | l->handle, l->slot, l->uid); 100 | 101 | *lp = l->next; 102 | free(l); 103 | return 0; 104 | } 105 | } 106 | 107 | return IFD_ERROR_NOLOCK; 108 | } 109 | 110 | /* 111 | * Release all locks held by a client 112 | * (called when the client socket is closed) 113 | */ 114 | void ifdhandler_unlock_all(ct_socket_t * sock) 115 | { 116 | ct_lock_t *l, **lp; 117 | 118 | lp = &locks; 119 | while ((l = *lp) != NULL) { 120 | if (l->owner == sock) { 121 | ifd_debug(1, 122 | "released %s lock %u for slot %u by uid=%u", 123 | l->exclusive ? "excl" : "shared", 124 | l->handle, l->slot, l->uid); 125 | *lp = l->next; 126 | free(l); 127 | } else { 128 | lp = &l->next; 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/ifd/manager.c: -------------------------------------------------------------------------------- 1 | /* 2 | * IFD manager 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #include "internal.h" 8 | #include 9 | #include 10 | 11 | static ifd_reader_t *ifd_readers[OPENCT_MAX_READERS]; 12 | static unsigned int ifd_reader_handle = 1; 13 | 14 | /* 15 | * Return number of readers available 16 | */ 17 | int ifd_reader_count(void) 18 | { 19 | return OPENCT_MAX_READERS; 20 | } 21 | 22 | /* 23 | * Register a reader 24 | */ 25 | int ifd_attach(ifd_reader_t * reader) 26 | { 27 | unsigned int slot; 28 | 29 | if (!reader) 30 | return -1; 31 | if (reader->num) 32 | return 0; 33 | 34 | for (slot = 0; slot < OPENCT_MAX_READERS; slot++) { 35 | if (!ifd_readers[slot]) 36 | break; 37 | } 38 | 39 | if (slot >= OPENCT_MAX_READERS) { 40 | ct_error("Too many readers"); 41 | return -1; 42 | } 43 | 44 | reader->handle = ifd_reader_handle++; 45 | reader->num = slot; 46 | ifd_readers[slot] = reader; 47 | 48 | return 0; 49 | } 50 | 51 | /* 52 | * Functions to look up registered readers 53 | */ 54 | ifd_reader_t *ifd_reader_by_handle(unsigned int handle) 55 | { 56 | ifd_reader_t *reader; 57 | unsigned int i; 58 | 59 | for (i = 0; i < OPENCT_MAX_READERS; i++) { 60 | if ((reader = ifd_readers[i]) 61 | && reader->handle == handle) 62 | return reader; 63 | } 64 | return NULL; 65 | } 66 | 67 | ifd_reader_t *ifd_reader_by_index(unsigned int idx) 68 | { 69 | ifd_reader_t *reader; 70 | 71 | if (idx >= OPENCT_MAX_READERS) { 72 | ct_error("ifd_reader_by_index: invalid index %u", idx); 73 | return NULL; 74 | } 75 | if (!(reader = ifd_readers[idx])) 76 | return NULL; 77 | 78 | return reader; 79 | } 80 | 81 | /* 82 | * Unregister a reader 83 | */ 84 | void ifd_detach(ifd_reader_t * reader) 85 | { 86 | unsigned int slot; 87 | 88 | if (reader->num == 0) 89 | return; 90 | 91 | if ((slot = reader->num) >= OPENCT_MAX_READERS 92 | || ifd_readers[slot] != reader) { 93 | ct_error("ifd_detach: unknown reader"); 94 | return; 95 | } 96 | 97 | ifd_readers[slot] = NULL; 98 | } 99 | -------------------------------------------------------------------------------- /src/ifd/modules.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Module handling 3 | * 4 | * Copyright (C) 2003 Olaf Kirch 5 | */ 6 | 7 | #include "internal.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | static const char *ifd_module_path(const char *subdir) 16 | { 17 | static char path[PATH_MAX]; 18 | 19 | if (!ct_config.modules_dir 20 | && !(ct_config.modules_dir = getenv("IFD_MODULES"))) 21 | ct_config.modules_dir = OPENCT_MODULES_PATH; 22 | 23 | snprintf(path, sizeof(path), "%s/%ss", ct_config.modules_dir, subdir); 24 | return path; 25 | } 26 | 27 | int ifd_load_module(const char *type, const char *name) 28 | { 29 | const char *dirname; 30 | char path[PATH_MAX]; 31 | lt_dlhandle handle; 32 | void (*init_func) (void); 33 | 34 | if (strstr(name, "..")) { 35 | ct_error("Illegal module path \"%s\"", name); 36 | return -1; 37 | } 38 | 39 | if (!strcmp(type, "driver")) { 40 | dirname = ct_config.driver_modules_dir; 41 | } else if (!strcmp(type, "protocol")) { 42 | dirname = ct_config.protocol_modules_dir; 43 | } else { 44 | ct_error("Unknown module type \"%s\"", type); 45 | return -1; 46 | } 47 | 48 | if (!dirname) 49 | dirname = ifd_module_path(type); 50 | 51 | #if defined(HAVE_DLFCN_H) && defined(__APPLE__) 52 | snprintf(path, sizeof(path), "%s/%s.so", dirname, name); 53 | #elif defined(__APPLE__) 54 | snprintf(path, sizeof(path), "%s/%s.bundle", dirname, name); 55 | #else 56 | snprintf(path, sizeof(path), "%s/%s.so", dirname, name); 57 | #endif 58 | 59 | handle = lt_dlopen(path); 60 | if (!handle) { 61 | ct_error("Failed to load %s: %s", path, lt_dlerror()); 62 | return -1; 63 | } 64 | 65 | init_func = (void (*)(void))lt_dlsym(handle, "ifd_init_module"); 66 | if (!init_func) { 67 | ct_error("%s: no function called ifd_init_module", path); 68 | lt_dlclose(handle); 69 | return -1; 70 | } 71 | 72 | init_func(); 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /src/ifd/pcmcia-block.c: -------------------------------------------------------------------------------- 1 | /* 2 | * I/O routines for pcmcia devices 3 | * 4 | * Copyright (C) 2003 Olaf Kirch 5 | * Copyright (C) 2005 Harald Welte 6 | */ 7 | 8 | #include "internal.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | /* 19 | * Input/output routines 20 | */ 21 | static int 22 | ifd_pcmcia_block_send(ifd_device_t * dev, const unsigned char *buffer, 23 | size_t len) 24 | { 25 | size_t total = len; 26 | int n; 27 | 28 | while (len) { 29 | n = write(dev->fd, buffer, len); 30 | if (n < 0) { 31 | ct_error("Error writing to %s: %m", dev->name); 32 | return -1; 33 | } 34 | buffer += n; 35 | len -= n; 36 | } 37 | 38 | return total; 39 | } 40 | 41 | static int 42 | ifd_pcmcia_block_recv(ifd_device_t * dev, unsigned char *buffer, size_t len, 43 | long timeout) 44 | { 45 | struct timeval begin; 46 | int n; 47 | 48 | struct pollfd pfd; 49 | long wait; 50 | 51 | gettimeofday(&begin, NULL); 52 | 53 | if ((wait = timeout - ifd_time_elapsed(&begin)) < 0) 54 | goto timeout; 55 | 56 | pfd.fd = dev->fd; 57 | pfd.events = POLLIN; 58 | n = poll(&pfd, 1, wait); 59 | if (n < 0) { 60 | ct_error("%s: error while waiting for input: %m", dev->name); 61 | return -1; 62 | } 63 | if (n == 0) 64 | goto timeout; 65 | 66 | n = read(dev->fd, buffer, len); 67 | if (n < 0) { 68 | ct_error("%s: failed to read from device: %m", dev->name); 69 | return -1; 70 | } 71 | if (ct_config.debug >= 9) 72 | ifd_debug(9, "pcmcia recv:%s", ct_hexdump(buffer, n)); 73 | 74 | return n; 75 | 76 | timeout: /* Timeouts are a little special; they may happen e.g. 77 | * when trying to obtain the ATR */ 78 | if (!ct_config.suppress_errors) 79 | ct_error("%s: timed out while waiting for input", dev->name); 80 | return IFD_ERROR_TIMEOUT; 81 | } 82 | 83 | /* 84 | * Set pcmcia params 85 | */ 86 | static int ifd_pcmcia_block_set_params(ifd_device_t * dev, 87 | const ifd_device_params_t * params) 88 | { 89 | /* nothing to do so far */ 90 | dev->settings = *params; 91 | return 0; 92 | } 93 | 94 | /* 95 | * Close the device 96 | */ 97 | static void ifd_pcmcia_block_close(ifd_device_t * dev) 98 | { 99 | if (dev->fd >= 0) 100 | close(dev->fd); 101 | dev->fd = -1; 102 | } 103 | 104 | static struct ifd_device_ops ifd_pcmcia_block_ops; 105 | 106 | /* 107 | * Open serial device 108 | */ 109 | ifd_device_t *ifd_open_pcmcia_block(const char *name) 110 | { 111 | ifd_device_t *dev; 112 | int fd; 113 | 114 | if ((fd = open(name, O_RDWR)) < 0) { 115 | ct_error("Unable to open %s: %m", name); 116 | return NULL; 117 | } 118 | 119 | ifd_pcmcia_block_ops.send = ifd_pcmcia_block_send; 120 | ifd_pcmcia_block_ops.recv = ifd_pcmcia_block_recv; 121 | ifd_pcmcia_block_ops.set_params = ifd_pcmcia_block_set_params; 122 | ifd_pcmcia_block_ops.close = ifd_pcmcia_block_close; 123 | 124 | dev = ifd_device_new(name, &ifd_pcmcia_block_ops, sizeof(*dev)); 125 | dev->timeout = 1000; /* acceptable? */ 126 | dev->type = IFD_DEVICE_TYPE_PCMCIA_BLOCK; 127 | dev->fd = fd; 128 | 129 | return dev; 130 | } 131 | -------------------------------------------------------------------------------- /src/ifd/pcmcia.c: -------------------------------------------------------------------------------- 1 | /* 2 | * I/O routines for pcmcia devices 3 | * 4 | * Copyright (C) 2003 Olaf Kirch 5 | * Copyright (C) 2005 Harald Welte 6 | */ 7 | 8 | #include "internal.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | /* 19 | * Input/output routines 20 | */ 21 | static int ifd_pcmcia_send(ifd_device_t * dev, const unsigned char *buffer, 22 | size_t len) 23 | { 24 | size_t total = len; 25 | int n; 26 | 27 | while (len) { 28 | n = write(dev->fd, buffer, len); 29 | if (n < 0) { 30 | ct_error("Error writing to %s: %m", dev->name); 31 | return -1; 32 | } 33 | buffer += n; 34 | len -= n; 35 | } 36 | 37 | return total; 38 | } 39 | 40 | static int ifd_pcmcia_recv(ifd_device_t * dev, unsigned char *buffer, 41 | size_t len, long timeout) 42 | { 43 | size_t total = len, to_read; 44 | struct timeval begin; 45 | int n; 46 | 47 | gettimeofday(&begin, NULL); 48 | 49 | while (len) { 50 | struct pollfd pfd; 51 | long wait; 52 | 53 | if ((wait = timeout - ifd_time_elapsed(&begin)) < 0) 54 | goto timeout; 55 | 56 | pfd.fd = dev->fd; 57 | pfd.events = POLLIN; 58 | n = poll(&pfd, 1, wait); 59 | if (n < 0) { 60 | ct_error("%s: error while waiting for input: %m", 61 | dev->name); 62 | return -1; 63 | } 64 | if (n == 0) 65 | continue; 66 | 67 | to_read = len; 68 | 69 | n = read(dev->fd, buffer, to_read); 70 | if (n < 0) { 71 | ct_error("%s: failed to read from device: %m", 72 | dev->name); 73 | return -1; 74 | } 75 | if (ct_config.debug >= 9) 76 | ifd_debug(9, "pcmcia recv:%s", ct_hexdump(buffer, n)); 77 | buffer += n; 78 | len -= n; 79 | } 80 | 81 | return total; 82 | 83 | timeout: /* Timeouts are a little special; they may happen e.g. 84 | * when trying to obtain the ATR */ 85 | if (!ct_config.suppress_errors) 86 | ct_error("%s: timed out while waiting for input", dev->name); 87 | ifd_debug(9, "(%u bytes received so far)", total - len); 88 | return IFD_ERROR_TIMEOUT; 89 | } 90 | 91 | /* 92 | * Set pcmcia params 93 | */ 94 | static int ifd_pcmcia_set_params(ifd_device_t * dev, 95 | const ifd_device_params_t * params) 96 | { 97 | /* nothing to do so far */ 98 | dev->settings = *params; 99 | return 0; 100 | } 101 | 102 | /* 103 | * Close the device 104 | */ 105 | static void ifd_pcmcia_close(ifd_device_t * dev) 106 | { 107 | if (dev->fd >= 0) 108 | close(dev->fd); 109 | dev->fd = -1; 110 | } 111 | 112 | static struct ifd_device_ops ifd_pcmcia_ops; 113 | 114 | /* 115 | * Open serial device 116 | */ 117 | ifd_device_t *ifd_open_pcmcia(const char *name) 118 | { 119 | ifd_device_t *dev; 120 | int fd; 121 | 122 | if ((fd = open(name, O_RDWR)) < 0) { 123 | ct_error("Unable to open %s: %m", name); 124 | return NULL; 125 | } 126 | 127 | ifd_pcmcia_ops.send = ifd_pcmcia_send; 128 | ifd_pcmcia_ops.recv = ifd_pcmcia_recv; 129 | ifd_pcmcia_ops.set_params = ifd_pcmcia_set_params; 130 | ifd_pcmcia_ops.close = ifd_pcmcia_close; 131 | 132 | dev = ifd_device_new(name, &ifd_pcmcia_ops, sizeof(*dev)); 133 | dev->timeout = 1000; /* acceptable? */ 134 | dev->type = IFD_DEVICE_TYPE_PCMCIA; 135 | dev->fd = fd; 136 | 137 | return dev; 138 | } 139 | -------------------------------------------------------------------------------- /src/ifd/proto-escape.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Escape protocol - simply pass everything to the reader driver's escape() 3 | * 4 | * This is required for exporting access to vendor-specific CCID extensions, 5 | * such as the Omnikey CardMan 5121 RFID support. 6 | * 7 | * The higher-level applications select a virtual slot (the last available slot 8 | * number). This virtual slot will automatically get the IFD_PROTOCOL_ESCAPE 9 | * assgigned to it and can then be used to transceive() data to/from the CCID. 10 | * 11 | * It's a bit ugly, but I was unable to come up with something cleaner. 12 | * 13 | * Copyright (C) 2005, Harald Welte 14 | */ 15 | 16 | #include "internal.h" 17 | #include 18 | #include 19 | #include 20 | 21 | static int escape_init(ifd_protocol_t * prot) 22 | { 23 | ifd_reader_t *reader = prot->reader; 24 | const ifd_driver_t *drv; 25 | 26 | if (!reader || !(drv = reader->driver) 27 | || !drv->ops || !drv->ops->escape) 28 | return -1; 29 | return 0; 30 | } 31 | 32 | static void escape_release(ifd_protocol_t * prot) 33 | { 34 | /* NOP */ 35 | } 36 | 37 | static int escape_set_param(ifd_protocol_t * prot, int type, long value) 38 | { 39 | ct_error("set_pameter not supported"); 40 | return -1; 41 | } 42 | 43 | static int escape_get_param(ifd_protocol_t * prot, int type, long *result) 44 | { 45 | ct_error("get_pameter not supported"); 46 | return -1; 47 | } 48 | 49 | static int 50 | escape_transceive(ifd_protocol_t * prot, int dad, 51 | const void *sbuf, size_t slen, void *rbuf, size_t rlen) 52 | { 53 | ifd_reader_t *reader = prot->reader; 54 | const ifd_driver_t *drv = reader->driver; 55 | 56 | return drv->ops->escape(reader, dad, sbuf, slen, rbuf, rlen); 57 | } 58 | 59 | struct ifd_protocol_ops ifd_protocol_esc = { 60 | IFD_PROTOCOL_ESCAPE, /* id */ 61 | "escape", /* name */ 62 | sizeof(ifd_protocol_t), /* size */ 63 | escape_init, /* init */ 64 | escape_release, /* release */ 65 | escape_set_param, /* set_param */ 66 | escape_get_param, /* get_param */ 67 | NULL, /* resynchronize */ 68 | escape_transceive, /* transceive */ 69 | NULL, /* sync_read */ 70 | NULL, /* sync_write */ 71 | }; 72 | -------------------------------------------------------------------------------- /src/ifd/proto-trans.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Transparent protocol - simply pass everything to the reader driver 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #include "internal.h" 8 | #include 9 | #include 10 | #include 11 | 12 | /* 13 | * Attach t0 protocol 14 | */ 15 | static int trans_init(ifd_protocol_t * prot) 16 | { 17 | ifd_reader_t *reader = prot->reader; 18 | const ifd_driver_t *drv; 19 | 20 | if (!reader || !(drv = reader->driver) 21 | || !drv->ops || !drv->ops->transparent) 22 | return -1; 23 | return 0; 24 | } 25 | 26 | /* 27 | * Detach t0 protocol 28 | */ 29 | static void trans_release(ifd_protocol_t * prot) 30 | { 31 | /* NOP */ 32 | } 33 | 34 | /* 35 | * Get/set parmaters for T1 protocol 36 | */ 37 | static int trans_set_param(ifd_protocol_t * prot, int type, long value) 38 | { 39 | ct_error("set_pameter not supported"); 40 | return -1; 41 | } 42 | 43 | static int trans_get_param(ifd_protocol_t * prot, int type, long *result) 44 | { 45 | ct_error("get_pameter not supported"); 46 | return -1; 47 | } 48 | 49 | /* 50 | * Transceive an APDU 51 | */ 52 | static int trans_transceive(ifd_protocol_t * prot, int dad, const void *sbuf, 53 | size_t slen, void *rbuf, size_t rlen) 54 | { 55 | ifd_reader_t *reader = prot->reader; 56 | const ifd_driver_t *drv = reader->driver; 57 | 58 | return drv->ops->transparent(reader, dad, sbuf, slen, rbuf, rlen); 59 | } 60 | 61 | /* 62 | * Protocol struct 63 | */ 64 | struct ifd_protocol_ops ifd_protocol_trans = { 65 | IFD_PROTOCOL_TRANSPARENT, /* id */ 66 | "transparent", /* name */ 67 | sizeof(ifd_protocol_t), /* size */ 68 | trans_init, /* init */ 69 | trans_release, /* release */ 70 | trans_set_param, /* set_param */ 71 | trans_get_param, /* get_param */ 72 | NULL, /* resynchronize */ 73 | trans_transceive, /* transceive */ 74 | NULL, /* sync_read */ 75 | NULL, /* sync_write */ 76 | }; 77 | -------------------------------------------------------------------------------- /src/ifd/ria.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Access to remote IFD handlers 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #ifndef IFD_REMOTE_H 8 | #define IFD_REMOTE_H 9 | 10 | typedef struct ria_client { 11 | /* Socket for communication with ifdproxy */ 12 | ct_socket_t *sock; 13 | uint32_t xid; 14 | 15 | /* queue for buffering data */ 16 | ct_buf_t data; 17 | 18 | /* application data */ 19 | void *user_data; 20 | } ria_client_t; 21 | 22 | #define RIA_NAME_MAX 32 23 | typedef struct ria_device { 24 | char address[RIA_NAME_MAX]; 25 | char type[RIA_NAME_MAX / 2]; 26 | char handle[RIA_NAME_MAX]; 27 | char name[RIA_NAME_MAX]; 28 | } ria_device_t; 29 | 30 | typedef struct ria_serial_conf { 31 | uint32_t speed; 32 | uint8_t bits; 33 | uint8_t stopbits; 34 | uint8_t parity; 35 | uint8_t check_parity; 36 | uint8_t dtr; 37 | uint8_t rts; 38 | } ria_serial_conf_t; 39 | 40 | enum { 41 | /* These are for the manager only */ 42 | RIA_MGR_LIST = 0x00, 43 | RIA_MGR_INFO, 44 | RIA_MGR_CLAIM, 45 | RIA_MGR_REGISTER, 46 | 47 | __RIA_PEER_CMD_BASE = 0x10, 48 | RIA_RESET_DEVICE = 0x10, 49 | RIA_FLUSH_DEVICE, 50 | RIA_SEND_BREAK, 51 | RIA_SERIAL_GET_CONFIG, 52 | RIA_SERIAL_SET_CONFIG, 53 | 54 | RIA_DATA = 0x80 55 | }; 56 | 57 | extern ria_client_t *ria_connect(const char *); 58 | extern void ria_free(ria_client_t *); 59 | extern int ria_send(ria_client_t *, unsigned char, const void *, size_t); 60 | extern int ria_command(ria_client_t *, unsigned char, 61 | const void *, size_t, void *, size_t, long timeout); 62 | 63 | extern int ria_svc_listen(const char *, int); 64 | extern ria_client_t *ria_export_device(const char *, const char *); 65 | extern int ria_register_device(ria_client_t *, const char *); 66 | extern void ria_print_packet(ct_socket_t *, int, 67 | const char *, header_t *, ct_buf_t *); 68 | 69 | #endif /* IFD_REMOTE_H */ 70 | -------------------------------------------------------------------------------- /src/ifd/sys-null.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A void implementation for any platform 3 | * 4 | * Copyright (C) 2003 Olaf Kirch 5 | * 6 | * These functions need to be re-implemented for every 7 | * new platform. 8 | */ 9 | 10 | #include "internal.h" 11 | #if !defined(sun) && !defined (__NetBSD__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__FreeBSD_kernel__) && !defined(__linux__) && !defined(__APPLE__) && !defined(__DragonFly__) 12 | #include 13 | #include 14 | #include 15 | 16 | /* 17 | * USB handling 18 | */ 19 | int ifd_sysdep_usb_poll_presence(ifd_device_t * dev, struct pollfd *pfd) 20 | { 21 | #if 0 22 | if (pfd->revents & POLLHUP) 23 | return 0; 24 | pfd->fd = dev->fd; 25 | pfd->events = POLLHUP; 26 | return 1; 27 | #else 28 | return -1; 29 | #endif 30 | } 31 | 32 | int ifd_sysdep_usb_get_eventfd(ifd_device_t * dev, short *events) 33 | { 34 | return -1; 35 | } 36 | 37 | int ifd_sysdep_usb_control(ifd_device_t * dev, unsigned int requesttype, 38 | unsigned int request, unsigned int value, 39 | unsigned int index, void *data, size_t len, 40 | long timeout) 41 | { 42 | return -1; 43 | } 44 | 45 | int ifd_sysdep_usb_set_configuration(ifd_device_t * dev, int config) 46 | { 47 | return -1; 48 | } 49 | 50 | int ifd_sysdep_usb_set_interface(ifd_device_t * dev, int ifc, int alt) 51 | { 52 | return -1; 53 | } 54 | 55 | int ifd_sysdep_usb_claim_interface(ifd_device_t * dev, int interface) 56 | { 57 | return -1; 58 | } 59 | 60 | int ifd_sysdep_usb_release_interface(ifd_device_t * dev, int interface) 61 | { 62 | return -1; 63 | } 64 | 65 | /* 66 | * USB bulk transfer 67 | */ 68 | int ifd_sysdep_usb_bulk(ifd_device_t * dev, int ep, void *buffer, size_t len, 69 | long timeout) 70 | { 71 | return -1; 72 | } 73 | 74 | /* 75 | * USB URB capture 76 | */ 77 | struct ifd_usb_capture { 78 | int type; 79 | int endpoint; 80 | size_t maxpacket; 81 | unsigned int interface; 82 | }; 83 | 84 | int ifd_sysdep_usb_begin_capture(ifd_device_t * dev, int type, int endpoint, 85 | size_t maxpacket, ifd_usb_capture_t ** capret) 86 | { 87 | return -1; 88 | } 89 | 90 | int ifd_sysdep_usb_capture_event(ifd_device_t * dev, ifd_usb_capture_t * cap, 91 | void *buffer, size_t len) 92 | { 93 | return IFD_ERROR_NOT_SUPPORTED; 94 | } 95 | 96 | int ifd_sysdep_usb_capture(ifd_device_t * dev, ifd_usb_capture_t * cap, 97 | void *buffer, size_t len, long timeout) 98 | { 99 | return -1; 100 | } 101 | 102 | int ifd_sysdep_usb_end_capture(ifd_device_t * dev, ifd_usb_capture_t * cap) 103 | { 104 | return -1; 105 | } 106 | 107 | int ifd_sysdep_usb_open(const char *device) 108 | { 109 | return -1; 110 | } 111 | 112 | int ifd_sysdep_usb_reset(ifd_device_t * dev) 113 | { 114 | return -1; 115 | } 116 | 117 | /* 118 | * Scan all usb devices to see if there is one we support 119 | */ 120 | int ifd_scan_usb(void) 121 | { 122 | return 0; 123 | } 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /src/ifd/sys-osx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Mac OS X specific implementation - TO BE DONE 3 | * 4 | * Copyright (C) 2003 Olaf Kirch 5 | * 6 | */ 7 | 8 | #include "internal.h" 9 | #if defined(__APPLE__) 10 | #include 11 | #include 12 | #include 13 | 14 | /* 15 | * USB handling 16 | */ 17 | int ifd_sysdep_usb_poll_presence(ifd_device_t * dev, struct pollfd *pfd) 18 | { 19 | return -1; 20 | } 21 | 22 | int ifd_sysdep_usb_get_eventfd(ifd_device_t * dev, short *events) 23 | { 24 | return -1; 25 | } 26 | 27 | int ifd_sysdep_usb_control(ifd_device_t * dev, unsigned int requesttype, 28 | unsigned int request, unsigned int value, 29 | unsigned int index, void *data, size_t len, 30 | long timeout) 31 | { 32 | return -1; 33 | } 34 | 35 | int ifd_sysdep_usb_set_configuration(ifd_device_t * dev, int config) 36 | { 37 | return -1; 38 | } 39 | 40 | int ifd_sysdep_usb_set_interface(ifd_device_t * dev, int ifc, int alt) 41 | { 42 | return -1; 43 | } 44 | 45 | int ifd_sysdep_usb_claim_interface(ifd_device_t * dev, int interface) 46 | { 47 | return -1; 48 | } 49 | 50 | int ifd_sysdep_usb_release_interface(ifd_device_t * dev, int interface) 51 | { 52 | return -1; 53 | } 54 | 55 | /* 56 | * USB bulk transfer 57 | */ 58 | int ifd_sysdep_usb_bulk(ifd_device_t * dev, int ep, void *buffer, size_t len, 59 | long timeout) 60 | { 61 | return -1; 62 | } 63 | 64 | /* 65 | * USB URB capture 66 | */ 67 | struct ifd_usb_capture { 68 | int type; 69 | int endpoint; 70 | size_t maxpacket; 71 | unsigned int interface; 72 | }; 73 | 74 | int ifd_sysdep_usb_begin_capture(ifd_device_t * dev, int type, int endpoint, 75 | size_t maxpacket, ifd_usb_capture_t ** capret) 76 | { 77 | return -1; 78 | } 79 | 80 | int ifd_sysdep_usb_capture_event(ifd_device_t * dev, ifd_usb_capture_t * cap, 81 | void *buffer, size_t len) 82 | { 83 | return IFD_ERROR_NOT_SUPPORTED; 84 | } 85 | 86 | int ifd_sysdep_usb_capture(ifd_device_t * dev, ifd_usb_capture_t * cap, 87 | void *buffer, size_t len, long timeout) 88 | { 89 | return -1; 90 | } 91 | 92 | int ifd_sysdep_usb_end_capture(ifd_device_t * dev, ifd_usb_capture_t * cap) 93 | { 94 | return -1; 95 | } 96 | 97 | int ifd_sysdep_usb_open(const char *device) 98 | { 99 | return -1; 100 | } 101 | 102 | int ifd_sysdep_usb_reset(ifd_device_t * dev) 103 | { 104 | return -1; 105 | } 106 | 107 | /* 108 | * Scan all usb devices to see if there is one we support 109 | */ 110 | int ifd_scan_usb(void) 111 | { 112 | return 0; 113 | } 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /src/ifd/usb-descriptors.h: -------------------------------------------------------------------------------- 1 | /* 2 | * USB Descriptor parsing functions 3 | * 4 | * Copyright (c) 2000-2001 Johannes Erdfelt 5 | * Copyright 2003, Chaskiel Grundman 6 | * 7 | * This header file is purely internal to OpenCT. 8 | */ 9 | #ifndef __USB_DESCRIPTORS_H__ 10 | #define __USB_DESCRIPTORS_H__ 11 | 12 | #include 13 | 14 | /* 15 | * Descriptor types 16 | */ 17 | #define IFD_USB_DT_DEVICE 0x01 18 | #define IFD_USB_DT_CONFIG 0x02 19 | #define IFD_USB_DT_STRING 0x03 20 | #define IFD_USB_DT_INTERFACE 0x04 21 | #define IFD_USB_DT_ENDPOINT 0x05 22 | 23 | /* 24 | * Descriptor sizes per descriptor type 25 | */ 26 | #define IFD_USB_DT_DEVICE_SIZE 18 27 | #define IFD_USB_DT_CONFIG_SIZE 9 28 | #define IFD_USB_DT_INTERFACE_SIZE 9 29 | #define IFD_USB_DT_ENDPOINT_SIZE 7 30 | #define IFD_USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ 31 | #define IFD_USB_DT_HUB_NONVAR_SIZE 7 32 | 33 | struct ifd_usb_descriptor_header { 34 | uint8_t bLength; 35 | uint8_t bDescriptorType; 36 | }; 37 | 38 | /* String descriptor */ 39 | struct ifd_usb_string_descriptor { 40 | uint8_t bLength; 41 | uint8_t bDescriptorType; 42 | uint16_t wData[1]; 43 | }; 44 | 45 | /* Endpoint descriptor */ 46 | #define IFD_USB_MAXENDPOINTS 32 47 | struct ifd_usb_endpoint_descriptor { 48 | uint8_t bLength; 49 | uint8_t bDescriptorType; 50 | uint8_t bEndpointAddress; 51 | uint8_t bmAttributes; 52 | uint16_t wMaxPacketSize; 53 | uint8_t bInterval; 54 | uint8_t bRefresh; 55 | uint8_t bSynchAddress; 56 | 57 | unsigned char *extra; /* Extra descriptors */ 58 | int extralen; 59 | }; 60 | #define IFD_USB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ 61 | #define IFD_USB_ENDPOINT_DIR_MASK 0x80 62 | 63 | #define IFD_USB_ENDPOINT_TYPE_MASK 0x03 /* in bmAttributes */ 64 | #define IFD_USB_ENDPOINT_TYPE_CONTROL 0 65 | #define IFD_USB_ENDPOINT_TYPE_ISOCHRONOUS 1 66 | #define IFD_USB_ENDPOINT_TYPE_BULK 2 67 | #define IFD_USB_ENDPOINT_TYPE_INTERRUPT 3 68 | 69 | /* Interface descriptor */ 70 | #define IFD_USB_MAXINTERFACES 32 71 | struct ifd_usb_interface_descriptor { 72 | uint8_t bLength; 73 | uint8_t bDescriptorType; 74 | uint8_t bInterfaceNumber; 75 | uint8_t bAlternateSetting; 76 | uint8_t bNumEndpoints; 77 | uint8_t bInterfaceClass; 78 | uint8_t bInterfaceSubClass; 79 | uint8_t bInterfaceProtocol; 80 | uint8_t iInterface; 81 | 82 | struct ifd_usb_endpoint_descriptor *endpoint; 83 | 84 | unsigned char *extra; /* Extra descriptors */ 85 | int extralen; 86 | }; 87 | 88 | #define IFD_USB_MAXALTSETTING 128 /* Hard limit */ 89 | struct ifd_usb_interface { 90 | struct ifd_usb_interface_descriptor *altsetting; 91 | 92 | int num_altsetting; 93 | }; 94 | 95 | /* Configuration descriptor information.. */ 96 | #define IFD_USB_MAXCONFIG 8 97 | struct ifd_usb_config_descriptor { 98 | uint8_t bLength; 99 | uint8_t bDescriptorType; 100 | uint16_t wTotalLength; 101 | uint8_t bNumInterfaces; 102 | uint8_t bConfigurationValue; 103 | uint8_t iConfiguration; 104 | uint8_t bmAttributes; 105 | uint8_t MaxPower; 106 | 107 | struct ifd_usb_interface *interface; 108 | 109 | unsigned char *extra; /* Extra descriptors */ 110 | int extralen; 111 | }; 112 | 113 | /* Device descriptor */ 114 | struct ifd_usb_device_descriptor { 115 | uint8_t bLength; 116 | uint8_t bDescriptorType; 117 | uint16_t bcdUSB; 118 | uint8_t bDeviceClass; 119 | uint8_t bDeviceSubClass; 120 | uint8_t bDeviceProtocol; 121 | uint8_t bMaxPacketSize0; 122 | uint16_t idVendor; 123 | uint16_t idProduct; 124 | uint16_t bcdDevice; 125 | uint8_t iManufacturer; 126 | uint8_t iProduct; 127 | uint8_t iSerialNumber; 128 | uint8_t bNumConfigurations; 129 | }; 130 | #define IFD_USB_REQ_GET_DESCRIPTOR 0x06 131 | 132 | #define IFD_USB_TYPE_STANDARD (0x00 << 5) 133 | #define IFD_USB_TYPE_CLASS (0x01 << 5) 134 | #define IFD_USB_TYPE_VENDOR (0x02 << 5) 135 | #define IFD_USB_TYPE_RESERVED (0x03 << 5) 136 | 137 | #define IFD_USB_RECIP_DEVICE 0x00 138 | #define IFD_USB_RECIP_INTERFACE 0x01 139 | #define IFD_USB_RECIP_ENDPOINT 0x02 140 | #define IFD_USB_RECIP_OTHER 0x03 141 | 142 | #define IFD_USB_ENDPOINT_IN 0x80 143 | #define IFD_USB_ENDPOINT_OUT 0x00 144 | 145 | #define IFD_USB_LE16_TO_CPU(x) do { unsigned char *y=(unsigned char *)(&x); x = (y[1] << 8) | y[0] ; } while(0) 146 | 147 | extern int ifd_usb_get_device(ifd_device_t * dev, 148 | struct ifd_usb_device_descriptor *d); 149 | 150 | extern int ifd_usb_get_config(ifd_device_t * dev, 151 | int n, struct ifd_usb_config_descriptor *c); 152 | extern void ifd_usb_free_configuration(struct ifd_usb_config_descriptor *c); 153 | 154 | #endif 155 | -------------------------------------------------------------------------------- /src/ifd/utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Utility functions 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #include "internal.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #ifndef __GNUC__ 21 | void ifd_debug(int level, const char *fmt, ...) 22 | { 23 | va_list ap; 24 | char str[2048]; 25 | 26 | va_start(ap, fmt); 27 | vsnprintf(str, sizeof(str), fmt, ap); 28 | if (level <= ct_config.debug) 29 | ct_debug(str); 30 | va_end(ap); 31 | } 32 | #endif 33 | 34 | unsigned int ifd_count_bits(unsigned int word) 35 | { 36 | static unsigned int bcount[16] = { 37 | 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 38 | }; 39 | unsigned int num; 40 | 41 | for (num = 0; word; word >>= 4) 42 | num += bcount[word & 0xF]; 43 | return num; 44 | } 45 | 46 | void ifd_revert_bits(unsigned char *data, size_t len) 47 | { 48 | unsigned char j, k, c, d; 49 | 50 | while (len--) { 51 | c = *data; 52 | for (j = 1, k = 0x80, d = 0; k != 0; j <<= 1, k >>= 1) { 53 | if (c & j) 54 | d |= k; 55 | } 56 | *data++ = d ^ 0xFF; 57 | } 58 | } 59 | 60 | #ifndef timersub 61 | # define timersub(a, b, result) \ 62 | do { \ 63 | (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ 64 | (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ 65 | if ((result)->tv_usec < 0) { \ 66 | --(result)->tv_sec; \ 67 | (result)->tv_usec += 1000000; \ 68 | } \ 69 | } while (0) 70 | #endif 71 | 72 | /* return time elapsed since "then" in miliseconds */ 73 | long ifd_time_elapsed(struct timeval *then) 74 | { 75 | struct timeval now, delta; 76 | 77 | gettimeofday(&now, NULL); 78 | timersub(&now, then, &delta); 79 | return delta.tv_sec * 1000 + (delta.tv_usec / 1000); 80 | } 81 | 82 | /* 83 | * Spawn an ifdhandler 84 | */ 85 | int ifd_spawn_handler(const char *driver, const char *devtype, int idx) 86 | { 87 | const char *argv[16]; 88 | char reader[16], debug[10]; 89 | char *type, *device; 90 | int argc, n; 91 | pid_t pid; 92 | char *user = NULL; 93 | int force_poll = 1; 94 | 95 | ifd_debug(1, "driver=%s, devtype=%s, index=%d", driver, devtype, idx); 96 | 97 | if ((pid = fork()) < 0) { 98 | ct_error("fork failed: %m"); 99 | return 0; 100 | } 101 | 102 | if (pid != 0) { 103 | /* We're the parent process. The child process should 104 | * call daemon(), causing the process to exit 105 | * immediately after allocating a slot in the status 106 | * file. We wait for it here to make sure USB devices 107 | * don't claim a slot reserved for another device */ 108 | waitpid(pid, NULL, 0); 109 | return 1; 110 | } 111 | 112 | argc = 0; 113 | argv[argc++] = ct_config.ifdhandler; 114 | 115 | if (idx >= 0) { 116 | snprintf(reader, sizeof(reader), "-r%u", idx); 117 | argv[argc++] = reader; 118 | } else { 119 | argv[argc++] = "-H"; 120 | } 121 | 122 | if (ct_config.debug) { 123 | if ((n = ct_config.debug) > 6) 124 | n = 6; 125 | debug[n + 1] = '\0'; 126 | while (n--) 127 | debug[n + 1] = 'd'; 128 | debug[0] = '-'; 129 | argv[argc++] = debug; 130 | } 131 | 132 | ifd_conf_get_bool("ifdhandler.force_poll", &force_poll); 133 | if (force_poll) { 134 | argv[argc++] = "-p"; 135 | } 136 | 137 | type = strdup(devtype); 138 | device = strtok(type, ":"); 139 | device = strtok(NULL, ":"); 140 | if (!device || !type) { 141 | ct_error("failed to parse devtype %s", devtype); 142 | exit(1); 143 | } 144 | 145 | argv[argc++] = driver; 146 | argv[argc++] = type; 147 | argv[argc++] = device; 148 | argv[argc] = NULL; 149 | 150 | n = getdtablesize(); 151 | while (--n > 2) 152 | close(n); 153 | 154 | if ((n = ifd_conf_get_string_list("ifdhandler.groups", NULL, 0)) > 0) { 155 | char **groups = (char **)calloc(n, sizeof(char *)); 156 | gid_t *gids = (gid_t *)calloc(n, sizeof(gid_t)); 157 | int j; 158 | if (!groups || !gids) { 159 | ct_error("out of memory"); 160 | exit(1); 161 | } 162 | n = ifd_conf_get_string_list("ifdhandler.groups", groups, n); 163 | for (j = 0; j < n; j++) { 164 | struct group *g = getgrnam(groups[j]); 165 | if (g == NULL) { 166 | ct_error("failed to parse group %s", groups[j]); 167 | exit(1); 168 | } 169 | gids[j] = g->gr_gid; 170 | } 171 | if (setgroups(n-1, &gids[1]) == -1) { 172 | ct_error("failed set groups %m"); 173 | exit(1); 174 | } 175 | if (setgid(gids[0]) == -1) { 176 | ct_error("failed setgid %d %m", gids[0]); 177 | exit(1); 178 | } 179 | free(groups); 180 | free(gids); 181 | } 182 | 183 | if (ifd_conf_get_string("ifdhandler.user", &user) >= 0) { 184 | struct passwd *p = getpwnam(user); 185 | 186 | if (p == NULL) { 187 | ct_error("failed to parse user %s", user); 188 | exit(1); 189 | } 190 | 191 | if (setuid(p->pw_uid) == -1) { 192 | ct_error("failed to set*uid user %s %m", user); 193 | exit(1); 194 | } 195 | } 196 | 197 | execv(ct_config.ifdhandler, (char **)argv); 198 | ct_error("failed to execute %s: %m", ct_config.ifdhandler); 199 | exit(1); 200 | } 201 | 202 | /* 203 | * Replacement for the BSD daemon() function 204 | */ 205 | #ifndef HAVE_DAEMON 206 | int daemon(int nochdir, int noclose) 207 | { 208 | pid_t pid; 209 | 210 | pid = fork(); 211 | 212 | /* In case of fork is error. */ 213 | if (pid < 0) 214 | return -1; 215 | 216 | /* In case of this is parent process. */ 217 | if (pid != 0) 218 | exit(0); 219 | 220 | /* Become session leader and get pid. */ 221 | pid = setsid(); 222 | 223 | if (pid < -1) { 224 | perror("setsid"); 225 | return -1; 226 | } 227 | 228 | /* Change directory to root. */ 229 | if (!nochdir) 230 | chdir("/"); 231 | 232 | /* File descriptor close. */ 233 | if (!noclose) { 234 | int fd; 235 | 236 | fd = open("/dev/null", O_RDWR, 0); 237 | if (fd != -1) { 238 | dup2(fd, STDIN_FILENO); 239 | dup2(fd, STDOUT_FILENO); 240 | dup2(fd, STDERR_FILENO); 241 | if (fd > 2) 242 | close(fd); 243 | } 244 | } 245 | umask(0027); 246 | return 0; 247 | } 248 | #endif 249 | -------------------------------------------------------------------------------- /src/include/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = $(srcdir)/Makefile.in 2 | 3 | SUBDIRS = openct 4 | -------------------------------------------------------------------------------- /src/include/openct/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = $(srcdir)/Makefile.in 2 | DISTCLEANFILES = types.h 3 | 4 | openctinclude_HEADERS = \ 5 | apdu.h buffer.h conf.h device.h driver.h error.h ifd.h \ 6 | logging.h openct.h path.h protocol.h server.h socket.h tlv.h 7 | nodist_openctinclude_HEADERS = $(builddir)/types.h 8 | -------------------------------------------------------------------------------- /src/include/openct/apdu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * APDU type definitions 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #ifndef OPENCT_APDU_H 8 | #define OPENCT_APDU_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | typedef struct ifd_iso_apdu { 15 | unsigned char cse, cla, ins, p1, p2; 16 | unsigned int lc, le; 17 | unsigned int sw; 18 | void * data; 19 | size_t len; 20 | 21 | /* xxx go away */ 22 | unsigned char * rcv_buf; 23 | unsigned int rcv_len; 24 | } ifd_iso_apdu_t; 25 | 26 | enum { 27 | IFD_APDU_CASE_1 = 0x00, 28 | IFD_APDU_CASE_2S = 0x01, 29 | IFD_APDU_CASE_3S = 0x02, 30 | IFD_APDU_CASE_4S = 0x03, 31 | IFD_APDU_CASE_2E = 0x10, 32 | IFD_APDU_CASE_3E = 0x20, 33 | IFD_APDU_CASE_4E = 0x30, 34 | 35 | IFD_APDU_BAD = -1 36 | }; 37 | 38 | #define IFD_APDU_CASE_LC(c) ((c) & 0x02) 39 | #define IFD_APDU_CASE_LE(c) ((c) & 0x01) 40 | 41 | extern int ifd_iso_apdu_parse(const void *, size_t, ifd_iso_apdu_t *); 42 | extern int ifd_apdu_case(const void *, size_t); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif /* OPENCT_APDU_H */ 49 | -------------------------------------------------------------------------------- /src/include/openct/buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Buffer handling functions of the IFD handler library 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #ifndef OPENCT_BUFFER_H 8 | #define OPENCT_BUFFER_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include 15 | 16 | typedef struct ct_buf { 17 | unsigned char * base; 18 | unsigned int head, tail, size; 19 | unsigned int overrun; 20 | } ct_buf_t; 21 | 22 | extern void ct_buf_init(ct_buf_t *, void *, size_t); 23 | extern void ct_buf_set(ct_buf_t *, void *, size_t); 24 | extern void ct_buf_clear(ct_buf_t *); 25 | extern int ct_buf_get(ct_buf_t *, void *, size_t); 26 | extern int ct_buf_gets(ct_buf_t *, char *, size_t); 27 | extern int ct_buf_put(ct_buf_t *, const void *, size_t); 28 | extern int ct_buf_putc(ct_buf_t *, int); 29 | extern int ct_buf_puts(ct_buf_t *, const char *); 30 | extern int ct_buf_push(ct_buf_t *, const void *, size_t); 31 | extern unsigned int ct_buf_avail(ct_buf_t *); 32 | extern unsigned int ct_buf_tailroom(ct_buf_t *); 33 | extern unsigned int ct_buf_size(ct_buf_t *); 34 | extern void * ct_buf_head(ct_buf_t *); 35 | extern void * ct_buf_tail(ct_buf_t *); 36 | extern int ct_buf_read(ct_buf_t *, int); 37 | extern void ct_buf_compact(ct_buf_t *); 38 | extern int ct_buf_overrun(ct_buf_t *); 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | 44 | #endif /* OPENCT_BUFFER_H */ 45 | -------------------------------------------------------------------------------- /src/include/openct/conf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Configuration stuff for IFD library 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #ifndef OPENCT_CONF_H 8 | #define OPENCT_CONF_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | extern struct ct_config { 15 | int debug; 16 | int autoload; 17 | int hotplug; 18 | int suppress_errors; 19 | const char * ifdhandler; 20 | const char * modules_dir; 21 | const char * driver_modules_dir; 22 | const char * protocol_modules_dir; 23 | const char * socket_dir; 24 | } ct_config; 25 | 26 | typedef struct ifd_conf_node { 27 | struct ifd_conf_node *next; 28 | struct ifd_conf_node *children; 29 | char * name; 30 | char * value; 31 | } ifd_conf_node_t; 32 | 33 | extern int ifd_config_parse(const char *); 34 | extern int ifd_conf_get_string(const char *, char **); 35 | extern int ifd_conf_get_integer(const char *, unsigned int *); 36 | extern int ifd_conf_get_bool(const char *, unsigned int *); 37 | extern int ifd_conf_get_string_list(const char *, char **, size_t); 38 | extern int ifd_conf_get_nodes(const char *, ifd_conf_node_t **, size_t); 39 | extern int ifd_conf_node_get_string(ifd_conf_node_t *, 40 | const char *, char **); 41 | extern int ifd_conf_node_get_integer(ifd_conf_node_t *, 42 | const char *, unsigned int *); 43 | extern int ifd_conf_node_get_bool(ifd_conf_node_t *, 44 | const char *, unsigned int *); 45 | extern int ifd_conf_node_get_string_list(ifd_conf_node_t *, 46 | const char *, char **, size_t); 47 | extern int ifd_conf_node_get_nodes(ifd_conf_node_t *, 48 | const char *, ifd_conf_node_t **, size_t); 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif /* OPENCT_CONF_H */ 55 | -------------------------------------------------------------------------------- /src/include/openct/device.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Device functions of the IFD handler library 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #ifndef OPENCT_DEVICE_H 8 | #define OPENCT_DEVICE_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include 15 | 16 | struct pollfd; /* for poll_presence */ 17 | 18 | /* Types of devices supported by libifd */ 19 | enum { 20 | IFD_DEVICE_TYPE_SERIAL = 0, 21 | IFD_DEVICE_TYPE_USB, 22 | IFD_DEVICE_TYPE_PS2, 23 | IFD_DEVICE_TYPE_PCMCIA, 24 | IFD_DEVICE_TYPE_PCMCIA_BLOCK, 25 | IFD_DEVICE_TYPE_OTHER 26 | }; 27 | 28 | union ifd_device_params { 29 | struct { 30 | unsigned int speed; 31 | int bits; 32 | int stopbits; 33 | int parity; 34 | int check_parity; 35 | unsigned int rts : 1, 36 | dtr : 1; 37 | } serial; 38 | struct { 39 | int configuration; 40 | int interface; 41 | int altsetting; 42 | int ep_o; 43 | int ep_i; 44 | int ep_intr; 45 | } usb; 46 | }; 47 | 48 | enum { 49 | IFD_SERIAL_PARITY_NONE = 0, 50 | IFD_SERIAL_PARITY_ODD = 1, 51 | IFD_SERIAL_PARITY_EVEN = 2 52 | }; 53 | #define IFD_SERIAL_PARITY_TOGGLE(n) ((n)? ((n) ^ 3) : 0) 54 | 55 | #define IFD_MAX_DEVID_PARTS 5 56 | typedef struct ifd_devid { 57 | int type; 58 | unsigned int num; 59 | unsigned int val[IFD_MAX_DEVID_PARTS]; 60 | } ifd_devid_t; 61 | 62 | /* 63 | * Control messages to be sent through 64 | * ifd_device_control must always have a guard word 65 | * that contains the device type. 66 | */ 67 | enum { 68 | IFD_USB_URB_TYPE_ISO = 0, 69 | IFD_USB_URB_TYPE_INTERRUPT = 1, 70 | IFD_USB_URB_TYPE_CONTROL = 2, 71 | IFD_USB_URB_TYPE_BULK = 3 72 | }; 73 | typedef struct ifd_usb_capture ifd_usb_capture_t; 74 | 75 | extern ifd_device_t * ifd_device_open(const char *); 76 | extern void ifd_device_close(ifd_device_t *); 77 | extern int ifd_device_type(ifd_device_t *); 78 | extern int ifd_device_reset(ifd_device_t *); 79 | extern void ifd_device_flush(ifd_device_t *); 80 | extern void ifd_device_send_break(ifd_device_t *, unsigned int); 81 | extern int ifd_device_identify(const char *, char *, size_t); 82 | extern int ifd_device_get_parameters(ifd_device_t *, 83 | ifd_device_params_t *); 84 | extern int ifd_device_set_parameters(ifd_device_t *, 85 | const ifd_device_params_t *); 86 | extern int ifd_device_transceive(ifd_device_t *, 87 | const void *, size_t, 88 | void *, size_t, long); 89 | extern int ifd_device_send(ifd_device_t *, const unsigned char *, size_t); 90 | extern int ifd_device_recv(ifd_device_t *, unsigned char *, size_t, long); 91 | extern int ifd_device_control(ifd_device_t *, void *, size_t); 92 | extern void ifd_device_set_hotplug(ifd_device_t *, int); 93 | extern int ifd_device_get_eventfd(ifd_device_t *, short *events); 94 | extern int ifd_device_poll_presence(ifd_device_t *, 95 | struct pollfd *); 96 | 97 | extern int ifd_device_id_parse(const char *, ifd_devid_t *); 98 | extern int ifd_device_id_match(const ifd_devid_t *, 99 | const ifd_devid_t *); 100 | 101 | extern int ifd_usb_control(ifd_device_t *, 102 | unsigned int requesttype, 103 | unsigned int request, 104 | unsigned int value, 105 | unsigned int index, 106 | void *data, size_t len, 107 | long timeout); 108 | extern int ifd_usb_begin_capture(ifd_device_t *, 109 | int type, int endpoint, 110 | size_t maxpacket, 111 | ifd_usb_capture_t **); 112 | extern int ifd_usb_capture_event(ifd_device_t *, 113 | ifd_usb_capture_t *, 114 | void *buffer, size_t len); 115 | extern int ifd_usb_capture(ifd_device_t *, 116 | ifd_usb_capture_t *, 117 | void *buffer, size_t len, 118 | long timeout); 119 | extern int ifd_usb_end_capture(ifd_device_t *, 120 | ifd_usb_capture_t *); 121 | 122 | extern void ifd_serial_send_break(ifd_device_t *, unsigned int usec); 123 | extern int ifd_serial_get_cts(ifd_device_t *); 124 | extern int ifd_serial_get_dsr(ifd_device_t *); 125 | extern int ifd_serial_get_dtr(ifd_device_t *); 126 | 127 | #ifdef __cplusplus 128 | } 129 | #endif 130 | 131 | #endif /* OPENCT_DEVICE_H */ 132 | -------------------------------------------------------------------------------- /src/include/openct/error.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Error codes 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #ifndef OPENCT_ERROR_H 8 | #define OPENCT_ERROR_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #define IFD_SUCCESS 0 15 | #define IFD_ERROR_GENERIC -1 16 | #define IFD_ERROR_TIMEOUT -2 17 | #define IFD_ERROR_INVALID_SLOT -3 18 | #define IFD_ERROR_NOT_SUPPORTED -4 19 | #define IFD_ERROR_COMM_ERROR -5 20 | #define IFD_ERROR_NO_CARD -6 21 | #define IFD_ERROR_LOCKED -7 22 | #define IFD_ERROR_NOLOCK -8 23 | #define IFD_ERROR_INVALID_ARG -9 24 | #define IFD_ERROR_NO_MEMORY -10 25 | #define IFD_ERROR_BUFFER_TOO_SMALL -11 26 | #define IFD_ERROR_USER_TIMEOUT -12 27 | #define IFD_ERROR_USER_ABORT -13 28 | #define IFD_ERROR_PIN_MISMATCH -14 29 | #define IFD_ERROR_NO_ATR -15 30 | #define IFD_ERROR_INCOMPATIBLE_DEVICE -16 31 | #define IFD_ERROR_DEVICE_DISCONNECTED -17 32 | #define IFD_ERROR_INVALID_ATR -18 33 | 34 | /* for application/resource manager protocol */ 35 | #define IFD_ERROR_INVALID_MSG -100 36 | #define IFD_ERROR_INVALID_CMD -101 37 | #define IFD_ERROR_MISSING_ARG -102 38 | #define IFD_ERROR_NOT_CONNECTED -103 39 | 40 | /* Specific error codes for proxy protocol */ 41 | #define IFD_ERROR_ALREADY_CLAIMED -200 42 | #define IFD_ERROR_DEVICE_BUSY -201 43 | #define IFD_ERROR_UNKNOWN_DEVICE -202 44 | 45 | extern const char * ct_strerror(int); 46 | 47 | #ifdef __cplusplus 48 | } 49 | #endif 50 | 51 | #endif /* OPENCT_ERROR_H */ 52 | -------------------------------------------------------------------------------- /src/include/openct/ifd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Core functions of the IFD handler library 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #ifndef OPENCT_IFD_H 8 | #define OPENCT_IFD_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | typedef struct ifd_device ifd_device_t; 19 | typedef union ifd_device_params ifd_device_params_t; 20 | 21 | enum { 22 | IFD_PROTOCOL_DEFAULT = -1, 23 | IFD_PROTOCOL_T0 = 0, 24 | IFD_PROTOCOL_T1, 25 | IFD_PROTOCOL_2WIRE = 16, 26 | IFD_PROTOCOL_3WIRE, 27 | IFD_PROTOCOL_I2C_SHORT, 28 | IFD_PROTOCOL_I2C_LONG, 29 | IFD_PROTOCOL_TLP, /* older Gemplus protocol */ 30 | IFD_PROTOCOL_GBP, /* Gemplus block protocol */ 31 | IFD_PROTOCOL_EUROCHIP, /* Eurochip Countercard */ 32 | IFD_PROTOCOL_TCL, /* ISO 14443-4 T=CL */ 33 | IFD_PROTOCOL_ESCAPE, /* Virtual 'escape' protocol */ 34 | IFD_PROTOCOL_TRANSPARENT = 128 35 | }; 36 | 37 | typedef struct ifd_protocol ifd_protocol_t; 38 | 39 | typedef struct ifd_driver { 40 | const char * name; 41 | struct ifd_driver_ops * ops; 42 | } ifd_driver_t; 43 | 44 | #define IFD_MAX_ATR_LEN 64 45 | typedef struct ifd_slot { 46 | unsigned int handle; 47 | 48 | int status; 49 | time_t next_update; 50 | 51 | unsigned char dad; /* address when using T=1 */ 52 | unsigned int atr_len; 53 | unsigned char atr[IFD_MAX_ATR_LEN]; 54 | 55 | ifd_protocol_t * proto; 56 | void * reader_data; 57 | } ifd_slot_t; 58 | 59 | typedef struct ifd_reader { 60 | unsigned int num; 61 | unsigned int handle; 62 | 63 | const char * name; 64 | unsigned int flags; 65 | unsigned int nslots; 66 | ifd_slot_t slot[OPENCT_MAX_SLOTS]; 67 | 68 | const ifd_driver_t * driver; 69 | ifd_device_t * device; 70 | ct_info_t * status; 71 | 72 | /* In case the IFD needs to keep state */ 73 | void * driver_data; 74 | } ifd_reader_t; 75 | 76 | #define IFD_READER_ACTIVE 0x0001 77 | #define IFD_READER_HOTPLUG 0x0002 78 | #define IFD_READER_DISPLAY 0x0100 79 | #define IFD_READER_KEYPAD 0x0200 80 | 81 | enum { 82 | IFD_PROTOCOL_RECV_TIMEOUT = 0x0000, 83 | IFD_PROTOCOL_BLOCK_ORIENTED, 84 | 85 | /* T=0 specific parameters */ 86 | __IFD_PROTOCOL_T0_PARAM_BASE = IFD_PROTOCOL_T0 << 16, 87 | 88 | /* T=1 specific parameters */ 89 | __IFD_PROTOCOL_T1_PARAM_BASE = IFD_PROTOCOL_T1 << 16, 90 | IFD_PROTOCOL_T1_BLOCKSIZE, 91 | IFD_PROTOCOL_T1_CHECKSUM_CRC, 92 | IFD_PROTOCOL_T1_CHECKSUM_LRC, 93 | IFD_PROTOCOL_T1_IFSC, 94 | IFD_PROTOCOL_T1_IFSD, 95 | IFD_PROTOCOL_T1_STATE, 96 | IFD_PROTOCOL_T1_MORE 97 | }; 98 | 99 | enum { 100 | IFD_DAD_HOST = 0, 101 | IFD_DAD_IFD, 102 | IFD_DAD_ICC1, 103 | IFD_DAD_ICC2 104 | }; 105 | 106 | 107 | extern int ifd_init(void); 108 | 109 | extern ifd_reader_t * ifd_open(const char *driver_name, 110 | const char *device_name); 111 | extern void ifd_close(ifd_reader_t *); 112 | extern int ifd_reader_count(void); 113 | extern int ifd_attach(ifd_reader_t *); 114 | extern void ifd_detach(ifd_reader_t *); 115 | extern ifd_reader_t * ifd_reader_by_handle(unsigned int handle); 116 | extern ifd_reader_t * ifd_reader_by_index(unsigned int index); 117 | 118 | extern int ifd_spawn_handler(const char *, const char *, int); 119 | extern int ifd_scan_usb(void); 120 | 121 | extern int ifd_activate(ifd_reader_t *); 122 | extern int ifd_deactivate(ifd_reader_t *); 123 | extern int ifd_output(ifd_reader_t *, const char *); 124 | 125 | extern int ifd_atr_complete(const unsigned char *, size_t); 126 | 127 | extern int ifd_set_protocol(ifd_reader_t *reader, 128 | unsigned int slot, 129 | int id); 130 | extern int ifd_card_command(ifd_reader_t *reader, 131 | unsigned int slot, 132 | const void *sbuf, size_t slen, 133 | void *rbuf, size_t rlen); 134 | extern int ifd_card_status(ifd_reader_t *reader, 135 | unsigned int slot, 136 | int *status); 137 | extern int ifd_card_reset(ifd_reader_t *reader, 138 | unsigned int slot, 139 | void *atr_buf, 140 | size_t atr_len); 141 | extern int ifd_card_request(ifd_reader_t *reader, 142 | unsigned int slot, 143 | time_t timeout, 144 | const char *message, 145 | void *atr_buf, 146 | size_t atr_len); 147 | extern int ifd_card_eject(ifd_reader_t *reader, 148 | unsigned int slot, 149 | time_t timeout, 150 | const char *message); 151 | extern int ifd_card_perform_verify(ifd_reader_t *reader, 152 | unsigned int slot, 153 | time_t timeout, 154 | const char *message, 155 | const unsigned char *data, size_t data_len, 156 | unsigned char *resp, size_t resp_len); 157 | extern int ifd_card_read_memory(ifd_reader_t *, 158 | unsigned int, unsigned short, 159 | unsigned char *, size_t); 160 | extern int ifd_card_write_memory(ifd_reader_t *, 161 | unsigned int, unsigned short, 162 | const unsigned char *, size_t); 163 | 164 | extern ifd_protocol_t * ifd_protocol_new(int id, 165 | ifd_reader_t *reader, 166 | unsigned int dad); 167 | extern int ifd_protocol_set_parameter(ifd_protocol_t *p, 168 | int type, 169 | long value); 170 | extern int ifd_protocol_get_parameter(ifd_protocol_t *p, 171 | int type, 172 | long *value); 173 | extern int ifd_protocol_read_memory(ifd_protocol_t *, 174 | int, unsigned short, 175 | unsigned char *, size_t); 176 | extern int ifd_protocol_write_memory(ifd_protocol_t *, 177 | int, unsigned short, 178 | const unsigned char *, size_t); 179 | extern void ifd_protocol_free(ifd_protocol_t *); 180 | extern int ifd_before_command(ifd_reader_t *); 181 | extern int ifd_after_command(ifd_reader_t *); 182 | extern int ifd_get_eventfd(ifd_reader_t *, short *); 183 | extern void ifd_poll(ifd_reader_t *); 184 | extern int id_event(ifd_reader_t *); 185 | 186 | /* Debugging macro */ 187 | #ifdef __GNUC__ 188 | #define ifd_debug(level, fmt, args...) \ 189 | do { \ 190 | if ((level) <= ct_config.debug) \ 191 | ct_debug("%s: " fmt, __FUNCTION__ , ##args); \ 192 | } while (0) 193 | #else 194 | extern void ifd_debug(int level, const char *fmt, ...); 195 | #endif 196 | 197 | #ifdef __cplusplus 198 | } 199 | #endif 200 | 201 | #endif /* OPENCT_IFD_H */ 202 | -------------------------------------------------------------------------------- /src/include/openct/logging.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Logging functions 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #ifndef OPENCT_LOGGING_H 8 | #define OPENCT_LOGGING_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | extern void ct_log_destination(const char *); 15 | 16 | extern void ct_error(const char *, ...); 17 | extern void ct_debug(const char *, ...); 18 | 19 | extern const char * ct_hexdump(const void *, size_t); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif /* OPENCT_LOGGING_H */ 26 | -------------------------------------------------------------------------------- /src/include/openct/openct.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Main OpenCT include file 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #ifndef OPENCT_OPENCT_H 8 | #define OPENCT_OPENCT_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include 15 | 16 | /* Various implementation limits */ 17 | #define OPENCT_MAX_READERS 16 18 | #define OPENCT_MAX_SLOTS 8 19 | 20 | typedef struct ct_info { 21 | char ct_name[64]; 22 | unsigned int ct_slots; 23 | unsigned int ct_card[OPENCT_MAX_SLOTS]; 24 | unsigned ct_display : 1, 25 | ct_keypad : 1; 26 | pid_t ct_pid; 27 | } ct_info_t; 28 | 29 | typedef struct ct_handle ct_handle; 30 | 31 | #define IFD_CARD_PRESENT 0x0001 32 | #define IFD_CARD_STATUS_CHANGED 0x0002 33 | 34 | /* Lock types 35 | * - shared locks allow concurrent access from 36 | * other applications run by the same user. 37 | * Used e.g. by pkcs11 login. 38 | * - exclusive locks deny any access by other 39 | * applications. 40 | * 41 | * When a lock is granted, a lock handle is passed 42 | * to the client, which it must present in the 43 | * subsequent unlock call. 44 | */ 45 | typedef unsigned int ct_lock_handle; 46 | enum { 47 | IFD_LOCK_SHARED, 48 | IFD_LOCK_EXCLUSIVE 49 | }; 50 | 51 | /* 52 | * PIN encoding types 53 | */ 54 | enum { 55 | IFD_PIN_ENCODING_BCD, 56 | IFD_PIN_ENCODING_ASCII 57 | }; 58 | 59 | extern int ct_status(const ct_info_t **); 60 | 61 | extern int ct_reader_info(unsigned int, ct_info_t *); 62 | extern ct_handle * ct_reader_connect(unsigned int); 63 | extern void ct_reader_disconnect(ct_handle *); 64 | extern int ct_reader_status(ct_handle *, ct_info_t *); 65 | extern int ct_card_status(ct_handle *h, unsigned int slot, int *status); 66 | extern int ct_card_set_protocol(ct_handle *h, unsigned int slot, 67 | unsigned int protocol); 68 | extern int ct_card_reset(ct_handle *h, unsigned int slot, 69 | void *atr, size_t atr_len); 70 | extern int ct_card_request(ct_handle *h, unsigned int slot, 71 | unsigned int timeout, const char *message, 72 | void *atr, size_t atr_len); 73 | extern int ct_card_lock(ct_handle *h, unsigned int slot, 74 | int type, ct_lock_handle *); 75 | extern int ct_card_unlock(ct_handle *h, unsigned int slot, 76 | ct_lock_handle); 77 | extern int ct_card_transact(ct_handle *h, unsigned int slot, 78 | const void *apdu, size_t apdu_len, 79 | void *recv_buf, size_t recv_len); 80 | extern int ct_card_verify(ct_handle *h, unsigned int slot, 81 | unsigned int timeout, const char *prompt, 82 | unsigned int pin_encoding, 83 | unsigned int pin_length, 84 | unsigned int pin_offset, 85 | const void *send_buf, size_t send_len, 86 | void *recv_buf, size_t recv_len); 87 | extern int ct_card_read_memory(ct_handle *, unsigned int slot, 88 | unsigned short address, 89 | void *recv_buf, size_t recv_len); 90 | extern int ct_card_write_memory(ct_handle *, unsigned int slot, 91 | unsigned short address, 92 | const void *send_buf, size_t send_len); 93 | 94 | extern int ct_status_destroy(void); 95 | extern int ct_status_clear(unsigned int, const char *); 96 | extern ct_info_t * ct_status_alloc_slot(int *); 97 | extern int ct_status_update(ct_info_t *); 98 | 99 | #ifdef __cplusplus 100 | } 101 | #endif 102 | 103 | #endif /* OPENCT_OPENCT_H */ 104 | -------------------------------------------------------------------------------- /src/include/openct/path.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Path handling routines 3 | * 4 | * Copyright (C) 2006, Andreas Jellinghaus 5 | */ 6 | 7 | #ifndef OPENCT_PATH_H 8 | #define OPENCT_PATH_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | extern int ct_format_path(char *path, const size_t pathlen, const char *file); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | #endif /* OPENCT_PATH_H */ 20 | -------------------------------------------------------------------------------- /src/include/openct/protocol.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Protocol for communication between application and 3 | * resource manager 4 | * 5 | * Copyright (C) 2003, Olaf Kirch 6 | */ 7 | 8 | #ifndef OPENCT_PROTOCOL_H 9 | #define OPENCT_PROTOCOL_H 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | /* 16 | * A protocol message from client to server 17 | * consists of 18 | * - command byte 19 | * - unit byte 20 | * - optional data, TLV encoded 21 | */ 22 | 23 | #define CT_CMD_STATUS 0x00 24 | #define CT_CMD_LOCK 0x01 /* prevent concurrent access */ 25 | #define CT_CMD_UNLOCK 0x02 26 | #define CT_CMD_RESET 0x10 27 | #define CT_CMD_REQUEST_ICC 0x11 28 | #define CT_CMD_EJECT_ICC 0x12 29 | #define CT_CMD_OUTPUT 0x13 30 | #define CT_CMD_PERFORM_VERIFY 0x14 31 | #define CT_CMD_CHANGE_PIN 0x15 32 | #define CT_CMD_MEMORY_READ 0x16 33 | #define CT_CMD_MEMORY_WRITE 0x17 34 | #define CT_CMD_INPUT 0x18 35 | #define CT_CMD_TRANSACT_OLD 0x20 /* transceive APDU */ 36 | #define CT_CMD_TRANSACT 0x21 /* transceive APDU */ 37 | #define CT_CMD_SET_PROTOCOL 0x22 38 | 39 | #define CT_UNIT_ICC1 0x00 40 | #define CT_UNIT_ICC2 0x01 41 | #define CT_UNIT_ICC3 0x02 42 | #define CT_UNIT_ICC4 0x03 43 | #define CT_UNIT_READER 0x10 44 | #define CT_UNIT_DISPLAY 0x11 45 | #define CT_UNIT_KEYPAD 0x12 46 | 47 | /* 48 | * TLV items. 49 | */ 50 | #define CT_TAG_READER_NAME 0x00 /* ASCII string */ 51 | #define CT_TAG_READER_UNITS 0x01 /* list CT_UNIT_* bytes */ 52 | #define CT_TAG_CARD_STATUS 0x02 /* IFD_CARD_* byte */ 53 | #define CT_TAG_ATR 0x03 /* Answer to reset */ 54 | #define CT_TAG_LOCK 0x04 55 | #define CT_TAG_CARD_RESPONSE 0x05 /* Card response to VERIFY etc */ 56 | #define CT_TAG_TIMEOUT 0x80 57 | #define CT_TAG_MESSAGE 0x81 58 | #define CT_TAG_LOCKTYPE 0x82 59 | #define CT_TAG_PIN_DATA 0x83 /* CTBCS verify APDU */ 60 | #define CT_TAG_CARD_REQUEST 0x84 61 | #define CT_TAG_ADDRESS 0x85 62 | #define CT_TAG_DATA 0x86 63 | #define CT_TAG_COUNT 0x87 64 | #define CT_TAG_PROTOCOL 0x88 65 | 66 | #define __CT_TAG_LARGE 0x40 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | 72 | #endif /* OPENCT_PROTOCOL_H */ 73 | -------------------------------------------------------------------------------- /src/include/openct/server.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Server side functionality 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #ifndef OPENCT_SERVER_H 8 | #define OPENCT_SERVER_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include 15 | 16 | extern void ct_mainloop_add_socket(ct_socket_t *); 17 | extern void ct_mainloop(void); 18 | extern void ct_mainloop_leave(void); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif /* OPENCT_SERVER_H */ 25 | -------------------------------------------------------------------------------- /src/include/openct/socket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Socket type definitions 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #ifndef OPENCT_SOCKET_H 8 | #define OPENCT_SOCKET_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | /* forward decl */ 19 | struct pollfd; 20 | 21 | typedef struct header { 22 | uint32_t xid; 23 | uint32_t dest; 24 | int16_t error; 25 | uint16_t count; 26 | } header_t; 27 | 28 | typedef struct ct_socket { 29 | struct ct_socket *next, *prev; 30 | 31 | int fd; 32 | int eof; 33 | ct_buf_t rbuf, sbuf; 34 | 35 | unsigned int use_large_tags : 1, 36 | use_network_byte_order : 1, 37 | listener : 1; 38 | 39 | /* events to poll for */ 40 | int events; 41 | 42 | void * user_data; 43 | int (*poll)(struct ct_socket *, struct pollfd *); 44 | int (*error)(struct ct_socket *); 45 | int (*recv)(struct ct_socket *); 46 | int (*send)(struct ct_socket *); 47 | int (*process)(struct ct_socket *, header_t *, 48 | ct_buf_t *, ct_buf_t *); 49 | void (*close)(struct ct_socket *); 50 | 51 | pid_t client_id; 52 | uid_t client_uid; 53 | } ct_socket_t; 54 | 55 | #define CT_SOCKET_BUFSIZ 4096 56 | 57 | extern ct_socket_t * ct_socket_new(unsigned int); 58 | extern void ct_socket_free(ct_socket_t *); 59 | extern void ct_socket_reuseaddr(int); 60 | extern int ct_socket_connect(ct_socket_t *, const char *); 61 | extern int ct_socket_listen(ct_socket_t *, const char *, int); 62 | extern ct_socket_t * ct_socket_accept(ct_socket_t *); 63 | extern void ct_socket_close(ct_socket_t *); 64 | extern int ct_socket_call(ct_socket_t *, ct_buf_t *, ct_buf_t *); 65 | extern int ct_socket_flsbuf(ct_socket_t *, int); 66 | extern int ct_socket_filbuf(ct_socket_t *, long); 67 | extern int ct_socket_put_packet(ct_socket_t *, 68 | header_t *, ct_buf_t *); 69 | extern int ct_socket_puts(ct_socket_t *, const char *); 70 | extern int ct_socket_get_packet(ct_socket_t *, 71 | header_t *, ct_buf_t *); 72 | extern int ct_socket_gets(ct_socket_t *, char *, size_t); 73 | extern int ct_socket_send(ct_socket_t *, header_t *, 74 | ct_buf_t *); 75 | extern int ct_socket_recv(ct_socket_t *, header_t *, 76 | ct_buf_t *); 77 | extern int ct_socket_write(ct_socket_t *, void *, size_t); 78 | extern int ct_socket_read(ct_socket_t *, void *, size_t); 79 | extern void ct_socket_link(ct_socket_t *, ct_socket_t *); 80 | extern void ct_socket_unlink(ct_socket_t *); 81 | extern int ct_socket_getpeername(ct_socket_t *, char *, size_t); 82 | 83 | #ifdef __cplusplus 84 | } 85 | #endif 86 | 87 | #endif /* OPENCT_SOCKET_H */ 88 | -------------------------------------------------------------------------------- /src/include/openct/tlv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Handle TLV encoded data 3 | * 4 | * Copyright (C) 2003, Olaf Kirch 5 | */ 6 | 7 | #ifndef OPENCT_TLV_H 8 | #define OPENCT_TLV_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include 15 | #include 16 | 17 | typedef unsigned char ifd_tag_t; 18 | 19 | typedef struct ct_tlv_parser { 20 | unsigned char use_large_tags; 21 | unsigned char * val[256]; 22 | unsigned int len[256]; 23 | } ct_tlv_parser_t; 24 | 25 | typedef struct ct_tlv_builder { 26 | int error; 27 | unsigned char use_large_tags; 28 | ct_buf_t * buf; 29 | unsigned int len; 30 | unsigned char * lenp; 31 | } ct_tlv_builder_t; 32 | 33 | extern int ct_tlv_parse(ct_tlv_parser_t *, ct_buf_t *); 34 | /* ct_tlv_get return 0 == not there, 1 == there */ 35 | extern int ct_tlv_get_int(ct_tlv_parser_t *, 36 | ifd_tag_t, unsigned int *); 37 | extern int ct_tlv_get_string(ct_tlv_parser_t *, 38 | ifd_tag_t, char *, size_t); 39 | extern int ct_tlv_get_opaque(ct_tlv_parser_t *, 40 | ifd_tag_t, unsigned char **, size_t *); 41 | /* or number of bytes */ 42 | extern int ct_tlv_get_bytes(ct_tlv_parser_t *, 43 | ifd_tag_t, void *, size_t); 44 | 45 | extern void ct_tlv_builder_init(ct_tlv_builder_t *, ct_buf_t *, int); 46 | extern void ct_tlv_put_int(ct_tlv_builder_t *, 47 | ifd_tag_t, unsigned int); 48 | extern void ct_tlv_put_string(ct_tlv_builder_t *, 49 | ifd_tag_t, const char *); 50 | extern void ct_tlv_put_opaque(ct_tlv_builder_t *, ifd_tag_t, 51 | const unsigned char *, size_t); 52 | extern void ct_tlv_put_tag(ct_tlv_builder_t *, ifd_tag_t); 53 | extern void ct_tlv_add_byte(ct_tlv_builder_t *, unsigned char); 54 | extern void ct_tlv_add_bytes(ct_tlv_builder_t *, 55 | const unsigned char *, size_t); 56 | 57 | #ifdef __cplusplus 58 | } 59 | #endif 60 | 61 | #endif /* OPENCT_TLV_H */ 62 | -------------------------------------------------------------------------------- /src/pcsc/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = $(srcdir)/Makefile.in 2 | 3 | if ENABLE_PCSC 4 | lib_LTLIBRARIES = openct-ifd.la 5 | endif 6 | 7 | openct_ifd_la_SOURCES = pcsc.c 8 | openct_ifd_la_LDFLAGS = -module -shared -avoid-version -no-undefined 9 | openct_ifd_la_LIBADD = $(PCSC_LIBS) $(top_builddir)/src/ctapi/libopenctapi.la 10 | openct_ifd_la_CFLAGS = $(AM_CFLAGS) \ 11 | -I$(top_srcdir)/src/include \ 12 | -I$(top_builddir)/src/include \ 13 | -I$(top_srcdir)/src/ctapi \ 14 | $(PCSC_CFLAGS) 15 | 16 | # Don't use ENABLE_BUNDLES for this case, pcsc-lite loads 17 | # USB drivers from MacOS X like bundles for all platforms 18 | install-exec-local: install-libLTLIBRARIES 19 | if ENABLE_PCSC 20 | if ENABLE_BUNDLES 21 | $(MKDIR_P) "$(DESTDIR)$(bundledir)" 22 | "$(top_srcdir)/macos/libtool-bundle" -e "$(top_srcdir)/etc/Info.plist" \ 23 | "$(DESTDIR)$(libdir)/openct-ifd.so" "$(DESTDIR)$(bundledir)" 24 | endif 25 | endif 26 | 27 | uninstall-local: uninstall-libLTLIBRARIES 28 | if ENABLE_PCSC 29 | if ENABLE_BUNDLES 30 | rm -rf "$(DESTDIR)$(bundledir)/openct-ifd.bundle/" 31 | endif 32 | endif 33 | -------------------------------------------------------------------------------- /src/tools/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = $(srcdir)/Makefile.in 2 | 3 | bin_PROGRAMS = openct-tool 4 | sbin_PROGRAMS = openct-control 5 | man1_MANS = openct-tool.1 6 | 7 | openct_tool_SOURCES = openct-tool.c 8 | openct_tool_LDADD = $(top_builddir)/src/ct/libopenct.la 9 | openct_tool_CFLAGS = $(AM_CFLAGS) \ 10 | -I$(top_srcdir)/src/include \ 11 | -I$(top_builddir)/src/include 12 | 13 | openct_control_SOURCES = openct-control.c 14 | openct_control_LDADD = $(top_builddir)/src/ifd/libifd.la $(top_builddir)/src/ct/libopenct.la 15 | openct_control_CFLAGS = $(AM_CFLAGS) \ 16 | -I$(top_srcdir)/src/include \ 17 | -I$(top_builddir)/src/include 18 | -------------------------------------------------------------------------------- /src/tools/openct-tool.1.in: -------------------------------------------------------------------------------- 1 | .TH openct-tool "1" "May 2005" "OpenCT @VERSION@" "OpenCT" 2 | .SH NAME 3 | openct-tool \- OpenCT smart card utility 4 | .SH SYNOPSIS 5 | openct\-tool [options] command ... 6 | .SH OPTIONS 7 | .TP 8 | \fB\-d\fR 9 | enable debugging; repeat to increase verbosity 10 | .TP 11 | \fB\-f\fR \fIconfigfile\fR 12 | specify config file (default @openct_conf_path@) 13 | .TP 14 | \fB\-r\fR \fIreader\fR 15 | specify index of reader to use 16 | .TP 17 | \fB\-h\fR 18 | display this message 19 | .TP 20 | \fB\-v\fR 21 | display version and exit 22 | .SH COMMANDS 23 | .TP 24 | \fBlist\fR 25 | list all readers found 26 | .TP 27 | \fBatr\fR 28 | print ATR of card in selected reader 29 | .TP 30 | \fBwait\fR 31 | wait for card to be inserted 32 | .TP 33 | \fBrwait\fR 34 | wait for reader to be attached 35 | .TP 36 | \fBmf\fR 37 | try to select main folder of card 38 | .TP 39 | \fBread\fR 40 | dump memory of synchronous card 41 | --------------------------------------------------------------------------------