aboutsummaryrefslogtreecommitdiff
path: root/projects/hsm
diff options
context:
space:
mode:
Diffstat (limited to 'projects/hsm')
-rwxr-xr-xprojects/hsm/cryptech_upload190
1 files changed, 131 insertions, 59 deletions
diff --git a/projects/hsm/cryptech_upload b/projects/hsm/cryptech_upload
index 559195d..b6e02bd 100755
--- a/projects/hsm/cryptech_upload
+++ b/projects/hsm/cryptech_upload
@@ -37,6 +37,7 @@ import sys
import time
import struct
import serial
+import socket
import getpass
import os.path
import tarfile
@@ -46,7 +47,7 @@ import platform
from binascii import crc32
FIRMWARE_CHUNK_SIZE = 4096
-FPGA_CHUNK_SIZE = 4096
+FPGA_CHUNK_SIZE = 4096
def parse_args():
@@ -70,6 +71,12 @@ def parse_args():
help = "Name of management port USB serial device",
)
+ parser.add_argument("--socket",
+ default = os.getenv("CRYPTECH_CTY_CLIENT_SOCKET_NAME",
+ "/tmp/.cryptech_muxd.cty"),
+ help = "Name of cryptech_muxd management port socket",
+ )
+
parser.add_argument("--firmware-tarball",
type = argparse.FileType("rb"),
default = default_tarball,
@@ -126,63 +133,126 @@ def parse_args():
return parser.parse_args()
-def _write(dst, data):
- numeric = isinstance(data, (int, long))
- if numeric:
- data = struct.pack("<I", data)
- dst.write(data)
- dst.flush()
- if args.debug:
+class ManagementPortAbstract(object):
+ """
+ Abstract class encapsulating actions on the HSM management port.
+ """
+
+ def __init__(self, args):
+ self.args = args
+
+ def write(self, data):
+ numeric = isinstance(data, (int, long))
if numeric:
- print("Wrote 0x{!s}".format(data.encode("hex")))
- else:
- print("Wrote {!r}".format(data))
-
-def _read(dst):
- res = ""
- x = dst.read(1)
- while not x:
- x = dst.read(1)
- while x:
- res += x
- x = dst.read(1)
- if args.debug:
- print ("Read {!r}".format(res))
- return res
-
-def _execute(dst, cmd):
- global args
- _write(dst, "\r")
- prompt = _read(dst)
- #if prompt.endswith("This is the bootloader speaking..."):
- # prompt = _read(dst)
- if prompt.endswith("Username: "):
- _write(dst, args.username + "\r")
- prompt = _read(dst)
- if prompt.endswith("Password: "):
- if not args.pin or args.separate_pins:
- args.pin = getpass.getpass("{} PIN: ".format(args.username))
- _write(dst, args.pin + "\r")
- prompt = _read(dst)
- if not prompt.endswith(("> ", "# ")):
- print("Device does not seem to be ready for a file transfer (got {!r})".format(prompt))
- return prompt
- _write(dst, cmd + "\r")
- response = _read(dst)
- return response
+ data = struct.pack("<I", data)
+ self.send(data)
+ if self.args.debug:
+ if numeric:
+ print("Wrote 0x{!s}".format(data.encode("hex")))
+ else:
+ print("Wrote {!r}".format(data))
+
+ def read(self):
+ res = ""
+ x = self.recv()
+ while not x:
+ x = self.recv()
+ while x:
+ res += x
+ x = self.recv()
+ if self.args.debug:
+ print ("Read {!r}".format(res))
+ return res
+
+ def execute(self, cmd):
+ self.write("\r")
+ prompt = self.read()
+ #if prompt.endswith("This is the bootloader speaking..."):
+ # prompt = self.read()
+ if prompt.endswith("Username: "):
+ self.write(self.args.username + "\r")
+ prompt = self.read()
+ if prompt.endswith("Password: "):
+ if not self.args.pin or self.args.separate_pins:
+ self.args.pin = getpass.getpass("{} PIN: ".format(self.args.username))
+ self.write(self.args.pin + "\r")
+ prompt = self.read()
+ if not prompt.endswith(("> ", "# ")):
+ print("Device does not seem to be ready for a file transfer (got {!r})".format(prompt))
+ return prompt
+ self.write(cmd + "\r")
+ response = self.read()
+ return response
+
+
+class ManagementPortSerial(ManagementPortAbstract):
+ """
+ Implmentation of HSM management port abstraction over a direct
+ serial connection.
+ """
+
+ def __init__(self, args, timeout = 1):
+ super(ManagementPortSerial, self).__init__(args)
+ self.serial = serial.Serial(args.device, 921600, timeout = timeout)
+
+ def send(self, data):
+ self.serial.write(data)
+ self.serial.flush()
+
+ def recv(self):
+ return self.serial.read(1)
+
+ def set_timeout(self, timeout):
+ self.serial.timeout = timeout
+
+ def close(self):
+ self.serial.close()
+
+class ManagementPortSocket(ManagementPortAbstract):
+ """
+ Implmentation of HSM management port abstraction over a PF_UNIX
+ socket connection to the cryptech_muxd management socket.
+ """
+
+ def __init__(self, args, timeout = 1):
+ super(ManagementPortSocket, self).__init__(args)
+ self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ self.socket.connect(args.socket)
+ self.socket.settimeout(timeout)
+
+ def send(self, data):
+ self.socket.sendall(data)
+
+ def recv(self):
+ try:
+ return self.socket.recv(1)
+ except socket.timeout:
+ return ""
+
+ def set_timeout(self, timeout):
+ self.socket.settimeout(timeout)
+
+ def close(self):
+ self.socket.close()
+
def send_file(src, size, args, dst):
+ """
+ Upload an image from some file-like source to the management port.
+ Details depend on what kind of image it is.
+ """
+
if args.fpga:
chunk_size = FPGA_CHUNK_SIZE
- response = _execute(dst, "fpga bitstream upload")
+ response = dst.execute("fpga bitstream upload")
elif args.firmware:
chunk_size = FIRMWARE_CHUNK_SIZE
- response = _execute(dst, "firmware upload")
+ response = dst.execute("firmware upload")
if "Rebooting" in response:
- response = _execute(dst, "firmware upload")
+ response = dst.execute("firmware upload")
elif args.bootloader:
chunk_size = FIRMWARE_CHUNK_SIZE
- response = _execute(dst, "bootloader upload")
+ response = dst.execute("bootloader upload")
if "Access denied" in response:
print "Access denied"
return False
@@ -190,12 +260,12 @@ def send_file(src, size, args, dst):
print("Device did not accept the upload command (got {!r})".format(response))
return False
- dst.timeout = 0.001
+ dst.set_timeout(0.001)
crc = 0
counter = 0
# 1. Write size of file (4 bytes)
- _write(dst, struct.pack("<I", size))
- response = _read(dst)
+ dst.write(struct.pack("<I", size))
+ response = dst.read()
if not response.startswith("Send "):
print response
return False
@@ -205,13 +275,12 @@ def send_file(src, size, args, dst):
for counter in xrange(chunks):
data = src.read(chunk_size)
dst.write(data)
- dst.flush()
if not args.quiet:
print("Wrote {!s} bytes (chunk {!s}/{!s})".format(len(data), counter + 1, chunks))
# read ACK (a counter of number of 4k chunks received)
ack_bytes = ""
while len(ack_bytes) < 4:
- ack_bytes += _read(dst)
+ ack_bytes += dst.read()
ack = struct.unpack("<I", ack_bytes[:4])[0]
if ack != counter + 1:
print("ERROR: Did not receive the expected counter as ACK (got {!r}/{!r}, not {!r})".format(ack, ack_bytes, counter))
@@ -221,8 +290,8 @@ def send_file(src, size, args, dst):
crc = crc32(data, crc) & 0xffffffff
# 3. Write CRC-32 (4 bytes)
- _write(dst, struct.pack("<I", crc))
- response = _read(dst)
+ dst.write(struct.pack("<I", crc))
+ response = dst.read()
if not args.quiet:
print response
@@ -230,10 +299,10 @@ def send_file(src, size, args, dst):
if args.fpga:
# tell the fpga to read its new configuration
- _execute(dst, "fpga reset")
+ dst.execute("fpga reset")
# log out of the CLI
# (firmware/bootloader upgrades reboot, don't need an exit)
- _execute(dst, "exit")
+ dst.execute("exit")
return True
@@ -300,8 +369,11 @@ def main():
print "Uploading {} from {}".format(name, args.firmware_tarball.name)
if not args.quiet:
- print "Initializing serial port and synchronizing with HSM, this may take a few seconds"
- dst = serial.Serial(args.device, 921600, timeout = 1)
+ print "Initializing management port and synchronizing with HSM, this may take a few seconds"
+ try:
+ dst = ManagementPortSocket(args, timeout = 1)
+ except socket.error as e:
+ dst = ManagementPortSerial(args, timeout = 1)
send_file(src, size, args, dst)
dst.close()
ode&id=c2b116a5e46ed89bf1426def0c447d2e46cc9474'>c2b116a
d56ce9a
c2b116a



d56ce9a

c2b116a
d56ce9a


c2b116a
c2b116a

d56ce9a


c2b116a
38c4b78
c2b116a



d56ce9a



c2b116a
d56ce9a
c2b116a





b121408
a1e4e4f

c2b116a
d56ce9a

c2b116a



d56ce9a

c2b116a
d56ce9a
c2b116a
b121408
c2b116a

a1e4e4f
c2b116a













38c4b78
c2b116a





a1e4e4f

a1e4e4f

86b35d7
c2b116a

8f9c3d1
b121408
8f9c3d1

c2b116a
d56ce9a

8f9c3d1
c2b116a

8f9c3d1
d56ce9a

8f9c3d1
d56ce9a
c2b116a
















d56ce9a

c2b116a
d56ce9a





c2b116a
8f9c3d1
d56ce9a

8f9c3d1


c2b116a
421626c

c2b116a







d56ce9a

86b35d7




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321