Commit c2cafa0b authored by Arturo Hernandez's avatar Arturo Hernandez

test advanced functions

parent 0d91fb2a
......@@ -141,3 +141,5 @@ python-3.6.8/
agetic_mst/
out/
mifare/
......@@ -14,5 +14,6 @@ MST_KEY = os.environ.get("MST_KEY", 'cert/server.key')
DEBUG = str2bool(os.environ.get("DEBUG", 'False'))
INIT_CM_KEY = os.environ.get("INIT_CM_KEY", '41 47 45 54 49 43 52 55 4c 45 53 21 31 6f 6e 65')
if __name__ == '__main__':
print("configs")
......@@ -4,6 +4,9 @@ import os
import sys
import logging
import datetime
import traceback
from time import sleep
from threading import Thread
import tornado.httpserver
......@@ -11,7 +14,8 @@ import tornado.ioloop
import tornado.web
from smartcard.util import toHexString, toASCIIString, padd
from smartcard.Exceptions import SmartcardException
from smartcard.sw.SWExceptions import SWException
#change CWD to parent of src/
os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
#print (os.getcwd())
......@@ -71,7 +75,7 @@ if __name__ == '__main__': #logging para los modulos
from parseATR import parseATR #https://github.com/LudovicRousseau/pyscard-contrib
import config
from rfid import OMNIKEYCard, OMNIKEYException
from rfid import OMNIKEYCard, OMNIKEYException, TYPE_KEYA, TYPE_KEYB
......@@ -95,6 +99,12 @@ class ReadCardHandler(tornado.web.RequestHandler):
self.finish()
def get(self):
print("reading card...")
block = int(self.get_argument("block",default=-1,strip=True))
key_a = self.get_argument("key_a",default="FFFFFFFFFFFF",strip=True)
key_a = list(bytes.fromhex(key_a))
key_b = self.get_argument("key_b",default="FFFFFFFFFFFF",strip=True)
key_b = list(bytes.fromhex(key_b))
try:
card = OMNIKEYCard.connect()
except OMNIKEYException as e:
......@@ -115,25 +125,126 @@ class ReadCardHandler(tornado.web.RequestHandler):
self.write({"error": str(e)})
return
LOGGER.info('UUIDHex: {}'.format(toHexString(uid, 1)))
atr_match = []
atr_possible = []
data = {
'reader': str(card.reader),
'ATR': atr,
'ATR_match': [],
'ATR_possible': [],
'UUIDHex': toHexString(uid, 1),
'message': 'OK'
}
if block >=0:
LOGGER.info("reading block %i", block)
card.send_key(key_a, 0)
card.send_key(key_b, 1)
#try auth_
auth = False
try:
card.auth_block(block, TYPE_KEYA, 0)
auth = True
except SWException as e:
LOGGER.warn("Trying keyB")
try:
card.auth_block(block, TYPE_KEYB, 1)
auth = True
except SWException as e:
LOGGER.error("Can't auth with keys. %s", e)
if auth:
block_data = card.read_block(block)
data["block"]=block
data["data"]= block_data
data["dataHex"]= toHexString(block_data,1)
found = parseATR.match_atr_differentiated(atr, "src/parseATR/smartcard_list.txt")
if found:
if atr in found:
for d in found[atr]:
atr_match.append(str(d))
data["ATR_match"].append(str(d))
del found[atr]
for a in found:
for d in found[a]:
atr_possible.append(str(d))
data["ATR_possible"].append(str(d))
self.write(data)
class InitCardHandler(tornado.web.RequestHandler):
""" WIP mf plus"""
def set_default_headers(self):
self.set_header("Access-Control-Allow-Origin", "*")
self.set_header('Access-Control-Allow-Methods', 'POST, OPTIONS')
self.set_header("Access-Control-Allow-Headers", "x-requested-with,access-control-allow-origin,authorization,content-type")
remote_ip = self.request.headers.get("X-Real-IP") or \
self.request.headers.get("X-Forwarded-For") or \
self.request.remote_ip
LOGGER.info("{} from {}".format(self.request.method, remote_ip))
def options(self):
# no body
self.set_status(204)
self.finish()
def post(self):
print("init card...")
try:
card = OMNIKEYCard.connect()
except OMNIKEYException as e:
LOGGER.info("Error: {}".format(e))
self.write({"error": str(e)})
return
try:
atr = toHexString(card.get_ATR())
except OMNIKEYException as e:
LOGGER.info("Error: {}".format(e))
self.write({"error": str(e)})
return
LOGGER.info('ATR: {}'.format(atr))
try:
uid = card.get_UID()
except OMNIKEYException as e:
LOGGER.info("Error: {}".format(e))
self.write({"error": str(e)})
return
LOGGER.info('UUIDHex: {}'.format(toHexString(uid, 1)))
card_uuid = self.get_argument("uuid")
LOGGER.info ("match to %s", card_uuid)
if card_uuid != toHexString(uid, 1):
LOGGER.info("UUID no coincide") #TODO: match ATR too
self.write({"error": "UUID no coincide"})
return
#init stuff here!
card.APDU_get_version()
try:
card.APDU_enter_transparent_session()
card.APDU_set_field(0)
sleep(0.05) #min 5ms
card.APDU_set_protocol(0x02)# iso 14443-A
card.APDU_set_speed()
card.APDU_transcieve([0x26], valid_bits=7) #REQA
adata = card.APDU_transcieve([0x93, 0x20]) #AntiCol1
sak = card.APDU_transcieve([0x93, 0x70] + adata, txrx_flags=0x0F)
if sak == [0x04]: #incomplete
adata2 = card.APDU_transcieve([0x95, 0x20]) #AntiCol1
sak = card.APDU_transcieve([0x95, 0x70] + adata2, txrx_flags=0x0F)
if sak == [0x04]: #incomplete
adata3 = card.APDU_transcieve([0x97, 0x20]) #AntiCol1
sak = card.APDU_transcieve([0x97, 0x70] + adata3, txrx_flags=0x0F)
if sak[0] & 0x20: #compliant with iso14443-4 (T=cl commands)
LOGGER.info("iso-4")
ats = card.APDU_transcieve([0xE0, 0x80], txrx_flags=0x0F) #rats
except SmartcardException as e:
LOGGER.error("SmartcardException: %s", e)
print(traceback.format_exc())
except SWException as e:
LOGGER.error("SWException: %s", e)
print(traceback.format_exc())
finally:
card.APDU_set_field(1) #turn off?
card.APDU_exit_transparent_session()
self.write({
'reader': str(card.reader),
'ATR': atr,
'ATR_match': atr_match,
'ATR_possible': atr_possible,
'UUIDHex': toHexString(uid, 1),
'message': 'OK'
})
class IndexHandler(tornado.web.RequestHandler):
def get(self, url):
LOGGER.info("via h")
......@@ -150,6 +261,7 @@ def make_app():
(r"/(index.*)?", IndexHandler),
(r"/api/?", TestHandler),
(r"/api/read-card/?", ReadCardHandler),
(r"/api/init-card/?", InitCardHandler),
(r"/api/write-card/?", MainHandler),
(r"/mst_cert.crt()",tornado.web.StaticFileHandler, {"path": config.MST_CERT}),
(r"/(.*)",tornado.web.StaticFileHandler, {"path": "src/www"},), #path fixed to top
......
......@@ -3,6 +3,7 @@
import sys
import traceback
from struct import pack, unpack
from smartcard.System import readers
from smartcard.scard import scard
from smartcard.pcsc.PCSCContext import PCSCContext
......@@ -104,7 +105,11 @@ class OMNIKEYCard(object):
self.connection = connection
def APDU_get_version(self):
pass
data, sw1, sw2 = self.connection.transmit([0xFF, 0x68, 0x0E, 0x08, 0x02, 0x01, 0x00]) # propietary reader command "get version"
print('VERSION {} sw: {}'.format(toHexString(data), toHexString([sw1, sw2])))
self.sw1 = sw1; self.sw2 = sw2
errorchain[0](data, sw1, sw2)
return toHexString(data) # 01 00
def APDU_enter_transparent_session(self):
data, sw1, sw2 = self.connection.transmit([0xFF, 0x68, 0x0E, 0x06, 0x01, 0x00]) # propietary reader command "read uid"
......@@ -112,13 +117,13 @@ class OMNIKEYCard(object):
self.sw1 = sw1; self.sw2 = sw2
errorchain[0](data, sw1, sw2)
def APDU_transcieve(self, command):
def APDU_transcieve(self, command, txrx_flags=0x0A, valid_bits=0, timeout_us=1084800):
TRANSCIEVE = [
0xFF, 0x68,
0x0E, 0x03,
10 + len(command),
0x1F, 0x00, 0x00, 0x1e, 0x84, 0x80, 0x00, 0x00, 0x00, 0x00
] + command + [0x00]
txrx_flags, valid_bits
] + list(pack('>I',int(timeout_us))) + [0x00, 0x00, 0x00, 0x00] + command + [0x00]
print("TR {}". format(toHexString(TRANSCIEVE)))
data, sw1, sw2 = self.connection.transmit(TRANSCIEVE)
print('APDU {} sw: {}'.format(toHexString(data), toHexString([sw1, sw2])))
......@@ -132,6 +137,18 @@ class OMNIKEYCard(object):
self.sw1 = sw1; self.sw2 = sw2
errorchain[0](data, sw1, sw2)
def APDU_set_field(self, field=0x01):
data, sw1, sw2 = self.connection.transmit([0xFF, 0x68, 0x0E, 0x02, 0x01, field])
print('SETF {} sw: {}'.format(toHexString(data), toHexString([sw1, sw2])))
self.sw1 = sw1; self.sw2 = sw2
errorchain[0](data, sw1, sw2)
def APDU_set_speed(self, tx_speed=0x00, rx_speed=0x00):
data, sw1, sw2 = self.connection.transmit([0xFF, 0x68, 0x0E, 0x01, 0x03, tx_speed, rx_speed, 0x00])
print('SETS {} sw: {}'.format(toHexString(data), toHexString([sw1, sw2])))
self.sw1 = sw1; self.sw2 = sw2
errorchain[0](data, sw1, sw2)
def APDU_exit_transparent_session(self):
data, sw1, sw2 = self.connection.transmit([0xFF, 0x68, 0x0E, 0x07, 0x01, 0x00])
print('XTS {} sw: {}'.format(toHexString(data), toHexString([sw1, sw2])))
......
......@@ -40,7 +40,9 @@
<div class="row">
<div class="btn-group">
<button id="btn1" class="btn btn-secondary">Leer UUID!</button>
<button id="btn2" class="btn btn-info">Escribir!</button>
<button id="btn2" class="btn btn-info">Inicializar +</button>
<button id="btn3" class="btn btn-info">Leer datos</button>
<button id="btn4" class="btn btn-info">Escribir!</button>
</div>
</div>
<div class="row">
......@@ -114,6 +116,109 @@ $(function() {
});
}
function read_card_data(){
$("#reader").text('');
$("#atr").text('');
$("#uiid").text('');
$("#mensaje").text('');
$("#spin").show();
$.ajax('https://127.0.0.1:8000/api/read-card', {method:'GET', data:{block:0}, timeout: 2000 }).done(function(data,st){
$("#spin").hide();
console.log(data,st);
if (data.UUIDHex){
$("#uiid").text("UUID: " + data.UUIDHex);
$("#reader").text("Lector: " + data.reader);
$("#atr").html("ATR: <a href=\"https://smartcard-atr.apdu.fr/parse?ATR=" + encodeURIComponent(data.ATR) + "\" target=\"_blank\"> " + data.ATR + "</a>");
if (data.ATR_match.length){
$("#atr").append("<h5>Tipo de tarjeta</h5>");
data.ATR_match.forEach(function(e,i){
$("#atr").append((i==0?"<strong class=\"alert-success\">":"") + e + (i==0?"</strong>":"") + "<br/>");
})
if (data.ATR_possible.length){
$("#atr").append("<br/><h5>Otros tipos</h5>");
data.ATR_possible.forEach(function(e,i){
$("#atr").append(e + "<br/>");
})
}
}else{
$("#atr").append("<h5 class=\"alert-danger\">Tarjeta desconocida</h5>");
}
$("#mensaje").removeClass('alert-danger').addClass('alert-success');
$("#mensaje").text(data.message);
}else{
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
$("#mensaje").text(data.error || data.message || "Error al recabar respuesta " + data.toString());
}
}).fail(function(err, st){
$("#spin").hide();
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
console.log("error", err);
console.log("st", st);
if (err.responseJSON){
var data = err.responseJSON;
$("#mensaje").text(data.message);
} else {
$("#mensaje").text("Sin Conexión con el microservicio de tarjetas https://127.0.0.1:8000");
}
});
}
function init_card(){
if ($("#uiid").text().trim().length == 0){
console.log("sin uuid");
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
$("#mensaje").text("identifique una tarjeta primero");
return;
}else{
console.log("trying uuid", $("#uiid").text().trim())
}
$("#reader").text('');
$("#atr").text('');
$("#mensaje").text('');
$("#spin").show();
$.ajax('https://127.0.0.1:8000/api/init-card', {method:'POST', data:{uuid:$("#uiid").text().substring(6)}, timeout: 2000 }).done(function(data,st){
$("#spin").hide();
console.log(data,st);
if (data.UUIDHex){
$("#uiid").text("UUID: " + data.UUIDHex);
$("#reader").text("Lector: " + data.reader);
$("#atr").html("ATR: <a href=\"https://smartcard-atr.apdu.fr/parse?ATR=" + encodeURIComponent(data.ATR) + "\" target=\"_blank\"> " + data.ATR + "</a>");
if (data.ATR_match && data.ATR_match.length){
$("#atr").append("<h5>Tipo de tarjeta</h5>");
data.ATR_match.forEach(function(e,i){
$("#atr").append((i==0?"<strong class=\"alert-success\">":"") + e + (i==0?"</strong>":"") + "<br/>");
})
if (data.ATR_possible && data.ATR_possible.length){
$("#atr").append("<br/><h5>Otros tipos</h5>");
data.ATR_possible.forEach(function(e,i){
$("#atr").append(e + "<br/>");
})
}
}else{
$("#atr").append("<h5 class=\"alert-danger\">Tarjeta desconocida</h5>");
}
$("#mensaje").removeClass('alert-danger').addClass('alert-success');
$("#mensaje").text(data.message);
}else{
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
$("#mensaje").text(data.error || data.message || "Error al recabar respuesta " + data.toString());
}
}).fail(function(err, st){
$("#spin").hide();
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
console.log("error", err);
console.log("st", st);
if (err.responseJSON){
var data = err.responseJSON;
$("#mensaje").text(data.message);
} else {
$("#mensaje").text("Sin Conexión con el microservicio de tarjetas https://127.0.0.1:8000");
}
});
}
function put_get_huella(metodo){
if (metodo == 'POST'){
var minuta = $("#minuta").val();
......@@ -185,7 +290,9 @@ $(function() {
}
$("#btn1").click(function(){read_card()});
$("#btn2").click(function(){write_card()});
$("#btn2").click(function(){init_card()});
$("#btn3").click(function(){read_card_data()});
$("#btn4").click(function(){write_card()});
$("#spin").hide();
/*
socket.on('connect', function(){console.log("io.connected");});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment