Skip to content

Commit bc0ff76

Browse files
committed
SAE progress
1 parent 51f9ae4 commit bc0ff76

2 files changed

Lines changed: 100 additions & 31 deletions

File tree

TODO

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,6 @@ TODO: Do we need the owner field in class Block? We known the owner by virtue of
9595

9696
TODO: If signature validation fails, return fragment to pool
9797

98-
TODO: Test case for this
98+
TODO: Test case for this
99+
100+
TODO: Error message if --client or --hub does not exist in topology

manager.py

Lines changed: 97 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -300,87 +300,147 @@ def etsi_qkd(self):
300300
"""
301301
ETSI QKD operations.
302302
"""
303-
master_node = self.find_kme_node_for_sae(self._args.master_sae_id)
304-
slave_node = self.find_kme_node_for_sae(self._args.slave_sae_id)
303+
# ETSI QKD 014 uses different terminology than DSKE:
304+
#
305+
# ETSI QKD 014 term DSKE term
306+
# ---------------------------------- ----------------------------------
307+
# SAE (Secure Application Entity) Encryptor
308+
# SAE ID Encryptor name
309+
# KME (Key Management Entity) Client
310+
# KME ID Client name
311+
# N/A Hub
312+
# N/A Hub name
313+
#
314+
# In the code related to ETSI QKD 014, we use the ETSI terminology.
315+
316+
master_sae_id = self._args.master_sae_id
317+
slave_sae_id = self._args.slave_sae_id
318+
master_kme_node = self.find_kme_node_for_sae_id(master_sae_id)
319+
slave_kme_node = self.find_kme_node_for_sae_id(slave_sae_id)
305320
match self._args.etsi_qkd_command:
306321
case "get-status":
307-
self.etsi_qkd_get_status(master_node, slave_node)
322+
self.etsi_qkd_get_status(master_kme_node, master_sae_id, slave_sae_id)
308323
case "get-key":
309324
size = self._args.size
310-
self.etsi_qkd_get_key(master_node, slave_node, size)
325+
self.etsi_qkd_get_key(
326+
master_kme_node, master_sae_id, slave_sae_id, size
327+
)
311328
case "get-key-with-key-ids":
312329
key_id = self._args.key_id
313-
self.etsi_qkd_get_key_with_key_ids(master_node, slave_node, key_id)
330+
self.etsi_qkd_get_key_with_key_ids(
331+
slave_kme_node, master_sae_id, slave_sae_id, key_id
332+
)
314333
case "get-key-pair":
315334
size = self._args.size
316-
self.etsi_qkd_get_key_pair(master_node, slave_node, size)
335+
self.etsi_qkd_get_key_pair(
336+
master_kme_node, slave_kme_node, master_sae_id, slave_sae_id, size
337+
)
317338

318-
def find_kme_node_for_sae(self, sae_id: str) -> Node:
339+
def find_kme_node_for_sae_id(self, sae_id: str) -> Node:
319340
"""
320-
Given an SAE ID, find the KME node that is associated with it.
341+
Given an encryptor name (SAE ID), find the client node (KME) that is associated with it.
321342
"""
322-
# $$$
323343
for node in self._nodes:
324-
if node.type == NodeType.CLIENT and node.name == sae_id:
344+
if node.type == NodeType.CLIENT and sae_id in node.encryptor_names:
325345
return node
326-
self.fatal_error(f"Could not find KME client node for SAE ID {sae_id}")
346+
self.fatal_error(
347+
f"There is no encryptor (SAE) in the topology with name (SAE ID) {sae_id}"
348+
)
349+
350+
# In the following ETSI QKD 014 API calls, the master SAE ID neither passed in a request query
351+
# parameter nor passed as a JSON attribute in the request body. In real life, the KME would
352+
# determine the SAE ID from the TLS authentication. However, we only have a simplified
353+
# implementation of ETSI QKD 014 without HTTPS (TLS). For that reason, we pass the master SAE ID
354+
# in cleartext in an HTTP "Authorization" header. This is, of course, not secure, but it is
355+
# sufficient for our simplified implementation and testing purposes.
327356

328-
def etsi_qkd_get_status(self, master_node: Node, slave_node: Node):
357+
def etsi_qkd_get_status(
358+
self,
359+
master_kme_node: Node,
360+
master_sae_id: str,
361+
slave_sae_id: str,
362+
):
329363
"""
330364
Invoke the ETSI QKD Status API.
331365
"""
332366
print(
333-
f"Invoke ETSI QKD Status API for client {master_node.name} on port {master_node.port}"
367+
f"Invoke ETSI QKD Status API on client {master_kme_node.name} "
368+
f"on port {master_kme_node.port}"
369+
)
370+
url = f"{master_kme_node.base_url}/etsi/api/v1/keys/{slave_sae_id}/status"
371+
self.http_request(
372+
"GET",
373+
url,
374+
"ETSI QKD Get status",
375+
headers={"Authorization": master_sae_id},
334376
)
335-
url = f"{master_node.base_url}/etsi/api/v1/keys/{slave_node.name}/status"
336-
self.http_request("GET", url, "ETSI QKD Get status")
337377

338378
def etsi_qkd_get_key(
339379
self,
340-
master_node: Node,
341-
slave_node: Node,
380+
master_kme_node: Node,
381+
master_sae_id: str,
382+
slave_sae_id: str,
342383
size: int | None,
343384
) -> None | dict:
344385
"""
345386
Invoke the ETSI QKD Get Key API.
346387
"""
347388
print(
348-
f"Invoke ETSI QKD Get Key API for client {master_node.name} on port {master_node.port}"
389+
f"Invoke ETSI QKD Get Key API on client {master_kme_node.name} "
390+
f"on port {master_kme_node.port}"
349391
)
350-
url = f"{master_node.base_url}/etsi/api/v1/keys/{slave_node.name}/enc_keys"
392+
url = f"{master_kme_node.base_url}/etsi/api/v1/keys/{slave_sae_id}/enc_keys"
351393
params = {}
352394
if size is not None:
353395
params["size"] = size
354-
response = self.http_request("GET", url, "ETSI QKD Get key", params=params)
396+
response = self.http_request(
397+
"GET",
398+
url,
399+
"ETSI QKD Get key",
400+
params=params,
401+
headers={"Authorization": master_sae_id},
402+
)
355403
return response
356404

357405
def etsi_qkd_get_key_with_key_ids(
358-
self, master_node: Node, slave_node: Node, key_id: str
406+
self,
407+
slave_kme_node: Node,
408+
master_sae_id: str,
409+
slave_sae_id: str,
410+
key_id: str,
359411
) -> None | dict:
360412
"""
361413
Invoke the ETSI QKD Get Key with Key IDs API.
362414
"""
363415
print(
364-
f"Invoke ETSI QKD Get Key with Key IDs API for client {slave_node.name} "
365-
f"on port {slave_node.port}"
416+
f"Invoke ETSI QKD Get Key with Key IDs API on client {slave_kme_node.name} "
417+
f"on port {slave_kme_node.port}"
366418
)
367-
url = f"{slave_node.base_url}/etsi/api/v1/keys/{master_node.name}/dec_keys"
419+
url = f"{slave_kme_node.base_url}/etsi/api/v1/keys/{master_sae_id}/dec_keys"
368420
params = {"key_ID": key_id}
369421
response = self.http_request(
370-
"GET", url, "ETSI QKD Get key with key IDs", params=params
422+
"GET",
423+
url,
424+
"ETSI QKD Get key with key IDs",
425+
params=params,
426+
headers={"Authorization": slave_sae_id},
371427
)
372428
return response
373429

374430
def etsi_qkd_get_key_pair(
375431
self,
376-
master_node: Node,
377-
slave_node: Node,
432+
master_kme_node: Node,
433+
slave_kme_node: None,
434+
master_sae_id: str,
435+
slave_sae_id: str,
378436
size: int | None,
379437
):
380438
"""
381439
Invoke the ETSI QKD Get Key API on master, followed by Get Key with Key IDs API on slave.
382440
"""
383-
master_response = self.etsi_qkd_get_key(master_node, slave_node, size)
441+
master_response = self.etsi_qkd_get_key(
442+
master_kme_node, master_sae_id, slave_sae_id, size
443+
)
384444
if master_response is None:
385445
return
386446
if master_response.status_code != 200:
@@ -389,7 +449,7 @@ def etsi_qkd_get_key_pair(
389449
key_id = master_response_json["keys"]["key_ID"]
390450
master_key_value = master_response_json["keys"]["key"]
391451
slave_response = self.etsi_qkd_get_key_with_key_ids(
392-
master_node, slave_node, key_id
452+
slave_kme_node, master_sae_id, slave_sae_id, key_id
393453
)
394454
if slave_response is None:
395455
return
@@ -408,13 +468,20 @@ def http_request(
408468
url: str,
409469
action: str | None,
410470
params: dict | None = None,
471+
headers: dict | None = None,
411472
quiet_success: bool = False,
412473
) -> httpx.Response:
413474
"""
414475
Make an HTTP request.
415476
"""
416477
try:
417-
response = httpx.request(method=method, url=url, params=params, timeout=1.0)
478+
response = httpx.request(
479+
method=method,
480+
url=url,
481+
params=params,
482+
headers=headers,
483+
timeout=1.0,
484+
)
418485
except httpx.HTTPError as exc:
419486
if action is not None:
420487
print(f"Failed to {action}: {method} {url} raised exception {exc}")

0 commit comments

Comments
 (0)