From 99ff2a4f25165a8ec24238f6c055734d127809a1 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Wed, 29 Mar 2017 17:51:25 +0200 Subject: [PATCH 01/19] Start work on adding a belpic implementation BELPIC (BELgian Personal Identity Card) is the official electronic ID card of Belgium. Start adding a virtual implementation of this card to vsmartcard. Not remotely there yet, but at least this runs without error already, and sends the correct ATR when asked. Beyond that... much TODO. --- virtualsmartcard/src/vpicc/Makefile.am | 3 ++- virtualsmartcard/src/vpicc/vicc.in | 2 +- .../vpicc/virtualsmartcard/CardGenerator.py | 7 +++++ .../virtualsmartcard/VirtualSmartcard.py | 3 +++ .../vpicc/virtualsmartcard/cards/belpic.py | 27 +++++++++++++++++++ 5 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py diff --git a/virtualsmartcard/src/vpicc/Makefile.am b/virtualsmartcard/src/vpicc/Makefile.am index add04c16..c9f75d73 100644 --- a/virtualsmartcard/src/vpicc/Makefile.am +++ b/virtualsmartcard/src/vpicc/Makefile.am @@ -24,7 +24,8 @@ vpicccards_PYTHON = virtualsmartcard/cards/__init__.py \ virtualsmartcard/cards/ePass.py \ virtualsmartcard/cards/nPA.py \ virtualsmartcard/cards/Relay.py \ - virtualsmartcard/cards/cryptoflex.py + virtualsmartcard/cards/cryptoflex.py \ + virtualsmartcard/cards/belpic.py do_subst = $(SED) \ -e 's,[@]PYTHON[@],$(PYTHON),g' \ diff --git a/virtualsmartcard/src/vpicc/vicc.in b/virtualsmartcard/src/vpicc/vicc.in index b016998a..09de9ff8 100644 --- a/virtualsmartcard/src/vpicc/vicc.in +++ b/virtualsmartcard/src/vpicc/vicc.in @@ -35,7 +35,7 @@ Report bugs to @PACKAGE_BUGREPORT@ parser.add_argument("-t", "--type", action="store", - choices=['iso7816', 'cryptoflex', 'ePass', 'nPA', 'relay', 'handler_test'], + choices=['iso7816', 'cryptoflex', 'ePass', 'nPA', 'relay', 'handler_test', 'belpic'], default='iso7816', help="type of smart card to emulate (default: %(default)s)") parser.add_argument("-v", "--verbose", diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py b/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py index 93c5ef39..580173b7 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py @@ -665,6 +665,11 @@ def __generate_cryptoflex(self): data="\x00\x00\x00\x01\x00\x01\x00\x00")) # EF.ICCSN self.sam = CryptoflexSAM(self.mf) + def __generate_belpic(self): + # TODO: implement this in a somewhat more rational manner. For now + # though, use the ISO7816 implementation + self.__generate_iso_card() + def generateCard(self): """Generate a new card""" if self.type == 'iso7816': @@ -675,6 +680,8 @@ def generateCard(self): self.__generate_cryptoflex() elif self.type == 'nPA': self.__generate_nPA() + elif self.type == 'belpic': + self.__generate_belpic() else: return (None, None) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/VirtualSmartcard.py b/virtualsmartcard/src/vpicc/virtualsmartcard/VirtualSmartcard.py index a8c6377f..23aabb62 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/VirtualSmartcard.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/VirtualSmartcard.py @@ -428,6 +428,9 @@ def __init__(self, datasetfile, card_type, host, port, elif card_type == "handler_test": from virtualsmartcard.cards.HandlerTest import HandlerTestOS self.os = HandlerTestOS() + elif card_type == "belpic": + from virtualsmartcard.cards.belpic import BelpicOS + self.os = BelpicOS(MF, SAM) else: logging.warning("Unknown cardtype %s. Will use standard card_type \ (ISO 7816)", card_type) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py new file mode 100644 index 00000000..4ce2ba49 --- /dev/null +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py @@ -0,0 +1,27 @@ +# +# Copyright (C) 2017 Wouter Verhelst, Federal Public Service BOSA, DG DT +# +# This file is part of virtualsmartcard. +# +# virtualsmartcard is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# virtualsmartcard is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# virtualsmartcard. If not, see . + +from virtualsmartcard.VirtualSmartcard import Iso7816OS +from virtualsmartcard.ConstantDefinitions import MAX_SHORT_LE +from virtualsmartcard.SmartcardFilesystem import MF + +class BelpicOS(Iso7816OS): + def __init__(self, mf, sam, ins2handler=None, maxle=MAX_SHORT_LE): + Iso7816OS.__init__(self, mf, sam, ins2handler, maxle) + self.atr = '\x3B\x98\x13\x40\x0A\xA5\x03\x01\x01\x01\xAD\x13\x11' + From 793a3053d771e082a62b4afb95a45bd03e5dfed3 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Fri, 12 May 2017 14:48:49 +0200 Subject: [PATCH 02/19] Do not allow creation of files The BeID card does not allow the user to create extra files, so disallow when it is tried --- virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py index 4ce2ba49..6d408b45 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py @@ -25,3 +25,7 @@ def __init__(self, mf, sam, ins2handler=None, maxle=MAX_SHORT_LE): Iso7816OS.__init__(self, mf, sam, ins2handler, maxle) self.atr = '\x3B\x98\x13\x40\x0A\xA5\x03\x01\x01\x01\xAD\x13\x11' + + @staticmethod + def create(p1, p2, data): + raise SwError(SW["ERR_INSNOTSUPPORTED"]) From 5c6c52298dae0b51207053d44d94225805ac0479 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Fri, 12 May 2017 14:50:24 +0200 Subject: [PATCH 03/19] Upon initialisation, read the XML file Current BeID development tools work with XML files to represent the data on the card. Reuse that format, so that existing developers don't have to regenerate their cards (and so that a certain level of interoperability between those tools exists) We may add another option in the future, but that's not for now. Also, add the Belpic applet's AID as the DF name for the MF --- .../vpicc/virtualsmartcard/cards/belpic.py | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py index 6d408b45..384d589d 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py @@ -17,14 +17,42 @@ # virtualsmartcard. If not, see . from virtualsmartcard.VirtualSmartcard import Iso7816OS -from virtualsmartcard.ConstantDefinitions import MAX_SHORT_LE -from virtualsmartcard.SmartcardFilesystem import MF +from virtualsmartcard.ConstantDefinitions import MAX_SHORT_LE, FDB, LCB +from virtualsmartcard.SmartcardFilesystem import MF, DF, TransparentStructureEF + +import xml.etree.ElementTree as ET class BelpicOS(Iso7816OS): def __init__(self, mf, sam, ins2handler=None, maxle=MAX_SHORT_LE): Iso7816OS.__init__(self, mf, sam, ins2handler, maxle) self.atr = '\x3B\x98\x13\x40\x0A\xA5\x03\x01\x01\x01\xAD\x13\x11' +class BelpicMF(MF): + def __init__(self, datafile, filedescriptor=FDB["NOTSHAREABLEFILE" ] | FDB["DF"], + lifecycle=LCB["ACTIVATED"],simpletlv_data = None, bertlv_data = None): + MF.__init__(self, filedescriptor, lifecycle, simpletlv_data, bertlv_data, dfname = "A00000003029057000AD13100101FF".decode('hex')) + tree = ET.parse(datafile) + root = tree.getroot() + ns = {'f': 'urn:be:fedict:eid:dev:virtualcard:1.0'} + DF00 = DF(self, 0xDF00) + self.append(DF00) + DF01 = DF(self, 0xDF01) + self.append(DF01) + parent = self + fid = 0 + for f in root.findall('f:file', ns): + id = f.find('f:id', ns).text + content = f.find('f:content', ns).text + if content is not None: + if(len(id) == 12): + fid = int(id[8:], 16) + if (id[4:8] == 'DF00'): + parent = DF00 + if (id[4:8] == 'DF01'): + parent = DF01 + else: + fid = int(id[4:], 16) + parent.append(TransparentStructureEF(parent, fid, data = content.decode('hex'))) @staticmethod def create(p1, p2, data): From 8e6266a4ef550d3b5efd8884da3c95adce21d5a2 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Fri, 12 May 2017 15:59:52 +0200 Subject: [PATCH 04/19] Initialize the Belpic card as a BelpicMF --- virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py b/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py index 580173b7..2b549301 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py @@ -668,7 +668,10 @@ def __generate_cryptoflex(self): def __generate_belpic(self): # TODO: implement this in a somewhat more rational manner. For now # though, use the ISO7816 implementation + from virtualsmartcard.cards.belpic import BelpicMF self.__generate_iso_card() + self.mf = BelpicMF('belpic.xml') + self.sam.set_MF(self.mf) def generateCard(self): """Generate a new card""" From 07510769c1d0ab9105f609bde828b379ec9762c8 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Fri, 12 May 2017 16:01:42 +0200 Subject: [PATCH 05/19] Update TODO note --- virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py b/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py index 2b549301..b9941717 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py @@ -666,8 +666,8 @@ def __generate_cryptoflex(self): self.sam = CryptoflexSAM(self.mf) def __generate_belpic(self): - # TODO: implement this in a somewhat more rational manner. For now - # though, use the ISO7816 implementation + # TODO: make BelpicMF actually work. Right now, an application which + # tries to use it will fail. from virtualsmartcard.cards.belpic import BelpicMF self.__generate_iso_card() self.mf = BelpicMF('belpic.xml') From 6bba615d4929f6434869994a1dc1d6724c42d0d8 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Wed, 17 May 2017 10:22:17 +0200 Subject: [PATCH 06/19] Add an example XML file Generated by . TODO: generate it here, rather than there. Not for now. --- .../belpic-example-data/belpic.xml | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 virtualsmartcard/belpic-example-data/belpic.xml diff --git a/virtualsmartcard/belpic-example-data/belpic.xml b/virtualsmartcard/belpic-example-data/belpic.xml new file mode 100644 index 00000000..2883416d --- /dev/null +++ b/virtualsmartcard/belpic-example-data/belpic.xml @@ -0,0 +1,82 @@ + + +beid +1 +myfriendlyname +534C494E336600296CFF278E5519202E +534C4790432100003077FEAA12925086 +F336012201170003002101 +3B9813400AA503010101AD1311 + +3F002F00 +61234F0CA000000177504B43532D3135500642454C50494351043F00DF0073050603603802 + + +3F00DF005031 +A00A300804063F00DF005035A40A300804063F00DF005037A80A300804063F00DF005034 + + +3F00DF005032 +30270201000410534C494E336600296CFF278E5519202E800642454C504943030204309E0403020000 + + +3F00DF005034 +3033300F0C0942617369632050494E030206C03003040101A11B30190302020C0A01000201040201088001010401FF300404023F00 + + +3F00DF005035 +303A30170C0E41757468656E7469636174696F6E030206C0040101300F04010203020520030203B802020082A10E300C300604043F00DF0002020800303930150C095369676E6174757265030206C004010102010130100401030303060040030203B802020083A10E300C300604043F00DF0002020800 + + +3F00DF005037 +302C30170C0E41757468656E7469636174696F6E030206C00401013003040102A10C300A300804063F00DF005038302730120C095369676E6174757265030206C00401013003040103A10C300A300804063F00DF0050393023300B0C024341030206C004010130060401040101FFA10C300A300804063F00DF00503A3025300D0C04526F6F74030206C004010130060401060101FFA10C300A300804063F00DF00503B + + +3F00DF005038 +3082053A30820322A003020102020102300D06092A864886F70D01010B05003031310B30090603550406130242453122302006035504030C1941636D652C20496E6320496E7465726D656469617465204341301E170D3136303732373132323035315A170D3236303732373132323035315A3072310B30090603550406130242453129302706035504031620576F757465722056657268656C7374202841757468656E7469636174696F6E293111300F0603550404130856657268656C7374310F300D060355042A1306576F75746572311430120603550405130B373830353036303939333630820122300D06092A864886F70D01010105000382010F003082010A02820101009367852537831DBFE04BC2BB17242449F8A0E116B5251EF8A4D0FD88893E555DA7AB278E5F203506B88AC50AD5DDA3212FFE6141A0D3E3BEC0344C17515313187D76DBD3C67AF487AF0856CCD894310576C01E6F411560CF71C165432365BD4EBD718456213AF216042339633CD6953403DC1939025325CED854B099B85DCA44C298B6EF4A83E403C3F74001C2C1F4A89F68C4C0C6AA03B41B895B5801727D4DA8C3EF6262BD07F4F2A5442807631109B77E29E1F204B2BEEF0FF0EAD05E99DA05A3BAA5821041DB7056D9786DB3F20F7B732D3ACF7E6CE3EB9A0688D14D40AC1363FC3B8524BBABD38F624D525667F1A9BDA600862E4CAB1D26221D9E0BA21F0203010001A382011A30820116301F0603551D230418301680145E9D7128B78D690D537A036367B4566199DF726F305C06082B060105050701010450304E302806082B06010505073002861C687474703A2F2F6C6F63616C686F73742F63612F726F6F742E637274302206082B060105050730018616687474703A2F2F6C6F63616C686F73743A383838382F30440603551D20043D303B3039060760380A01010202302E302C06082B060105050702011620687474703A2F2F7265706F7369746F72792E6569642E62656C6769756D2E6265302C0603551D1F042530233021A01FA01D861B687474703A2F2F6C6F63616C686F73742F63726C2F63612E63726C300E0603551D0F0101FF040403020780301106096086480186F84201010404030205A0300D06092A864886F70D01010B050003820201005DFBB612B00436D9204A57449750C27D05E6C4931C9680CEBC0D6C2B791664C54774919ECB4A407A93627B711ACC64FE69406F74B55EA2C62B9B88DF41CE0FE11A875ED9F2E82047D1F0AA2F82F685EC19213327B959DF376276C9B05171FD8E07172B559625A6583ECE2E66825A7F84FF0FFC2C4A3C624E100D4B7F2AFBE7CB5A00904D20405FF8E01F867089EFAA2A2595A2EBB21FE7E40DA6C8F080B9493D26C0465FBCE6FD1A19E949118364FCF4BBE4E726C53BFCD55C6E7DA7A5DCDED9320253A49F485960582D85A08134AF48F99B1BCD5FB3DB33630E0F56A883D9AB41A5E5BB619A1A28FAA5C34AF0EF4E9271AEAE865394A8B308E0A364BB1018F0FE6A94947890ECDB8E5BE4FF9891168CC2BF2A7CAE8DC8F145981FA36A0A8A38E06E52C1CF483C21B7A1BDC1F96DC5650E34A317C9CDB5C0D7A2689BCED768B3A75221EE71FBED0F86A264500B2ACC4597EFC5DE4A481A583787BC00B3449368667455C0BD495DFF7C1B8A349B251583519256D719CF12018B964B15F08334CCDF1CC70CD74D87647D8098DFB2988BC654B1D6FB17BA336B25D8EEE8A2DFE4F4618F74203E4125463F301894FE49C7437522D8587D71CCDC39CD491E0C850EB7DE80505CC7006508FDC2A51E89DC159821E174716E36110240C5D3433132D53F67AE34CA7A4323EECB0EDCC766371778E9A9C9B1D2DD6E8C35FFB4592B620BB6 + + +3F00DF005039 +3082054F30820337A003020102020101300D06092A864886F70D01010B05003031310B30090603550406130242453122302006035504030C1941636D652C20496E6320496E7465726D656469617465204341301E170D3136303732373132323035315A170D3236303732373132323035315A306D310B3009060355040613024245312430220603550403161B576F757465722056657268656C737420285369676E6174757265293111300F0603550404130856657268656C7374310F300D060355042A1306576F75746572311430120603550405130B373830353036303939333630820122300D06092A864886F70D01010105000382010F003082010A0282010100C1376C76A5FBB9BD070A81BAB947D144471EE26BAC347FF55E2C9A292F5E5CE24B22163D7CE1812D625EA2BA16444ABC43B693DCF4E4E1AA615BAD689E130AE424508A8A9B7339F535138D16A70BA81255F8124C7918903D4B97856D702C8144B4BACEA425B749264B34565CC8F920F78DEA9CFCA5A4F812522663D2404609E68E41904A08548BED4210D950E83CDD5995E30171ACA2AC645A7FA67A7445DED5502A4036FBEAC66B249FEB2B337EBF5D56BC96A195A690E735510CE0D036DF7ECB86A8FF2300FB0E8D2D585D3C9F34F26FBB477077699D4369C97E22F9E6AF8897398168CFE84F06C130F460EB6DB2DADF28D6CB09539AFEC347E7D15AF725D50203010001A382013430820130301F0603551D230418301680145E9D7128B78D690D537A036367B4566199DF726F305C06082B060105050701010450304E302806082B06010505073002861C687474703A2F2F6C6F63616C686F73742F63612F726F6F742E637274302206082B060105050730018616687474703A2F2F6C6F63616C686F73743A383838382F30440603551D20043D303B3039060760380A01010201302E302C06082B060105050702011620687474703A2F2F7265706F7369746F72792E6569642E62656C6769756D2E6265302C0603551D1F042530233021A01FA01D861B687474703A2F2F6C6F63616C686F73742F63726C2F63612E63726C300E0603551D0F0101FF040403020640301106096086480186F8420101040403020520301806082B06010505070103040C300A3008060604008E460101300D06092A864886F70D01010B05000382020100831B92FD2BFFF504BD7BC3B131D79AAFC86F9745B5CDD00285576D8858828BF239D4E082E5A1CFF3ED890DC19F4DD6D9B284890691A3C3DBAECE8DF87634DB6639B0B9789F0C67E3FAE130AB42F4370583B70BA4F422CB541EB0216360385F3F935FE00A36B3135318EFEB26D807ADBEC71AC62A35B03772FFE0EDB0E90B537460CC0A58C4A1D42D78DF57A3009DC7AE9DD87A6CEEBAE86E1B0F64A2D28AFA18CABD9F7D7923508B2A3DF50CEB186BB5B695012F1A3DD7D760173180BABDF19AB054FFCEC061C82D0F01E1FB9649625F4E28FE00E836E775782925A53C3378104AFCDB404AA11C90AE35C7D9A2A16BEE2E7B33303CA1F2D18919DAC3D05015484774B403F2CC0D4A6FAC4354A6320504DAB3138E396A7012332B563E80BA5BFEE3A91EE6A5D6AE0412F01AC33C0198EBCADDFA8DE072F9D67CEAA00D411B6855C1D2605437CCD0607254AE6ABE5913D966748F6EAABB6F7003ADBFA4AAA6DE1015FEAAB9E01B6773FCF9DD66B738EBCCD47F77D51F5FB5F0F0449AE3B674D8C756A5763A85D5C099E543E1F0871335C3F4A409A16A66869D60D3AB5C7D1D7BB9D857CAD564FA34CDE7400D0F9086A4EACCDD08F246101A2A60711D352D4D1BD12B63984C0226ED16FA6FC9BB20623FF2E1434FC6C26C30CA526B32D54AE983A135FE149603DB486D82583A97C68D5DB9ABB1A018511ADBBB85CE8EF603F6B383 + + +3F00DF00503A +308205C9308203B1A003020102020102300D06092A864886F70D01010B0500302F310B30090603550406130242453120301E06035504030C1741636D652C20496E6320654944205465737420526F6F74301E170D3136303732373038353630385A170D3238303732373038353630385A3031310B30090603550406130242453122302006035504030C1941636D652C20496E6320496E7465726D65646961746520434130820222300D06092A864886F70D01010105000382020F003082020A0282020100C873CD4F1AF071C4EB47A344DF775B56F3BE33117F8D7185128E91A32115F6FAFAF0C0B5A2B9E4BA9AB1D264F1E213810F4E13D57A93C8DFA249406A6EF8C857CD905C75D06B38FD517E250CC4E9D653AD1AF55B7E15C5D7632D27DA64F3D4988D1F4B1F5B959D4C2ED0B79F5D1A4A28A346109A895EE69E687BBEF0EDB082835CC6AE0A3EF4026ADA8D6EF3FFF62858235C1C6193CCDF71A1DE9EFECC725B93C577413287B01DA2345016FB1211C7E284E4613DAE781A96D68E27FBDE6DE165D5EC5AF7D0C21DA6EB6636F7EFB279AAD9559BC081915AB245BB69BFB7B7B2EFCB0991E0F3EA1277A4910E8A7922C4BA4F5575B32B913363E19D1EFD5ED0DB4818AEBC1662C28E55323615F62DE16D7DF0628FABBE81CC5F5C50CF4816430F9A966DF412B2CAE12F10A72605E151B87CD2EFCD5FBBB227146A53336C0545D2E498EE83824A2FFC83669D592362FFD911F3FED62F94C9BE45A894216CC2A214F8C377E2E82682813770221DFEC6133E3E69C11F91217508B0F1C171F67E97D3A41AB01C9F0640034AABA7AE37DB2BE1C40FB824AF9A814667F25E020DC5C02B011E3E0AD6E4CA0CC546889A5825E7B04BC7A39DA1316669FA9089A4477561DC3C5C1355693DDEB450EB2BEE0E2C1E2116B6224F9324B2AB6609B5D20724B50C11116DBCDB12FDDA629A991CB129BFF6724A064AED39E34A62C5CE326D63AD19E70203010001A381ED3081EA300E0603551D0F0101FF04040302010630120603551D130101FF040830060101FF02010030430603551D20043C303A3038060660380A010102302E302C06082B060105050702011620687474703A2F2F7265706F7369746F72792E6569642E62656C6769756D2E6265301D0603551D0E041604145E9D7128B78D690D537A036367B4566199DF726F302C0603551D1F042530233021A01FA01D861B687474703A2F2F6C6F63616C686F73742F63726C2F63612E63726C301106096086480186F8420101040403020007301F0603551D230418301680145BC5455E692614597D3F8CD0602276373E71B1CE300D06092A864886F70D01010B050003820201006F78C085841F2744C01F582654193EEA5425FEC3FB09FA9FE85E04D96C2EDC4E38C7DD73B48FC5A7B3F6A0350017C74129AE2A5BD1D317E40A49BE21D5EBD2B9798397BEA39681BAF05EDCFCE09898D490EB113D4945CF17E38FA2E1D4F7EB318E21BB63D9EAC114FB560B149E8EDA82A964517203250B00D9966D4FA70247258265A093194A0B19F2D6C980744B38DA46DD66B3F3077E4A32E912934B4B2C798E5AF6F33337CD2159E07B5FD5A8FBEFECA6BC8E1F1A30CF546C8E10DFFD90C9A98631637CF5D1B1CB82457C7BE9DEF55CAFB0484CE9298C5DCBAA1B67D06FE25BC81575B9EBB55BDAD50E5873DD43F40DD0A984AFECE9CD5F48ACB2A28F40A8A8A2ABEF9C6813BADD7CD96C2653580A781A337D5F2179AC041B3DC42072B557A0F546ADF6B67F8E17E678D3B4E9D4DE39D4FF5A9762FC27337ACB897C41C1522CDC34C9C0B5700FBFA0A945A17AA35F8377CB8C70B036DCD9D07944077E337D38E01B77AE15B229E561ACF60C74B5B03E5B71ECFADAA0D4A30EAF9102736C24B2E0CF80A8C9355D58FD032C15A2971F7B1EA57CF55E766D92972451936152826DD363B567B20437810B1136D8B9F8D2FE791D6C9558257CA9396403E89B1AE92B6C58F74A36B65763EBC7A72B0DE3368BF146BFA9481E5AD2833D184211FAF11C665925EF48C75C5D0ED980EBEC5D92552D1B1E8220E5B4AACE9F77127109BC + + +3F00DF00503B +3082059D30820385A003020102020900C8BA1AB52E6F1D22300D06092A864886F70D01010B0500302F310B30090603550406130242453120301E06035504030C1741636D652C20496E6320654944205465737420526F6F74301E170D3136303732373038353630375A170D3331303732373038353630375A302F310B30090603550406130242453120301E06035504030C1741636D652C20496E6320654944205465737420526F6F7430820222300D06092A864886F70D01010105000382020F003082020A02820201009FB9137A4650090166906CE38C7A78773AA508D7B4937759D73673E4BFAAE2427BCAE38405761FFB214BE5AA0A2AA57827D4F7F1394E6047FA728F14F44D557878D32C9E8E6AF0F460566E38BC1A207A58E115FCC6035B3F7870A1DD07368490401B3485B7391DFC26F11B9C26432F2F5350CB7AD02D54AD7E9F67738E4ECC39442B53FDA5DEF8A24188E1531E560BC779041165AD46AACEAC10A66504AED94C5865798920CB4EC6AD67284967031A8E08ECFE7DADD0053AA2665BFC32C9130B00CB2703AA7D49DE792EC946F5BDB310ADF5C43BE5DDC493E3AF0DF2B9AA9F75D645F47DCC9D201D0C382AF2670446AE1CC319C558D83C84C5484B5948AE771103535043ACEB20CE71280058E89B08F0212F6D307FBB97CBE3F516390C8A4CA8D505E8A09F9B9B9D2A133DDC0A1DF112D554D8EE7B6FFB8D09DF8C89D03D1C81221E4AA4B4F86F233318E9EFEE85A9E2F3336B622766E5F30994615E0D2574754576F7A8E91709202F80D3C8A591E4A8B9CDDD4D43D86163F150B0B0C8C48F6474DF2084ADA22858B63A8BBF770D4D8177B49DB16968BEC42D9398F021FA179E11A7D0BC28D851EC995E0760A2027FA28F31FAD195E584FC4379E931BB3E32C611908740EB6B6A5A45A36262E572648536CF18C7D034573670D5A253AF3510C787E78258C4CFB25247D01FD4F1DDD069CADC5C6EB49658FF12D9C9E3AA77D7F30203010001A381BB3081B8300E0603551D0F0101FF040403020106300F0603551D130101FF040530030101FF30420603551D20043B30393037060560380A0101302E302C06082B060105050702011620687474703A2F2F7265706F7369746F72792E6569642E62656C6769756D2E6265301D0603551D0E041604145BC5455E692614597D3F8CD0602276373E71B1CE301106096086480186F8420101040403020007301F0603551D230418301680145BC5455E692614597D3F8CD0602276373E71B1CE300D06092A864886F70D01010B050003820201009006A7587713B7496FEADA39D860ABE1C2284E4164469DBCF73252B874DC1B048451F07EA233D3D49EB7AF94107B380C98745E7C306DDCF944966609561EB3F65C9B08DF212F78BFDBCAD3B21CD64D0BE0A70608B9F4F21912B87F8BDDCF6454B9ED82FF7993FAE1AC5F87F156FD229CED6234B5E077A6E3D816EB19EBA3BDCFF89DA9A065A06BC0C5170B7BEAD5FFD6878298DBEAF036AF63C509E430FE99A757D26EECFDDD747E003DA998619EE7467E9978E999BE0817D8B772A72ACCCDE546DB94AE45D1C3CBA2C1D6A7F1E8A39FDAC82ABF71C2C397934E1BA4A380897C2BC7C9144B88367A3C2D0C5ED07B20E0BA43A0CAD6DB489D41C83EDD95BD2E170912FEAC7A0EAA09597A27B1D70CDD5EEFA7523D23DFFF76B7423C405B9902744B3399DA2DE7E178514328A3688156F9603C202868BFDFE6D87E97897AC49973FBDC619F1A6525D5A3A827F6F744C82DE46547F34E8EA497B255A4AA5CF1AF1B27530830DB6B8EAE692B8ABFADB592AC6D2F3069F4DA201412412FC76FEB8F839485CDBAA43B56EFAE55B9FD808FD686D84EF1D11CC5810A57DBA3BDE17C05AA6E7F7AAAE37DF87A676C8F3F5D0E8032FC987EFC4D4B5745EDD83527D582973A4D36E84A4FD88FC23CA215E7E4C880762D0D215BC741F7BF92FEA55169791A225F2CE830AE23F9896ABF7141E31C481FD36FFF7CDFD2D59DF5D0EC86E15F3D13 + + +3F00DF00503C +308204B63082029EA003020102020101300D06092A864886F70D01010B0500302F310B30090603550406130242453120301E06035504030C1741636D652C20496E6320654944205465737420526F6F74301E170D3136303732373038353630375A170D3238303732373038353630375A3038310B300906035504061302424531123010060355040A0C0941636D652C20496E633115301306035504030C0C65494420746573742052524E30820122300D06092A864886F70D01010105000382010F003082010A0282010100B8E713EFF26C1F419C2BE14D190DE1FAB265A121C919C17E75380F460B02AC1A89166F8C407883D36BA434C4F22BCBBA4DF68DA0E6DD3C93C4F4225E41952BA32F978451F5A6EE809BE594B6B4F761D509EF391F3013EB99F698A2CDBE485EED07CACE1C716DE570F654A918C07B60A11265DD0AF6104A17143990564A93FC5DB0201DF5BBB9EA4C215898F5733CC25B832F35983CD2775B3FB52179FFE1D8DCCB9CC8A5565646CF5FB38222B43A4EB5135B144730479CA884606DF2A0FA515831A0668C3152ACC5BF1EAB035C6D0D9ACDBB178954FBC0B8BEBADF56C2137A9B7A70EDADC85CE51931591D61A7602FAB4BED1070498A872E76F430493A407B050203010001A381D33081D0300E0603551D0F0101FF0404030206C030090603551D130402300030430603551D20043C303A3038060660380A010104302E302C06082B060105050702011620687474703A2F2F7265706F7369746F72792E6569642E62656C6769756D2E6265301D0603551D0E0416041437659109E415D93B8C49EE27CE8D1E90836AC370301F0603551D230418301680145BC5455E692614597D3F8CD0602276373E71B1CE302E0603551D1F042730253023A021A01F861D687474703A2F2F6C6F63616C686F73742F63726C2F726F6F742E63726C300D06092A864886F70D01010B050003820201006A78D9F256D6646E7B108BDCE6D1D376FA982DD89584543F265526B3E725D19784722C9496CD9658C84E420BCF45CBB8756E941AEA11E860C14A1ABEFEBF2D10FB35667BBC7CC86C176E676D06C980EB6BF72EE027896BA879F85B8EBE3D384C4622F2C7932C7913947D6D9408FBD25BC7F1FEAF3775BB8FC7027F05BA8DF086D498B96CC1CA09B94B5FBF6EE36BA19571A075177B968150A8E0667E26280B32E56C7A9F6F52FC91E610CA8C4B4817F8461DDB26147C22F64BE6C87A6F47A579EBD39258FBC80175C1912E6240F3896936A554575CFF9AFBF52C95F74B3A58DA0E56EEDF2F8A9809A9B569DC4AD415D7C02BE03074D9BFD230A621AFE024652BDE5BD192A8775ED4251568AF3A3A9844E3A5903BD77AFDEF834C96B695F6FFBA12BCD93DC43E6886ECBF1F4667919B1EBC7AB5BD39BDCBCDB499BFB0C8AA292D91A326AC6EB967C0C016A66E1E14B263B3D4B0E3712347CF36049823B10908A4331C5635058E204831F1CCE04AEA103AFB18D1F5867001C699F6D8AE8EBBD785250F2EC9FC18CEE8175E975F6D47DC2433AFA8EF3131D9A034167DA08F65678448B61980754B460EF0D677A7D5C8387FE4199515242D886C40C64D3D234B5922CEF9881189762E0805EF58EE0AA6620EEA0D666F64553C60673F296493DDE245B78156EC8D5EE6162BC65DE05E5572D8FF96296A9A2F4A002857E8F37100BC48 + + +3F00DF014031 +010C3539323030303035363638420210534C494E336600296CFF278E5519202E030A31372E30322E32303136040A31392E30322E32303536050E4D794D756E69636970616C697479060D31393732303530313532353637070A4D794C6173746E616D65080C4D7946697273746E616D652009000A0442656C670B0B4D794269727468436974790C0B3235204D414920313936350D014D0E000F0231311114C03D39E3B4660AD8D3A9710617CBB56C7F5C2475 + + +3F00DF014032 + + + +3F00DF014033 +010D4D696A6E73747261617420363302043130303003074272757373656C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + +3F00DF014034 + + + +3F00DF014035 +FFD8FFE000104A46494600010201012C012C0000FFDB00430007050606060507060606080807090B120C0B0A0A0B1710110D121B171C1C1A171A191D212A241D1F2820191A253225282C2D2F302F1D233438342E372A2E2F2EFFC0000B0800C8008C01011100FFC400D20000010501010101010100000000000000000102030405060708090A0B100002010303020403050504040000017D01020300041105122131410613516107227114328191A1082342B1C11552D1F02433627282090A161718191A25262728292A3435363738393A434445464748494A535455565758595A636465666768696A737475767778797A838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE1E2E3E4E5E6E7E8E9EAF1F2F3F4F5F6F7F8F9FAFFDA0008010100003F00F59A28A28A28A3DA970719C71EB460FA5277C77A0F1D78A28A28A28A28A28A28AB965632DCB03B4AC79E5FFC3D6B660D36D62E76B39F5739ABA005185181E828201EA01FA8A67930E49312127D54557B8D3ED671831EC3EA9C566DCE912A9CDB9F307A1201ACC7564764604329C107A8A6D14514514514E8D1A47088A598F402B6ECB4A543BEE70CDD901E07F8D6A850A0000003B0A28A28A28ACDD62C1AE504D085F3D3D7F887A573CAC186452D145145147703D78AEA34EB74B7B68F0803B282CC47273CE2AD514514514514573FAEDAF9322DD46004908570077EC7F4ACDA28A28A2AEE956EB71743783B106E3FD2BA5A28A28A28A28A2A2BA856E2DA485B1F3A9009EC7D6B8E8D5D098A45DAC87041A928A28A2BA4D26DD61B457DB8924E5BFA7E957A8A28A28A28A28A2B9CF10C5E55DC573C00E307EA3BFE445503ED45145364384623D2BADB16DD6701FF00A66BFCAA7A28A28A28A28A28AE6FC5320F3AD62E72159BF3C7F85501D052D1452372A4574BA21CE956FF0043FCCD5EA28A28A28A28A28AE57C4BCEAB0AFF00D301FF00A11AAE38028A28A46FBA6BA7D1D1E3D3204914AB00720F51C9AB94514514514514515C9F88195F58509C848954FD724FF5A89BAD25153597946F20598128CD8C76CF6FD715D3B5BC0EC1DE18CB0E84A8C8A968A28A28A28A28A28AC3D534A964B896F2270DD0F978E7818FC6B2739EC476C1EB4544265EE3069A660278E503EE106BB953900FAD1451451451451451452D71DAD485758B945C0036F4FF007466A0132FA11F5AAD4927DC61EA2BB7D326FB4585BCBC64A0071EA383FA8AB5451451451451451452332A297760A8A32493800579DACC6E2E65B83D65667FA64D4D83553CD93FBDFA52348EC30589AECFC2F2AC9A52A0FF00964ECA78EF9CFF005AD8A28A28A28A28A28A2B1FC55702DF449FE7DAD2E22518EB93C8FF00BE41AE1EDD888D48383CD4E2690746FD2AB79C9E868F3D71C039AD4D075D4D30CA97113341236ECA75538C7427A702BB7B2BBB7BDB64B9B593CC89FA3631D3AD4F45145145145145616AFE28D334ABA6B5B8F3DA6500958E3CF519F5AE5BC43AE26B12DAADB24D1C316599640012C463A027A0FE66A8C72AAA0520E47A53BCE4F435537A7F7C7E746F4FEF0FCE918C6C305979F7AD6F086AC2C2FF00ECD71262DAE0851B8F0AFD8FE3D3F2AF48A28A28A28A28A5AF27F11C865F116A0EE08C49B3DF0063FA540BE5A7008E7BE7AD2974C13B87E746F4FEF0FCEA98E9EB477C518E7A734C9B063604E0819EB5EA3E10D446A3A15BB96CCB10F2A4CF5C81D7F1183F8D6DD14514514514633DF15E2525F9BED42E2E0E3134ACC31F5352707D28E319C0FAD2E2B30330180C40F634BBDF39DC73D339A424B72493F5A4CED04921571C93D3157BE1EF8F7C3F6BE2A3A0B6A20CD7ACB02A88DC8F346768DC063B91D7B8AF6FA4A28A28A28AE2BE2878BEC7C25A0AF9F73E4DDDF9305B000939FE26E01E808F4E48AF32B53FBBC83CE738A9B24F5A50CC060138F4CD1B8F7E7EB59D3DEADBC6649A78E3400925C81FCEB95D4FE2069166A45ABCB793E0E1114AAE7DD8FF00300D7357FF0012F589C6CB0B4B7B418FBEC3CD6CFE381FA5721A86ABAA6A008BDBFB9B90CFBB6BC84A83ECBD056BFC3D87CFF1F78663F33CB3FDA76E4363383E62E3F5C57DE9494514514515F3DFED5F8FB1F8638C9F32E47E91D79A7803C58E5A3D235299CB924433C8F9DDFEC1CFE383F857A389A418F9A813483BD1E73FAD7CE0C0BB1777666272493CD281818CD2D15E8FF00ECBEDBF13F49046560124CDC74DA848FD715F67514514514515F3C7ED5CEA20F0B21CEE67BA23E80459FE62BE7039C82A4820F04576FE1FF1DDCDA7976BAA279F1018F3C125C0F523BF6F4FC6BBEB0D6ECB50844B672C72AF7DAFCAFD4751F8D5AFB5FF00D33FFC7ABC068A28AF6CFD972CD66F1B6A578CDCDBE9EC1467BB3A73F903F9D7D53451451451457CD9FB59DCC4D75E14B40DFBE8A3B99187A2B18C0FFD01BF2AF9F690807AD58B2BDBBD3E71716333452E3048EE3D083D6BAAB4F1DCF1DBA25E5AACB30EAEA76EEFC2B8EA28A2B63C2DE24D5BC2BACDBEADA3CC63B88C8DCA49DB22E4128D8232A71C8AFBB3C3DACE9FE21D16CF5AD2E6F36CEEE31221C8CAFAAB609C3039047620D68D145145151DC4D15B5BCB713CA914312179249182AA28192493C0007735F0FF00C56F193F8D7C6575A92106C211F66B218DBFB956243107072C496E79E40ED5C751452601EA052D1451457B2FECFBF10B4FF0ADE5DE83ADDCBC361A84A8F0CCC7F7704B820EEF40C360CF6DA33C723EAE8DD258D2489D5E3750CAC872181E841EE29D4514528E7A5784FED1FE37B3B6F0F8F09E977F1C97F792E2F44122B18624E4A3E0E5 + + +3F00DF014038 +E0EAAC4F2D3B0FD8CD78AE57AED01BA915543E57 + + +3F00DF01404A +02080000000000010001038180842A3A869015FB42F727FE5143DC22FAB85C56D2F969DCBD384C6DA1BEC39F8D0D22ED4814C2E69BBF06A3DE4CD53DDFB9F66B09EE29843AD798DD5413B55D560271FAE2A2A28997DF12AC2A7503540085E373CFE099473B42B05B66C266E29802865B3B3FB79F11AADB8084EE86BA317F9BCC49A96EA9AB89E73F673D490997 + + From cdbe8fc1b1f7d1628449bec01511d1d8122c7b39 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Wed, 17 May 2017 20:10:50 +0200 Subject: [PATCH 07/19] Clarify this here, too (and trigger a travis build while we're at it) Signed-off-by: Wouter Verhelst --- virtualsmartcard/belpic-example-data/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 virtualsmartcard/belpic-example-data/README.md diff --git a/virtualsmartcard/belpic-example-data/README.md b/virtualsmartcard/belpic-example-data/README.md new file mode 100644 index 00000000..c1ebc9ef --- /dev/null +++ b/virtualsmartcard/belpic-example-data/README.md @@ -0,0 +1,3 @@ +The .xml file in this directory was generated by [the scripts in the +eid-test-cards project](https://github.com/Fedict/eid-test-cards). We'll +make this look better at some point in the future, but not now. From 9dc0f733dd2da1b46dcbabbb77f820969e71fca2 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Thu, 18 May 2017 11:30:41 +0200 Subject: [PATCH 08/19] Disable coverity for fork... --- .travis.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 980ea274..d43987f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -82,15 +82,6 @@ before_script: ./configure OPENSC_LIBS="-L$PREFIX/lib -lopensc" || cat config.log; fi -addons: - coverity_scan: - project: - name: "frankmorgner/vsmartcard" - description: "Umbrella project for various projects concerned with the emulation of different types of smart card readers or smart cards themselves" - notification_email: frankmorgner@gmail.com - build_command: make -C $TRAVIS_BUILD_DIR/virtualsmartcard -C $TRAVIS_BUILD_DIR/ccid -C $TRAVIS_BUILD_DIR/pcsc-relay - branch_pattern: master - script: # Build virtualsmartcard - make -C $TRAVIS_BUILD_DIR/virtualsmartcard From a8ca1d37e0c7196b5fca05027949a8a724470256 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Fri, 9 Jun 2017 18:00:20 +0200 Subject: [PATCH 09/19] Make the Relay card still parse and log the APDU The basic VirtualSmartcard implementation parses and logs the APDU sent to the card in the execute instance method, and logs the received APDU after calling that method. The Relay implementation, however, overrides the execute method, but does not log it. The result, when running at the info log level, is that you see the reply from the card, but not the request from the application. This is confusing. Additionally, if the relay implementation shows the request APDU, then it can be used as a method to analyze what an application is trying to do. To remedy all that, parse the APDU and log that parsed value, but don't do anything further with it. Signed-off-by: Wouter Verhelst --- .../src/vpicc/virtualsmartcard/cards/Relay.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/Relay.py b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/Relay.py index 69c27b3e..843a1f48 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/Relay.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/Relay.py @@ -22,7 +22,7 @@ import smartcard import sys from virtualsmartcard.VirtualSmartcard import SmartcardOS - +from virtualsmartcard.utils import C_APDU class RelayOS(SmartcardOS): """ @@ -113,6 +113,13 @@ def reset(self): self.powerUp() def execute(self, msg): + try: + c = C_APDU(msg) + logging.info("Parsed APDU:\n%s", str(c)) + except ValueError as e: + # ignore the parse failure, just don't log the parsed APDU + logging.warning("Could not parse APDU:%s", str(e)) + # sendCommandAPDU() expects a list of APDU bytes apdu = map(ord, msg) From e3a1aacce7c9758482420f8515beb49dc2abd41f Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Wed, 14 Jun 2017 18:47:19 +0200 Subject: [PATCH 10/19] Allow for unparsed logging Some unknown cards, which the Relay card may need to deal with, may not use the APDU format. Trying to parse commands sent to those cards as though they were in the APDU format is obviously wrong. However, most cards do support APDU, so default to logging parsed APDUs, still. --- virtualsmartcard/src/vpicc/vicc.in | 3 ++- .../src/vpicc/virtualsmartcard/VirtualSmartcard.py | 10 ++++++++-- .../src/vpicc/virtualsmartcard/cards/Relay.py | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/virtualsmartcard/src/vpicc/vicc.in b/virtualsmartcard/src/vpicc/vicc.in index 09de9ff8..6acf3210 100644 --- a/virtualsmartcard/src/vpicc/vicc.in +++ b/virtualsmartcard/src/vpicc/vicc.in @@ -58,6 +58,7 @@ parser.add_argument("-P", "--port", parser.add_argument("-R", "--reversed", action="store_true", help="use reversed connection mode. vicc will wait for an incoming connection from vpcd. (default: %(default)s)") +parser.add_argument('--log-unparsed', action="store_true", help="Log unparsed command APDUs, rather than trying to parse them") parser.add_argument('--version', action='version', version='%(prog)s @PACKAGE_VERSION@') relay = parser.add_argument_group('Relaying a local smart card (`--type=relay`)') @@ -156,7 +157,7 @@ vicc = VirtualICC(args.datasetfile, args.type, hostname, args.port, readernum=args.reader, ef_cardaccess=ef_cardaccess_data, ef_cardsecurity=ef_cardsecurity_data, ca_key=ca_key_data, cvca=cvca, disable_checks=args.disable_ta_checks, esign_ca_cert=esign_ca_cert, - esign_cert=esign_cert, logginglevel=logginglevel) + esign_cert=esign_cert, logginglevel=logginglevel, logunparsed=args.log_unparsed) try: vicc.run() except KeyboardInterrupt: diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/VirtualSmartcard.py b/virtualsmartcard/src/vpicc/virtualsmartcard/VirtualSmartcard.py index 23aabb62..26fe26f6 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/VirtualSmartcard.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/VirtualSmartcard.py @@ -56,6 +56,11 @@ def execute(self, msg): """ return "" + def logAPDU(self, parsed, unparsed): + if(self.logunparsed): + logging.info("Unparsed APDU:\n%s", hexdump(unparsed)); + else: + logging.info("Parsed APDU:\n%s", str(parsed)) class Iso7816OS(SmartcardOS): @@ -286,7 +291,7 @@ def notImplemented(*argz, **args): return self.formatResult(False, 0, "", SW["ERR_INCORRECTPARAMETERS"], False) - logging.info("Parsed APDU:\n%s", str(c)) + self.logAPDU(parsed=c, unparsed=msg) # Handle Class Byte # {{{ @@ -391,7 +396,7 @@ def __init__(self, datasetfile, card_type, host, port, readernum=None, ef_cardsecurity=None, ef_cardaccess=None, ca_key=None, cvca=None, disable_checks=False, esign_key=None, esign_ca_cert=None, esign_cert=None, - logginglevel=logging.INFO): + logginglevel=logging.INFO, logunparsed=False): from os.path import exists logging.basicConfig(level=logginglevel, @@ -437,6 +442,7 @@ def __init__(self, datasetfile, card_type, host, port, card_type = "iso7816" self.os = Iso7816OS(MF, SAM) self.type = card_type + self.os.logunparsed = logunparsed # Connect to the VPCD self.host = host diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/Relay.py b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/Relay.py index 843a1f48..4ef33d0d 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/Relay.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/Relay.py @@ -115,7 +115,7 @@ def reset(self): def execute(self, msg): try: c = C_APDU(msg) - logging.info("Parsed APDU:\n%s", str(c)) + self.logAPDU(parsed=c, unparsed=msg) except ValueError as e: # ignore the parse failure, just don't log the parsed APDU logging.warning("Could not parse APDU:%s", str(e)) From efb57b0ac3be7e5baf04e63cf103b5a89cff2d0b Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Thu, 15 Jun 2017 11:21:55 +0200 Subject: [PATCH 11/19] Only respond to the commands that this card actually implements Also, implement a stub version of the "GET CARD DATA" and "LOG OFF" commands that are proprietary to the Belpic applet. --- .../vpicc/virtualsmartcard/cards/belpic.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py index 384d589d..a0e7a872 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py @@ -19,14 +19,33 @@ from virtualsmartcard.VirtualSmartcard import Iso7816OS from virtualsmartcard.ConstantDefinitions import MAX_SHORT_LE, FDB, LCB from virtualsmartcard.SmartcardFilesystem import MF, DF, TransparentStructureEF +from virtualsmartcard.SWutils import SW, SwError import xml.etree.ElementTree as ET class BelpicOS(Iso7816OS): def __init__(self, mf, sam, ins2handler=None, maxle=MAX_SHORT_LE): Iso7816OS.__init__(self, mf, sam, ins2handler, maxle) + self.ins2handler = { + 0xc0: self.getResponse, + 0xa4: self.mf.selectFile, + 0xb0: self.mf.readBinaryPlain, + 0x20: self.SAM.verify, + 0x24: self.SAM.change_reference_data, + 0x22: self.SAM.manage_security_environment, + 0x2a: self.SAM.perform_security_operation, + 0xe4: self.getCardData, + 0xe6: self.logOff + } self.atr = '\x3B\x98\x13\x40\x0A\xA5\x03\x01\x01\x01\xAD\x13\x11' + def getCardData(self, p1, p2, data): + return SW["NORMAL"], "534C494E0123456789ABCDEF01234567F3360125011700030021010f".decode("hex") + + # TODO: actually log off + def logOff(self, p1, p2, data): + return SW["NORMAL"] + class BelpicMF(MF): def __init__(self, datafile, filedescriptor=FDB["NOTSHAREABLEFILE" ] | FDB["DF"], lifecycle=LCB["ACTIVATED"],simpletlv_data = None, bertlv_data = None): From ddc0df1bc7080177c545bf761e78ad997ac87319 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Thu, 15 Jun 2017 11:23:03 +0200 Subject: [PATCH 12/19] Make the virtual card act slightly more like an actual belpic card --- .../src/vpicc/virtualsmartcard/cards/belpic.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py index a0e7a872..a5a60514 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py @@ -17,7 +17,7 @@ # virtualsmartcard. If not, see . from virtualsmartcard.VirtualSmartcard import Iso7816OS -from virtualsmartcard.ConstantDefinitions import MAX_SHORT_LE, FDB, LCB +from virtualsmartcard.ConstantDefinitions import MAX_SHORT_LE, FDB, LCB, REF from virtualsmartcard.SmartcardFilesystem import MF, DF, TransparentStructureEF from virtualsmartcard.SWutils import SW, SwError @@ -53,7 +53,7 @@ def __init__(self, datafile, filedescriptor=FDB["NOTSHAREABLEFILE" ] | FDB["DF"] tree = ET.parse(datafile) root = tree.getroot() ns = {'f': 'urn:be:fedict:eid:dev:virtualcard:1.0'} - DF00 = DF(self, 0xDF00) + DF00 = DF(self, 0xDF00, dfname="A000000177504B43532D3135".decode('hex')) self.append(DF00) DF01 = DF(self, 0xDF01) self.append(DF01) @@ -73,6 +73,14 @@ def __init__(self, datafile, filedescriptor=FDB["NOTSHAREABLEFILE" ] | FDB["DF"] fid = int(id[4:], 16) parent.append(TransparentStructureEF(parent, fid, data = content.decode('hex'))) + def select(self, attribute, value, reference=REF["IDENTIFIER_FIRST"], index_current=0): + if (hasattr(self, attribute) and + ((getattr(self, attribute) == value) or + (attribute == 'dfname' and + getattr(self, attribute).startswith(value)))): + return self + return DF.select(self, attribute, value, reference, index_current) + @staticmethod def create(p1, p2, data): raise SwError(SW["ERR_INSNOTSUPPORTED"]) From a53b1728d9630202e8092965efe8e8cf2123f2d5 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Thu, 15 Jun 2017 11:23:55 +0200 Subject: [PATCH 13/19] Drop unneeded function Now that we have a correct ins2handler dict, drop the unneeded create method --- virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py index a5a60514..39ff9896 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py @@ -80,7 +80,3 @@ def select(self, attribute, value, reference=REF["IDENTIFIER_FIRST"], index_curr getattr(self, attribute).startswith(value)))): return self return DF.select(self, attribute, value, reference, index_current) - - @staticmethod - def create(p1, p2, data): - raise SwError(SW["ERR_INSNOTSUPPORTED"]) From fb7ec858c3bbd84e97c04a3cd3bca3311d4f8965 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Thu, 15 Jun 2017 11:28:50 +0200 Subject: [PATCH 14/19] Add note of what we're doing here --- virtualsmartcard/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/virtualsmartcard/README.md b/virtualsmartcard/README.md index 006c2e24..1874aac0 100644 --- a/virtualsmartcard/README.md +++ b/virtualsmartcard/README.md @@ -8,6 +8,7 @@ Currently the Virtual Smart Card supports the following types of smart cards: (PACE, TA, CA) - Electronic passport (ePass/MRTD) with support for BAC - Cryptoflex smart card (incomplete) +- Belgian electronic ID card (WIP, this fork) The vpcd is a smart card reader driver for [PCSC-Lite](http://pcsclite.alioth.debian.org/) and the windows smart card service. It allows smart card applications to access the vpicc through From 5fc6018aa7ae9705793679bd35f1109eb143f721 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Thu, 15 Jun 2017 12:28:51 +0200 Subject: [PATCH 15/19] Filter the SELECT FILE command The spec for the Belgian electronic ID card interprets the ISO 7816 "SELECT FILE" command in a somewhat simplified way. First, the MF (3F00) can be selected from anywhere when P1 = 0x02; second, child DFs are selected also with P1 = 0x02. The applet does not interpret or treat specially cases where P1 = 0x00 or P1 = 0x01. In order to not to have to rewrite the "select file" logic that already exists in the Iso7816OS class, filter those two commands so that they contain the P1 value which the Iso7816OS class would search for. --- .../vpicc/virtualsmartcard/cards/belpic.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py index 39ff9896..87bb7c58 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py @@ -20,6 +20,9 @@ from virtualsmartcard.ConstantDefinitions import MAX_SHORT_LE, FDB, LCB, REF from virtualsmartcard.SmartcardFilesystem import MF, DF, TransparentStructureEF from virtualsmartcard.SWutils import SW, SwError +from virtualsmartcard.utils import C_APDU + +import logging import xml.etree.ElementTree as ET @@ -46,6 +49,25 @@ def getCardData(self, p1, p2, data): def logOff(self, p1, p2, data): return SW["NORMAL"] + def execute(self, msg): + c = C_APDU(msg) + if (c.ins == 0xa4 and c.p1 == 0x02): + # The belpic applet is a bit loose with interpretation of + # the ISO 7816 standard on the A4 command: + # - The MF can be selected by name from anywhere with P1 == + # 0x02, rather than 0x00 as ISO 7816 requires + if (c.data == '3F00'.decode('hex')): + logging.info("Original APDU:\n%s\nRewritten to:\n", str(c)) + c.p1 = 0 + msg = c.render() + # - Child DFs can be selected with P1 == 0x02, rather than + # 0x01 as ISO 7816 requires + if (c.data == 'DF00'.decode('hex') or c.data == 'DF01'.decode('hex')): + logging.info("Original APDU:\n%s\nRewritten to:\n", str(c)) + c.p1 = 1 + msg = c.render() + return Iso7816OS.execute(self, msg) + class BelpicMF(MF): def __init__(self, datafile, filedescriptor=FDB["NOTSHAREABLEFILE" ] | FDB["DF"], lifecycle=LCB["ACTIVATED"],simpletlv_data = None, bertlv_data = None): From 5eb000d303999dc352d9dbc495bdc24d56ddefca Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Thu, 15 Jun 2017 13:43:43 +0200 Subject: [PATCH 16/19] Filter out warnings The belpic applet does not deal with file sizes. It just returns less data than was requested, and the remote is supposed to figure out that the file was smaller than it assumed before based on that. It still returns SW12 0x9000 in that case, however. Add a "formatResult" method which filters out the SW12 = 0x6282 case, so that applications don't see values they don't expect. --- .../src/vpicc/virtualsmartcard/cards/belpic.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py index 87bb7c58..38738023 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py @@ -20,7 +20,7 @@ from virtualsmartcard.ConstantDefinitions import MAX_SHORT_LE, FDB, LCB, REF from virtualsmartcard.SmartcardFilesystem import MF, DF, TransparentStructureEF from virtualsmartcard.SWutils import SW, SwError -from virtualsmartcard.utils import C_APDU +from virtualsmartcard.utils import C_APDU, R_APDU import logging @@ -68,6 +68,17 @@ def execute(self, msg): msg = c.render() return Iso7816OS.execute(self, msg) + def formatResult(self, seekable, le, data, sw, sm): + r = R_APDU(Iso7816OS.formatResult(self, seekable, le, data, sw, sm)) + # The Belpic applet provides a bogus file length of 65536 for + # every file, and does not return an error or warning when the + # actual file length is shorter that the file as found; so + # filter out the EOFBEFORENEREAD warning + if (r.sw1 == 0x62 and r.sw2 == 0x82): + logging.info("Filtering out warning") + r.sw = "9000".decode("hex") + return r.render() + class BelpicMF(MF): def __init__(self, datafile, filedescriptor=FDB["NOTSHAREABLEFILE" ] | FDB["DF"], lifecycle=LCB["ACTIVATED"],simpletlv_data = None, bertlv_data = None): From 03a1136c50595b18caf95561e247bc45876e70fd Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Thu, 15 Jun 2017 13:46:20 +0200 Subject: [PATCH 17/19] Add one more TODO item --- virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py index 38738023..3d2fa59c 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/belpic.py @@ -42,6 +42,7 @@ def __init__(self, mf, sam, ins2handler=None, maxle=MAX_SHORT_LE): } self.atr = '\x3B\x98\x13\x40\x0A\xA5\x03\x01\x01\x01\xAD\x13\x11' + # TODO: don't hardcode the value below, so that we can also emulate the v1.1 applet def getCardData(self, p1, p2, data): return SW["NORMAL"], "534C494E0123456789ABCDEF01234567F3360125011700030021010f".decode("hex") From 75f5b496a1d5472b68ffaf721a85711fcdc41763 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Tue, 20 Jun 2017 15:43:19 +0200 Subject: [PATCH 18/19] Make sure these files actually have some content Otherwise the file is unavailable and the eid-mw PKCS#11 module complains that the card is broken. --- virtualsmartcard/belpic-example-data/belpic.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/virtualsmartcard/belpic-example-data/belpic.xml b/virtualsmartcard/belpic-example-data/belpic.xml index 2883416d..d621530d 100644 --- a/virtualsmartcard/belpic-example-data/belpic.xml +++ b/virtualsmartcard/belpic-example-data/belpic.xml @@ -57,7 +57,7 @@ 3F00DF014032 - +AF 3F00DF014033 @@ -65,7 +65,7 @@ 3F00DF014034 - +AF 3F00DF014035 From e65e13a6b3d288ee12f225a12600b31e820bacc0 Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Tue, 20 Jun 2017 16:09:00 +0200 Subject: [PATCH 19/19] Drop bogus TODO item (the MF works, the SAM doesn't yet) --- virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py b/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py index b9941717..037b8d61 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/CardGenerator.py @@ -666,8 +666,6 @@ def __generate_cryptoflex(self): self.sam = CryptoflexSAM(self.mf) def __generate_belpic(self): - # TODO: make BelpicMF actually work. Right now, an application which - # tries to use it will fail. from virtualsmartcard.cards.belpic import BelpicMF self.__generate_iso_card() self.mf = BelpicMF('belpic.xml')