Commit 48c73d73fa8001c9910eb5def17adb3f78716ae1

Authored by Brice Colombier
1 parent 1ca3b2c206
Exists in master

Reverse reference response to match board response

Showing 12 changed files with 200 additions and 72 deletions

CASCADE/binary_par.py View file @ 48c73d7
... ... @@ -28,7 +28,6 @@
28 28 blocks_return = []
29 29 ref_rep = []
30 30 parities = gpfi.get_parities_from_indices(blocks_to_correct_first_half, tclsh, board_manager)
31   - print parities
32 31 if len(blocks_to_correct[0]) > 2:
33 32 for i, j in enumerate(parities):
34 33 if par.parity(reference_response[i][:block_size/2], j):
CASCADE/cascade.py View file @ 48c73d7
... ... @@ -56,6 +56,7 @@
56 56  
57 57 split.split(reference_response, block_size)
58 58 split.split(indices, block_size)
  59 + print "Parity check"
59 60 parities = gpfi.get_parities_from_indices(indices, tclsh, board_manager)
60 61 blocks_to_correct = []
61 62 reference_response_to_correct = []
62 63  
... ... @@ -71,10 +72,8 @@
71 72 if passe > 0:
72 73 even_parity_blocks.append(indices[block_index])
73 74 if blocks_to_correct:
74   - print "Narrow down to single bit errors"
75   - # Narrow down to single bit errors
  75 + print "Narrow down to single bit errors to correct "+str(len(blocks_to_correct))+" blocks"
76 76 while len(blocks_to_correct[0]) > 2:
77   - print blocks_to_correct
78 77 reference_response_to_correct, blocks_to_correct = bi_par.binary_par(reference_response_to_correct, blocks_to_correct, tclsh, board_manager)
79 78 # Final BINARY execution where single PUF bits are queried from the board
80 79 _, indices_to_flip = bi_par.binary_par(reference_response_to_correct, blocks_to_correct, tclsh, board_manager)
... ... @@ -91,20 +90,21 @@
91 90 fb.flip_bits(reference_response, indices_to_flip, indices)
92 91 indices_to_flip = []
93 92 blocks_to_correct = []
94   - if passe > 0:
95   - # Backtracking process
96   - while odd_parity_blocks:
97   - backtracked_pos = 0
98   - block_to_correct = min(odd_parity_blocks, key=len) # Get the smallest block
99   - reference_response_block = [reference_response[indices.index(x)] for x in block_to_correct]
100   - while len(block_to_correct) > 2:
101   - [reference_response_block], [block_to_correct] = bi_par.binary_par([reference_response_block], [block_to_correct], tclsh, board_manager)
102   - # Final BINARY execution where single PUF bits are queried from the board
103   - _, backtracked_pos = bi_par.binary_par([reference_response_block], [block_to_correct], tclsh, board_manager)
104   - # backtracked_pos = bi.binary(reference_response_block, block_to_correct, response_on_board)
105   - fb.flip_bits(reference_response, backtracked_pos, indices)
106   - # Move blocks from one group to the other if they contain the bit to flip
107   - sb.swap_blocks(even_parity_blocks, odd_parity_blocks, backtracked_pos[0])
  93 + # if passe > 0:
  94 + # print "Backtracking process"
  95 + # # Backtracking process
  96 + # while odd_parity_blocks:
  97 + # backtracked_pos = 0
  98 + # block_to_correct = min(odd_parity_blocks, key=len) # Get the smallest block
  99 + # reference_response_block = [reference_response[indices.index(x)] for x in block_to_correct]
  100 + # while len(block_to_correct) > 2:
  101 + # [reference_response_block], [block_to_correct] = bi_par.binary_par([reference_response_block], [block_to_correct], tclsh, board_manager)
  102 + # # Final BINARY execution where single PUF bits are queried from the board
  103 + # _, backtracked_pos = bi_par.binary_par([reference_response_block], [block_to_correct], tclsh, board_manager)
  104 + # # backtracked_pos = bi.binary(reference_response_block, block_to_correct, response_on_board)
  105 + # fb.flip_bits(reference_response, backtracked_pos, indices)
  106 + # # Move blocks from one group to the other if they contain the bit to flip
  107 + # sb.swap_blocks(even_parity_blocks, odd_parity_blocks, backtracked_pos[0])
108 108 if [x for x in even_parity_blocks if x in odd_parity_blocks]:
109 109 raise ValueError("Blocks are simultaneously in the even and odd group")
110 110 # Un-shuffle
CASCADE/get_parities_from_indices.py View file @ 48c73d7
... ... @@ -8,6 +8,13 @@
8 8  
9 9 import Tkinter
10 10  
  11 +import os
  12 +
  13 +import sys
  14 +sys.path.append(os.path.abspath("./../"))
  15 +
  16 +from boards_management import board_commands
  17 +
11 18 def get_parities_from_indices(indices, tclsh, board_manager):
12 19  
13 20 """Get the parities of the on-board response blocks.
... ... @@ -22,5 +29,14 @@
22 29  
23 30  
24 31 if __name__ == "__main__":
25   - print get_parities_from_indices()
  32 + tcl_obj = Tkinter.Tcl()
  33 + board_manager = board_commands.Board_manager()
  34 + tcl_obj.eval(board_manager.source_tcl_package())
  35 + tcl_obj.eval(board_manager.connect("COM5"))
  36 + tcl_obj.eval(board_manager.reset_boards())
  37 + tcl_obj.eval(board_manager.generate_response())
  38 + indices = [range(i, i+4) for i in range(0, 64, 4)]
  39 + # indices = [[0, 1, 2, 3], [4, 5, 6, 7]]
  40 + print indices
  41 + print get_parities_from_indices(indices, tcl_obj, board_manager)
add_frame_elements.py View file @ 48c73d7
... ... @@ -268,10 +268,11 @@
268 268 self.activation_word_label = Label(self.activation_word_encryption_frame,
269 269 text="Activation word:")
270 270 self.activation_word_label.grid(sticky=E)
271   - self.activation_word_entry = Entry(self.activation_word_encryption_frame,
272   - textvariable=self.activation_word_file,
273   - width=90)
274   - self.activation_word_entry.grid(row=0, column=1, sticky="EW")
  271 + self.activation_word_display_label = Label(self.activation_word_encryption_frame,
  272 + textvariable=self.activation_word,
  273 + font=("Courier", 8),
  274 + background="white")
  275 + self.activation_word_display_label.grid(row=0, column=1, sticky="EW", padx=10)
275 276 self.search_activation_word_button = Button(self.activation_word_encryption_frame,
276 277 text="Search...",
277 278 command=self.open_activation_word)
... ... @@ -16,12 +16,12 @@
16 16 from Tkinter import *
17 17 from ttk import *
18 18  
19   -import add_frame_elements
20   -import build_menu
21   -import build_tabs
22   -import declare_initialize_variables
23   -import declare_pack_frames
24   -import status_bar
  19 +from add_frame_elements import add_frame_elements
  20 +from build_menu import build_menu
  21 +from build_tabs import build_tabs
  22 +from declare_initialize_variables import declare_initialize_variables
  23 +from declare_pack_frames import declare_pack_frames
  24 +from status_bar import status_bar
25 25  
26 26 from key_derivation.blake2 import BLAKE2s
27 27  
... ... @@ -46,6 +46,9 @@
46 46  
47 47 from CASCADE.cascade import cascade
48 48  
  49 +from response_converter.response_converter import response_converter_to_hex
  50 +from response_converter.response_converter import response_converter_to_bin_list
  51 +
49 52 class App:
50 53  
51 54 """Main class for the demonstrator GUI app"""
52 55  
53 56  
54 57  
55 58  
56 59  
... ... @@ -64,22 +67,22 @@
64 67 self.board_manager = board_commands.Board_manager()
65 68  
66 69 # Tabs
67   - build_tabs.build_tabs(self)
  70 + build_tabs(self)
68 71  
69 72 # Menu bar
70   - build_menu.build_menu(self)
  73 + build_menu(self)
71 74  
72 75 # Variables
73   - declare_initialize_variables.declare_initialize_variables(self)
  76 + declare_initialize_variables(self)
74 77  
75 78 # Frames
76   - declare_pack_frames.declare_pack_frames(self)
  79 + declare_pack_frames(self)
77 80  
78 81 # Frame elements
79   - add_frame_elements.add_frame_elements(self)
  82 + add_frame_elements(self)
80 83  
81 84 # Status bar
82   - status_bar.status_bar(self)
  85 + status_bar(self)
83 86  
84 87  
85 88 def select_file(self):
86 89  
87 90  
88 91  
... ... @@ -133,23 +136,27 @@
133 136 def open_server_reference_response(self):
134 137 rrtypes = [("Reference response file", ".txt")]
135 138 self.server_reference_response_file.set(tkFileDialog.askopenfilename(initialdir = "./../User_space/",
136   - filetypes=rrtypes))
  139 + filetypes=rrtypes))
137 140 with open(self.server_reference_response_file.get(), "r") as rrfile:
138 141 line = rrfile.readline()
139 142 if line[:20] != "Reference response: ":
140   - raise SyntaxError ("The file could not be parsed as a Reference response file")
  143 + raise SyntaxError ("The file could not be parsed as a Reference Response file")
141 144 else:
142   - self.server_reference_response = line[20:]
143   - for i in self.server_reference_response:
144   - if i not in ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"]:
145   - raise SyntaxError ("The reference response contains illegal characters")
146   - else:
147   - self.server_reference_response_displayed.set(self.server_reference_response)
  145 + self.server_reference_response = str(line[20:])
  146 + self.server_reference_response_displayed.set(self.server_reference_response)
  147 + self.server_reference_response = response_converter_to_bin_list(self.server_reference_response)
148 148  
149 149 def open_activation_word(self):
150   - ttypes = [("Activation word", ".txt")]
151   - self.activation_word_file.set(tkFileDialog.askopenfilename(initialdir = "./../User_space/",
152   - filetypes=ttypes))
  150 + awtypes = [("Activation word", ".txt")]
  151 + self.activation_word_file = tkFileDialog.askopenfilename(initialdir = "./../User_space/",
  152 + filetypes=awtypes)
  153 + with open(self.activation_word_file, "r") as awfile:
  154 + line = awfile.readline()
  155 + line = awfile.readline() # Get the second line
  156 + if not set(line) <= {"0", "1"}:
  157 + raise SyntaxError ("The file could not be parsed as an Activation Word file")
  158 + else:
  159 + self.activation_word.set(line)
153 160  
154 161 def round_masking(self, _): # Dummy second argument
155 162 self.masking_overhead.set(int(round(self.masking_overhead.get())))
... ... @@ -160,13 +167,11 @@
160 167 def get_PUF_response(self):
161 168 self.PUF_response_displayed.set("")
162 169 try:
163   - self.PUF_response_displayed.set(self.tcl_obj.eval(self.board_manager.generate_and_offload_response()))
164   - self.PUF_response = self.PUF_response_displayed.get()
165   - temporary_response = ""
166   - for i in self.PUF_response:
167   - binary = bin(int(i, 16))[2:]
168   - temporary_response+=((4-len(binary))*"0"+binary)
169   - self.PUF_response = [int(i) for i in temporary_response]
  170 + self.tcl_obj.eval(self.board_manager.reset_boards())
  171 + self.tcl_obj.eval(self.board_manager.generate_response())
  172 + temp_hex_response = self.tcl_obj.eval(self.board_manager.offload_response())
  173 + self.PUF_response = list(reversed(response_converter_to_bin_list(temp_hex_response)))
  174 + self.PUF_response_displayed.set(response_converter_to_hex(self.PUF_response))
170 175 except:
171 176 self.status.set("Response could not be obtained")
172 177  
... ... @@ -253,7 +258,7 @@
253 258 self.prim_in,
254 259 self.prim_out,
255 260 self.nodes,
256   - self.masking_overhead.get(),
  261 + self.locking_overhead.get(),
257 262 self.masking_heuristic.get())
258 263 elif self.masking.get():
259 264 self.graph_modified, self.unmasking_word = masking(self.g,
260 265  
... ... @@ -303,19 +308,21 @@
303 308 self.message_AW_saved.set(str("Activation word saved under "+filename))
304 309  
305 310 def perform_reconciliation(self):
306   - cascade(self.PUF_response,
307   - 0.02,
308   - int(self.reconciliation_parameter_number_of_passes_spinbox.get()),
309   - self.tcl_obj,
310   - self.board_manager,
311   - int(self.reconciliation_parameter_initial_block_size_spinbox.get()))
  311 + self.tcl_obj.eval(self.board_manager.reset_boards())
  312 + self.tcl_obj.eval(self.board_manager.generate_response())
  313 + self.server_reference_response = cascade(self.server_reference_response,
  314 + 0.02,
  315 + int(self.reconciliation_parameter_number_of_passes_spinbox.get()),
  316 + self.tcl_obj,
  317 + self.board_manager,
  318 + int(self.reconciliation_parameter_initial_block_size_spinbox.get()))
312 319 print ("Reconciliation done")
313 320  
314 321 def reset_board(self):
315 322 self.tcl_obj.eval(self.board_manager.reset_boards())
316 323  
317 324 def reset(self):
318   - print "Not implemented yet"
  325 + print ("To be implemented soon")
319 326  
320 327 def every_second():
321 328 # To be filled
... ... @@ -324,7 +331,6 @@
324 331 if __name__ == "__main__":
325 332  
326 333 fenetre = Tk()
327   -
328 334 app = App(fenetre)
329 335  
330 336 fenetre.after(1000, every_second)
boards_management/board_commands.py View file @ 48c73d7
... ... @@ -37,9 +37,12 @@
37 37 command = "selectDaughterBoard $dev "+str(port)+"\n"
38 38 return command
39 39  
40   - def generate_and_offload_response(self):
41   - command = "sendFabricCommand $dev 4 7\n\
42   -sendFabricCommand $dev 4 3\n\
  40 + def generate_response(self):
  41 + command = "sendFabricCommand $dev 4 7\n"
  42 + return command
  43 +
  44 + def offload_response(self):
  45 + command = "sendFabricCommand $dev 4 3\n\
43 46 set rep \"[sendFabricCommand $dev 5 3]\
44 47 [sendFabricCommand $dev 5 2]\
45 48 [sendFabricCommand $dev 5 1]\
boards_management/get_response.py View file @ 48c73d7
... ... @@ -18,7 +18,9 @@
18 18 board_manager = board_commands.Board_manager()
19 19 tclsh.eval(board_manager.source_tcl_package())
20 20 tclsh.eval(board_manager.connect("COM5"))
21   - response = tclsh.eval(board_manager.generate_and_offload_response())
  21 + tclsh.eval(board_manager.reset_boards())
  22 + tclsh.eval(board_manager.generate_response())
  23 + response = tclsh.eval(board_manager.offload_response())
22 24 return response
23 25  
24 26  
declare_initialize_variables.py View file @ 48c73d7
... ... @@ -52,8 +52,8 @@
52 52 self.save_as_reference_response_status = StringVar()
53 53 self.save_as_reference_response_status.set("")
54 54  
55   - self.activation_word_file = StringVar()
56   - self.activation_word_file.set("")
  55 + self.activation_word = StringVar()
  56 + self.activation_word.set("")
57 57 self.design_format = StringVar()
58 58 self.design_format.set("BENCH")
59 59 self.generated_design_format = StringVar()
declare_pack_frames.py View file @ 48c73d7
... ... @@ -37,10 +37,7 @@
37 37 self.get_PUF_response_frame = LabelFrame(self.tab_enrolment,
38 38 text="PUF response")
39 39 self.get_PUF_response_frame.pack(fill="x", side="top")
40   - self.key_derivation_frame = LabelFrame(self.tab_enrolment,
41   - text="Key derivation")
42   - self.key_derivation_frame.pack(fill="x", side="top")
43   -
  40 +
44 41 # Tab activation
45 42 self.load_server_reference_response_frame = LabelFrame(self.tab_activation,
46 43 text="Load server reference response")
... ... @@ -48,6 +45,9 @@
48 45 self.CASCADE_frame = LabelFrame(self.tab_activation,
49 46 text="CASCADE protocol")
50 47 self.CASCADE_frame.pack(fill="x")
  48 + self.key_derivation_frame = LabelFrame(self.tab_activation,
  49 + text="Key derivation")
  50 + self.key_derivation_frame.pack(fill="x", side="top")
51 51 self.activation_word_encryption_frame = LabelFrame(self.tab_activation,
52 52 text="Activation word encryption")
53 53 self.activation_word_encryption_frame.pack(fill="x")
locking/locking.py View file @ 48c73d7
... ... @@ -45,6 +45,8 @@
45 45 if len(list_nodes_to_lock) > (float(overhead)/100) * len(nodes):
46 46 print "Overhead is too low to allow total locking"
47 47 print "some outputs will remain unaltered."
  48 + print len(list_nodes_to_lock)
  49 + print float(overhead)*len(nodes)/100
48 50 list_nodes_to_lock = list_nodes_to_lock[:overhead * len(nodes)]
49 51 h = modify_nodes_lock.modify_nodes_lock(h, list_nodes_to_lock)
50 52  
response_converter/response_converter.py View file @ 48c73d7
  1 +# Author: Brice Colombier
  2 +# Laboratoire Hubert Curien
  3 +# 42000 Saint-Etienne - France
  4 +# Contact: b.colombier@univ-st-etienne.fr
  5 +# Project: Demonstrator
  6 +# File: response_converter.py
  7 +# Date: 2016-11-04
  8 +
  9 +import unittest
  10 +from split import split
  11 +
  12 +def response_converter_to_hex(response):
  13 +
  14 + """Convert a response from binary list to hexadecimal string
  15 +
  16 + >>> response_converter_to_hex([0, 1, 0, 1])
  17 + '5'
  18 + >>> response_converter_to_hex([1, 1, 1, 1, 0, 1, 1, 0, 1, 0])
  19 + '3DA'
  20 + """
  21 +
  22 + if type(response) != list:
  23 + raise TypeError("Response must be a list")
  24 + elif set(response) != {0, 1}:
  25 + raise ValueError("The response list contains non-binary values")
  26 + temp_response = split(response, 4, start="tail")
  27 + temp_response = ["".join(map(str, x)) for x in temp_response]
  28 + return "".join(map(str, [hex(int(x, 2))[2:].upper() for x in temp_response]))
  29 +
  30 +def response_converter_to_bin_list(response):
  31 +
  32 + """Convert a response from hexadecimal string to binary list
  33 +
  34 + >>> response_converter_to_bin_list("A")
  35 + [1, 0, 1, 0]
  36 + >>> response_converter_to_bin_list("45")
  37 + [0, 1, 0, 0, 0, 1, 0, 1]
  38 + """
  39 +
  40 + if type(response) != str:
  41 + print type(response)
  42 + raise TypeError("Response must be a string")
  43 + if not set(response) <= {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}:
  44 + raise TypeError("Response contains non-hexadecimal characters")
  45 + temporary_response = ""
  46 + for i in response:
  47 + binary = bin(int(i, 16))[2:]
  48 + temporary_response+=((4-len(binary))*"0"+binary)
  49 + return [int(i) for i in temporary_response]
response_converter/split.py View file @ 48c73d7
  1 +# Author: Brice Colombier
  2 +# Laboratoire Hubert Curien
  3 +# 42000 Saint-Etienne - France
  4 +# Contact: b.colombier@univ-st-etienne.fr
  5 +# Project: Demonstrator
  6 +# File: split.py
  7 +# Date : 2016-10-12
  8 +
  9 +from copy import deepcopy
  10 +
  11 +def split(m, size, start="head"):
  12 +
  13 + """Split a list into blocks of equal size
  14 + starting from the head or the tail
  15 +
  16 + >>> split([0, 1, 0, 1], 2)
  17 + [[0, 1], [0, 1]]
  18 + >>> split([0, 1, 0, 1, 0, 1, 0, 1], 4)
  19 + [[0, 1, 0, 1], [0, 1, 0, 1]]
  20 +
  21 + """
  22 +
  23 + if start=="head":
  24 + m_ret = m
  25 + for i in range(int(len(m)/size)):
  26 + m_ret.append([m_ret.pop(0) for w in range(int(size))])
  27 + temp = []
  28 + while type(m_ret[0]) != list:
  29 + temp.append(m_ret.pop(0))
  30 + if temp:
  31 + m_ret+=[temp]
  32 + return m_ret
  33 + elif start=="tail":
  34 + m_temp = deepcopy(m)
  35 + m_ret = []
  36 + while len(m_temp) > size:
  37 + temp = []
  38 + for _ in range(size):
  39 + temp.append(m_temp.pop())
  40 + m_ret.append(list(reversed(temp)))
  41 + return [m_temp]+list(reversed(m_ret))
  42 +
  43 +if __name__ == "__main__":
  44 + print split([1, 2, 3, 4, 5, 6, 7, 8], 3, start="tail")
  45 + print split([1, 2, 3, 4, 5, 6, 7, 8], 3, start="head")
  46 + print split([1, 2, 3, 4, 5, 6, 7, 8], 4, start="tail")
  47 + print split([1, 2, 3, 4, 5, 6, 7, 8], 4, start="head")
  48 + print split([1, 2, 3, 4, 5, 6, 7, 8], 2, start="tail")
  49 + print split([1, 2, 3, 4, 5, 6, 7, 8], 2, start="head")