# -*- coding: utf-8 -*-
# Author: Brice Colombier
# Laboratoire Hubert Curien
# 42000 Saint-Etienne - France
# Contact: b.colombier@univ-st-etienne.fr
# Project: Demonstrator
# File: app.py
# Date: 2016-10-13
import random
import sys
import time
import tkFileDialog
from Tkinter import *
from ttk import *
import add_frame_elements
import build_menu
import build_tabs
import declare_initialize_variables
import declare_pack_frames
import status_bar
from key_derivation.blake2 import BLAKE2s
from locking.locking import locking
from masking.masking import masking
from parsers.build_bench import build as build_bench
from parsers.build_blif import build as build_blif
from parsers.build_edif import build as build_edif
from parsers.build_slif import build as build_slif
from parsers.build_verilog_df import build as build_verilog_df
from parsers.build_verilog_struct import build as build_verilog_struct
from parsers.build_vhd_df import build as build_vhd_df
from parsers.build_vhd_struct import build as build_vhd_struct
from parsers.build_xilinx import build as build_xilinx
from generate_modified_netlist.convert_back_bench import convert_back as convert_back_bench
from generate_modified_netlist.convert_back_vhd import convert_back as convert_back_vhd
from boards_management import board_commands
from CASCADE.cascade import cascade
class App:
"""Main class for the demonstrator GUI app"""
def __init__(self, master):
self.master = master
self.master.maxsize(width=1000, height=370)
self.master.minsize(width=1000, height=370)
self.master.resizable(width=False, height=False)
self.master.title("SALWARE IP protection tool")
self.master.iconbitmap(default='./contents/icon.ico')
self.tcl_obj = Tcl()
self.board_manager = board_commands.Board_manager()
# Tabs
build_tabs.build_tabs(self)
# Menu bar
build_menu.build_menu(self)
# Variables
declare_initialize_variables.declare_initialize_variables(self)
# Frames
declare_pack_frames.declare_pack_frames(self)
# Frame elements
add_frame_elements.add_frame_elements(self)
# Status bar
status_bar.status_bar(self)
def select_file(self):
ftypes = [("All netlist files", ".txt; .blif; .slif; .edf; .vhd; .v"),
("BENCH files", ".txt"),
("BLIF files", ".blif"),
("SLIF files", ".slif"),
("EDIF files", ".edf"),
("Xilinx EDIF files", ".edf"),
("Dataflow VHDL files", ".vhd"),
("Structural VHDL files", ".vhd"),
("Dataflow Verilog files", ".v"),
("Structural Verilog files", ".v")]
self.filename.set(tkFileDialog.askopenfilename(initialdir = "./user_space/",
filetypes=ftypes))
def build_graph(self):
self.graph_info.set(str("Building the graph from file "+self.filename.get().split("/")[-1]+"..."))
self.master.config(cursor="wait")
self.graph_info_label.configure(foreground="black")
self.master.update()
try:
if self.design_format.get() == "BENCH":
self.g, self.prim_in, self.prim_out, self.nodes = build_bench(self.filename.get())
elif self.design_format.get() == "BLIF":
self.g, self.prim_in, self.prim_out, self.nodes = build_blif(self.filename.get())
elif self.design_format.get() == "SLIF":
self.g, self.prim_in, self.prim_out, self.nodes = build_slif(self.filename.get())
elif self.design_format.get() == "EDIF":
self.g, self.prim_in, self.prim_out, self.nodes = build_edif(self.filename.get())
elif self.design_format.get() == "Xilinx EDIF":
self.g, self.prim_in, self.prim_out, self.nodes = build_xilinx(self.filename.get())
elif self.design_format.get() == "VHDL Dataflow":
self.g, self.prim_in, self.prim_out, self.nodes = build_vhd_df(self.filename.get())
elif self.design_format.get() == "VHDL Structural":
self.g, self.prim_in, self.prim_out, self.nodes = build_vhd_struct(self.filename.get())
elif self.design_format.get() == "Verilog Dataflow":
self.g, self.prim_in, self.prim_out, self.nodes = build_verilog_df(self.filename.get())
elif self.design_format.get() == "Verilog Structural":
self.g, self.prim_in, self.prim_out, self.nodes = build_verilog_struct(self.filename.get())
self.graph_info.set(str(str(len(self.nodes))+" nodes, "+
str(len(self.prim_in))+" inputs, "+
str(len(self.prim_out))+" outputs."))
except:
self.graph_info.set("Error in building the graph")
self.graph_info_label.configure(foreground="red")
self.master.config(cursor="")
self.master.update()
def open_server_reference_response(self):
rrtypes = [("Reference response file", ".txt")]
self.server_reference_response_file.set(tkFileDialog.askopenfilename(initialdir = "./../User_space/",
filetypes=rrtypes))
with open(self.server_reference_response_file.get(), "r") as rrfile:
line = rrfile.readline()
if line[:20] != "Reference response: ":
raise SyntaxError ("The file could not be parsed as a Reference response file")
else:
self.server_reference_response = line[20:]
for i in self.server_reference_response:
if i not in ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"]:
raise SyntaxError ("The reference response contains illegal characters")
else:
self.server_reference_response_displayed.set(self.server_reference_response)
def open_activation_word(self):
ttypes = [("Activation word", ".txt")]
self.activation_word_file.set(tkFileDialog.askopenfilename(initialdir = "./../User_space/",
filetypes=ttypes))
def round_masking(self, _): # Dummy second argument
self.masking_overhead.set(int(round(self.masking_overhead.get())))
def round_locking(self, _): # Dummy second argument
self.locking_overhead.set(int(round(self.locking_overhead.get())))
def get_PUF_response(self):
self.PUF_response_displayed.set("")
try:
self.PUF_response_displayed.set(self.tcl_obj.eval(self.board_manager.generate_and_offload_response()))
self.PUF_response = self.PUF_response_displayed.get()
temporary_response = ""
for i in self.PUF_response:
binary = bin(int(i, 16))[2:]
temporary_response+=((4-len(binary))*"0"+binary)
self.PUF_response = [int(i) for i in temporary_response]
except:
self.status.set("Response could not be obtained")
def save_as_reference_response(self):
with open("./user_space/rr.txt", "w") as rrfile:
rrfile.write("Reference response: "+self.PUF_response_displayed.get())
self.save_as_reference_response_status.set("Reference response saved under ./user_space/rr.txt")
def pop_up_about(self):
self.top = Toplevel(background="White")
self.top.title("About")
self.msg = Label(self.top, text="This software was realised in the frame of\n\
the SALWARE project number ANR-13-JS03-0003\n\
supported by the French \"Agence Nationale de\n\
la Recherche\" and by the French \"Fondation de\n\
Recherche pour l'Aéronautique et l'Espace\",\n\
funding for this project was also provided by\n\
a grant from \"La Région Rhône-Alpes\".", background="white")
self.msg.pack()
self.salware_logo = PhotoImage(file="./contents/Logo_SALWARE.gif")
self.label_salware_logo = Label(self.top,
image=self.salware_logo,
background="white")
self.label_salware_logo.image = self.salware_logo # keep a reference!
self.label_salware_logo.pack()
self.logo_RA = PhotoImage(file="./contents/Logo_RA.gif")
self.label_logo_RA = Label(self.top,
image=self.logo_RA,
background="white")
self.label_logo_RA.image = self.logo_RA # keep a reference!
self.label_logo_RA.pack()
def pop_up_license(self):
self.top = Toplevel()
self.top.title("License")
try:
self.License_file = open("LICENSE", 'r')
self.License_text = self.License_file.read()
self.License_file.close()
except:
self.License_text = "Cannot find LICENSE.txt"
self.msg = Label(self.top,
text=self.License_text,
background="white")
self.msg.pack()
def connect(self):
self.tcl_obj.eval(self.board_manager.source_tcl_package())
tcl_return = self.tcl_obj.eval(self.board_manager.connect(self.com_port.get()))
if tcl_return == "-1": # Error handling
self.status.set("Could not connect to the board")
else: # Connection successful
self.com_port_button_connect.configure(state=DISABLED)
self.com_port_button_disconnect.configure(state=NORMAL)
self.connected.set(True)
self.board_status.set("Board Connected")
self.board_status_label.configure(foreground="darkgreen")
self.status.set("")
def disconnect(self):
try:
self.tcl_obj.eval(self.board_manager.disconnect())
self.com_port_button_disconnect.configure(state=DISABLED)
self.com_port_button_connect.configure(state=NORMAL)
self.connected.set(False)
self.board_status.set("Board not connected")
self.board_status_label.configure(foreground="red")
except:
pass
def modify_design(self):
self.unlocking_word = ""
self.unmasking_word = ""
if self.locking.get():
self.graph_modified, self.unlocking_word = locking(self.g,
self.prim_in,
self.prim_out,
self.nodes,
self.locking_overhead.get())
if self.masking.get():
self.graph_modified, self.unmasking_word = masking(self.graph_modified,
self.prim_in,
self.prim_out,
self.nodes,
self.masking_overhead.get(),
self.masking_heuristic.get())
elif self.masking.get():
self.graph_modified, self.unmasking_word = masking(self.g,
self.prim_in,
self.prim_out,
self.nodes,
self.masking_overhead.get(),
self.masking_heuristic.get())
print self.unlocking_word, self.unmasking_word
def derive_key_from_response(self):
self.salt = bytes(''.join(random.SystemRandom().choice(["0", "1"]) for _ in range(32)))
PRK_f = BLAKE2s(digest_size=32, key=self.salt)
PRK_f.update(self.PUF_response_displayed)
self.key = ''.join('{0:08b}'.format(ord(x), 'b') for x in PRK_f.final()).replace("0b", "")
key_file_name = "./user_space/key_"+""+".txt"
with open(key_file_name, "w") as key_file:
key_file.write("Salt = "+self.salt+"\n")
key_file.write("Key = "+self.key)
self.message_key_saved.set("Key saved under "+key_file_name)
def generate_save_modified_design(self):
filename = self.filename.get().split("/")[-1]
filename = filename.split(".")
filename[0]+="_mod"
if self.generated_design_format.get() == "vhd":
filename[1] = "vhd"
filename = ".".join(filename)
filename = "/".join(self.filename.get().split("/")[:-1])+"/"+filename
convert_back_vhd(self.graph_modified, filename)
elif self.generated_design_format.get() == "bench":
filename[1] = "txt"
filename = ".".join(filename)
filename = "/".join(self.filename.get().split("/")[:-1])+"/"+filename
convert_back_bench(self.graph_modified, filename)
self.message_modified_design_saved.set(str("Modified design saved under "+filename))
def save_AW(self):
filename = self.filename.get().split("/")[-1]
filename = filename.split(".")
filename[0]+="_mod_AW"
filename[1] = "txt"
filename = ".".join(filename)
filename = "/".join(self.filename.get().split("/")[:-1])+"/"+filename
with open(filename, "w") as aw_file:
aw_file.write("Unocking word concatenated with unmasking word\n"+self.unlocking_word+self.unmasking_word)
self.message_AW_saved.set(str("Activation word saved under "+filename))
def perform_reconciliation(self):
cascade(self.PUF_response,
0.02,
int(self.reconciliation_parameter_number_of_passes_spinbox.get()),
self.tcl_obj,
self.board_manager,
int(self.reconciliation_parameter_initial_block_size_spinbox.get()))
print ("Reconciliation done")
def reset_board(self):
self.tcl_obj.eval(self.board_manager.reset_boards())
def reset(self):
print "Not implemented yet"
def every_second():
# To be filled
fenetre.after(1000, every_second)
if __name__ == "__main__":
fenetre = Tk()
app = App(fenetre)
fenetre.after(1000, every_second)
fenetre.mainloop()