Commit 87f01404efebb9fcc9ec72a595e805ee30e1c17b

Authored by Brice Colombier
1 parent 4b6935e6b8
Exists in master

More tabs, a status bar

Showing 11 changed files with 682 additions and 102 deletions

GUI/add_frame_elements.py View file @ 87f0140
... ... @@ -18,7 +18,8 @@
18 18 text="COM port (ex: COM3)")
19 19 self.com_port_text.pack(side=LEFT)
20 20 self.com_port_entry = Entry(self.motherboard_frame,
21   - width=10)
  21 + width=10,
  22 + textvariable=self.com_port)
22 23 self.com_port_entry.pack(side=LEFT)
23 24 self.com_port_button_connect = Button(self.motherboard_frame,
24 25 text="Connect",
... ... @@ -29,11 +30,6 @@
29 30 state=DISABLED,
30 31 command=self.disconnect)
31 32 self.com_port_button_disconnect.pack(side=LEFT)
32   - self.com_port_status_text = Label(self.motherboard_frame,
33   - text="Disconnected",
34   - foreground="red",
35   - font="-weight bold")
36   - self.com_port_status_text.pack()
37 33 # ------------------------------------------------------
38 34 self.Spartan_6_pick = Radiobutton(self.daughterboard_frame,
39 35 text="Xilinx Spartan 6",
... ... @@ -55,14 +51,6 @@
55 51 self.SmartFusion_2_pick.grid(row=0,
56 52 column=2)
57 53 # ------------------------------------------------------
58   - self.reference_response_frame = LabelFrame(self.PUF_frame,
59   - text="Reference response",
60   - style="Green.TLabelframe")
61   - self.reference_response_frame.pack(side=TOP)
62   - self.CASCADE_frame = LabelFrame(self.PUF_frame,
63   - text="CASCADE protocol",
64   - style="Green.TLabelframe")
65   - self.CASCADE_frame.pack(side=LEFT)
66 54 self.reconciliation_parameters_label = Label(self.CASCADE_frame,
67 55 text="Parameters:")
68 56 self.reconciliation_parameters_label.grid(row=0, column=0)
69 57  
70 58  
71 59  
72 60  
... ... @@ -96,23 +84,33 @@
96 84 column=3,
97 85 rowspan=2,
98 86 padx=10)
99   - self.get_reference_response_button=Button(self.reference_response_frame,
  87 + self.get_reference_response_button=Button(self.get_PUF_reference_response_frame,
100 88 text="Get/update reference response",
101 89 command=self.get_PUF_reference_response,
102   - width=28)
  90 + width=28,
  91 + state="disabled")
103 92 self.get_reference_response_button.pack(side=LEFT)
104   - self.reference_response_label=Label(self.reference_response_frame,
105   - textvariable=self.PUF_reference_response,
  93 + self.reference_response_label=Label(self.get_PUF_reference_response_frame,
  94 + textvariable=self.PUF_reference_response_displayed,
106 95 font=("Courier", 8),
107 96 background="white")
108 97 self.reference_response_label.pack(side=LEFT, padx=10)
  98 + self.derive_key_button=Button(self.key_derivation_frame,
  99 + text="Derive a key from the response",
  100 + command=self.derive_key_from_response,
  101 + width=28,
  102 + state="disabled")
  103 + self.derive_key_button.pack(side=LEFT)
  104 + self.key_saved_label=Label(self.key_derivation_frame,
  105 + textvariable=self.message_key_saved)
  106 + self.key_saved_label.pack(side=LEFT)
109 107 # ------------------------------------------------------
110 108 self.button_open_design=Button(self.file_frame,
111 109 text="Open design",
112 110 command=self.open_file)
113 111 self.button_open_design.pack(side=LEFT)
114 112 self.filename_label=Label(self.file_frame,
115   - textvariable=self.filename)
  113 + textvariable=self.filename)
116 114 self.filename_label.pack(side=LEFT)
117 115 # -------------------------------------------------------
118 116 self.locking_button=Checkbutton(self.modify_design_frame,
119 117  
... ... @@ -200,9 +198,22 @@
200 198 self.modify_design_button.grid(row=2, column=0)
201 199 # -------------------------------------------------------
202 200 self.generate_modified_design_button=Button(self.generate_modified_design_frame,
203   - text="Generate modified design")
  201 + text="Generate modified design",
  202 + state="disabled")
204 203 self.generate_modified_design_button.pack(side=LEFT)
205 204 # -------------------------------------------------------
  205 + self.label_program=Label(self.program_daughterboard_frame,
  206 + text="Bitstream:")
  207 + self.label_program.pack(side=LEFT)
  208 + self.bitstream_entry = Entry(self.program_daughterboard_frame,
  209 + textvariable=self.bitstream)
  210 + self.bitstream_entry.pack(side=LEFT,
  211 + expand="yes",
  212 + fill="x")
  213 + self.search_bitstream_button=Button(self.program_daughterboard_frame,
  214 + text="Search...",
  215 + command=self.open_bitstream_file)
  216 + self.search_bitstream_button.pack(side=LEFT)
206 217 self.program_daughterboard_button=Button(self.program_daughterboard_frame,
207 218 text="Program HECTOR daughterboard")
208 219 self.program_daughterboard_button.pack(side=LEFT)
GUI/build_menu.py View file @ 87f0140
... ... @@ -19,7 +19,7 @@
19 19 self.filemenu = Menu(self.menubar, tearoff=0)
20 20 self.filemenu.add_command(label="Exit", command=master.quit)
21 21 self.menubar.add_cascade(label="File", menu=self.filemenu)
22   -
  22 +
23 23 self.helpmenu = Menu(self.menubar, tearoff=0)
24 24 self.helpmenu.add_command(label="License", command=self.pop_up_license)
25 25 self.helpmenu.add_command(label="About", command=self.pop_up_about)
GUI/contents/Logo_SALWARE.gif View file @ 87f0140

4.12 KB

GUI/contents/icon.ico View file @ 87f0140

No preview for this file type

GUI/declare_initialize_variables.py View file @ 87f0140
... ... @@ -18,8 +18,8 @@
18 18 self.locking = BooleanVar()
19 19 self.daughter_board = StringVar()
20 20 self.daughter_board.set("")
21   - self.PUF_reference_response = StringVar()
22   - self.PUF_reference_response.set(256*" ")
  21 + self.PUF_reference_response_displayed = StringVar()
  22 + self.PUF_reference_response_displayed.set(256*" ")
23 23 self.filepath = StringVar()
24 24 self.filename = StringVar()
25 25 self.filename.set("No design loaded")
... ... @@ -41,4 +41,13 @@
41 41 self.masking_heuristic.set("random")
42 42 self.connected = BooleanVar()
43 43 self.connected.set(False)
  44 +
  45 + self.message_key_saved = StringVar()
  46 + self.message_key_saved.set("")
  47 +
  48 + self.status = StringVar()
  49 + self.status.set("Board not connected")
  50 +
  51 + self.bitstream = StringVar()
  52 + self.bitstream.set("./../User_space/design.bit")
GUI/declare_pack_frames.py View file @ 87f0140
... ... @@ -10,30 +10,46 @@
10 10 from ttk import *
11 11  
12 12  
13   -def declare_pack_frames(self, tab_logic_modifier, tab_enrolment, tab_activation):
  13 +def declare_pack_frames(self):
14 14  
15 15 """Declare the main GUI frames and pack them"""
16 16  
17   - self.motherboard_frame = LabelFrame(tab_activation, text="HECTOR motherboard")
18   - self.motherboard_frame.pack(side=TOP, fill=X)
19   -
20   - self.daughterboard_frame = LabelFrame(tab_activation, text="HECTOR daughterboard")
21   - self.daughterboard_frame.pack(side=TOP, fill=X)
22   -
23   - self.PUF_frame = LabelFrame(tab_activation, text="PUF")
24   - self.PUF_frame.pack(side=TOP, fill=X)
  17 + # Tab logic modifier
25 18  
26   - self.file_frame = LabelFrame(tab_logic_modifier, text="Current design")
  19 + self.file_frame = LabelFrame(self.tab_logic_modifier, text="Current design")
27 20 self.file_frame.pack(side=TOP, fill=X)
28 21  
29   - self.modify_design_frame = LabelFrame(tab_logic_modifier, text="Modify design")
30   - self.modify_design_frame.pack(fill="both", expand="yes")
  22 + self.modify_design_frame = LabelFrame(self.tab_logic_modifier, text="Modify design")
  23 + self.modify_design_frame.pack(fill="x")
31 24  
32   - self.generate_modified_design_frame = LabelFrame(tab_logic_modifier,
  25 + self.generate_modified_design_frame = LabelFrame(self.tab_logic_modifier,
33 26 text="Generate modified design")
34   - self.generate_modified_design_frame.pack(fill="both", expand="yes")
  27 + self.generate_modified_design_frame.pack(fill="x")
  28 +
  29 + # Tab HECTOR board management
35 30  
36   - self.program_daughterboard_frame = LabelFrame(tab_activation,
  31 + self.motherboard_frame = LabelFrame(self.tab_HECTOR_board_management, text="HECTOR motherboard")
  32 + self.motherboard_frame.pack(side=TOP, fill=X)
  33 +
  34 + self.daughterboard_frame = LabelFrame(self.tab_HECTOR_board_management, text="HECTOR daughterboard")
  35 + self.daughterboard_frame.pack(side=TOP, fill=X)
  36 +
  37 + self.program_daughterboard_frame = LabelFrame(self.tab_HECTOR_board_management,
37 38 text="Program HECTOR daughterboard")
38   - self.program_daughterboard_frame.pack(fill="both", expand="yes")
  39 + self.program_daughterboard_frame.pack(fill="x")
  40 +
  41 + # Tab enrolment
  42 +
  43 + self.get_PUF_reference_response_frame = LabelFrame(self.tab_enrolment,
  44 + text="PUF reference response")
  45 + self.get_PUF_reference_response_frame.pack(fill="x", side="top")
  46 + self.key_derivation_frame = LabelFrame(self.tab_enrolment,
  47 + text="Key derivation")
  48 + self.key_derivation_frame.pack(fill="x", side="top")
  49 +
  50 + # Tab activation
  51 +
  52 + self.CASCADE_frame = LabelFrame(self.tab_activation,
  53 + text="CASCADE protocol")
  54 + self.CASCADE_frame.pack(fill="x")
GUI/icon.ico View file @ 87f0140

No preview for this file type

GUI/tabbed_app.py View file @ 87f0140
... ... @@ -24,31 +24,40 @@
24 24 import masking
25 25 sys.path.append("../Locking/")
26 26 import locking
  27 +sys.path.append("../Key_derivation/")
  28 +import blake2
  29 +
  30 +
  31 +
27 32 class App:
28 33  
29 34 """Main class for the demonstrator GUI app"""
30 35  
31 36 def __init__(self, master):
32 37  
33   - s = Style()
34   - s.configure("Green.TLabelframe.Label",
35   - foreground="darkgreen")
36   -
37 38 master.maxsize(width=770, height=280)
38 39 master.minsize(width=770, height=280)
39 40 master.resizable(width=False, height=False)
40 41 master.title("SALWARE IP protection tool")
41   - master.iconbitmap(default='icon.ico')
  42 + master.iconbitmap(default='./contents/icon.ico')
42 43  
43   - # Tabs bar
44   - note = Notebook(master)
45   - tab_logic_modifier = Frame(note)
46   - note.add(tab_logic_modifier, text="Logic modifier", padding=[0, 5, 0, 0])
47   - tab_enrolment = Frame(note)
48   - note.add(tab_enrolment, text="Enrolment", padding=[0, 5, 0, 0])
49   - tab_activation = Frame(note)
50   - note.add(tab_activation, text="Activation", padding=[0, 5, 0, 0])
51   - note.pack()
  44 + # Tabs and status bar
  45 + self.note = Notebook(master, width = 762)
  46 + self.tab_logic_modifier = Frame(self.note)
  47 + self.note.add(self.tab_logic_modifier,
  48 + text="Logic modifier",
  49 + padding=[0, 5, 0, 0])
  50 + self.tab_enrolment = Frame(self.note)
  51 + self.tab_HECTOR_board_management = Frame(self.note)
  52 + self.note.add(self.tab_HECTOR_board_management,
  53 + text="HECTOR board management",
  54 + padding=[0, 5, 0, 0])
  55 + self.note.add(self.tab_enrolment, text="Enrolment",
  56 + padding=[0, 5, 0, 0])
  57 + self.tab_activation = Frame(self.note)
  58 + self.note.add(self.tab_activation, text="Activation",
  59 + padding=[0, 5, 0, 0])
  60 + self.note.pack(side = "top", fill="y", expand="yes")
52 61  
53 62 # Menu bar
54 63 build_menu.build_menu(self, master)
55 64  
... ... @@ -57,11 +66,21 @@
57 66 declare_initialize_variables.declare_initialize_variables(self)
58 67  
59 68 # Frames
60   - declare_pack_frames.declare_pack_frames(self, tab_logic_modifier, tab_activation, tab_enrolment)
  69 + declare_pack_frames.declare_pack_frames(self)
61 70  
62 71 # Frame elements
63 72 add_frame_elements.add_frame_elements(self)
64 73  
  74 + self.status_bar_frame = Frame(master, borderwidth=1, relief="ridge")
  75 + self.status_bar_frame.pack(side="bottom",fill="x")
  76 + self.status_label = Label(self.status_bar_frame,
  77 + textvariable=self.status,
  78 + foreground="red",
  79 + relief="ridge",
  80 + padding=[5, 0, 5, 0])
  81 + self.status_label.pack(side="right")
  82 +
  83 +
65 84 def open_file(self):
66 85  
67 86 ftypes = [("BENCH files", ".txt"),
... ... @@ -77,6 +96,10 @@
77 96 if self.filepath.get():
78 97 self.filename.set(self.filepath.get().split("/")[-1])
79 98  
  99 + def open_bitstream_file(self):
  100 + btypes = [("Xilinx bitstream", ".bit")]
  101 + self.bitstream.set(tkFileDialog.askopenfilename(filetypes=btypes))
  102 +
80 103 def round_masking(self, _): # Dummy second argument
81 104 self.masking_overhead.set(int(round(self.masking_overhead.get())))
82 105  
83 106  
84 107  
... ... @@ -84,17 +107,20 @@
84 107 self.locking_overhead.set(int(round(self.locking_overhead.get())))
85 108  
86 109 def get_PUF_reference_response(self):
87   - self.PUF_reference_response.set(hex(random.randint(0, 2**256))[2:-1])
88   - self.PUF_reference_response.set(" ".join(self.PUF_reference_response.get()[i:i+4] for i in range(0, len(self.PUF_reference_response.get()), 4)))
  110 + self.PUF_reference_response = ''.join(random.SystemRandom().choice(["0", "1"]) for _ in range(256))
  111 + self.PUF_reference_response_displayed.set(hex(int(self.PUF_reference_response, 2))[2:-1])
  112 +
89 113 # To be continued
90 114 self.reconciliation_performed.set(False)
91 115 self.reference_response_available.set(True)
  116 + self.message_key_saved.set("")
92 117  
93 118 def check_reference_response_available(self, a, b, c): # a, b, c dummy variables
94 119 if self.reference_response_available.get():
95 120 self.perform_reconciliation_button.configure(state="normal")
96 121 self.reconciliation_parameter_initial_block_size_spinbox.configure(state="normal")
97 122 self.reconciliation_parameter_number_of_passes_spinbox.configure(state="normal")
  123 + self.derive_key_button.configure(state="normal")
98 124  
99 125 def perform_reconciliation(self):
100 126 # To be continued
... ... @@ -115,7 +141,7 @@
115 141 self.modify_design_button.configure(state="disabled")
116 142  
117 143 def pop_up_about(self):
118   - self.top = Toplevel()
  144 + self.top = Toplevel(background="White")
119 145 self.top.title("About")
120 146  
121 147 self.msg = Label(self.top, text="This software was realised in the frame of\n\
... ... @@ -126,6 +152,12 @@
126 152 funding for this project was also provided by\n\
127 153 a grant from \"La Région Rhône-Alpes\".", background="white")
128 154 self.msg.pack()
  155 + self.salware_logo = PhotoImage(file="./contents/Logo_SALWARE.gif")
  156 +
  157 + self.label = Label(self.top,
  158 + image=self.salware_logo)
  159 + self.label.image = self.salware_logo # keep a reference!
  160 + self.label.pack()
129 161  
130 162 def pop_up_license(self):
131 163 self.top = Toplevel()
132 164  
... ... @@ -159,11 +191,18 @@
159 191 if self.masking.get():
160 192 masking.masking(g, prim_in, prim_out, nodes, self.masking_overhead, self.masking_heuristic)
161 193  
  194 + def derive_key_from_response(self):
  195 + self.salt = bytes(''.join(random.SystemRandom().choice(["0", "1"]) for _ in range(32)))
  196 + PRK_f = blake2.BLAKE2s(digest_size=32, key=self.salt)
  197 + PRK_f.update(self.PUF_reference_response)
  198 + self.key = ''.join('{0:08b}'.format(ord(x), 'b') for x in PRK_f.final()).replace("0b", "")
  199 + key_file_name = "./../User_space/key_"+""+".txt"
  200 + with open(key_file_name, "w") as key_file:
  201 + key_file.write("Key = "+self.key)
  202 + self.message_key_saved.set("Key saved under "+key_file_name)
  203 +
162 204 def every_second():
163   - if str(app.com_port_status_text.cget("foreground")) == "red":
164   - app.com_port_status_text.configure(foreground="black")
165   - elif str(app.com_port_status_text.cget("foreground")) == "black":
166   - app.com_port_status_text.configure(foreground="red")
  205 + # To be filled
167 206 fenetre.after(1000, every_second)
168 207  
169 208 if __name__ == "__main__":
Key_derivation/blake2.py View file @ 87f0140
  1 +
  2 +# encoding: utf-8
  3 +
  4 +doc = """
  5 +
  6 + blake2.py -- version 1
  7 +
  8 + This 100% Python implementation of BLAKE2 supports both
  9 + BLAKE2b and BLAKE2s. It runs under both Python 2.7 and
  10 + Python 3.3.
  11 +
  12 + https://blake2.net
  13 +
  14 + -----
  15 +
  16 + This copyright and license may change for future
  17 + versions. Until then...
  18 +
  19 + Copyright (c) 2013 by Larry Bugbee, Kent, WA
  20 + ALL RIGHTS RESERVED.
  21 +
  22 + blake2.py IS EXPERIMENTAL SOFTWARE FOR EDUCATIONAL
  23 + PURPOSES ONLY. IT IS MADE AVAILABLE "AS-IS" WITHOUT
  24 + WARRANTY OR GUARANTEE OF ANY KIND. USE SIGNIFIES
  25 + ACCEPTANCE OF ALL RISK.
  26 +
  27 + To make your learning and experimentation less
  28 + cumbersome, blake2.py is free for any use.
  29 +
  30 +
  31 + Enjoy,
  32 +
  33 + Larry Bugbee
  34 + December 2013
  35 +
  36 +"""
  37 +
  38 +import struct, binascii, copy
  39 +from ctypes import *
  40 +
  41 +
  42 +DBUG = False # True False
  43 +DBUG2 = False # True False
  44 +
  45 +if DBUG:
  46 + print('')
  47 + print(' *** this is a beta version of blake2.py ***')
  48 + print(' *** look for a final version in coming weeks ***')
  49 +
  50 +
  51 +MASK8BITS = 0xff
  52 +MASK16BITS = 0xffff
  53 +MASK32BITS = 0xffffffff
  54 +MASK48BITS = 0xffffffffffff
  55 +MASK64BITS = 0xffffffffffffffff
  56 +
  57 +
  58 +#---------------------------------------------------------------
  59 +
  60 +class BLAKE2(object):
  61 + """ BLAKE2 is a base class for BLAKE2b and BLAKE2s """
  62 +
  63 + sigma = [
  64 + [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 ],
  65 + [ 14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3 ],
  66 + [ 11, 8,12, 0, 5, 2,15,13,10,14, 3, 6, 7, 1, 9, 4 ],
  67 + [ 7, 9, 3, 1,13,12,11,14, 2, 6, 5,10, 4, 0,15, 8 ],
  68 + [ 9, 0, 5, 7, 2, 4,10,15,14, 1,11,12, 6, 8, 3,13 ],
  69 + [ 2,12, 6,10, 0,11, 8, 3, 4,13, 7, 5,15,14, 1, 9 ],
  70 + [ 12, 5, 1,15,14,13, 4,10, 0, 7, 6, 3, 9, 2, 8,11 ],
  71 + [ 13,11, 7,14,12, 1, 3, 9, 5, 0,15, 4, 8, 6, 2,10 ],
  72 + [ 6,15,14, 9,11, 3, 0, 8,12, 2,13, 7, 1, 4,10, 5 ],
  73 + [ 10, 2, 8, 4, 7, 6, 1, 5,15,11, 9,14, 3,12,13 ,0 ],
  74 + [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 ],
  75 + [ 14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3 ]
  76 + ] # only 1st 10 rows are used by BLAKE2s
  77 +
  78 +
  79 + # - - - - - - - - - - - - - - - - - - - - - - - - - - -
  80 +
  81 + def __init__(self, digest_size=0, **args):
  82 + print("""
  83 + ***********************************************
  84 + * You just instantiated a base class. Please *
  85 + * instantiate either BLAKE2b or BLAKE2s. *
  86 + ***********************************************
  87 + """)
  88 + raise Exception('base class instantiation')
  89 +
  90 +
  91 + # - - - - - - - - - - - - - - - - - - - - - - - - - - -
  92 +
  93 + def _init(self, key=b''):
  94 +
  95 + assert len(key) <= self.KEYBYTES
  96 +
  97 + # load parameters
  98 + P = self.PARAMS()
  99 + P.F.digest_size = self.digest_size
  100 + P.F.key_length = len(key)
  101 + P.F.fanout = self.fanout
  102 + P.F.depth = self.depth
  103 + P.F.leaf_size = self.leaf_size
  104 + P.F.node_offset_lo = self.node_offset & MASK32BITS
  105 + P.F.node_offset_hi = self.node_offset >> 32
  106 + P.F.node_depth = self.node_depth
  107 + P.F.inner_size = self.inner_size
  108 +# P.F.reserved is not defined in BLAKE2s so we cannot init it
  109 +# to zeros for both BLAKE2s and BLAKE2b here. Fortunately ctypes
  110 +# initializes to zeros so we don't have to. :-))
  111 +# P.F.reserved = chr(0) * 14
  112 + P.F.salt = (self.salt +
  113 + (chr(0).encode())*(self.SALTBYTES-len(self.salt)))
  114 + P.F.person = (self.person +
  115 + (chr(0).encode())*(self.PERSONALBYTES-len(self.person)))
  116 +
  117 +
  118 + if DBUG2:
  119 + print('')
  120 + fmt = '%0' + str(self.WORDBYTES*2) + 'x'
  121 + for i in range(8):
  122 + print(' %2d: %s' % (i*8, fmt % P.W[i]))
  123 +
  124 +
  125 + self.h = [self.IV[i] ^ P.W[i] for i in range(8)]
  126 +
  127 + self.totbytes = 0
  128 + self.t = [0]*2
  129 + self.f = [0]*2
  130 + self.buflen = 0
  131 + self.buf = b''
  132 + self.finalized = False
  133 + self.block_size = self.BLOCKBYTES
  134 +
  135 + if key:
  136 + block = key + (chr(0).encode())*(self.BLOCKBYTES-len(key))
  137 + self.update(block)
  138 +
  139 + if self.data:
  140 + self.update(self.data)
  141 +
  142 +
  143 + # - - - - - - - - - - - - - - - - - - - - - - - - - - -
  144 +
  145 + def _compress(self, block):
  146 +
  147 + # Dereference these for [very small] speed improvement.
  148 + # Perhaps more than anything, this makes the code
  149 + # easier to read.
  150 + MASKBITS = self.MASKBITS
  151 + WORDBITS = self.WORDBITS
  152 + WORDBYTES = self.WORDBYTES
  153 + IV = self.IV
  154 + sigma = self.sigma
  155 + ROT1 = self.ROT1
  156 + ROT2 = self.ROT2
  157 + ROT3 = self.ROT3
  158 + ROT4 = self.ROT4
  159 + WB_ROT1 = WORDBITS - ROT1
  160 + WB_ROT2 = WORDBITS - ROT2
  161 + WB_ROT3 = WORDBITS - ROT3
  162 + WB_ROT4 = WORDBITS - ROT4
  163 +
  164 + # convert block (bytes) into 16 LE words
  165 + m = struct.unpack_from('<16%s' % self.WORDFMT, bytes(block))
  166 +
  167 + v = [0]*16
  168 + v[ 0: 8] = self.h
  169 + v[ 8:12] = IV[:4]
  170 + v[12] = self.t[0] ^ IV[4]
  171 + v[13] = self.t[1] ^ IV[5]
  172 + v[14] = self.f[0] ^ IV[6]
  173 + v[15] = self.f[1] ^ IV[7]
  174 +
  175 + # Within the confines of the Python language, this is a
  176 + # highly optimized version of G(). It differs some from
  177 + # the formal specification and reference implementation.
  178 + def G(a, b, c, d):
  179 + # dereference v[] for another small speed improvement
  180 + va = v[a]
  181 + vb = v[b]
  182 + vc = v[c]
  183 + vd = v[d]
  184 + va = (va + vb + msri2) & MASKBITS
  185 + w = vd ^ va
  186 + vd = (w >> ROT1) | (w << (WB_ROT1)) & MASKBITS
  187 + vc = (vc + vd) & MASKBITS
  188 + w = vb ^ vc
  189 + vb = (w >> ROT2) | (w << (WB_ROT2)) & MASKBITS
  190 + va = (va + vb + msri21) & MASKBITS
  191 + w = vd ^ va
  192 + vd = (w >> ROT3) | (w << (WB_ROT3)) & MASKBITS
  193 + vc = (vc + vd) & MASKBITS
  194 + w = vb ^ vc
  195 + vb = (w >> ROT4) | (w << (WB_ROT4)) & MASKBITS
  196 + # re-reference v[]
  197 + v[a] = va
  198 + v[b] = vb
  199 + v[c] = vc
  200 + v[d] = vd
  201 +
  202 + # time to ChaCha
  203 + for r in range(self.ROUNDS):
  204 + # resolve as much as possible outside G() and
  205 + # don't pass as argument, let scope do its job.
  206 + # Result is a 50% speed increase, but sadly,
  207 + # "slow" divided by 1.5 is still "slow". :-/
  208 + sr = sigma[r]
  209 + msri2 = m[sr[0]]
  210 + msri21 = m[sr[1]]
  211 + G( 0, 4, 8, 12)
  212 + msri2 = m[sr[2]]
  213 + msri21 = m[sr[3]]
  214 + G( 1, 5, 9, 13)
  215 + msri2 = m[sr[4]]
  216 + msri21 = m[sr[5]]
  217 + G( 2, 6, 10, 14)
  218 + msri2 = m[sr[6]]
  219 + msri21 = m[sr[7]]
  220 + G( 3, 7, 11, 15)
  221 + msri2 = m[sr[8]]
  222 + msri21 = m[sr[9]]
  223 + G( 0, 5, 10, 15)
  224 + msri2 = m[sr[10]]
  225 + msri21 = m[sr[11]]
  226 + G( 1, 6, 11, 12)
  227 + msri2 = m[sr[12]]
  228 + msri21 = m[sr[13]]
  229 + G( 2, 7, 8, 13)
  230 + msri2 = m[sr[14]]
  231 + msri21 = m[sr[15]]
  232 + G( 3, 4, 9, 14)
  233 +
  234 + self.h = [self.h[i] ^ v[i] ^ v[i+8] for i in range(8)]
  235 +
  236 +
  237 + # - - - - - - - - - - - - - - - - - - - - - - - - - - -
  238 +
  239 + def update(self, data):
  240 +
  241 + assert self.finalized == False
  242 +
  243 + BLOCKBYTES = self.BLOCKBYTES
  244 +
  245 + datalen = len(data)
  246 + dataptr = 0
  247 + while True:
  248 + if len(self.buf) > BLOCKBYTES:
  249 + self._increment_counter(BLOCKBYTES)
  250 + self._compress(self.buf[:BLOCKBYTES])
  251 + self.buf = self.buf[BLOCKBYTES:]
  252 + if dataptr < datalen:
  253 + self.buf += data[dataptr:dataptr + BLOCKBYTES]
  254 + dataptr += BLOCKBYTES
  255 + else:
  256 + break
  257 +
  258 +
  259 + # - - - - - - - - - - - - - - - - - - - - - - - - - - -
  260 +
  261 + def final(self):
  262 + # is there any residue remaining to be processed?
  263 + if not self.finalized and len(self.buf):
  264 + self._increment_counter(len(self.buf))
  265 + self._set_lastblock()
  266 + # add padding
  267 + self.buf += (chr(0).encode())*(self.BLOCKBYTES - len(self.buf))
  268 + # final compress
  269 + self._compress(self.buf)
  270 + self.buf = b'' # nothing more (no residue)
  271 + # convert 8 LE words into digest (bytestring)
  272 + self.digest_ = struct.pack('<8%s' % self.WORDFMT, *tuple(self.h))
  273 + self.finalized = True
  274 + return self.digest_[:self.digest_size]
  275 +
  276 + digest = final
  277 +
  278 + def hexdigest(self):
  279 + return binascii.hexlify(self.final()).decode()
  280 +
  281 +
  282 + # - - - - - - - - - - - - - - - - - - - - - - - - - - -
  283 + # f0 = 0 if NOT last block, 0xffffffff... if last block
  284 + # f1 = 0 if sequential mode or (tree mode and NOT last
  285 + # node), 0xffffffff... if tree mode AND last node
  286 +
  287 + def _set_lastblock(self):
  288 + if self.last_node:
  289 + self.f[1] = self.MASKBITS
  290 + self.f[0] = self.MASKBITS
  291 +
  292 + def _increment_counter(self, numbytes):
  293 + self.totbytes += numbytes
  294 + self.t[0] = self.totbytes & self.MASKBITS
  295 + self.t[1] = self.totbytes >> self.WORDBITS
  296 +
  297 +
  298 + # - - - - - - - - - - - - - - - - - - - - - - - - - - -
  299 + # common utility functions
  300 +
  301 + def copy(self):
  302 + return copy.deepcopy(self)
  303 +
  304 +
  305 +#---------------------------------------------------------------
  306 +
  307 +class BLAKE2b(BLAKE2):
  308 +
  309 + WORDBITS = 64
  310 + WORDBYTES = 8
  311 + MASKBITS = MASK64BITS
  312 + WORDFMT = 'Q' # used in _compress() and final()
  313 +
  314 + ROUNDS = 12
  315 + BLOCKBYTES = 128
  316 + OUTBYTES = 64
  317 + KEYBYTES = 64
  318 + SALTBYTES = 16 # see also hardcoded value in ParamFields64
  319 + PERSONALBYTES = 16 # see also hardcoded value in ParamFields64
  320 +
  321 + IV = [
  322 + 0x6a09e667f3bcc908, 0xbb67ae8584caa73b,
  323 + 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
  324 + 0x510e527fade682d1, 0x9b05688c2b3e6c1f,
  325 + 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179
  326 + ]
  327 +
  328 + ROT1 = 32
  329 + ROT2 = 24
  330 + ROT3 = 16
  331 + ROT4 = 63
  332 +
  333 +
  334 + # - - - - - - - - - - - - - - - - - - - - - - - - - - -
  335 +
  336 + def __init__(self, data=b'', digest_size=64, key=b'',
  337 + salt=b'', person=b'', fanout=1, depth=1,
  338 + leaf_size=0, node_offset=0, node_depth=0,
  339 + inner_size=0, last_node=False):
  340 +
  341 + assert 1 <= digest_size <= self.OUTBYTES
  342 + assert len(key) <= self.KEYBYTES
  343 + assert len(salt) <= self.SALTBYTES
  344 + assert len(person) <= self.PERSONALBYTES
  345 + assert 0 <= fanout <= MASK8BITS
  346 + assert 0 <= depth <= MASK8BITS
  347 + assert 0 <= leaf_size <= MASK32BITS
  348 + assert 0 <= node_offset <= MASK64BITS
  349 + assert 0 <= node_depth <= MASK8BITS
  350 + assert 0 <= inner_size <= MASK8BITS
  351 +
  352 + # - - - - - - - - - - - - - - - - - - - - - - - - -
  353 + # use ctypes LittleEndianStructure and Union as a
  354 + # convenient way to organize complex structs, convert
  355 + # to little endian, and access by words
  356 + class ParamFields64(LittleEndianStructure):
  357 + _fields_ = [("digest_size", c_ubyte),
  358 + ("key_length", c_ubyte),
  359 + ("fanout", c_ubyte),
  360 + ("depth", c_ubyte),
  361 + ("leaf_size", c_uint32),
  362 + ("node_offset_lo", c_uint32),
  363 + ("node_offset_hi", c_uint32),
  364 + ("node_depth", c_ubyte),
  365 + ("inner_size", c_ubyte),
  366 + ("reserved", c_char * 14),
  367 + ("salt", c_char * 16),
  368 + ("person", c_char * 16),
  369 + ]
  370 +
  371 + class Params64(Union):
  372 + _fields_ = [("F", ParamFields64),
  373 + ("W", c_uint64 * 8),
  374 + ]
  375 +
  376 + # this next makes PARAMS a 'proper' instance variable
  377 + self.PARAMS = Params64
  378 +
  379 + # key is passed as an argument; all other variables are
  380 + # defined as instance variables
  381 + self.digest_size = digest_size
  382 + self.data = data
  383 + self.salt = salt
  384 + self.person = person
  385 + self.fanout = fanout
  386 + self.depth = depth
  387 + self.leaf_size = leaf_size
  388 + self.node_offset = node_offset
  389 + self.node_depth = node_depth
  390 + self.inner_size = inner_size
  391 + self.last_node = last_node
  392 +
  393 + # now call init routine common to BLAKE2b and BLAKE2s
  394 + self._init(key=key)
  395 +
  396 +
  397 +#---------------------------------------------------------------
  398 +
  399 +class BLAKE2s(BLAKE2):
  400 +
  401 + WORDBITS = 32
  402 + WORDBYTES = 4
  403 + MASKBITS = MASK32BITS
  404 + WORDFMT = 'L' # used in _compress() and final()
  405 +
  406 + ROUNDS = 10
  407 + BLOCKBYTES = 64
  408 + OUTBYTES = 32
  409 + KEYBYTES = 32
  410 + SALTBYTES = 8
  411 + PERSONALBYTES = 8
  412 +
  413 + IV = [
  414 + 0x6a09e667, 0xbb67ae85,
  415 + 0x3c6ef372, 0xa54ff53a,
  416 + 0x510e527f, 0x9b05688c,
  417 + 0x1f83d9ab, 0x5be0cd19
  418 + ]
  419 +
  420 + ROT1 = 16
  421 + ROT2 = 12
  422 + ROT3 = 8
  423 + ROT4 = 7
  424 +
  425 +
  426 + # - - - - - - - - - - - - - - - - - - - - - - - - - - -
  427 +
  428 + def __init__(self, data=b'', digest_size=32, key=b'',
  429 + salt=b'', person=b'', fanout=1, depth=1,
  430 + leaf_size=0, node_offset=0, node_depth=0,
  431 + inner_size=0, last_node=False):
  432 +
  433 + assert 1 <= digest_size <= self.OUTBYTES
  434 + assert len(key) <= self.KEYBYTES
  435 + assert len(salt) <= self.SALTBYTES
  436 + assert len(person) <= self.PERSONALBYTES
  437 + assert 0 <= fanout <= MASK8BITS
  438 + assert 0 <= depth <= MASK8BITS
  439 + assert 0 <= leaf_size <= MASK32BITS
  440 + assert 0 <= node_offset <= MASK48BITS
  441 + assert 0 <= node_depth <= MASK8BITS
  442 + assert 0 <= inner_size <= MASK8BITS
  443 +
  444 + # there is a circular class relationship having
  445 + # to do with defining the values of SALTBYTES and
  446 + # PERSONALBYTES. By creating an empty class and
  447 + # loading its contents individually, we get access
  448 + # to the parent block's scope and have to define the
  449 + # field's values only once. ...but this can look
  450 + # confusing. Perhaps it is better to define the
  451 + # values 16 and 8 twice and annotate the second
  452 + # occurance. It's not like the values will be
  453 + # changing often. Which is better? BLAKE2b is
  454 + # defined twice and BLAKE2s uses the empty class
  455 + # approach.
  456 +
  457 + class ParamFields32(LittleEndianStructure):
  458 + pass
  459 +
  460 + ParamFields32.SALTBYTES = self.SALTBYTES
  461 + ParamFields32.PERSONALBYTES = self.PERSONALBYTES
  462 + ParamFields32._fields_ = [
  463 + ("digest_size", c_ubyte),
  464 + ("key_length", c_ubyte),
  465 + ("fanout", c_ubyte),
  466 + ("depth", c_ubyte),
  467 + ("leaf_size", c_uint32),
  468 + ("node_offset_lo", c_uint32),
  469 + ("node_offset_hi", c_uint16),
  470 + ("node_depth", c_ubyte),
  471 + ("inner_size", c_ubyte),
  472 + ("salt", c_char * self.SALTBYTES),
  473 + ("person", c_char * self.PERSONALBYTES),
  474 + ]
  475 +
  476 + class Params32(Union):
  477 + _fields_ = [("F", ParamFields32),
  478 + ("W", c_uint32 * 8),
  479 + ]
  480 +
  481 + # this next makes PARAMS union a 'proper' instance variable
  482 + self.PARAMS = Params32
  483 +
  484 + # key is passed as an argument; all other variables are
  485 + # defined as instance variables
  486 + self.digest_size = digest_size
  487 + self.data = data
  488 + self.salt = salt
  489 + self.person = person
  490 + self.fanout = fanout
  491 + self.depth = depth
  492 + self.leaf_size = leaf_size
  493 + self.node_offset = node_offset
  494 + self.node_depth = node_depth
  495 + self.inner_size = inner_size
  496 + self.last_node = last_node
  497 +
  498 + # now call init routine common to BLAKE2b and BLAKE2s
  499 + self._init(key=key)
  500 +
  501 +
  502 +#---------------------------------------------------------------
  503 +#---------------------------------------------------------------
  504 +#---------------------------------------------------------------
Key_derivation/key_expander.vhd View file @ 87f0140
  1 +--Header
  2 +
  3 +LIBRARY ieee;
  4 +USE ieee.std_logic_1164.ALL;
  5 +
  6 +ENTITY key_expander IS
  7 +
  8 + GENERIC (
  9 + ACTIVATION_WORD_SIZE : INTEGER := 128;
  10 + UN_LOCKING_WORD_SIZE : INTEGER := 128;
  11 + UN_MASKING_WORD_SIZE : INTEGER := 128);
  12 +
  13 + PORT (
  14 + activation_word : IN STD_LOGIC_VECTOR(ACTIVATION_WORD_SIZE - 1 DOWNTO 0);
  15 + un_locking_word : OUT STD_LOGIC_VECTOR(UN_LOCKING_WORD_SIZE - 1 DOWNTO 0);
  16 + un_masking_word : OUT STD_LOGIC_VECTOR(UN_MASKING_WORD_SIZE - 1 DOWNTO 0));
  17 +
  18 +END ENTITY key_expander;
  19 +
  20 +ARCHITECTURE rtl OF key_expander IS
  21 +
  22 + CONSTANT EXPECTED_ACTIVATION_WORD : STD_LOGIC_VECTOR(ACTIVATION_WORD_SIZE - 1 DOWNTO 0);
  23 + CONSTANT LOCKING_WORD : STD_LOGIC_VECTOR(UN_LOCKING_WORD_SIZE - 1 DOWNTO 0);
  24 + CONSTANT UNLOCKING_WORD : STD_LOGIC_VECTOR(UN_LOCKING_WORD_SIZE - 1 DOWNTO 0);
  25 + CONSTANT UNMASKING_WORD : STD_LOGIC_VECTOR(UN_MASKING_WORD_SIZE - 1 DOWNTO 0);
  26 +
  27 +BEGIN -- ARCHITECTURE rtl
  28 +
  29 + PROCESS (activation_word) IS
  30 + BEGIN -- PROCESS
  31 + IF activation_word = EXPECTED_ACTIVATION_WORD THEN
  32 + un_locking_word <= UNLOCKING_WORD;
  33 + un_masking_word <= UNMASKING_WORD;
  34 + ELSE
  35 + un_locking_word <= LOCKING_WORD;
  36 + un_masking_word <= activation_word;
  37 + END IF;
  38 + END PROCESS;
  39 +
  40 +END ARCHITECTURE rtl;
Key_expansion/key_expander.vhd View file @ 87f0140
1   ---Header
2   -
3   -LIBRARY ieee;
4   -USE ieee.std_logic_1164.ALL;
5   -
6   -ENTITY key_expander IS
7   -
8   - GENERIC (
9   - ACTIVATION_WORD_SIZE : INTEGER := 128;
10   - UN_LOCKING_WORD_SIZE : INTEGER := 128;
11   - UN_MASKING_WORD_SIZE : INTEGER := 128);
12   -
13   - PORT (
14   - activation_word : IN STD_LOGIC_VECTOR(ACTIVATION_WORD_SIZE - 1 DOWNTO 0);
15   - un_locking_word : OUT STD_LOGIC_VECTOR(UN_LOCKING_WORD_SIZE - 1 DOWNTO 0);
16   - un_masking_word : OUT STD_LOGIC_VECTOR(UN_MASKING_WORD_SIZE - 1 DOWNTO 0));
17   -
18   -END ENTITY key_expander;
19   -
20   -ARCHITECTURE rtl OF key_expander IS
21   -
22   - CONSTANT EXPECTED_ACTIVATION_WORD : STD_LOGIC_VECTOR(ACTIVATION_WORD_SIZE - 1 DOWNTO 0);
23   - CONSTANT LOCKING_WORD : STD_LOGIC_VECTOR(UN_LOCKING_WORD_SIZE - 1 DOWNTO 0);
24   - CONSTANT UNLOCKING_WORD : STD_LOGIC_VECTOR(UN_LOCKING_WORD_SIZE - 1 DOWNTO 0);
25   - CONSTANT UNMASKING_WORD : STD_LOGIC_VECTOR(UN_MASKING_WORD_SIZE - 1 DOWNTO 0);
26   -
27   -BEGIN -- ARCHITECTURE rtl
28   -
29   - PROCESS (activation_word) IS
30   - BEGIN -- PROCESS
31   - IF activation_word = EXPECTED_ACTIVATION_WORD THEN
32   - un_locking_word <= UNLOCKING_WORD;
33   - un_masking_word <= UNMASKING_WORD;
34   - ELSE
35   - un_locking_word <= LOCKING_WORD;
36   - un_masking_word <= activation_word;
37   - END IF;
38   - END PROCESS;
39   -
40   -END ARCHITECTURE rtl;