Selaa lähdekoodia

First commit

master
Thibauld Feneuil 4 vuotta sitten
commit
926764d0fc
17 muutettua tiedostoa jossa 1124 lisäystä ja 0 poistoa
  1. 2
    0
      .gitignore
  2. 11
    0
      README.md
  3. 0
    0
      __init__.py
  4. 192
    0
      engine.py
  5. 66
    0
      executorthread.py
  6. 6
    0
      launch.py
  7. 39
    0
      listeningthread.py
  8. 214
    0
      project_base.py
  9. 42
    0
      project_reader.py
  10. 3
    0
      projects/.gitignore
  11. BIN
      projects/elmoasmfunctions.o
  12. 257
    0
      projects/elmoasmfunctions.s
  13. 55
    0
      projects/elmoasmfunctionsdef.h
  14. 134
    0
      protocol.py
  15. 24
    0
      run
  16. 36
    0
      run_server.py
  17. 43
    0
      servicethread.py

+ 2
- 0
.gitignore Näytä tiedosto

@@ -0,0 +1,2 @@
*.pyc
elmo/*

+ 11
- 0
README.md Näytä tiedosto

@@ -0,0 +1,11 @@
# ELMO Online
ELMO Online is a Python library which proposes an encapsulation of the binary project ELMO.
[MOW17] **Towards Practical Tools for Side
Channel Aware Software Engineering : ’Grey Box’ Modelling for Instruction Leakages**
by _David McCann, Elisabeth Oswald et Carolyn Whitnall_.
https://www.usenix.org/conference/
usenixsecurity17/technical-sessions/presentation/mccann.
**ELMO GitHub**: https://github.com/sca-research/ELMO

+ 0
- 0
__init__.py Näytä tiedosto


+ 192
- 0
engine.py Näytä tiedosto

@@ -0,0 +1,192 @@
import numpy as np
import os
def hweight(n):
c = 0
while n>0:
c += (n & 1)
n >>= 1
return c
def hdistance(x,y):
return hweight(x^y)
def binary_writing(n, nb_bits=32, with_hamming=False):
n = np.array(n)
w, h = np.zeros((nb_bits, len(n))), np.zeros((len(n)))
for ind in range(nb_bits):
w[ind] = (n & 1)
h += w[ind]
n >>= 1
ind += 1
return (w, h) if with_hamming else w
PREVIOUS = 0
CURRENT = 1
SUBSEQUENT = 2
class ELMOEngine:
def __init__(self):
self.load_coefficients()
self.reset_points()
def _extract_data(self, nb):
coeffs = self.coefficients[self.pos:self.pos+nb]
self.pos += nb
return coeffs
def load_coefficients(self):
filename = os.path.dirname(os.path.abspath(__file__))+'/elmo/coeffs.txt'
self.coefficients = None
with open(filename, 'r') as _file:
self.coefficients = np.array([list(map(float, line.split())) for line in _file.readlines()[:2153]])
if self.coefficients is None:
raise IOError('Problem to read the coefficients.')
self.pos = 0
self.constant = np.squeeze(self._extract_data(1))
self.PrvInstr = self._extract_data(4)
self.SubInstr = self._extract_data(4)
self.Operand1 = self._extract_data(32)
self.Operand2 = self._extract_data(32)
self.BitFlip1 = self._extract_data(32)
self.BitFlip2 = self._extract_data(32)
self.HWOp1PrvInstr = self._extract_data(4)
self.HWOp2PrvInstr = self._extract_data(4)
self.HDOp1PrvInstr = self._extract_data(4)
self.HDOp2PrvInstr = self._extract_data(4)
self.HWOp1SubInstr = self._extract_data(4)
self.HWOp2SubInstr = self._extract_data(4)
self.HDOp1SubInstr = self._extract_data(4)
self.HDOp2SubInstr = self._extract_data(4)
self.Operand1_bitinteractions = self._extract_data(496)
self.Operand2_bitinteractions = self._extract_data(496)
self.BitFlip1_bitinteractions = self._extract_data(496)
self.BitFlip2_bitinteractions = self._extract_data(496)
def reset_points(self):
self.points = []
self.power = None
def add_point(self, triplet, previous_ops, current_ops):
self.points.append((triplet, previous_ops, current_ops))
def _dot(self, a, b):
return np.sum(a * b, axis=0)
def calculate_point(self, triplet, previous_ops, current_ops, debug=False):
nb_points = triplet.shape[1]
instructiontype = triplet[CURRENT]
instructiontype = instructiontype % 5 # Type 5 = Instruction was not profiled
# Previous
previous_instruction_typedec = triplet[PREVIOUS]
previous_instruction_type = np.zeros((5, nb_points))
for i in range(nb_points):
if previous_instruction_typedec[i] < 5:
previous_instruction_type[previous_instruction_typedec[i],i] = 1
# Current
(current_op1_binary, hw_op1) = binary_writing(current_ops[0], with_hamming=True)
(current_op2_binary, hw_op2) = binary_writing(current_ops[1], with_hamming=True)
(current_op1_bitflip, hd_op1) = binary_writing(previous_ops[0] ^ current_ops[0], with_hamming=True)
(current_op2_bitflip, hd_op2) = binary_writing(previous_ops[1] ^ current_ops[1], with_hamming=True)
current_instruction_typedec = instructiontype
current_instruction_type = np.zeros((5, nb_points))
for i in range(nb_points):
if triplet[CURRENT,i] < 5:
current_instruction_type[current_instruction_typedec[i],i] = 1
# Subsequent
subsequent_instruction_typedec = triplet[SUBSEQUENT]
subsequent_instruction_type = np.zeros((5, nb_points))
for i in range(nb_points):
if subsequent_instruction_typedec[i] < 5:
subsequent_instruction_type[subsequent_instruction_typedec[i],i] = 1
# Component variables
PrvInstr_data = self._dot( previous_instruction_type[1:], self.PrvInstr[:,instructiontype] )
SubInstr_data = self._dot( subsequent_instruction_type[1:], self.SubInstr[:,instructiontype] )
Operand1_data = self._dot( current_op1_binary, self.Operand1[:,instructiontype] )
Operand2_data = self._dot( current_op2_binary, self.Operand2[:,instructiontype] )
BitFlip1_data = self._dot( current_op1_bitflip, self.BitFlip1[:,instructiontype] )
BitFlip2_data = self._dot( current_op2_bitflip, self.BitFlip2[:,instructiontype] )
HWOp1PrvInstr_data = hw_op1 * self._dot(previous_instruction_type[1:], self.HWOp1PrvInstr[:,instructiontype])
HWOp2PrvInstr_data = hw_op2 * self._dot(previous_instruction_type[1:], self.HWOp2PrvInstr[:,instructiontype])
HDOp1PrvInstr_data = hd_op1 * self._dot(previous_instruction_type[1:], self.HDOp1PrvInstr[:,instructiontype])
HDOp2PrvInstr_data = hd_op2 * self._dot(previous_instruction_type[1:], self.HDOp2PrvInstr[:,instructiontype])
HWOp1SubInstr_data = hw_op1 * self._dot(subsequent_instruction_type[1:], self.HWOp1SubInstr[:,instructiontype])
HWOp2SubInstr_data = hw_op2 * self._dot(subsequent_instruction_type[1:], self.HWOp2SubInstr[:,instructiontype])
HDOp1SubInstr_data = hd_op1 * self._dot(subsequent_instruction_type[1:], self.HDOp1SubInstr[:,instructiontype])
HDOp2SubInstr_data = hd_op2 * self._dot(subsequent_instruction_type[1:], self.HDOp2SubInstr[:,instructiontype])
Operand1_bitinteractions_data = np.zeros((nb_points))
Operand2_bitinteractions_data = np.zeros((nb_points))
BitFlip1_bitinteractions_data = np.zeros((nb_points))
BitFlip2_bitinteractions_data = np.zeros((nb_points))
count = 0
for i in range(32):
for j in range(i+1,32):
Operand1_bitinteractions_data += self.Operand1_bitinteractions[count,instructiontype] * current_op1_binary[i] * current_op1_binary[j]
Operand2_bitinteractions_data += self.Operand2_bitinteractions[count,instructiontype] * current_op2_binary[i] * current_op2_binary[j]
BitFlip1_bitinteractions_data += self.BitFlip1_bitinteractions[count,instructiontype] * current_op1_bitflip[i] * current_op1_bitflip[j]
BitFlip2_bitinteractions_data += self.BitFlip2_bitinteractions[count,instructiontype] * current_op2_bitflip[i] * current_op2_bitflip[j]
count += 1
power = self.constant[instructiontype] \
+ PrvInstr_data + SubInstr_data \
+ Operand1_data + Operand2_data \
+ BitFlip1_data + BitFlip2_data \
+ HWOp1PrvInstr_data + HWOp2PrvInstr_data \
+ HDOp1PrvInstr_data + HDOp2PrvInstr_data \
+ HWOp1SubInstr_data + HWOp2SubInstr_data \
+ HDOp1SubInstr_data + HDOp2SubInstr_data \
+ Operand1_bitinteractions_data + Operand2_bitinteractions_data \
+ BitFlip1_bitinteractions_data + BitFlip2_bitinteractions_data
for i in range(nb_points):
if triplet[CURRENT,i] == 5:
power[i] = self.constant[triplet[CURRENT,i]]
if debug:
print([self.constant[instructiontype], \
PrvInstr_data, SubInstr_data, \
Operand1_data, Operand2_data, \
BitFlip1_data, BitFlip2_data, \
HWOp1PrvInstr_data, HWOp2PrvInstr_data, \
HDOp1PrvInstr_data, HDOp2PrvInstr_data, \
HWOp1SubInstr_data, HWOp2SubInstr_data, \
HDOp1SubInstr_data, HDOp2SubInstr_data, \
Operand1_bitinteractions_data, Operand2_bitinteractions_data, \
BitFlip1_bitinteractions_data, BitFlip2_bitinteractions_data])
return power
def run(self):
nb_points = len(self.points)
triplet = np.array([p[0] for p in self.points]).T # shape = (3, nb_points)
previous_ops = np.array([p[1] for p in self.points]).T # shape = (2, nb_points)
current_ops = np.array([p[2] for p in self.points]).T # shape = (2, nb_points)
self.power = self.calculate_point(triplet, previous_ops, current_ops)
def oneshot_point(self, triplet, previous_ops, current_ops):
self.reset_points()
self.add_point(triplet, previous_ops, current_ops)
self.run()
return self.power

+ 66
- 0
executorthread.py Näytä tiedosto

@@ -0,0 +1,66 @@
from servicethread import OneShotServiceThread
import subprocess
import shutil
from project_reader import ProjectReader
global_variables = {}
class ExecutorThread(OneShotServiceThread):
def __init__(self, ip, port, clientsocket, **kwargs):
super().__init__(ip, port, clientsocket)
self.projects = kwargs['projects'] if 'projects' in kwargs else None
def execute(self):
projects = self.projects
if project is None:
reader = ProjectReader()
projects = {sc.get_project_label(): sc for sc in reader.get_project_classes()}
print('Warning: need to research the projects.')
else:
print('Already have projects')
data = self.protocol.get_data()
self.protocol.please_assert(data)
self.protocol.please_assert('project' in data)
self.protocol.please_assert(data['project'] in projects)
self.protocol.send_ack()
# Get the project
project = projects[data['project']]
# Make the compilation
if False:
print('Compiling binary...')
# Adapt the project source
with open('binaries/Frodo/frodo-base.c', 'r') as _src_file:
content = _src_file.read()
with open('binaries/Frodo/frodo.c', 'w') as _dst_file:
_dst_file.write(content.replace('%NEED_TO_FILL%', str(n)))
# Compile the project
make_directory = 'projects/{}/{}'.format(project.get_project_directory(), project.get_make_directory())
process = subprocess.Popen('make', shell=True, cwd=make_directory, executable='/bin/bash', stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, error = process.communicate()
if error and ('error' in error.decode('latin-1')):
print("Error to compile")
print(error)
raise Exception()
# Save last compilation data
global_variables[project_name] = {
'last_n': n,
}
# Generate the trace by launching ELMO
command = './elmo ../projects/{}/{}'.format(project.get_project_directory(), project.get_binary())
process = subprocess.Popen(command, shell=True, cwd='elmo_online/elmo/', executable='/bin/bash', stdout=subprocess.PIPE)
output, error = process.communicate()
# Send results
self.protocol.send_data({
'output': output.decode('latin-1') if output else None,
'error': error.decode('latin-1') if error else None,
})
self.protocol.close()

+ 6
- 0
launch.py Näytä tiedosto

@@ -0,0 +1,6 @@
from .project_reader import Project
reader = ProjectReader()
projects = reader.get_projects()
for key, project in projects.items():
globals()[key] = project

+ 39
- 0
listeningthread.py Näytä tiedosto

@@ -0,0 +1,39 @@
from servicethread import PermanentServiceThread
import socket
class ListeningThread(PermanentServiceThread):
def __init__(self, host, port, threadclass, **kwargs):
super().__init__()
self.hostname = host
self.port = port
self.threadclass = threadclass
self.kwargs = kwargs
def execute(self):
self.tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
# self.tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_ATTACH_REUSEPORT_CBPF, 1)
self.tcpsock.bind((self.hostname, self.port))
self.tcpsock.listen(5)
print('[port][%s] Listening' % self.port)
while self.is_running():
try:
(clientsocket, (ip, port)) = self.tcpsock.accept()
print('[port][{}] Accepted: {} <=> {}'.format(
self.port,
clientsocket.getsockname(),
clientsocket.getpeername(),
))
newthread = self.threadclass(ip, port, clientsocket, **self.kwargs)
newthread.start()
except socket.timeout:
pass
def stop(self):
super().stop()
clientsocker = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocker.connect( (self.hostname, self.port) )
self.tcpsock.close()
print('[port][%s] Stop listening' % self.port)

+ 214
- 0
project_base.py Näytä tiedosto

@@ -0,0 +1,214 @@
import os, re
import socket
from protocol import SocketTool
import numpy as np
def to_hex(v, nb_bits=16):
try:
v_hex = v.hex()
except AttributeError:
v_hex = hex(v)[2:]
return '0'*(nb_bits//4-len(v_hex)) + v_hex
def split_octet(hexstr):
return [hexstr[i:i+2] for i in range(0, len(hexstr), 2)]
def to_signed_hex(v, nb_bits=16):
return split_octet(to_hex(v & (2**nb_bits-1), nb_bits=nb_bits))
def write(_input, uintXX, nb_bits=16):
uintXX = to_signed_hex(uintXX, nb_bits=nb_bits)
for i in range(nb_bits//8):
_input.write(uintXX[i]+'\n')
def write_list(_input, uint16_list):
for uint16 in uint16_list:
write(_input, uint16)
def launch_simulation(quiet=False, **kwargs):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 5000))
SocketTool.send_data(s, kwargs)
if not SocketTool.get_ack(s):
raise RuntimeError("The request has been refused !")
else:
data = SocketTool.get_data(s)
if data['error'] and not quiet:
raise Exception("The simulation return an error")
return data['output'], data['error']
s.close()
except IOError:
raise RuntimeError("The connection refused. Has the ELMO server been switch on ?")
class SimulationProject:
_nb_bits_for_nb_challenges = 16
_project_directory = None
### Define the project
@classmethod
def get_project_directory(cl):
if cl._project_directory:
return cl._project_directory
else:
raise NotImplementedError()
@classmethod
def set_project_directory(cl, project_directory):
cl._project_directory = project_directory
@classmethod
def get_project_label(cl):
return cl.get_project_directory()
@classmethod
def get_make_directory(cl):
return ''
@classmethod
def get_binary(cl):
raise NotImplementedError()
@classmethod
def get_parameters_names(cl):
return set()
@classmethod
def adapt_project(cl, parameters):
return
def get_challenge_format(self):
raise NotImplementedError()
### Tools to realize the simulation of the project
def __init__(self, challenges=None):
self.elmo_folder = os.path.dirname(os.path.abspath(__file__))+'/elmo'
self.challenges = challenges
self.is_executed = False
def set_challenges(self, challenges):
self.challenges = challenges
def get_writable_input_file(self):
return open('{}/input.txt'.format(self.elmo_folder), 'w')
def set_input_for_each_challenge(self, input, challenge):
format = self.get_challenge_format()
def aux(sizes, data):
if len(sizes) == 0:
write(input, data)
else:
assert len(data) == sizes[0], 'Incorrect format for challenge. Get {} instead of {}'.format(len(data), sizes[0])
for i in range(sizes[0]):
aux(sizes[1:], data[i])
for num_part in range(len(format)):
aux(format[num_part], challenge[num_part])
def set_input(self, input):
assert len(self.challenges) < 2**16, 'The number of challenges must be strictly lower than 65536. Currently, there are {} challenges.'.format(len(self.challenges))
write(input, len(self.challenges), nb_bits=self._nb_bits_for_nb_challenges)
for challenge in self.challenges:
self.set_input_for_each_challenge(input, challenge)
def run(self):
with open('{}/input.txt'.format(self.elmo_folder), 'w') as _input:
self.set_input(_input)
launch_simulation(project=self.get_project_label(), quiet=False)
self.is_executed = True
def get_asmtrace_filename(self):
return '{}/output/asmoutput/asmtrace00001.txt'.format(self.elmo_folder)
def get_indexes_of(self, condition):
with open(self.get_asmtrace_filename(), 'r') as _file:
asmtrace = _file.readlines()
return [i for i, instr in enumerate(asmtrace) if condition(instr)]
def get_number_of_traces(self):
return len(self.challenges)
def get_results(self, only_filenames=False, reorganise=None, indexes=None):
assert self.is_executed
nb_traces = self.get_number_of_traces()
trace_filenames = []
for filename in os.listdir('{}/output/traces/'.format(self.elmo_folder)):
if re.search(r'^trace\d+\.trc$', filename):
trace_filenames.append('{}/output/traces/{}'.format(self.elmo_folder, filename))
if len(trace_filenames) >= nb_traces:
break
assert len(trace_filenames) == nb_traces
results = trace_filenames
if not only_filenames:
for i in range(len(results)):
with open(results[i], 'r') as _file:
if indexes is not None:
results[i] = list(map(float, _file.readlines()[indexes]))
else:
results[i] = list(map(float, _file.readlines()))
if reorganise is not None:
results = reorganise(results)
return results
def get_traces(self, reorganise=None, indexes=None):
results = self.get_results(only_filenames=False, reorganise=reorganise,indexes=indexes)
nb_traces = self.get_number_of_traces()
trace_length = len(results[0])
traces = np.zeros((nb_traces, trace_length))
for i in range(nb_traces):
traces[i,:] = results[i]
if reorganise is not None:
traces = reorganise(traces)
return traces
def get_printed_data(self):
with open('{}/output/printdata.txt'.format(self.elmo_folder), 'r') as _file:
data = list(map(lambda x: int(x, 16), _file.readlines()))
nb_traces = self.get_number_of_traces()
nb_data_per_trace = len(data) // nb_traces
return [data[nb_data_per_trace*i:nb_data_per_trace*(i+1)] for i in range(nb_traces)]
def analyse_operands(self, num_line, num_trace=1):
num_str = str(num_trace)
num_str = '0'*(5-len(num_str)) + num_str
operands_filename = self.elmo_folder + '/output/operands/operands{}.txt'.format(num_str)
trace_filename = self.elmo_folder + '/output/traces/trace0000{}.trc'.format(num_trace)
is_multiple = (type(num_line) is list)
if not is_multiple:
num_line = [num_line]
output = [{}]*len(num_line)
with open(operands_filename, 'r') as _file:
lines = _file.readlines()
for i, num in enumerate(num_line):
line = lines[num].split()
data = list(map(int, line[0:7]))
output[i]['previous'] = data[0:2]
output[i]['current'] = data[2:4]
output[i]['triplet'] = data[4:7]
output[i]['other'] = list(map(float, line[7:]))
with open(trace_filename, 'r') as _file:
lines = _file.readlines()
for i, num in enumerate(num_line):
line = lines[num]
output[i]['power'] = float(line)
return output if is_multiple else output[0]

+ 42
- 0
project_reader.py Näytä tiedosto

@@ -0,0 +1,42 @@
from project_base import SimulationProject
import os, re
import inspect
PROJECTS_REPOSITORY = 'projects'
class ProjectReader:
def __init__(self):
pass
def get_projects(self):
projects = {}
for root, repositories, files in os.walk(PROJECTS_REPOSITORY):
for filename in files:
if re.fullmatch(r'.*project.*\.py', filename):
# Encapsulation the project
complete_filename = root+'/'+filename
globals = {
#'__builtins__': {'__build_class__': __build_class__},
'SimulationProject': SimulationProject,
}
locals = {}
# Read the project code
with open(complete_filename, 'r') as _file:
project = '\n'.join(_file.readlines())
exec(project, globals, locals)
# Extract the simulations
for key, obj in locals.item():
if inspect.isclass(obj) and issubclass(obj, SimulationProject):
if key in projects:
print('Warning! Multiplie simulation with the same name. Simulation ignored: {} in {}'.format(key, complete_filename[len(PROJECTS_REPOSITORY)+1:]))
else:
obj.set_project_directory(root[len(PROJECTS_REPOSITORY)+1:])
projects[key] = obj
return projects
def get_project_classes(self):
return self.get_projects().values()

+ 3
- 0
projects/.gitignore Näytä tiedosto

@@ -0,0 +1,3 @@
*
!.gitignore
!elmoasmfunctions*

BIN
projects/elmoasmfunctions.o Näytä tiedosto


+ 257
- 0
projects/elmoasmfunctions.s Näytä tiedosto

@@ -0,0 +1,257 @@
##
## University of Bristol – Open Access Software Licence
## Copyright (c) 2016, The University of Bristol, a chartered
## corporation having Royal Charter number RC000648 and a charity
## (number X1121) and its place of administration being at Senate
## House, Tyndall Avenue, Bristol, BS8 1TH, United Kingdom.
## All rights reserved
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
##
## 1. Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
##
## 2. Redistributions in binary form must reproduce the above
## copyright notice, this list of conditions and the following
## disclaimer in the documentation and/or other materials provided
## with the distribution.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
## FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
## COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
## INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
## (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
## STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
## OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Any use of the software for scientific publications or commercial
## purposes should be reported to the University of Bristol
## (OSI-notifications@bristol.ac.uk and quote reference 2668). This is
## for impact and usage monitoring purposes only.
##
## Enquiries about further applications and development opportunities
## are welcome. Please contact elisabeth.oswald@bristol.ac.uk
##

.syntax unified
.text
.thumb

.func starttrigger
.global starttrigger

starttrigger:
push {r0-r7}
movs r4, #0xE0
lsls r4, #24
movs r5, #0x04
eors r4, r5
movs r5, #1
str r5, [r4, #0]
pop {r0-r7}
bx lr

.endfunc

.func endtrigger
.global endtrigger

endtrigger:
push {r0-r7}
movs r4, #0xE0
lsls r4, #24
movs r5, #0x04
eors r4, r5
movs r5, #0
str r5, [r4, #0]
pop {r0-r7}
bx lr

.endfunc

.func readbyte
.global readbyte

readbyte:
push {r0-r7}
movs r4, #0xE1
lsls r4, #24
ldr r1, [r4, #0]
strb r1, [r0, #0]
pop {r0-r7}

bx lr

.endfunc

.func LoadN
.global LoadN

LoadN:
push {r0-r7}
movs r4, #0xE1
lsls r4, #24
movs r5, #0x10
eors r4, r5
ldr r1, [r4, #0]
str r1, [r0, #0]
pop {r0-r7}

bx lr

.endfunc

.func randbyte
.global randbyte

randbyte:
push {r0-r7}
movs r4, #0xE1
lsls r4, #24
movs r5, #0x04
eors r4, r5
ldr r1, [r4, #0]
strb r1, [r0, #0]
pop {r0-r7}

bx lr

.endfunc

.func getstart
.global getstart

getstart:
push {r0-r7}
movs r4, #0xE1
lsls r4, #24
movs r5, #0x08
eors r4, r5
ldr r1, [r4, #0]
str r1, [r0, #0]
pop {r0-r7}

bx lr

.endfunc


.func getruncount
.global getruncount

getruncount:
push {r0-r7}
movs r4, #0xE1
lsls r4, #24
movs r5, #0x0C
eors r4, r5
ldr r1, [r4, #0]
str r1, [r0, #0]
pop {r0-r7}

bx lr

.endfunc



.func printbyte
.global printbyte

printbyte:
push {r0-r7}
movs r4, #0xE0
lsls r4, #24
ldrb r5, [r0]
str r5, [r4]
pop {r0-r7}
bx lr

.endfunc

.func endprogram
.global endprogram

endprogram:
push {r0-r7}
movs r4, #0xF0
lsls r4, #24
movs r5, #0

str r5, [r4]
pop {r0-r7}
bx lr

.endfunc

.func initialisemaskflow
.global initialisemaskflow

# Takes address of key as input (r0)
initialisemaskflow:
push {r0-r7}
movs r4, #0xE0
lsls r4, #24
movs r5, #0x40
eors r4, r5
str r0, [r4]
pop {r0-r7}
bx lr

.endfunc

.func resetmaskflow
.global resetmaskflow

resetmaskflow:
push {r0-r7}
movs r4, #0xE0
lsls r4, #24
movs r5, #0x42
eors r4, r5
movs r5, #0
str r5, [r4]
pop {r0-r7}
bx lr

.endfunc

.func setmaskflowstart
.global setmaskflowstart

# Takes r0 as start number

setmaskflowstart:
push {r0-r7}
movs r4, #0xE0
lsls r4, #24
movs r5, #0x44
eors r4, r5
str r0, [r4]
pop {r0-r7}
bx lr

.endfunc

.func resetdatafile
.global resetdatafile

resetdatafile:
push {r0-r7}
movs r4, #0xE0
lsls r4, #24
movs r5, #0x46
eors r4, r5
movs r5, #0
str r5, [r4]
pop {r0-r7}
bx lr

.endfunc

+ 55
- 0
projects/elmoasmfunctionsdef.h Näytä tiedosto

@@ -0,0 +1,55 @@
/*
* University of Bristol – Open Access Software Licence
* Copyright (c) 2016, The University of Bristol, a chartered
* corporation having Royal Charter number RC000648 and a charity
* (number X1121) and its place of administration being at Senate
* House, Tyndall Avenue, Bristol, BS8 1TH, United Kingdom.
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Any use of the software for scientific publications or commercial
* purposes should be reported to the University of Bristol
* (OSI-notifications@bristol.ac.uk and quote reference 2668). This is
* for impact and usage monitoring purposes only.
*
* Enquiries about further applications and development opportunities
* are welcome. Please contact elisabeth.oswald@bristol.ac.uk
*/

extern void starttrigger(void);
extern void endtrigger(void);
extern void randbyte(unsigned char * pointer);
extern void LoadN(void* addr);
extern void readbyte(unsigned char * pointer);
extern void printbyte(unsigned char * pointer);
extern void endprogram(void);
extern void getstart(unsigned int * pointer);
extern void getruncount(unsigned int * pointer);
extern void initialisemaskflow(unsigned char * pointer);
extern void resetmaskflow(void);
extern void setmaskflowstart(unsigned int start);
extern void resetdatafile(void);

+ 134
- 0
protocol.py Näytä tiedosto

@@ -0,0 +1,134 @@
import os
import json
class ClosureException(Exception):
pass
# https://stackoverflow.com/questions/20007319/how-to-do-a-large-text-file-transfer-in-python
class SocketTool:
@classmethod
def convert_to_bytes(cl, no):
result = bytearray()
result.append(no & 255)
for i in range(3):
no = no >> 8
result.append(no & 255)
return result
@classmethod
def bytes_to_number(cl, b):
import sys
b = b if (sys.version_info > (3, 0)) else map(ord, b)
res = 0
for i in range(4):
res += b[i] << (i*8)
return res
@classmethod
def send_file(cl, s, filename, mode='rb'):
length = os.path.getsize(filename)
s.send(cl.convert_to_bytes(length)) # has to be 4 bytes
with open(filename, mode) as infile:
d = infile.read(1024*64) # We send by pack of 64 ko
while d:
s.send(d)
d = infile.read(1024*64)
@classmethod
def get_file(cl, s):
size = s.recv(4) # assuming that the size won't be bigger then 1GB
size = cl.bytes_to_number(size)
current_size = 0
buffer = b''
while current_size < size:
data = s.recv(1024*64)
if not data:
break
if len(data) + current_size > size:
data = data[:size-current_size] # trim additional data
buffer += data
# you can stream here to disk
current_size += len(data)
# you have entire file in memory
return buffer
@classmethod
def send_data(cl, s, data):
data = json.dumps(data)
data = data.encode('utf-8')
s.send(cl.convert_to_bytes(len(data))) # has to be 4 bytes
s.send(data)
@classmethod
def get_data(cl, s):
import sys
exception_class = json.decoder.JSONDecodeError if (sys.version_info > (3, 0)) else ValueError
try:
size = s.recv(4)
if not size:
return None
size = cl.bytes_to_number(size)
data = s.recv(size)
data = data.decode('utf-8')
data = json.loads(data)
return data
except exception_class:
return None
@classmethod
def send_ack(cl, s, positive=True):
data = 'OK' if positive else 'NO'
s.send(data.encode('ascii'))
@classmethod
def get_ack(cl, s):
data = s.recv(2).decode('ascii')
return (data == 'OK')
class Protocol:
def __init__(self, clientsocket):
self.clientsocket = clientsocket
def send_file(self, filename, mode='rb'):
SocketTool.send_file(self.clientsocket, filename, mode)
def get_file(self):
return SocketTool.get_file(self.clientsocket)
def send_data(self, data):
SocketTool.send_data(self.clientsocket, data)
def get_data(self):
return SocketTool.get_data(self.clientsocket)
def send_ack(self, positive=True):
SocketTool.send_ack(self.clientsocket, positive)
def send_nack(self, positive=True):
SocketTool.send_ack(self.clientsocket, not positive)
def get_ack(self):
return SocketTool.get_ack(self.clientsocket)
def please_assert(self, condition):
if not condition:
self.send_nack()
self.clientsocket.close()
raise ClosureException
def get_object_or_nack(self, model, **kwargs):
try:
return model.objects.get(**kwargs)
except model.DoesNotExist:
self.send_nack()
self.clientsocket.close()
raise ClosureException
def close(self):
self.clientsocket.close()

+ 24
- 0
run Näytä tiedosto

@@ -0,0 +1,24 @@
elmo_repository="elmo"
elmo_source="https://github.com/sca-research/ELMO.git"

echo "====== ELMO Online ======"
if [ -d ${elmo_repository} ]; then
echo " - ELMO tool already installed."
else
# Download the tool
git clone --depth=1 --branch=master ${elmo_source} ${elmo_repository}
rm -rf ./${elmo_repository}/.git
# Compile the tool
cd ./${elmo_repository}
make
cd ..
fi

#current_directory=${PWD##*/}
#echo " - Current directory: ${current_directory}"
echo

#cd ..
#python3 -m ${current_directory}.run_server
python3 run_server.py

+ 36
- 0
run_server.py Näytä tiedosto

@@ -0,0 +1,36 @@
from listeningthread import ListeningThread
from executorthread import ExecutorThread
def do_main_program(projects):
global thread, stop
thread = ListeningThread('localhost', 5000, ExecutorThread, projects=projects)
thread.start()
def program_cleanup(signum, frame):
global thread, stop
thread.stop()
stop = True
thread = None
stop = False
# Information
from project_reader import ProjectReader
reader = ProjectReader()
projects = {sc.get_project_label(): sc for sc in reader.get_project_classes()}
print('Available projects: %s' % list(projects.keys()))
print('')
# Execute
print("Executing...")
do_main_program(projects)
print("Done ! And now, listening...")
import signal
signal.signal(signal.SIGINT, program_cleanup)
signal.signal(signal.SIGTERM, program_cleanup)
# Wait
import time
while not stop:
time.sleep(1)

+ 43
- 0
servicethread.py Näytä tiedosto

@@ -0,0 +1,43 @@
import threading
from protocol import Protocol, ClosureException
class ServiceThread(threading.Thread):
def run(self):
self.execute()
def execute(self):
# Method where the service runs
pass
class OneShotServiceThread(ServiceThread):
def __init__(self, ip, port, clientsocket):
threading.Thread.__init__(self)
self.ip = ip
self.port = port
self.clientsocket = clientsocket
self.protocol = Protocol(clientsocket)
def run(self):
try:
self.execute()
except ClosureException:
return
def execute(self):
# Method where the service runs
pass
class PermanentServiceThread(ServiceThread):
def __init__(self):
threading.Thread.__init__(self)
self._is_running = True
def is_running(self):
return self._is_running
def stop(self):
self._is_running = False

Loading…
Peruuta
Tallenna