diff --git a/Makefile b/Makefile index cdef7ff..1004e5f 100644 --- a/Makefile +++ b/Makefile @@ -9,16 +9,23 @@ platform=2 -src = $(wildcard *.c) $(wildcard crypto/*.c) crypto/tiny-AES-c/aes.c +src = $(wildcard pc/*.c) $(wildcard fido2/*.c) $(wildcard crypto/sha256/*.c) crypto/tiny-AES-c/aes.c obj = $(src:.c=.o) uECC.o LDFLAGS = -Wl,--gc-sections ./tinycbor/lib/libtinycbor.a -CFLAGS = -O2 -fdata-sections -ffunction-sections -I./tinycbor/src -I./crypto -I./crypto/micro-ecc/ -Icrypto/tiny-AES-c/ -I. +CFLAGS = -O2 -fdata-sections -ffunction-sections + +INCLUDES = -I./tinycbor/src -I./crypto/sha256 -I./crypto/micro-ecc/ -Icrypto/tiny-AES-c/ -I./fido2/ -I./pc + +CFLAGS += $(INCLUDES) name = main all: main +cbor: + cd tinycbor/ && $(MAKE) clean && $(MAKE) -j8 + test: testgcm efm8prog: diff --git a/pc/app.h b/pc/app.h new file mode 100644 index 0000000..301ae7d --- /dev/null +++ b/pc/app.h @@ -0,0 +1,18 @@ +/* + * app.h + * + * Created on: Jun 26, 2018 + * Author: conor + */ + +#ifndef SRC_APP_H_ +#define SRC_APP_H_ + +#define USING_DEV_BOARD + +#define BRIDGE_TO_WALLET + +void printing_init(); + + +#endif /* SRC_APP_H_ */ diff --git a/pc/device.c b/pc/device.c index fac0168..184656c 100644 --- a/pc/device.c +++ b/pc/device.c @@ -95,12 +95,12 @@ void udp_close(int fd) -uint64_t millis() +uint32_t millis() { struct timeval te; gettimeofday(&te, NULL); // get current time uint64_t milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // calculate milliseconds - return milliseconds; + return (uint32_t)milliseconds; } diff --git a/tools/http2udb.py b/tools/http2udb.py new file mode 100644 index 0000000..915abf2 --- /dev/null +++ b/tools/http2udb.py @@ -0,0 +1,128 @@ +#!/usr/bin/python +from __future__ import print_function, absolute_import, unicode_literals +from http.server import BaseHTTPRequestHandler,HTTPServer + +from fido2.hid import CtapHidDevice, CTAPHID +from fido2.client import Fido2Client, ClientError +from fido2.ctap import CtapError +from fido2.ctap1 import CTAP1 +from fido2.ctap2 import * +from fido2.cose import * +from fido2.utils import Timeout + +import socket,json,base64,ssl + +httpport = 8080 +udpport = 8111 + + + +def ForceU2F(client,device): + client.ctap = CTAP1(device) + client.pin_protocol = None + client._do_make_credential = client._ctap1_make_credential + client._do_get_assertion = client._ctap1_get_assertion + + +if __name__ == '__main__': + dev = next(CtapHidDevice.list_devices(), None) + print(dev) + if not dev: + raise RuntimeError('No FIDO device found') + client = Fido2Client(dev, 'https://example.com') + ForceU2F(client, dev) + ctap = client.ctap + + +def to_websafe(data): + data = data.replace('+','-') + data = data.replace('/','_') + data = data.replace('=','') + return data + +def from_websafe(data): + data = data.replace('-','+') + data = data.replace('_','/') + return data + '=='[:(3*len(data)) % 4] + +def write(data): + msg = from_websafe(data) + msg = base64.b64decode(msg) + chal = b'A'*32 + appid = b'A'*32 + #print (msg) + #print (msg.decode()) + #print (str(msg)) + #msg = msg.decode('ascii') + #print('ascii:',repr(msg)) + #print('ascii:',(type(msg))) + #print(msg + chal) + + #data = client_param + app_param + struct.pack('>B', len(key_handle)) + key_handle + #msg = str(msg.decode()) + #print(msg.decode()) + s = ctap.authenticate(chal,appid,msg,) + print(s) + #sock.sendto(msg, ('127.0.0.1', udpport)) + +def read(): + #msg = [0]*64 + pkt, _ = sock.recvfrom(1000) + #for i,v in enumerate(pkt): + #msg[i] = ord(v) + msg = base64.b64encode(pkt) + msg = to_websafe(pkt) + return msg + +class UDPBridge(BaseHTTPRequestHandler): + def end_headers (self): + self.send_header('Access-Control-Allow-Origin', '*') + BaseHTTPRequestHandler.end_headers(self) + + def do_POST(self): + content_len = int(self.headers.get('Content-Length', 0)) + post_body = self.rfile.read(content_len) + data = json.loads(post_body)['data'] + + print(data) + msg = from_websafe(data) + msg = base64.b64decode(msg) + chal = b'A'*32 + appid = b'A'*32 + + s = ctap.authenticate(chal,appid,msg,) + + data = struct.pack('B',s.user_presence) + struct.pack('>L',s.counter) + s.signature + data = base64.b64encode(data).decode('ascii') + data = to_websafe(data) + data = json.dumps({'data':data}) + data = data.encode('ascii') + + self.send_response(200) + self.send_header('Content-type','text/json') + self.end_headers() + self.wfile.write(data) + + + def do_GET(self): + self.send_response(200) + self.send_header('Content-type','text/json') + self.end_headers() + + #msg = {'data': read()} + msg = {'data': 'rest'} + + self.wfile.write(json.dumps(msg).encode()) + +try: + server = HTTPServer(('', httpport), UDPBridge) + print('Started httpserver on port ' , httpport) + + server.socket = ssl.wrap_socket (server.socket, + keyfile="../web/localhost.key", + certfile='../web/localhost.crt', server_side=True) + + server.serve_forever() +except KeyboardInterrupt: + server.socket.close() + diff --git a/web/js/wallet.js b/web/js/wallet.js index 6981d91..5cccc46 100644 --- a/web/js/wallet.js +++ b/web/js/wallet.js @@ -162,7 +162,68 @@ var PIN = { getPinToken: 0x05, }; -function send_msg(data, func, timeout) { +// Create the XHR object. +function createCORSRequest(method, url) { + var xhr = new XMLHttpRequest(); + if ("withCredentials" in xhr) { + // XHR for Chrome/Firefox/Opera/Safari. + xhr.open(method, url, true); + } else if (typeof XDomainRequest != "undefined") { + // XDomainRequest for IE. + xhr = new XDomainRequest(); + xhr.open(method, url); + } else { + // CORS not supported. + xhr = null; + } + return xhr; +} + +function parse_device_response(arr) +{ + var dataview = new DataView(arr.slice(1,5).buffer); + + count = dataview.getUint32(0,true); // get count as 32 bit LE integer + + data = null; + if (arr[5] == 0) { + data = arr.slice(6,arr.length); + } + return {count: count, status: error2string(arr[5]), data: data}; +} + + + +// For development purposes +function send_msg_http(data, func, timeout) { + var url = 'https://localhost:8080'; + + var req = JSON.stringify({data: array2websafe(data)}); + + var xhr = createCORSRequest('POST', url); + + if (!xhr) { + console.log('CORS not supported'); + return; + } + + // Response handlers. + xhr.onload = function() { + var text = xhr.responseText; + var resp = JSON.parse(text); + arr = websafe2array(resp.data); + data = parse_device_response(arr); + if (func) func(data); + }; + + xhr.onerror = function() { + console.log('Woops, there was an error making the request.'); + }; + + xhr.send(req); +} +//run_tests(); +function send_msg_u2f(data, func, timeout) { // Use key handle and signature response as comm channel var d = new Date(); var t1 = d.getTime(); @@ -186,28 +247,19 @@ function send_msg(data, func, timeout) { var d2 = new Date(); t2 = d2.getTime(); sig = websafe2array(res.signatureData) - - //console.log(sig); - //console.log(sig.slice(1,5)); - var dataview = new DataView(sig.slice(1,5).buffer); - - count = dataview.getUint32(0,true); // get count as 32 bit LE integer - - //console.log('sig:',sig); - //console.log('count:',count); - data = null; - if (sig[5] == 0) { - data = sig.slice(6,sig.length); - } - func({count: count, status: error2string(sig[5]), data: data}); - //console.log('response:', res); - //console.log('time:', t2-t1); - //i += 1; + data = parse_device_response(sig); + func(data); },timeout); } - +DEVELOPMENT = 1 +var send_msg; +if (DEVELOPMENT) { + send_msg = send_msg_http; +} else { + send_msg = send_msg_u2f; +} // Format a request message @@ -405,4 +457,6 @@ function run_tests() EC = elliptic.ec -run_tests(); + +run_tests() +