Commit 0b2a831c authored by Guillermo Vélez Fernández's avatar Guillermo Vélez Fernández
Browse files

UPM final reference implementation proposal for ETSI GS QKD 004 v3.1.1

parent b8c54363
Loading
Loading
Loading
Loading

CHANGES.md

deleted100644 → 0
+0 −647

File deleted.

Preview size limit exceeded, changes collapsed.

Dockerfile

100644 → 100755
+5 −1
Original line number Diff line number Diff line
FROM docker.io/debian:bookworm
FROM docker.io/debian:trixie

ARG PACKAGES=" g++ \
    pkg-config clang clang-format make cmake cppcheck \
    ninja-build \
    libssl-dev uuid-dev \
    openssl zlib1g-dev libzstd-dev \
    python3-pytest python3-pytest-xdist python3-yaml \
    gcc-i686-linux-gnu \
    libc6-i386 lib32stdc++6 \
    libssl-dev:i386 uuid-dev:i386 \
    zlib1g-dev:i386 libzstd-dev:i386 \
    gcc-arm-linux-gnueabihf \
    libc6-armhf-cross \
    libssl-dev:armhf uuid-dev:armhf \
    zlib1g-dev:armhf libzstd-dev:armhf \
    "

RUN dpkg --add-architecture i386 && dpkg --add-architecture armhf
+77 −20
Original line number Diff line number Diff line
@@ -6,32 +6,30 @@
## Overview

This repository contains a C-based ETSI GS QKD 004 reference implementation under development.
It is intended to correspond to an update of
[ETSI GS QKD 004 V2.1.1 (2020-08)](https://www.etsi.org/deliver/etsi_gs/QKD/001_099/004/02.01.01_60/gs_QKD004v020101p.pdf)
It is intended to correspond to an update corresponding to
[ETSI GS QKD 004 V3.1.1 (2026-05)](https://docbox.etsi.org/ISG/QKD/70-Drafts/0004ed3_AppIntf/QKD-004ed3_AppIntfv222.docx)
"Quantum Key Distribution (QKD); Application Interface" by
[ETSI ISG QKD](https://www.etsi.org/committee/qkd) in work item
[RGS/QKD-004ed3_AppIntf](https://portal.etsi.org/webapp/WorkProgram/Report_WorkItem.asp?WKI_ID=68576).

## Proposed Changes to ETSI GS QKD 004 Version 2.1.1 (2020-08)

We propose a number of clarifications, simplifications, and enhancements to ETSI QKD version 2.1.1.
These are summarized in [CHANGES.md](CHANGES.md).

The given reference implementation takes these changes into account.

## Main Elements

The main elements provided in this repository include:
* A reusable library that enables ETSI GS QKD 004 in C projects.
  The implementation consists of TLS socket connections using packets
  with an ETSI GS QKD 004 compliant structure.
* A simple example of a client application (focusing on key retrieval).
  with an ETSI GS QKD 004 compliant structure. The structures and
  connection establishment is compliant with the newly introduced
  initial capabilites negotiation procedure and the base capability
  suite (ETSI-GS-QKD004-TLS13-BIN-001) is implemented.
* A client-side, simple implementation of the ETSI GS QKD 004 API as a library.
* A simple example of a client application (focusing on key retrieval) using said library.
* A mock-up implementation of a key management server.
* Examples of different use cases and error scenarios.

## Target Platform Support

During initial development, we target Debian based GNU/Linux based systems running on x86 architectures.
During initial development, we target Debian Stable based GNU/Linux based systems running on x86 architectures.
The implementation should also be compatible with other non-GNU based Linux systems such as Alpine Linux.

One of the reasons for using Cmake as a cross-platform, compiler-independent
build system generator is to be able to add Windows support prior to releasing
@@ -45,6 +43,10 @@ reference implementation of the client is not MT-safe (multithread safe) in the
one must not call its interface routines from concurrent threads.  Calls to the interface
routines of the ETSI QKD 004 reference implementation need to happen in a sequential fashion.

Furthermore, the client application and mock-up key management server perform all operations
sequentially in a blocking fashion. A real implementation should make use of multithreading,
non-blocking I/O or any other means for concurrent execution to avoid heavy bottlenecks.

## Dependencies

To build this reference code, you will need the following tools and libraries
@@ -91,6 +93,29 @@ Libuuid is used to implement KSIDs (Key Stream IDs).
sudo apt install uuid-dev
```

### OpenSSL

OpenSSL is used to provide a TLS implementation with support for external
providers.

```shell
sudo apt install openssl
```

## Optional dependencies

Optionally, you can build this reference code with support for other features
by installing the following dependencies.

### Liboqs and oqs-provider

Oqs-provider and liboqs are used to provide optional PQC algorithms in TLS.
As of the time of writtng, this packages must be manually compiled and
installed. Check the documentation of each project.

[liboqs](https://github.com/open-quantum-safe/liboqs?tab=readme-ov-file#quickstart)
[oqs-provider](https://github.com/open-quantum-safe/oqs-provider?tab=readme-ov-file#building-and-testing----quick-start)

## Build, Test, and Documentation

The user can build library, tests, and examples using the following commands.
@@ -105,10 +130,24 @@ make test
cd ..
```

For a debug build, use
For a debug build (the default is release with debug info), use
  `cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..`
instead of
  `cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..`
For a release build, use
  `cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..`
For a build with support for PQC, use
  `cmake -DQKD_PQC=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..`
For a build with informational logging, use
  `cmake -DQKD_LOG_INFO=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..`
For a build with debugging logging, use
  `cmake -DQKD_LOG_INFO=ON -DQKD_LOG_DEBUG=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..`

It is also possible to build static (default) and dynamic libraries and link
against the static version of system libraries (if available).
  `cmake -DBUILD_SHARED_LIBS=ON -DLINK_STATIC_DEPENDENCIES=OFF -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..`

After compiling the project succesfully, it is possible to generate a packaged version that can be
installed in most Debian-based (Trixie or higher) systems by running
  `make package`

Documentation can thereafter be generated using the following commands.

@@ -165,6 +204,13 @@ shell script has been provided to build and start the development container.
./build_and_start_dev_container.sh
```

To aid with the installation of liboqs and oqs-provider another shell script
is provided to clone, build, test, package and install both packages inside
of the container.
```shell
./download_and_compile_liboqs.sh
```

Using the development container, a (native) Linux 64-bit build can be started
as follows.
```shell
@@ -212,7 +258,7 @@ Assuming `build-dir` is the name of the build directory.

## Top-level Client API

See [include/interfaces.h](etsi-gs-qkd-004-c/include/qkd/interfaces.h).
See [include/qkd/interfaces.h](etsi-gs-qkd-004-c/include/qkd/interfaces.h).

## Protocol Implementation Notes

@@ -228,9 +274,17 @@ Within a TLS session, commands must be processed in order though. That
is, after submitting a request, a client must first wait for the server
to send the complete response prior to transmitting the next request.

In the case of the PUSH mode, the server may issue a command concurrently
with the client. This could potentially cause a deadlock in some cases, but
the asynchronous nature of the GIVE_KEY operation assures that the client
will process the command even while waiting for a different command to
complete. The server handles this by waiting for the client to respond
before processing the command, but different implementations may handle
this differently.

The network representation (a.k.a. byte buffer protocol) is rather
straightforward.
See [include/serializers.h](etsi-gs-qkd-004-c/include/qkd/serializers.h)
See [include/qkd/serializers.h](etsi-gs-qkd-004-c/include/qkd/serializers.h)
and [src/qkd/shared/serializers.c](etsi-gs-qkd-004-c/src/qkd/shared/serializers.c)
for details.

@@ -266,11 +320,14 @@ examples aimed at providing long-term security (LTS) against record-now-decrypt-
  benefit of whatever forward secrecy classic asymmetric key exchanges will
  offer in the long run.)  Be aware of RFC 8773 in this context.
* Keep an eye open for post-quantum crytography (PQC) extensions to
  TLS.  (OpenSSL 3.2 already offers plugable signature algorithms and
  key establishment mechanisms (KEMs) in conjunction with TLS 1.3.)
  TLS. In particular, this implementation contains support to optionally
  load at run-time some PQC extensions via oqs-provider, which in turn
  enables ML-KEM and ML-DSA if the certificates are generated correctly.
  Hybrid modes combining classical asymmetric cryptography (e.g., RSA)
  and PQC are preferred.  Mind that the use of PSKs is still required
  to achieve LTS, even in the presence of PQC extensions.
  to achieve LTS, even in the presence of PQC extensions. Hybrid modes
  are now the default in OpenSSL >= 3.5.0 if both client and server
  support them without the need of liboqs.
* Use mutual authentication and, hence, require client authentication
  (i.e., verification of the client certificate).
* Consider implementing an authorization scheme, i.e., in addition to requiring
+47 −0
Original line number Diff line number Diff line
#!/bin/bash

# Build and install liboqs and oqs-provider into the dev container for the ETSI QKD 004 reference implementation

CONTAINER_MANAGER=podman
SCRIPT_DIR=`dirname $0`
CONTAINER=etsi-004-builder
WORK_DIR=/workspace/builder/

# Release version to pull of liboqs
LIBOQS_TAG=0.15.0
# Release version to pull of oqs-provider
OQSPROVIDER_TAG=0.11.0

set -eu

# Shallow clone both repos locally, if they were not already
if [ ! -d ${SCRIPT_DIR}/liboqs ]; then
    git clone https://github.com/open-quantum-safe/liboqs -b ${LIBOQS_TAG} --depth=1 ${SCRIPT_DIR}/liboqs
fi
if [ ! -d ${SCRIPT_DIR}/oqs-provider ]; then
    git clone https://github.com/open-quantum-safe/oqs-provider -b ${OQSPROVIDER_TAG} --depth=1 ${SCRIPT_DIR}/oqs-provider
fi

# Build liboqs in the container first, if it is needed, run the tests and package it
if [ ! -d ${SCRIPT_DIR}/liboqs/build ]; then
    mkdir ${SCRIPT_DIR}/liboqs/build
    ${CONTAINER_MANAGER} exec ${CONTAINER} cmake -S ${WORK_DIR}/liboqs -B ${WORK_DIR}/liboqs/build -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release -DOQS_DIST_BUILD=ON
fi
if [ ! -f ${SCRIPT_DIR}/liboqs/build/*.deb ]; then
    ${CONTAINER_MANAGER} exec ${CONTAINER} make -C ${WORK_DIR}/liboqs/build -j$(nproc --all)
    ${CONTAINER_MANAGER} exec ${CONTAINER} make -C ${WORK_DIR}/liboqs/build run_tests
    ${CONTAINER_MANAGER} exec ${CONTAINER} make -C ${WORK_DIR}/liboqs/build package
fi
${CONTAINER_MANAGER} exec ${CONTAINER} dpkg -i ${WORK_DIR}/liboqs/build/liboqs-${LIBOQS_TAG}-Linux.deb

# Build oqs-provider in the container after installing liboqs, run the tests and package it
if [ ! -d ${SCRIPT_DIR}/oqs-provider/build ]; then
    mkdir ${SCRIPT_DIR}/oqs-provider/build
    ${CONTAINER_MANAGER} exec ${CONTAINER} cmake -S ${WORK_DIR}/oqs-provider -B ${WORK_DIR}/oqs-provider/build -DCMAKE_BUILD_TYPE=Release
fi
if [ ! -f ${SCRIPT_DIR}/oqs-provider/build/*.deb ]; then
    ${CONTAINER_MANAGER} exec ${CONTAINER} make -C ${WORK_DIR}/oqs-provider/build -j$(nproc --all)
    ${CONTAINER_MANAGER} exec ${CONTAINER} make -C ${WORK_DIR}/oqs-provider/build test
    ${CONTAINER_MANAGER} exec ${CONTAINER} make -C ${WORK_DIR}/oqs-provider/build package
fi
${CONTAINER_MANAGER} exec ${CONTAINER} dpkg -i ${WORK_DIR}/oqs-provider/build/oqs-provider-${OQSPROVIDER_TAG}-Linux.deb
+76 −12
Original line number Diff line number Diff line
@@ -3,11 +3,14 @@ cmake_minimum_required(VERSION 3.10)
project(etsi-gs-qkd-004 VERSION 2.1.1 LANGUAGES C)

option(LINK_STATIC_DEPENDENCIES "Determine whether to link dependencies statically or not" ON)
option(BUILD_SHARED_LIBS "Build using shared libraries" OFF)
option(QKD_OQS "Build with support for oqs-provider" OFF)
option(QKD_LOG_INFO "Enable INFO logging messages" ON)
option(QKD_LOG_DEBUG "Enable DEBUG logging messages" OFF)

include(CTest)

set(CMAKE_C_STANDARD 11)
set(CMAKE_POSITION_INDEPENDENT_CODE True)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")

@@ -16,16 +19,26 @@ if (LINK_STATIC_DEPENDENCIES)
  set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
endif ()

if (BUILD_SHARED_LIBS)
  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif ()

if (QKD_OQS)
  add_compile_definitions(QKD_OQS)
endif ()

if (QKD_LOG_INFO)
  add_compile_definitions(QKD_LOG_INFO)
endif ()
if (QKD_LOG_DEBUG)
  add_compile_definitions(QKD_LOG_DEBUG)
endif ()

find_package(OpenSSL REQUIRED)
find_package(Uuid REQUIRED)

include_directories(include)

add_compile_definitions(
        QKD_LOG_INFO
#        QKD_LOG_DEBUG
)

# Check whether source code files need formatting (enforced)

add_custom_target(check_formatting ALL
@@ -44,14 +57,17 @@ add_custom_target(format_code

# Static code analysis (via cppcheck)
add_custom_target(static_code_analysis ALL
  COMMAND cppcheck --error-exitcode=42 --project=compile_commands.json
  COMMAND cppcheck --error-exitcode=42 --project=compile_commands.json --check-level=exhaustive
  COMMENT "Static code analysis"
  VERBATIM
  )

# Headers installation for DEB packaging
install(DIRECTORY include/ DESTINATION include FILES_MATCHING PATTERN "*.h")

# This library contains code that it shared by client and server.

add_library(etsi-gs-qkd-004-shared STATIC
add_library(etsi-gs-qkd-004-shared
  src/qkd/shared/copy.c
  src/qkd/shared/cfg_parser.c
  src/qkd/shared/interfaces.c
@@ -62,7 +78,7 @@ add_library(etsi-gs-qkd-004-shared STATIC
  src/qkd/shared/utils.c
  )
target_link_libraries(etsi-gs-qkd-004-shared
  PUBLIC OpenSSL::SSL Uuid::uuid
  PUBLIC OpenSSL::SSL Uuid::uuid z zstd crypto
)

# Server library
@@ -78,6 +94,7 @@ target_link_libraries(etsi-gs-qkd-004-server

add_library(etsi-gs-qkd-004-client
  src/qkd/client/ssl_socket_client.c
  src/examples/client_interface.c
  )
target_link_libraries(etsi-gs-qkd-004-client
  etsi-gs-qkd-004-shared
@@ -89,6 +106,16 @@ add_library(etsi-gs-qkd-004-examples-utils
  src/examples/ringbuffer.c
  )

# Libraries installation for DEB packaging

set(etsi-gs-qkd-004-libs etsi-gs-qkd-004-shared etsi-gs-qkd-004-server
  etsi-gs-qkd-004-client etsi-gs-qkd-004-examples-utils)
if(BUILD_SHARED_LIBS)
  install(TARGETS ${etsi-gs-qkd-004-libs} LIBRARY)
else()
  install(TARGETS ${etsi-gs-qkd-004-libs} ARCHIVE)
endif()

# Binaries used in examples

add_executable(server_example
@@ -116,6 +143,11 @@ target_compile_definitions(client_example_no_initial_wait
  PUBLIC INITIAL_WAIT_TIME=0
  )

# Binaries installation for DEB packaging
set(qkd-bins server_example client_example
  client_example_no_initial_wait)
install(TARGETS ${qkd-bins} RUNTIME)

# Binaries used for unit testing

add_executable(ringbuffer_test
@@ -159,6 +191,27 @@ set_tests_properties(key_rate_too_low__short
  PROPERTIES FIXTURES_REQUIRED generate_ca_and_selfsigned_cert__short
  )

add_test(NAME push_with_pull_server__short
  COMMAND ../examples/push_with_pull_server/run_test.sh
  )
set_tests_properties(push_with_pull_server__short
  PROPERTIES FIXTURES_REQUIRED generate_ca_and_selfsigned_cert__short
  )

add_test(NAME invalid_qos__short
  COMMAND ../examples/invalid_qos/run_test.sh
  )
set_tests_properties(invalid_qos__short
  PROPERTIES FIXTURES_REQUIRED generate_ca_and_selfsigned_cert__short
  )

add_test(NAME hybrid_mode_multiple_clients__short
  COMMAND ../examples/hybrid_mode_multiple_clients/run_test.sh
  )
set_tests_properties(hybrid_mode_multiple_clients__short
  PROPERTIES FIXTURES_REQUIRED generate_ca_and_selfsigned_cert__short
  )

add_test(NAME trying_to_access_the_same_key_twice__short
  COMMAND ../examples/trying_to_access_the_same_key_twice/run_test.sh
  )
@@ -200,3 +253,14 @@ add_custom_target(docs
  COMMAND doxygen ../doxy.conf
  COMMENT "Generating API documentation with Doxygen"
  VERBATIM)

# Packaging the installer
install(FILES ${CMAKE_SOURCE_DIR}/../LICENSE TYPE DOC)
include(InstallRequiredSystemLibraries)
set(CPACK_GENERATOR "DEB")
set(CPACK_PACKAGE_NAME "etsi-004")
set(CPACK_PACKAGE_VERSION "2.2.1")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "ETSI ISG QKD")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6, libssl3t64, libuuid1, zlib1g, libzstd1")
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/../LICENSE)
include(CPack)
Loading