Skip to content

Commit

Permalink
integrating qkd-kem, work in progress
Browse files Browse the repository at this point in the history
minor changes

completing

fixes
  • Loading branch information
fj-blanco committed Dec 5, 2024
1 parent 9eec848 commit af9ca9a
Show file tree
Hide file tree
Showing 11 changed files with 491 additions and 1 deletion.
4 changes: 4 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ ARG_DISBL_SET([nonce], [disable nonce generation plugin.])
ARG_ENABL_SET([frodo], [enable FrodoKEM Post Quantum Safe plugin.])
ARG_ENABL_SET([oqs], [enable Open Quantum Safe (liboqs) plugin.])
ARG_ENABL_SET([qkd], [enable QKD plugin.])
ARG_ENABL_SET([qkd-kem], [enable QKD-KEM plugin.])
ARG_DISBL_SET([openssl], [disable the OpenSSL crypto plugin.])
ARG_ENABL_SET([wolfssl], [enables the wolfSSL crypto plugin.])
ARG_ENABL_SET([padlock], [enables VIA Padlock crypto plugin.])
Expand Down Expand Up @@ -1600,6 +1601,7 @@ ADD_PLUGIN([gcm], [s charon scripts nm cmd])
ADD_PLUGIN([frodo], [s charon scripts nm cmd])
ADD_PLUGIN([oqs], [s charon scripts nm cmd])
ADD_PLUGIN([qkd], [s charon scripts nm cmd])
ADD_PLUGIN([qkd-kem], [s charon scripts nm cmd])
ADD_PLUGIN([drbg], [s charon pki scripts nm cmd])
ADD_PLUGIN([curl], [s charon pki scripts nm cmd])
ADD_PLUGIN([files], [s charon pki scripts nm cmd])
Expand Down Expand Up @@ -1770,6 +1772,7 @@ AM_CONDITIONAL(USE_AF_ALG, test x$af_alg = xtrue)
AM_CONDITIONAL(USE_DRBG, test x$drbg = xtrue)
AM_CONDITIONAL(USE_OQS, test x$oqs = xtrue)
AM_CONDITIONAL(USE_QKD, test x$qkd = xtrue)
AM_CONDITIONAL(USE_QKD_KEM, test x$qkd_kem = xtrue)
AM_CONDITIONAL(USE_FRODO, test x$frodo = xtrue)

# charon plugins
Expand Down Expand Up @@ -2054,6 +2057,7 @@ AC_CONFIG_FILES([
src/libstrongswan/plugins/oqs/Makefile
src/libstrongswan/plugins/oqs/tests/Makefile
src/libstrongswan/plugins/qkd/Makefile
src/libstrongswan/plugins/qkd-kem/Makefile
src/libstrongswan/plugins/test_vectors/Makefile
src/libstrongswan/tests/Makefile
src/libipsec/Makefile
Expand Down
7 changes: 7 additions & 0 deletions src/libstrongswan/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,13 @@ if MONOLITHIC
endif
endif

if USE_QKD_KEM
SUBDIRS += plugins/qkd-kem
if MONOLITHIC
libstrongswan_la_LIBADD += plugins/qkd-kem/libstrongswan-qkd_kem.la
endif
endif

if USE_FRODO
SUBDIRS += plugins/frodo
if MONOLITHIC
Expand Down
1 change: 1 addition & 0 deletions src/libstrongswan/crypto/key_exchange.c
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,7 @@ bool key_exchange_verify_pubkey(key_exchange_method_t ke, chunk_t value)
case KE_HQC_L3:
case KE_HQC_L5:
case KE_QKD: // TODO_QKD: implement verification in plugin
case KE_QKD_KYBER_L3:
/* verification currently not supported, do in plugin */
valid = FALSE;
break;
Expand Down
1 change: 1 addition & 0 deletions src/libstrongswan/crypto/key_exchange.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ enum key_exchange_method_t {
KE_HQC_L5 = 1094,
/** QKD KEX */
KE_QKD = 1095,
KE_QKD_KYBER_L3 = 1096,
/** MODP group with custom generator/prime */
/** internally used DH group with additional parameters g and p, outside
* of PRIVATE USE (i.e. IKEv2 DH group range) so it can't be negotiated */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,5 +192,6 @@ hqc1, KEY_EXCHANGE_METHOD, KE_HQC_L1, 0
hqc3, KEY_EXCHANGE_METHOD, KE_HQC_L3, 0
hqc5, KEY_EXCHANGE_METHOD, KE_HQC_L5, 0
qkd, KEY_EXCHANGE_METHOD, KE_QKD, 0
qkd_kyber3, KEY_EXCHANGE_METHOD, KE_QKD_KYBER_L3, 0
noesn, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0
esn, EXTENDED_SEQUENCE_NUMBERS, EXT_SEQ_NUMBERS, 0
19 changes: 19 additions & 0 deletions src/libstrongswan/plugins/qkd-kem/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/src/libstrongswan

AM_CFLAGS = \
$(PLUGIN_CFLAGS)

if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-qkd-kem.la
else
plugin_LTLIBRARIES = libstrongswan-qkd-kem.la
endif

libstrongswan_qkd_kem_la_SOURCES = \
qkd_kem_plugin.h qkd_kem_plugin.c \
qkd_kem.h qkd_kem.c

libstrongswan_qkd_kem_la_LDFLAGS = -module -avoid-version

libstrongswan_qkd_kem_la_LIBADD = $(OPENSSL_LIB)
263 changes: 263 additions & 0 deletions src/libstrongswan/plugins/qkd-kem/qkd_kem.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
/*
* Copyright (C) 2018-2020 Andreas Steffen
*
* Copyright (C) secunet Security Networks AG
*
* Copyright (C) 2024 Javier Blanco-Romero @fj-blanco (UC3M, QURSA project)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/

/*
* qkd_kem.c
*/

#include "qkd_kem.h"
#include <openssl/evp.h>
#include <openssl/provider.h>
#include <openssl/core_names.h>
#include <utils/debug.h>

typedef struct private_qkd_kem_t private_qkd_kem_t;

/**
* Private data of an qkd_kem_t object.
*/
struct private_qkd_kem_t {
/**
* Public qkd_kem_t interface.
*/
qkd_kem_t public;

/**
* Key exchange method
*/
key_exchange_method_t method;

/**
* OpenSSL library context
*/
OSSL_LIB_CTX *libctx;

/**
* EVP_PKEY context for KEM operations
*/
EVP_PKEY_CTX *ctx;

/**
* Key pair
*/
EVP_PKEY *key;

/**
* Ciphertext buffer
*/
unsigned char *ciphertext;
size_t ciphertext_len;

/**
* Shared secret buffer
*/
unsigned char *shared_secret;
size_t shared_secret_len;

/**
* OpenSSL OQS provider
*/
OSSL_PROVIDER *oqs_provider;
};

/**
* Get algorithm name for KEM method
*/
static const char* get_kem_name(key_exchange_method_t method)
{
switch (method)
{
case KE_KYBER_L3:
return "qkd_kyber768";
// TODO_QKD: Add other hybrid methods as needed
default:
return NULL;
}
}

METHOD(key_exchange_t, get_public_key, bool,
private_qkd_kem_t *this, chunk_t *value)
{
unsigned char *pubkey = NULL;
size_t pubkey_len;

if (this->ciphertext) {
*value = chunk_clone(chunk_create(this->ciphertext, this->ciphertext_len));
return TRUE;
}

if (!this->key) {
EVP_PKEY_CTX *gen_ctx = EVP_PKEY_CTX_new_from_name(this->libctx,
get_kem_name(this->method), NULL);
if (!gen_ctx || !EVP_PKEY_keygen_init(gen_ctx) ||
!EVP_PKEY_generate(gen_ctx, &this->key)) {
EVP_PKEY_CTX_free(gen_ctx);
return FALSE;
}
EVP_PKEY_CTX_free(gen_ctx);
}

if (!EVP_PKEY_get_raw_public_key(this->key, NULL, &pubkey_len)) {
return FALSE;
}

pubkey = malloc(pubkey_len);
if (!EVP_PKEY_get_raw_public_key(this->key, pubkey, &pubkey_len)) {
free(pubkey);
return FALSE;
}

*value = chunk_clone(chunk_create(pubkey, pubkey_len));
free(pubkey);
return TRUE;
}

METHOD(key_exchange_t, set_public_key, bool,
private_qkd_kem_t *this, chunk_t value)
{
if (this->key) {
if (!this->shared_secret) {
this->shared_secret = OPENSSL_malloc(this->shared_secret_len);
}
if (!EVP_PKEY_decapsulate_init(this->ctx, NULL) ||
!EVP_PKEY_decapsulate(this->ctx, this->shared_secret,
&this->shared_secret_len, value.ptr, value.len)) {
return FALSE;
}
return TRUE;
}

EVP_PKEY_CTX *tmp_ctx = EVP_PKEY_CTX_new_from_name(this->libctx,
get_kem_name(this->method), NULL);
EVP_PKEY *peer_key = NULL;

if (!tmp_ctx || !EVP_PKEY_fromdata_init(tmp_ctx)) {
EVP_PKEY_CTX_free(tmp_ctx);
return FALSE;
}

OSSL_PARAM params[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, value.ptr, value.len),
OSSL_PARAM_END
};

if (!EVP_PKEY_fromdata(tmp_ctx, &peer_key, EVP_PKEY_PUBLIC_KEY, params)) {
EVP_PKEY_CTX_free(tmp_ctx);
return FALSE;
}

EVP_PKEY_CTX_free(tmp_ctx);

EVP_PKEY_CTX_free(this->ctx);
this->ctx = EVP_PKEY_CTX_new_from_pkey(this->libctx, peer_key, NULL);
if (!this->ctx) {
EVP_PKEY_free(peer_key);
return FALSE;
}

if (!EVP_PKEY_encapsulate_init(this->ctx, NULL) ||
!EVP_PKEY_encapsulate(this->ctx, NULL, &this->ciphertext_len,
NULL, &this->shared_secret_len)) {
EVP_PKEY_free(peer_key);
return FALSE;
}

this->ciphertext = OPENSSL_malloc(this->ciphertext_len);
this->shared_secret = OPENSSL_malloc(this->shared_secret_len);
if (!this->ciphertext || !this->shared_secret) {
EVP_PKEY_free(peer_key);
return FALSE;
}

if (!EVP_PKEY_encapsulate(this->ctx, this->ciphertext, &this->ciphertext_len,
this->shared_secret, &this->shared_secret_len)) {
EVP_PKEY_free(peer_key);
return FALSE;
}

EVP_PKEY_free(peer_key);
return TRUE;
}

METHOD(key_exchange_t, get_shared_secret, bool,
private_qkd_kem_t *this, chunk_t *secret)
{
*secret = chunk_clone(chunk_create(this->shared_secret, this->shared_secret_len));
return TRUE;
}

METHOD(key_exchange_t, get_method, key_exchange_method_t,
private_qkd_kem_t *this)
{
return this->method;
}

METHOD(key_exchange_t, destroy, void,
private_qkd_kem_t *this)
{
if (this->shared_secret) {
OPENSSL_clear_free(this->shared_secret, this->shared_secret_len);
}
free(this->ciphertext);
EVP_PKEY_free(this->key);
EVP_PKEY_CTX_free(this->ctx);
OSSL_PROVIDER_unload(this->oqs_provider);
OSSL_LIB_CTX_free(this->libctx);
free(this);
}

/*
* Described in header
*/
qkd_kem_t *qkd_kem_create(key_exchange_method_t method)
{
private_qkd_kem_t *this;
const char *kem_name = get_kem_name(method);

if (!kem_name) {
return NULL;
}

INIT(this,
.public = {
.ke = {
.get_method = _get_method,
.get_public_key = _get_public_key,
.set_public_key = _set_public_key,
.get_shared_secret = _get_shared_secret,
.destroy = _destroy,
},
},
.method = method,
.libctx = OSSL_LIB_CTX_new()
);

this->oqs_provider = OSSL_PROVIDER_load(this->libctx, "qkdkemprovider");
if (!this->oqs_provider) {
destroy(this);
return NULL;
}

this->ctx = EVP_PKEY_CTX_new_from_name(this->libctx, kem_name, NULL);
if (!this->ctx) {
destroy(this);
return NULL;
}

return &this->public;
}
35 changes: 35 additions & 0 deletions src/libstrongswan/plugins/qkd-kem/qkd_kem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2018-2020 Andreas Steffen
*
* Copyright (C) secunet Security Networks AG
*
* Copyright (C) 2024 Javier Blanco-Romero @fj-blanco (UC3M, QURSA project)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/

/*
* qkd_kem.h
*/
#ifndef QKD_KEX_H_
#define QKD_KEX_H_

typedef struct qkd_kem_t qkd_kem_t;

#include <crypto/key_exchange.h>

struct qkd_kem_t {
key_exchange_t ke;
};

qkd_kem_t *qkd_kem_create(key_exchange_method_t method);

#endif /** QKD_KEX_H_ @}*/
Loading

0 comments on commit af9ca9a

Please sign in to comment.