You've already forked vsmartcard
mirror of
https://github.com/librekeys/vsmartcard.git
synced 2026-04-14 08:46:17 -07:00
542 lines
62 KiB
HTML
542 lines
62 KiB
HTML
<!DOCTYPE html>
|
||
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>Creating a Virtual Smart Card — vsmartcard 2021-04-28 documentation</title>
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||
<link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
|
||
<link rel="stylesheet" type="text/css" href="../_static/graphviz.css" />
|
||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||
<script src="../_static/jquery.js"></script>
|
||
<script src="../_static/underscore.js"></script>
|
||
<script src="../_static/doctools.js"></script>
|
||
<script src="../_static/js/jquery-1.11.0.min.js"></script>
|
||
<script src="../_static/js/jquery-fix.js"></script>
|
||
<script src="../_static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
|
||
<script src="../_static/bootstrap-sphinx.js"></script>
|
||
<link rel="shortcut icon" href="../_static/chip.ico"/>
|
||
<link rel="search" title="Search" href="../search.html" />
|
||
<link rel="prev" title="USB CCID Emulator" href="../ccid/README.html" />
|
||
<meta charset='utf-8'>
|
||
<meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
|
||
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1'>
|
||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||
|
||
</head><body>
|
||
|
||
<a href="https://github.com/frankmorgner/vsmartcard"
|
||
class="visible-desktop hidden-xs"><img
|
||
id="gh-banner"
|
||
style="position: absolute; top: 50px; right: 0; border: 0;"
|
||
src="https://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png"
|
||
alt="Fork me on GitHub"></a>
|
||
<script>
|
||
// Adjust banner height.
|
||
$(function () {
|
||
var navHeight = $(".navbar .container").css("height");
|
||
$("#gh-banner").css("top", navHeight);
|
||
});
|
||
</script>
|
||
|
||
|
||
<div id="navbar" class="navbar navbar-default ">
|
||
<div class="container">
|
||
<div class="navbar-header">
|
||
<!-- .btn-navbar is used as the toggle for collapsed navbar content -->
|
||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".nav-collapse">
|
||
<span class="icon-bar"></span>
|
||
<span class="icon-bar"></span>
|
||
<span class="icon-bar"></span>
|
||
</button>
|
||
<a class="navbar-brand" href="../index.html">
|
||
vsmartcard</a>
|
||
<span class="navbar-text navbar-version pull-left"><b></b></span>
|
||
</div>
|
||
|
||
<div class="collapse navbar-collapse nav-collapse">
|
||
<ul class="nav navbar-nav">
|
||
|
||
|
||
<li class="dropdown globaltoc-container">
|
||
<a role="button"
|
||
id="dLabelGlobalToc"
|
||
data-toggle="dropdown"
|
||
data-target="#"
|
||
href="../index.html">Site <b class="caret"></b></a>
|
||
<ul class="dropdown-menu globaltoc"
|
||
role="menu"
|
||
aria-labelledby="dLabelGlobalToc"><ul>
|
||
<li class="toctree-l1"><a class="reference internal" href="README.html">Virtual Smart Card</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="../remote-reader/README.html">Remote Smart Card Reader</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="../ACardEmulator/README.html">Android Smart Card Emulator</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="../TCardEmulator/README.html">Tizen Smart Card Emulator</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="../pcsc-relay/README.html">PC/SC Relay</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="../ccid/README.html">USB CCID Emulator</a></li>
|
||
</ul>
|
||
<ul class="current">
|
||
<li class="toctree-l1 current"><a class="current reference internal" href="#">Creating a Virtual Smart Card</a></li>
|
||
</ul>
|
||
</ul>
|
||
</li>
|
||
|
||
<li class="dropdown">
|
||
<a role="button"
|
||
id="dLabelLocalToc"
|
||
data-toggle="dropdown"
|
||
data-target="#"
|
||
href="#">Page <b class="caret"></b></a>
|
||
<ul class="dropdown-menu localtoc"
|
||
role="menu"
|
||
aria-labelledby="dLabelLocalToc"><ul>
|
||
<li><a class="reference internal" href="#">Creating a Virtual Smart Card</a><ul>
|
||
<li><a class="reference internal" href="#examples">Examples</a><ul>
|
||
<li><a class="reference internal" href="#implementing-a-iso-7816-like-smart-card">Implementing a ISO 7816 like Smart Card</a></li>
|
||
<li><a class="reference internal" href="#implementing-an-other-type-of-card">Implementing an Other Type of Card</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</ul>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
<li>
|
||
<a href="../ccid/README.html" title="Previous Chapter: USB CCID Emulator"><span class="glyphicon glyphicon-chevron-left visible-sm"></span><span class="hidden-sm hidden-tablet">« USB CCID Emulator</span>
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
<li class="hidden-sm"></li>
|
||
|
||
</ul>
|
||
|
||
|
||
|
||
<form class="navbar-form navbar-right" action="../search.html" method="get">
|
||
<div class="form-group">
|
||
<input type="text" name="q" class="form-control" placeholder="Search" />
|
||
</div>
|
||
<input type="hidden" name="check_keywords" value="yes" />
|
||
<input type="hidden" name="area" value="default" />
|
||
</form>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="container">
|
||
<div class="row">
|
||
<div class="col-md-12 content">
|
||
|
||
<div class="section" id="creating-a-virtual-smart-card">
|
||
<span id="virtualsmartcard-api"></span><h1>Creating a Virtual Smart Card<a class="headerlink" href="#creating-a-virtual-smart-card" title="Permalink to this headline">¶</a></h1>
|
||
<p><abbr title="virtual smart card reader">vpcd</abbr> communicates over a socked with <abbr title="virtual smart card">vpicc</abbr> usually on port <code class="docutils literal notranslate"><span class="pre">0x8C7B</span></code>
|
||
(configurably via <code class="file docutils literal notranslate"><span class="pre">/etc/reader.conf.d/vpcd</span></code>). So you can connect
|
||
virtually any program to the virtual smart card reader, as long as you respect
|
||
the following protocol:</p>
|
||
<table class="docutils align-default" id="vpcd-commands">
|
||
<colgroup>
|
||
<col style="width: 22%" />
|
||
<col style="width: 34%" />
|
||
<col style="width: 22%" />
|
||
<col style="width: 22%" />
|
||
</colgroup>
|
||
<thead>
|
||
<tr class="row-odd"><th class="head" colspan="2"><p><abbr title="virtual smart card reader">vpcd</abbr></p></th>
|
||
<th class="head" colspan="2"><p><abbr title="virtual smart card">vpicc</abbr></p></th>
|
||
</tr>
|
||
<tr class="row-even"><th class="head"><p>Length</p></th>
|
||
<th class="head"><p>Command</p></th>
|
||
<th class="head"><p>Length</p></th>
|
||
<th class="head"><p>Response</p></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">0x00</span> <span class="pre">0x01</span></code></p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">0x00</span></code> (Power Off)</p></td>
|
||
<td></td>
|
||
<td><p>(No Response)</p></td>
|
||
</tr>
|
||
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">0x00</span> <span class="pre">0x01</span></code></p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">0x01</span></code> (Power On)</p></td>
|
||
<td></td>
|
||
<td><p>(No Response)</p></td>
|
||
</tr>
|
||
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">0x00</span> <span class="pre">0x01</span></code></p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">0x02</span></code> (Reset)</p></td>
|
||
<td></td>
|
||
<td><p>(No Response)</p></td>
|
||
</tr>
|
||
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">0x00</span> <span class="pre">0x01</span></code></p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">0x04</span></code> (Get ATR)</p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">0xXX</span> <span class="pre">0xXX</span></code></p></td>
|
||
<td><p>(ATR)</p></td>
|
||
</tr>
|
||
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">0xXX</span> <span class="pre">0xXX</span></code></p></td>
|
||
<td><p>(APDU)</p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">0xXX</span> <span class="pre">0xXX</span></code></p></td>
|
||
<td><p>(R-APDU)</p></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>The communication is initiated by <abbr title="virtual smart card reader">vpcd</abbr>. First the length of the data (in
|
||
network byte order, i.e. big endian) is sent followed by the data itself.</p>
|
||
<div class="section" id="examples">
|
||
<h2>Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h2>
|
||
<div class="section" id="implementing-a-iso-7816-like-smart-card">
|
||
<h3>Implementing a ISO 7816 like Smart Card<a class="headerlink" href="#implementing-a-iso-7816-like-smart-card" title="Permalink to this headline">¶</a></h3>
|
||
<p><abbr title="virtual smart card">vpicc</abbr> includes an emulation of a card acting according to ISO 7816. This
|
||
includes all standard commands for file management and secure messaging.</p>
|
||
<p>Let’s assume we want to create a cryptoflex card, that acts mostly according to
|
||
ISO 7816. In this example we only want to add little things that differ from
|
||
ISO 7816. But as for most complex software you need to know where you need to
|
||
hook into. Here we only want to give an overview to the design.</p>
|
||
<p>Back to the cryptoflex example.
|
||
<a class="reference internal" href="api/virtualsmartcard.VirtualSmartcard.html#virtualsmartcard.VirtualSmartcard.VirtualICC" title="virtualsmartcard.VirtualSmartcard.VirtualICC"><code class="xref py py-class docutils literal notranslate"><span class="pre">VirtualICC</span></code></a> provides the connection
|
||
to the virtual smart card reader. It fetches an <abbr title="Application Protocol Data Unit">APDU</abbr> and other requests from
|
||
the <abbr title="virtual smart card reader">vpcd</abbr>. In <a class="reference internal" href="api/virtualsmartcard.VirtualSmartcard.html#virtualsmartcard.VirtualSmartcard.VirtualICC" title="virtualsmartcard.VirtualSmartcard.VirtualICC"><code class="xref py py-class docutils literal notranslate"><span class="pre">VirtualICC</span></code></a> an <abbr title="Application Protocol Data Unit">APDU</abbr>
|
||
is only a buffer that is forwarded to the smart card OS. First we modify
|
||
<a class="reference internal" href="api/virtualsmartcard.VirtualSmartcard.html#virtualsmartcard.VirtualSmartcard.VirtualICC" title="virtualsmartcard.VirtualSmartcard.VirtualICC"><code class="xref py py-class docutils literal notranslate"><span class="pre">VirtualICC</span></code></a> to recognize a new type
|
||
<code class="docutils literal notranslate"><span class="pre">"cryptoflex"</span></code> and to load
|
||
<a class="reference internal" href="api/virtualsmartcard.cards.cryptoflex.html#virtualsmartcard.cards.cryptoflex.CryptoflexOS" title="virtualsmartcard.cards.cryptoflex.CryptoflexOS"><code class="xref py py-class docutils literal notranslate"><span class="pre">CryptoflexOS</span></code></a>. The
|
||
<a class="reference internal" href="api/virtualsmartcard.CardGenerator.html#module-virtualsmartcard.CardGenerator" title="virtualsmartcard.CardGenerator"><code class="xref py py-class docutils literal notranslate"><span class="pre">CardGenerator</span></code></a> is used to create a file system and a
|
||
<abbr title="Secure Access Module">SAM</abbr> specific to the cryptoflex (we come back to this later).</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">datasetfile</span><span class="p">,</span> <span class="n">card_type</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span>
|
||
<span class="n">readernum</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">mitmPath</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">ef_cardsecurity</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">ef_cardaccess</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||
<span class="n">ca_key</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">cvca</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">disable_checks</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">esign_key</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||
<span class="n">esign_ca_cert</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">esign_cert</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||
<span class="n">logginglevel</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">INFO</span><span class="p">):</span>
|
||
<span class="kn">from</span> <span class="nn">os.path</span> <span class="k">import</span> <span class="n">exists</span>
|
||
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">level</span><span class="o">=</span><span class="n">logginglevel</span><span class="p">,</span>
|
||
<span class="nb">format</span><span class="o">=</span><span class="s2">"</span><span class="si">%(asctime)s</span><span class="s2"> [</span><span class="si">%(levelname)s</span><span class="s2">] </span><span class="si">%(message)s</span><span class="s2">"</span><span class="p">,</span>
|
||
<span class="n">datefmt</span><span class="o">=</span><span class="s2">"</span><span class="si">%d</span><span class="s2">.%m.%Y %H:%M:%S"</span><span class="p">)</span>
|
||
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">cardGenerator</span> <span class="o">=</span> <span class="n">CardGenerator</span><span class="p">(</span><span class="n">card_type</span><span class="p">)</span>
|
||
|
||
<span class="c1"># If a dataset file is specified, read the card's data groups from disk</span>
|
||
<span class="k">if</span> <span class="n">datasetfile</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">exists</span><span class="p">(</span><span class="n">datasetfile</span><span class="p">):</span>
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">"Reading Data Groups from file </span><span class="si">%s</span><span class="s2">."</span><span class="p">,</span>
|
||
<span class="n">datasetfile</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">cardGenerator</span><span class="o">.</span><span class="n">readDatagroups</span><span class="p">(</span><span class="n">datasetfile</span><span class="p">)</span>
|
||
|
||
<span class="n">MF</span><span class="p">,</span> <span class="n">SAM</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cardGenerator</span><span class="o">.</span><span class="n">getCard</span><span class="p">()</span>
|
||
|
||
<span class="c1"># Generate an OS object of the correct card_type</span>
|
||
<span class="k">if</span> <span class="n">card_type</span> <span class="o">==</span> <span class="s2">"iso7816"</span> <span class="ow">or</span> <span class="n">card_type</span> <span class="o">==</span> <span class="s2">"ePass"</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">os</span> <span class="o">=</span> <span class="n">Iso7816OS</span><span class="p">(</span><span class="n">MF</span><span class="p">,</span> <span class="n">SAM</span><span class="p">)</span>
|
||
<span class="k">elif</span> <span class="n">card_type</span> <span class="o">==</span> <span class="s2">"nPA"</span><span class="p">:</span>
|
||
<span class="kn">from</span> <span class="nn">virtualsmartcard.cards.nPA</span> <span class="k">import</span> <span class="n">NPAOS</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">os</span> <span class="o">=</span> <span class="n">NPAOS</span><span class="p">(</span><span class="n">MF</span><span class="p">,</span> <span class="n">SAM</span><span class="p">,</span> <span class="n">ef_cardsecurity</span><span class="o">=</span><span class="n">ef_cardsecurity</span><span class="p">,</span>
|
||
<span class="n">ef_cardaccess</span><span class="o">=</span><span class="n">ef_cardaccess</span><span class="p">,</span> <span class="n">ca_key</span><span class="o">=</span><span class="n">ca_key</span><span class="p">,</span>
|
||
<span class="n">cvca</span><span class="o">=</span><span class="n">cvca</span><span class="p">,</span> <span class="n">disable_checks</span><span class="o">=</span><span class="n">disable_checks</span><span class="p">,</span>
|
||
<span class="n">esign_key</span><span class="o">=</span><span class="n">esign_key</span><span class="p">,</span> <span class="n">esign_ca_cert</span><span class="o">=</span><span class="n">esign_ca_cert</span><span class="p">,</span>
|
||
<span class="n">esign_cert</span><span class="o">=</span><span class="n">esign_cert</span><span class="p">)</span>
|
||
<span class="k">elif</span> <span class="n">card_type</span> <span class="o">==</span> <span class="s2">"cryptoflex"</span><span class="p">:</span>
|
||
<span class="kn">from</span> <span class="nn">virtualsmartcard.cards.cryptoflex</span> <span class="k">import</span> <span class="n">CryptoflexOS</span>
|
||
<span class="hll"> <span class="bp">self</span><span class="o">.</span><span class="n">os</span> <span class="o">=</span> <span class="n">CryptoflexOS</span><span class="p">(</span><span class="n">MF</span><span class="p">,</span> <span class="n">SAM</span><span class="p">)</span>
|
||
</span><span class="hll"> <span class="k">elif</span> <span class="n">card_type</span> <span class="o">==</span> <span class="s2">"relay"</span><span class="p">:</span>
|
||
</span><span class="hll"> <span class="kn">from</span> <span class="nn">virtualsmartcard.cards.Relay</span> <span class="k">import</span> <span class="n">RelayOS</span>
|
||
</span> <span class="kn">from</span> <span class="nn">virtualsmartcard.cards.RelayMiddleman</span> <span class="k">import</span> <span class="n">RelayMiddleman</span>
|
||
<span class="n">mitm</span> <span class="o">=</span> <span class="n">loadMitMFromPath</span><span class="p">(</span><span class="n">mitmPath</span><span class="p">)</span> <span class="k">if</span> <span class="n">mitmPath</span> <span class="k">else</span> <span class="n">RelayMiddleman</span><span class="p">()</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">os</span> <span class="o">=</span> <span class="n">RelayOS</span><span class="p">(</span><span class="n">readernum</span><span class="p">,</span><span class="n">mitm</span><span class="o">=</span><span class="n">mitm</span><span class="p">)</span>
|
||
<span class="k">elif</span> <span class="n">card_type</span> <span class="o">==</span> <span class="s2">"handler_test"</span><span class="p">:</span>
|
||
<span class="kn">from</span> <span class="nn">virtualsmartcard.cards.HandlerTest</span> <span class="k">import</span> <span class="n">HandlerTestOS</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">os</span> <span class="o">=</span> <span class="n">HandlerTestOS</span><span class="p">()</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s2">"Unknown cardtype </span><span class="si">%s</span><span class="s2">. Will use standard card_type </span><span class="se">\</span>
|
||
<span class="s2"> (ISO 7816)"</span><span class="p">,</span> <span class="n">card_type</span><span class="p">)</span>
|
||
<span class="n">card_type</span> <span class="o">=</span> <span class="s2">"iso7816"</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">os</span> <span class="o">=</span> <span class="n">Iso7816OS</span><span class="p">(</span><span class="n">MF</span><span class="p">,</span> <span class="n">SAM</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">card_type</span>
|
||
|
||
<span class="c1"># Connect to the VPCD</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">host</span> <span class="o">=</span> <span class="n">host</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">port</span> <span class="o">=</span> <span class="n">port</span>
|
||
<span class="k">if</span> <span class="n">host</span><span class="p">:</span>
|
||
<span class="c1"># use normal connection mode</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">sock</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">connectToPort</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">sock</span><span class="o">.</span><span class="n">settimeout</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">server_sock</span> <span class="o">=</span> <span class="kc">None</span>
|
||
<span class="k">except</span> <span class="n">socket</span><span class="o">.</span><span class="n">error</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">"Failed to open socket: </span><span class="si">%s</span><span class="s2">"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">"Is pcscd running at </span><span class="si">%s</span><span class="s2">? Is vpcd loaded? Is a </span><span class="se">\</span>
|
||
<span class="s2"> firewall blocking port </span><span class="si">%u</span><span class="s2">?"</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="c1"># use reversed connection mode</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">local_ip</span> <span class="o">=</span> <span class="p">[(</span><span class="n">s</span><span class="o">.</span><span class="n">connect</span><span class="p">((</span><span class="s1">'8.8.8.8'</span><span class="p">,</span> <span class="mi">53</span><span class="p">)),</span> <span class="n">s</span><span class="o">.</span><span class="n">getsockname</span><span class="p">()[</span><span class="mi">0</span><span class="p">],</span> <span class="n">s</span><span class="o">.</span><span class="n">close</span><span class="p">())</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="p">[</span><span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_DGRAM</span><span class="p">)]][</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>
|
||
<span class="n">custom_url</span> <span class="o">=</span> <span class="s1">'vicc://</span><span class="si">%s</span><span class="s1">:</span><span class="si">%d</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">local_ip</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'VICC hostname: </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">local_ip</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'VICC port: </span><span class="si">%d</span><span class="s1">'</span> <span class="o">%</span> <span class="n">port</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'On your NFC phone with the Android Smart Card Emulator app scan this code:'</span><span class="p">)</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="kn">import</span> <span class="nn">qrcode</span>
|
||
<span class="n">qr</span> <span class="o">=</span> <span class="n">qrcode</span><span class="o">.</span><span class="n">QRCode</span><span class="p">()</span>
|
||
<span class="n">qr</span><span class="o">.</span><span class="n">add_data</span><span class="p">(</span><span class="n">custom_url</span><span class="p">)</span>
|
||
<span class="n">qr</span><span class="o">.</span><span class="n">print_ascii</span><span class="p">()</span>
|
||
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'https://api.qrserver.com/v1/create-qr-code/?data=</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">custom_url</span><span class="p">)</span>
|
||
<span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sock</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">server_sock</span><span class="p">,</span> <span class="n">host</span><span class="p">)</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">openPort</span><span class="p">(</span><span class="n">port</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">sock</span><span class="o">.</span><span class="n">settimeout</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="k">except</span> <span class="n">socket</span><span class="o">.</span><span class="n">error</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">"Failed to open socket: </span><span class="si">%s</span><span class="s2">"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">"Is pcscd running? Is vpcd loaded and in </span><span class="se">\</span>
|
||
<span class="s2"> reversed connection mode? Is a firewall </span><span class="se">\</span>
|
||
<span class="s2"> blocking port </span><span class="si">%u</span><span class="s2">?"</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
|
||
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">"Connected to virtual PCD at </span><span class="si">%s</span><span class="s2">:</span><span class="si">%u</span><span class="s2">"</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span>
|
||
|
||
<span class="n">atexit</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stop</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Responses from our cryptoflex card look the same as for the 7816 card. But when
|
||
a command was successfull (or not) there is a little difference in what is
|
||
returned. So we need to edit
|
||
<a class="reference internal" href="api/virtualsmartcard.cards.cryptoflex.html#virtualsmartcard.cards.cryptoflex.CryptoflexOS.formatResult" title="virtualsmartcard.cards.cryptoflex.CryptoflexOS.formatResult"><code class="xref py py-class docutils literal notranslate"><span class="pre">formatResult</span></code></a>, which is
|
||
called to encode the <abbr title="status bytes SW 1 and SW 2">SWs</abbr> and the resulting data.</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="k">def</span> <span class="nf">formatResult</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ins</span><span class="p">,</span> <span class="n">le</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">sw</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="n">le</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
|
||
<span class="c1"># cryptoflex does not inpterpret le==0 as maxle</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">lastCommandSW</span> <span class="o">=</span> <span class="n">sw</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">lastCommandOffcut</span> <span class="o">=</span> <span class="n">data</span>
|
||
<span class="n">r</span> <span class="o">=</span> <span class="n">R_APDU</span><span class="p">(</span><span class="n">inttostring</span><span class="p">(</span><span class="n">SW</span><span class="p">[</span><span class="s2">"ERR_WRONGLENGTH"</span><span class="p">]</span> <span class="o">+</span>
|
||
<span class="nb">min</span><span class="p">(</span><span class="mh">0xff</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">))))</span><span class="o">.</span><span class="n">render</span><span class="p">()</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">ins</span> <span class="o">==</span> <span class="mh">0xa4</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
|
||
<span class="c1"># get response should be followed by select file</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">lastCommandSW</span> <span class="o">=</span> <span class="n">sw</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">lastCommandOffcut</span> <span class="o">=</span> <span class="n">data</span>
|
||
<span class="n">r</span> <span class="o">=</span> <span class="n">R_APDU</span><span class="p">(</span><span class="n">inttostring</span><span class="p">(</span><span class="n">SW</span><span class="p">[</span><span class="s2">"NORMAL_REST"</span><span class="p">]</span> <span class="o">+</span>
|
||
<span class="nb">min</span><span class="p">(</span><span class="mh">0xff</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">))))</span><span class="o">.</span><span class="n">render</span><span class="p">()</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">r</span> <span class="o">=</span> <span class="n">Iso7816OS</span><span class="o">.</span><span class="n">formatResult</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">Iso7816OS</span><span class="o">.</span><span class="n">seekable</span><span class="p">(</span><span class="n">ins</span><span class="p">),</span> <span class="n">le</span><span class="p">,</span>
|
||
<span class="n">data</span><span class="p">,</span> <span class="n">sw</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span>
|
||
|
||
<span class="k">return</span> <span class="n">r</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note that this also requires some insight knowledge about how
|
||
<a class="reference internal" href="api/virtualsmartcard.VirtualSmartcard.html#virtualsmartcard.VirtualSmartcard.Iso7816OS" title="virtualsmartcard.VirtualSmartcard.Iso7816OS"><code class="xref py py-class docutils literal notranslate"><span class="pre">Iso7816OS</span></code></a> works.</p>
|
||
<p>The previously created <abbr title="Secure Access Module">SAM</abbr> handles keys, encryption, secure messaging and so
|
||
on (we will not go into more details here). The file system creates, selects
|
||
and reads contents of files or directories. File handling for our cryptoflex
|
||
card is similar to ISO 7816, but the meaning of P1, P2 and the <abbr title="Application Protocol Data Unit">APDU</abbr> data is
|
||
completely different when creating a file on the smart card. So we derive
|
||
<a class="reference internal" href="api/virtualsmartcard.cards.cryptoflex.html#virtualsmartcard.cards.cryptoflex.CryptoflexMF" title="virtualsmartcard.cards.cryptoflex.CryptoflexMF"><code class="xref py py-class docutils literal notranslate"><span class="pre">CryptoflexMF</span></code></a> from
|
||
<a class="reference internal" href="api/virtualsmartcard.SmartcardFilesystem.html#virtualsmartcard.SmartcardFilesystem.MF" title="virtualsmartcard.SmartcardFilesystem.MF"><code class="xref py py-class docutils literal notranslate"><span class="pre">MF</span></code></a> and modify
|
||
<a class="reference internal" href="api/virtualsmartcard.cards.cryptoflex.html#virtualsmartcard.cards.cryptoflex.CryptoflexMF.create" title="virtualsmartcard.cards.cryptoflex.CryptoflexMF.create"><code class="xref py py-class docutils literal notranslate"><span class="pre">create</span></code></a> to our needs.</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="k">def</span> <span class="nf">create</span><span class="p">(</span><span class="n">p1</span><span class="p">,</span> <span class="n">p2</span><span class="p">,</span> <span class="n">data</span><span class="p">):</span>
|
||
|
||
<span class="k">if</span> <span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">2</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"</span><span class="se">\xff\xff</span><span class="s2">"</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="n">SwError</span><span class="p">(</span><span class="n">SW</span><span class="p">[</span><span class="s2">"ERR_INCORRECTPARAMETERS"</span><span class="p">])</span>
|
||
|
||
<span class="n">args</span> <span class="o">=</span> <span class="p">{</span>
|
||
<span class="s2">"parent"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
|
||
<span class="s2">"filedescriptor"</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
|
||
<span class="s2">"fid"</span><span class="p">:</span> <span class="n">stringtoint</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="mi">4</span><span class="p">:</span><span class="mi">6</span><span class="p">]),</span>
|
||
<span class="p">}</span>
|
||
<span class="k">if</span> <span class="n">data</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"</span><span class="se">\x01</span><span class="s2">"</span><span class="p">:</span>
|
||
<span class="n">args</span><span class="p">[</span><span class="s2">"data"</span><span class="p">]</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">*</span><span class="n">stringtoint</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="mi">2</span><span class="p">:</span><span class="mi">4</span><span class="p">])</span>
|
||
<span class="n">args</span><span class="p">[</span><span class="s2">"filedescriptor"</span><span class="p">]</span> <span class="o">=</span> <span class="n">FDB</span><span class="p">[</span><span class="s2">"EFSTRUCTURE_TRANSPARENT"</span><span class="p">]</span>
|
||
<span class="n">new_file</span> <span class="o">=</span> <span class="n">TransparentStructureEF</span><span class="p">(</span><span class="o">**</span><span class="n">args</span><span class="p">)</span>
|
||
<span class="k">elif</span> <span class="n">data</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"</span><span class="se">\x02</span><span class="s2">"</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="o">></span> <span class="mi">16</span><span class="p">:</span>
|
||
<span class="n">args</span><span class="p">[</span><span class="s2">"maxrecordsize"</span><span class="p">]</span> <span class="o">=</span> <span class="n">stringtoint</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="mi">16</span><span class="p">])</span>
|
||
<span class="k">elif</span> <span class="n">p2</span><span class="p">:</span>
|
||
<span class="c1"># if given a number of records</span>
|
||
<span class="n">args</span><span class="p">[</span><span class="s2">"maxrecordsize"</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">stringtoint</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="mi">2</span><span class="p">:</span><span class="mi">4</span><span class="p">])</span> <span class="o">/</span> <span class="n">p2</span><span class="p">)</span>
|
||
<span class="n">args</span><span class="p">[</span><span class="s2">"filedescriptor"</span><span class="p">]</span> <span class="o">=</span> <span class="n">FDB</span><span class="p">[</span><span class="s2">"EFSTRUCTURE_LINEAR_FIXED_"</span>
|
||
<span class="s2">"NOFURTHERINFO"</span><span class="p">]</span>
|
||
<span class="n">new_file</span> <span class="o">=</span> <span class="n">RecordStructureEF</span><span class="p">(</span><span class="o">**</span><span class="n">args</span><span class="p">)</span>
|
||
<span class="k">elif</span> <span class="n">data</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"</span><span class="se">\x03</span><span class="s2">"</span><span class="p">:</span>
|
||
<span class="n">args</span><span class="p">[</span><span class="s2">"filedescriptor"</span><span class="p">]</span> <span class="o">=</span> <span class="n">FDB</span><span class="p">[</span><span class="s2">"EFSTRUCTURE_LINEAR_VARIABLE_"</span>
|
||
<span class="s2">"NOFURTHERINFO"</span><span class="p">]</span>
|
||
<span class="n">new_file</span> <span class="o">=</span> <span class="n">RecordStructureEF</span><span class="p">(</span><span class="o">**</span><span class="n">args</span><span class="p">)</span>
|
||
<span class="k">elif</span> <span class="n">data</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"</span><span class="se">\x04</span><span class="s2">"</span><span class="p">:</span>
|
||
<span class="n">args</span><span class="p">[</span><span class="s2">"filedescriptor"</span><span class="p">]</span> <span class="o">=</span> <span class="n">FDB</span><span class="p">[</span><span class="s2">"EFSTRUCTURE_CYCLIC_NOFURTHERINFO"</span><span class="p">]</span>
|
||
<span class="n">new_file</span> <span class="o">=</span> <span class="n">RecordStructureEF</span><span class="p">(</span><span class="o">**</span><span class="n">args</span><span class="p">)</span>
|
||
<span class="k">elif</span> <span class="n">data</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"</span><span class="se">\x38</span><span class="s2">"</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">data</span><span class="p">[</span><span class="mi">12</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"</span><span class="se">\x03</span><span class="s2">"</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="n">SwError</span><span class="p">(</span><span class="n">SW</span><span class="p">[</span><span class="s2">"ERR_INCORRECTPARAMETERS"</span><span class="p">])</span>
|
||
<span class="n">new_file</span> <span class="o">=</span> <span class="n">DF</span><span class="p">(</span><span class="o">**</span><span class="n">args</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">"unknown type: 0x</span><span class="si">%x</span><span class="s2">"</span> <span class="o">%</span> <span class="nb">ord</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="mi">6</span><span class="p">]))</span>
|
||
<span class="k">raise</span> <span class="n">SwError</span><span class="p">(</span><span class="n">SW</span><span class="p">[</span><span class="s2">"ERR_INCORRECTPARAMETERS"</span><span class="p">])</span>
|
||
|
||
<span class="k">return</span> <span class="p">[</span><span class="n">new_file</span><span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>As you can see it is quite simple to extend the virtual smart card to your
|
||
requirements. Simply overwrite those functions, that differ from ISO 78166. But
|
||
as said before, the virtual smart card is quite complex and you might have to
|
||
read some documentation or even source code to find out where it’s best to do
|
||
your modifications…</p>
|
||
</div>
|
||
<div class="section" id="implementing-an-other-type-of-card">
|
||
<h3>Implementing an Other Type of Card<a class="headerlink" href="#implementing-an-other-type-of-card" title="Permalink to this headline">¶</a></h3>
|
||
<p>If you have a card entirely different to ISO 7816, you surely want to avoid all
|
||
magic that is done while parsing a buffer (an <abbr title="Application Protocol Data Unit">APDU</abbr>). As example we will
|
||
connect to an other smart card using PC/SC and forward it to <abbr title="virtual smart card reader">vpcd</abbr>.</p>
|
||
<p>As before with the cryptoflex card, we let
|
||
<a class="reference internal" href="api/virtualsmartcard.VirtualSmartcard.html#virtualsmartcard.VirtualSmartcard.VirtualICC" title="virtualsmartcard.VirtualSmartcard.VirtualICC"><code class="xref py py-class docutils literal notranslate"><span class="pre">VirtualICC</span></code></a> recognize the new type
|
||
<code class="docutils literal notranslate"><span class="pre">"relay"</span></code>. <a class="reference internal" href="api/virtualsmartcard.cards.Relay.html#virtualsmartcard.cards.Relay.RelayOS" title="virtualsmartcard.cards.Relay.RelayOS"><code class="xref py py-class docutils literal notranslate"><span class="pre">RelayOS</span></code></a> overwrites all
|
||
main functions from the template
|
||
<a class="reference internal" href="api/virtualsmartcard.VirtualSmartcard.html#virtualsmartcard.VirtualSmartcard.SmartcardOS" title="virtualsmartcard.VirtualSmartcard.SmartcardOS"><code class="xref py py-class docutils literal notranslate"><span class="pre">SmartcardOS</span></code></a>. Its functions correspond
|
||
to the <a class="reference internal" href="#vpcd-commands"><span class="std std-ref">commands sent by vpcd</span></a>. If you know how to use
|
||
<a class="reference external" href="http://pyscard.sourceforge.net/">pyscard</a> then the rest is pretty straight
|
||
forward, but see yourself…</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">RelayOS</span><span class="p">(</span><span class="n">SmartcardOS</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> This class implements relaying of a (physical) smartcard. The RelayOS</span>
|
||
<span class="sd"> forwards the command APDUs received from the vpcd to the real smartcard via</span>
|
||
<span class="sd"> an actual smart card reader and sends the responses back to the vpcd.</span>
|
||
<span class="sd"> This class can be used to implement relay or MitM attacks.</span>
|
||
<span class="sd"> """</span>
|
||
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">readernum</span><span class="p">,</span> <span class="n">mitm</span><span class="o">=</span><span class="n">RelayMiddleman</span><span class="p">()):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Initialize the connection to the (physical) smart card via a given</span>
|
||
<span class="sd"> reader</span>
|
||
<span class="sd"> """</span>
|
||
|
||
<span class="c1"># See which readers are available</span>
|
||
<span class="n">readers</span> <span class="o">=</span> <span class="n">smartcard</span><span class="o">.</span><span class="n">System</span><span class="o">.</span><span class="n">listReaders</span><span class="p">()</span>
|
||
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">readers</span><span class="p">)</span> <span class="o"><=</span> <span class="n">readernum</span><span class="p">:</span>
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">"Invalid number of reader '</span><span class="si">%u</span><span class="s2">' (only </span><span class="si">%u</span><span class="s2"> available)"</span><span class="p">,</span>
|
||
<span class="n">readernum</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">readers</span><span class="p">))</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
|
||
|
||
<span class="c1"># Connect to the reader and its card</span>
|
||
<span class="c1"># XXX this is a workaround, see on sourceforge bug #3083254</span>
|
||
<span class="c1"># should better use</span>
|
||
<span class="c1"># self.reader = smartcard.System.readers()[readernum]</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">reader</span> <span class="o">=</span> <span class="n">readers</span><span class="p">[</span><span class="n">readernum</span><span class="p">]</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">session</span> <span class="o">=</span> <span class="n">smartcard</span><span class="o">.</span><span class="n">Session</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">reader</span><span class="p">)</span>
|
||
<span class="k">except</span> <span class="n">smartcard</span><span class="o">.</span><span class="n">Exceptions</span><span class="o">.</span><span class="n">CardConnectionException</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">"Error connecting to card: </span><span class="si">%s</span><span class="s2">"</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
|
||
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">"Connected to card in '</span><span class="si">%s</span><span class="s2">'"</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">reader</span><span class="p">)</span>
|
||
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">mitm</span> <span class="o">=</span> <span class="n">mitm</span>
|
||
|
||
<span class="n">atexit</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">cleanup</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">cleanup</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Close the connection to the physical card</span>
|
||
<span class="sd"> """</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||
<span class="k">except</span> <span class="n">smartcard</span><span class="o">.</span><span class="n">Exceptions</span><span class="o">.</span><span class="n">CardConnectionException</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s2">"Error disconnecting from card: </span><span class="si">%s</span><span class="s2">"</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">getATR</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="c1"># when powerDown has been called, fetching the ATR will throw an error.</span>
|
||
<span class="c1"># In this case we must try to reconnect (and then get the ATR).</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">atr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">getATR</span><span class="p">()</span>
|
||
<span class="k">except</span> <span class="n">smartcard</span><span class="o">.</span><span class="n">Exceptions</span><span class="o">.</span><span class="n">CardConnectionException</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="c1"># Try to reconnect to the card</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">session</span> <span class="o">=</span> <span class="n">smartcard</span><span class="o">.</span><span class="n">Session</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">reader</span><span class="p">)</span>
|
||
<span class="n">atr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">getATR</span><span class="p">()</span>
|
||
<span class="k">except</span> <span class="n">smartcard</span><span class="o">.</span><span class="n">Exceptions</span><span class="o">.</span><span class="n">CardConnectionException</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">"Error getting ATR: </span><span class="si">%s</span><span class="s2">"</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
|
||
|
||
<span class="k">return</span> <span class="s2">""</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="nb">chr</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">atr</span><span class="p">])</span>
|
||
|
||
<span class="k">def</span> <span class="nf">powerUp</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="c1"># When powerUp is called multiple times the session is valid (and the</span>
|
||
<span class="c1"># card is implicitly powered) we can check for an ATR. But when</span>
|
||
<span class="c1"># powerDown has been called, the session gets lost. In this case we</span>
|
||
<span class="c1"># must try to reconnect (and power the card).</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">getATR</span><span class="p">()</span>
|
||
<span class="k">except</span> <span class="n">smartcard</span><span class="o">.</span><span class="n">Exceptions</span><span class="o">.</span><span class="n">CardConnectionException</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">session</span> <span class="o">=</span> <span class="n">smartcard</span><span class="o">.</span><span class="n">Session</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">reader</span><span class="p">)</span>
|
||
<span class="k">except</span> <span class="n">smartcard</span><span class="o">.</span><span class="n">Exceptions</span><span class="o">.</span><span class="n">CardConnectionException</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">"Error connecting to card: </span><span class="si">%s</span><span class="s2">"</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
|
||
|
||
<span class="k">def</span> <span class="nf">powerDown</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="c1"># There is no power down in the session context so we simply</span>
|
||
<span class="c1"># disconnect, which should implicitly power down the card.</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||
<span class="k">except</span> <span class="n">smartcard</span><span class="o">.</span><span class="n">Exceptions</span><span class="o">.</span><span class="n">CardConnectionException</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">"Error disconnecting from card: </span><span class="si">%s</span><span class="s2">"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
|
||
|
||
<span class="k">def</span> <span class="nf">reset</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">powerDown</span><span class="p">()</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">powerUp</span><span class="p">()</span>
|
||
|
||
<span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">msg</span><span class="p">):</span>
|
||
<span class="c1"># sendCommandAPDU() expects a list of APDU bytes</span>
|
||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span><span class="nb">str</span><span class="p">):</span>
|
||
<span class="n">apdu</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="nb">ord</span><span class="p">,</span> <span class="n">msg</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">apdu</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
|
||
|
||
<span class="n">apdu</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">mitm</span><span class="o">.</span><span class="n">handleInPDU</span><span class="p">(</span><span class="n">apdu</span><span class="p">)</span>
|
||
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">rapdu</span><span class="p">,</span> <span class="n">sw1</span><span class="p">,</span> <span class="n">sw2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">sendCommandAPDU</span><span class="p">(</span><span class="n">apdu</span><span class="p">)</span>
|
||
<span class="k">except</span> <span class="n">smartcard</span><span class="o">.</span><span class="n">Exceptions</span><span class="o">.</span><span class="n">CardConnectionException</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||
<span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">"Error transmitting APDU: </span><span class="si">%s</span><span class="s2">"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
|
||
|
||
<span class="c1"># XXX this is a workaround, see on sourceforge bug #3083586</span>
|
||
<span class="c1"># should better use</span>
|
||
<span class="c1"># rapdu = rapdu + [sw1, sw2]</span>
|
||
<span class="k">if</span> <span class="n">rapdu</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">:]</span> <span class="o">==</span> <span class="p">[</span><span class="n">sw1</span><span class="p">,</span> <span class="n">sw2</span><span class="p">]:</span>
|
||
<span class="k">pass</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">rapdu</span> <span class="o">=</span> <span class="n">rapdu</span> <span class="o">+</span> <span class="p">[</span><span class="n">sw1</span><span class="p">,</span> <span class="n">sw2</span><span class="p">]</span>
|
||
|
||
<span class="n">rapdu</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">mitm</span><span class="o">.</span><span class="n">handleOutPDU</span><span class="p">(</span><span class="n">rapdu</span><span class="p">)</span>
|
||
|
||
<span class="c1"># return the response APDU as string</span>
|
||
<span class="k">return</span> <span class="s2">""</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">chr</span><span class="p">,</span> <span class="n">rapdu</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
<footer class="footer">
|
||
<div class="container">
|
||
<p class="pull-right">
|
||
<a href="#">Back to top</a>
|
||
|
||
</p>
|
||
<p>
|
||
© Copyright 2009-2021 by Dominik Oepen and Frank Morgner.<br/>
|
||
</p>
|
||
</div>
|
||
</footer>
|
||
</body>
|
||
</html> |