mirror of
https://github.com/strongswan/strongswan.git
synced 2025-10-06 00:00:47 -04:00
frodo: FrodoKEM KE method
This commit is contained in:
parent
9ebbcc4be0
commit
5296a25c8d
@ -154,6 +154,7 @@ ARG_ENABL_SET([mgf1], [enable the MGF1 software implementation plugin.
|
|||||||
ARG_ENABL_SET([newhope], [enable New Hope crypto plugin.])
|
ARG_ENABL_SET([newhope], [enable New Hope crypto plugin.])
|
||||||
ARG_DISBL_SET([nonce], [disable nonce generation plugin.])
|
ARG_DISBL_SET([nonce], [disable nonce generation plugin.])
|
||||||
ARG_ENABL_SET([ntru], [enables the NTRU crypto plugin.])
|
ARG_ENABL_SET([ntru], [enables the NTRU crypto plugin.])
|
||||||
|
ARG_ENABL_SET([frodo], [enable FrodoKEM Post Quantum Safe plugin.])
|
||||||
ARG_ENABL_SET([oqs], [enable Open Quantum Safe (liboqs) plugin.])
|
ARG_ENABL_SET([oqs], [enable Open Quantum Safe (liboqs) plugin.])
|
||||||
ARG_ENABL_SET([openssl], [enables the OpenSSL crypto plugin.])
|
ARG_ENABL_SET([openssl], [enables the OpenSSL crypto plugin.])
|
||||||
ARG_ENABL_SET([wolfssl], [enables the wolfSSL crypto plugin.])
|
ARG_ENABL_SET([wolfssl], [enables the wolfSSL crypto plugin.])
|
||||||
@ -1493,6 +1494,7 @@ ADD_PLUGIN([ctr], [s charon scripts nm cmd])
|
|||||||
ADD_PLUGIN([ccm], [s charon scripts nm cmd])
|
ADD_PLUGIN([ccm], [s charon scripts nm cmd])
|
||||||
ADD_PLUGIN([gcm], [s charon scripts nm cmd])
|
ADD_PLUGIN([gcm], [s charon scripts nm cmd])
|
||||||
ADD_PLUGIN([ntru], [s charon scripts nm cmd])
|
ADD_PLUGIN([ntru], [s charon scripts nm cmd])
|
||||||
|
ADD_PLUGIN([frodo], [s charon scripts nm cmd])
|
||||||
ADD_PLUGIN([oqs], [s charon scripts nm cmd])
|
ADD_PLUGIN([oqs], [s charon scripts nm cmd])
|
||||||
ADD_PLUGIN([drbg], [s charon pki scripts nm cmd])
|
ADD_PLUGIN([drbg], [s charon pki scripts nm cmd])
|
||||||
ADD_PLUGIN([newhope], [s charon scripts nm cmd])
|
ADD_PLUGIN([newhope], [s charon scripts nm cmd])
|
||||||
@ -1666,6 +1668,7 @@ AM_CONDITIONAL(USE_NEWHOPE, test x$newhope = xtrue)
|
|||||||
AM_CONDITIONAL(USE_BLISS, test x$bliss = xtrue)
|
AM_CONDITIONAL(USE_BLISS, test x$bliss = xtrue)
|
||||||
AM_CONDITIONAL(USE_DRBG, test x$drbg = xtrue)
|
AM_CONDITIONAL(USE_DRBG, test x$drbg = xtrue)
|
||||||
AM_CONDITIONAL(USE_OQS, test x$oqs = xtrue)
|
AM_CONDITIONAL(USE_OQS, test x$oqs = xtrue)
|
||||||
|
AM_CONDITIONAL(USE_FRODO, test x$frodo = xtrue)
|
||||||
|
|
||||||
# charon plugins
|
# charon plugins
|
||||||
# ----------------
|
# ----------------
|
||||||
@ -1949,6 +1952,7 @@ AC_CONFIG_FILES([
|
|||||||
src/libstrongswan/plugins/bliss/tests/Makefile
|
src/libstrongswan/plugins/bliss/tests/Makefile
|
||||||
src/libstrongswan/plugins/newhope/Makefile
|
src/libstrongswan/plugins/newhope/Makefile
|
||||||
src/libstrongswan/plugins/newhope/tests/Makefile
|
src/libstrongswan/plugins/newhope/tests/Makefile
|
||||||
|
src/libstrongswan/plugins/frodo/Makefile
|
||||||
src/libstrongswan/plugins/oqs/Makefile
|
src/libstrongswan/plugins/oqs/Makefile
|
||||||
src/libstrongswan/plugins/oqs/tests/Makefile
|
src/libstrongswan/plugins/oqs/tests/Makefile
|
||||||
src/libstrongswan/plugins/test_vectors/Makefile
|
src/libstrongswan/plugins/test_vectors/Makefile
|
||||||
|
@ -681,6 +681,13 @@ if MONOLITHIC
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if USE_FRODO
|
||||||
|
SUBDIRS += plugins/frodo
|
||||||
|
if MONOLITHIC
|
||||||
|
libstrongswan_la_LIBADD += plugins/frodo/libstrongswan-frodo.la
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
if USE_TEST_VECTORS
|
if USE_TEST_VECTORS
|
||||||
SUBDIRS += plugins/test_vectors
|
SUBDIRS += plugins/test_vectors
|
||||||
if MONOLITHIC
|
if MONOLITHIC
|
||||||
|
26
src/libstrongswan/plugins/frodo/Makefile.am
Normal file
26
src/libstrongswan/plugins/frodo/Makefile.am
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
AM_CPPFLAGS = \
|
||||||
|
-I$(top_srcdir)/src/libstrongswan
|
||||||
|
|
||||||
|
AM_CFLAGS = \
|
||||||
|
$(PLUGIN_CFLAGS)
|
||||||
|
|
||||||
|
# these files are also used by the tests, we can't directly refer to them
|
||||||
|
# because of the subdirectory, which would cause distclean to fail
|
||||||
|
noinst_LTLIBRARIES = libfrodo.la
|
||||||
|
libfrodo_la_SOURCES = \
|
||||||
|
frodo.h frodo.c \
|
||||||
|
frodo_params.h frodo_params.c \
|
||||||
|
frodo_utils.h frodo_utils.c
|
||||||
|
|
||||||
|
if MONOLITHIC
|
||||||
|
noinst_LTLIBRARIES += libstrongswan-frodo.la
|
||||||
|
else
|
||||||
|
plugin_LTLIBRARIES = libstrongswan-frodo.la
|
||||||
|
endif
|
||||||
|
|
||||||
|
libstrongswan_frodo_la_SOURCES = \
|
||||||
|
frodo_plugin.h frodo_plugin.c
|
||||||
|
|
||||||
|
libstrongswan_frodo_la_LDFLAGS = -module -avoid-version
|
||||||
|
|
||||||
|
libstrongswan_frodo_la_LIBADD = libfrodo.la
|
596
src/libstrongswan/plugins/frodo/frodo.c
Normal file
596
src/libstrongswan/plugins/frodo/frodo.c
Normal file
@ -0,0 +1,596 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (C) Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Andreas Steffen
|
||||||
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "frodo.h"
|
||||||
|
#include "frodo_params.h"
|
||||||
|
#include "frodo_utils.h"
|
||||||
|
|
||||||
|
#include <utils/debug.h>
|
||||||
|
|
||||||
|
typedef struct private_frodo_t private_frodo_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private data of an frodo_t object.
|
||||||
|
*/
|
||||||
|
struct private_frodo_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public frodo_t interface.
|
||||||
|
*/
|
||||||
|
frodo_t public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* key exchange method
|
||||||
|
*/
|
||||||
|
key_exchange_method_t method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If TRUE use AES128 for generating matrix A, otherwise use SHAKE128
|
||||||
|
*/
|
||||||
|
bool use_aes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frodo parameters
|
||||||
|
*/
|
||||||
|
const frodo_params_t *params;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public Key
|
||||||
|
*/
|
||||||
|
uint8_t *public_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Secret Key
|
||||||
|
*/
|
||||||
|
uint8_t *secret_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ciphertext
|
||||||
|
*/
|
||||||
|
uint8_t *ciphertext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared secret
|
||||||
|
*/
|
||||||
|
uint8_t *shared_secret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NIST CTR DRBG
|
||||||
|
*/
|
||||||
|
drbg_t *drbg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SHAKE-128 or SHAKE-256 eXtended Output Function
|
||||||
|
*/
|
||||||
|
xof_t *xof;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static bool need_drbg(private_frodo_t *this)
|
||||||
|
{
|
||||||
|
uint32_t strength = 256;
|
||||||
|
rng_t *entropy;
|
||||||
|
|
||||||
|
if (this->drbg)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* entropy will be owned by drbg */
|
||||||
|
entropy = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
|
||||||
|
if (!entropy)
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "could not attach entropy source for DRBG");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->drbg = lib->crypto->create_drbg(lib->crypto, DRBG_CTR_AES256,
|
||||||
|
strength, entropy, chunk_empty);
|
||||||
|
if (!this->drbg)
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "could not instantiate DRBG at %u bit security", strength);
|
||||||
|
entropy->destroy(entropy);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generator function shared between encaps and decaps shared secret
|
||||||
|
*/
|
||||||
|
static bool generate(private_frodo_t *this, chunk_t G2in, uint8_t *k,
|
||||||
|
uint16_t *Bp, uint16_t *C)
|
||||||
|
{
|
||||||
|
const uint32_t n_x_nb = this->params->n * this->params->nb;
|
||||||
|
const uint32_t nb_x_nb = this->params->nb * this->params->nb;
|
||||||
|
const uint32_t log_q = this->params->log_q;
|
||||||
|
const uint32_t seed_A_len = this->params->seed_A_len;
|
||||||
|
const uint32_t ss_len = this->params->ss_len;
|
||||||
|
const uint32_t pk_len = this->params->pk_len;
|
||||||
|
|
||||||
|
uint8_t *mu = G2in.ptr + ss_len;
|
||||||
|
uint8_t *pk_seedA = this->public_key;
|
||||||
|
uint8_t *pk_b = this->public_key + seed_A_len;
|
||||||
|
uint16_t B[n_x_nb], Sp[n_x_nb], Ep[n_x_nb], Epp[nb_x_nb], V[nb_x_nb];
|
||||||
|
|
||||||
|
chunk_t seedSE = chunk_alloc(1 + ss_len);
|
||||||
|
|
||||||
|
if (!this->xof->set_seed(this->xof, G2in) ||
|
||||||
|
!this->xof->get_bytes(this->xof, ss_len, seedSE.ptr + 1) ||
|
||||||
|
!this->xof->get_bytes(this->xof, ss_len, k))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
*seedSE.ptr = 0x96;
|
||||||
|
|
||||||
|
/* Generate Sp and Ep, and compute Bp = Sp*A + Ep. Generate A on-the-fly */
|
||||||
|
if (!this->xof->set_seed(this->xof, seedSE) ||
|
||||||
|
!this->xof->get_bytes(this->xof,
|
||||||
|
n_x_nb * sizeof(uint16_t), (uint8_t*)Sp) ||
|
||||||
|
!this->xof->get_bytes(this->xof,
|
||||||
|
n_x_nb * sizeof(uint16_t), (uint8_t*)Ep) ||
|
||||||
|
!this->xof->get_bytes(this->xof,
|
||||||
|
nb_x_nb * sizeof(uint16_t), (uint8_t*)Epp))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
frodo_sample_n(this->params, Sp, n_x_nb);
|
||||||
|
frodo_sample_n(this->params, Ep, n_x_nb);
|
||||||
|
frodo_mul_add_sa_plus_e(this->params, Bp, Sp, Ep, pk_seedA, this->use_aes);
|
||||||
|
|
||||||
|
/* Generate Epp, and compute V = Sp*B + Epp */
|
||||||
|
frodo_sample_n(this->params, Epp, nb_x_nb);
|
||||||
|
frodo_unpack(B, n_x_nb, pk_b, pk_len - seed_A_len, log_q);
|
||||||
|
frodo_mul_add_sb_plus_e(this->params, V, B, Sp, Epp);
|
||||||
|
|
||||||
|
/* Encode mu, and compute C = V + enc(mu) (mod q) */
|
||||||
|
frodo_key_encode(this->params, C, (uint16_t*)mu);
|
||||||
|
frodo_add(this->params, C, V, C);
|
||||||
|
|
||||||
|
/* Cleanup */
|
||||||
|
memwipe((uint8_t *)Sp, n_x_nb * sizeof(uint16_t));
|
||||||
|
memwipe((uint8_t *)Ep, n_x_nb * sizeof(uint16_t));
|
||||||
|
memwipe((uint8_t *)Epp, nb_x_nb * sizeof(uint16_t));
|
||||||
|
memwipe((uint8_t *)V, nb_x_nb * sizeof(uint16_t));
|
||||||
|
chunk_clear(&seedSE);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the shared secret and encrypt it with the configured public key
|
||||||
|
*/
|
||||||
|
static bool encaps_shared_secret(private_frodo_t *this)
|
||||||
|
{
|
||||||
|
const uint32_t n_x_nb = this->params->n * this->params->nb;
|
||||||
|
const uint32_t nb_x_nb = this->params->nb * this->params->nb;
|
||||||
|
const uint32_t log_q = this->params->log_q;
|
||||||
|
const uint32_t extr_bits = this->params->extr_bits;
|
||||||
|
const uint32_t ct_c1_len = (n_x_nb * log_q)/8;
|
||||||
|
const uint32_t ct_c2_len = (nb_x_nb * log_q)/8;
|
||||||
|
const uint32_t mu_len = (nb_x_nb * extr_bits)/8;
|
||||||
|
const uint32_t ss_len = this->params->ss_len;
|
||||||
|
const uint32_t ct_len = this->params->ct_len;
|
||||||
|
const uint32_t pk_len = this->params->pk_len;
|
||||||
|
|
||||||
|
chunk_t pk = chunk_create(this->public_key, pk_len);
|
||||||
|
chunk_t G2in = chunk_alloca(ss_len + mu_len);
|
||||||
|
uint8_t *pkh = G2in.ptr;
|
||||||
|
uint8_t *mu = G2in.ptr + ss_len;
|
||||||
|
uint8_t *ct_c1, *ct_c2;
|
||||||
|
uint8_t Fin[ct_len + ss_len];
|
||||||
|
uint8_t *Fin_ct = &Fin[0];
|
||||||
|
uint8_t *Fin_k = &Fin[ct_len];
|
||||||
|
uint8_t k[ss_len];
|
||||||
|
uint16_t Bp[n_x_nb], C[nb_x_nb];
|
||||||
|
|
||||||
|
if (!this->ciphertext)
|
||||||
|
{
|
||||||
|
this->ciphertext = malloc(ct_len);
|
||||||
|
}
|
||||||
|
ct_c1 = this->ciphertext;
|
||||||
|
ct_c2 = this->ciphertext + ct_c1_len;
|
||||||
|
|
||||||
|
/* pkh <- G_1(pk) */
|
||||||
|
if (!this->xof->set_seed(this->xof, pk) ||
|
||||||
|
!this->xof->get_bytes(this->xof, ss_len, pkh))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate random mu */
|
||||||
|
if (!this->drbg->generate(this->drbg, mu_len, mu))
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "could not generate mu");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!generate(this, G2in, k, Bp, C))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
frodo_pack(ct_c1, ct_c1_len, Bp, n_x_nb, log_q);
|
||||||
|
frodo_pack(ct_c2, ct_c2_len, C, nb_x_nb, log_q);
|
||||||
|
|
||||||
|
/* Compute ss = F(ct||KK) */
|
||||||
|
memcpy(Fin_ct, this->ciphertext, ct_len);
|
||||||
|
memcpy(Fin_k, k, ss_len);
|
||||||
|
|
||||||
|
if (!this->xof->set_seed(this->xof, chunk_create(Fin, ct_len + ss_len)) ||
|
||||||
|
!this->xof->get_bytes(this->xof, ss_len, this->shared_secret))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cleanup */
|
||||||
|
memwipe(mu, mu_len);
|
||||||
|
memwipe(k, ss_len);
|
||||||
|
memwipe(Fin_k, ss_len);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decapsulate the shared secret using the secret key
|
||||||
|
*/
|
||||||
|
static bool decaps_shared_secret(private_frodo_t *this)
|
||||||
|
{
|
||||||
|
const uint32_t n_x_nb = this->params->n * this->params->nb;
|
||||||
|
const uint32_t nb_x_nb = this->params->nb * this->params->nb;
|
||||||
|
const uint32_t log_q = this->params->log_q;
|
||||||
|
const uint32_t extr_bits = this->params->extr_bits;
|
||||||
|
const uint32_t ct_c1_len = (n_x_nb * log_q)/8;
|
||||||
|
const uint32_t ct_c2_len = (nb_x_nb * log_q)/8;
|
||||||
|
const uint32_t mu_len = (nb_x_nb * extr_bits)/8;
|
||||||
|
const uint32_t ss_len = this->params->ss_len;
|
||||||
|
const uint32_t ct_len = this->params->ct_len;
|
||||||
|
const uint32_t pk_len = this->params->pk_len;
|
||||||
|
|
||||||
|
chunk_t G2in = chunk_alloca(ss_len + mu_len);
|
||||||
|
uint8_t *pkh = G2in.ptr;
|
||||||
|
uint8_t *muprime = G2in.ptr + ss_len;
|
||||||
|
uint8_t *ct_c1 = this->ciphertext;
|
||||||
|
uint8_t *ct_c2 = this->ciphertext + ct_c1_len;
|
||||||
|
uint8_t *sk_s = this->secret_key;
|
||||||
|
uint16_t *sk_S = (uint16_t *)(this->secret_key + ss_len + pk_len);
|
||||||
|
uint8_t *sk_pkh = this->secret_key + ss_len + pk_len + 2*n_x_nb;
|
||||||
|
uint8_t Fin[ct_len + ss_len];
|
||||||
|
uint8_t *Fin_ct = &Fin[0];
|
||||||
|
uint8_t *Fin_k = &Fin[ct_len];
|
||||||
|
uint8_t kprime[ss_len];
|
||||||
|
uint16_t Bp[n_x_nb], BBp[n_x_nb];
|
||||||
|
uint16_t W[nb_x_nb], C[nb_x_nb], CC[nb_x_nb];
|
||||||
|
|
||||||
|
/* Compute W = C - Bp*S (mod q), and decode the randomness mu */
|
||||||
|
frodo_unpack(Bp, n_x_nb, ct_c1, ct_c1_len, log_q);
|
||||||
|
frodo_unpack(C, nb_x_nb, ct_c2, ct_c2_len, log_q);
|
||||||
|
frodo_mul_bs(this->params, W, Bp, sk_S);
|
||||||
|
frodo_sub(this->params, W, C, W);
|
||||||
|
frodo_key_decode(this->params, (uint16_t*)muprime, W);
|
||||||
|
memcpy(pkh, sk_pkh, ss_len);
|
||||||
|
|
||||||
|
if (!generate(this, G2in, kprime, BBp, CC))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare input to F */
|
||||||
|
memcpy(Fin_ct, this->ciphertext, ct_len);
|
||||||
|
|
||||||
|
/* Reducing BBp modulo q */
|
||||||
|
for (int i = 0; i < n_x_nb; i++)
|
||||||
|
{
|
||||||
|
BBp[i] = BBp[i] & ((1 << log_q) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is (Bp == BBp & C == CC) = true */
|
||||||
|
if (memcmp(Bp, BBp, n_x_nb * sizeof(uint16_t)) == 0 &&
|
||||||
|
memcmp(C, CC, nb_x_nb * sizeof(uint16_t)) == 0)
|
||||||
|
{
|
||||||
|
/* Load k' to do ss = F(ct || k') */
|
||||||
|
memcpy(Fin_k, kprime, ss_len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Load s to do ss = F(ct || s) */
|
||||||
|
memcpy(Fin_k, sk_s, ss_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->xof->set_seed(this->xof, chunk_create(Fin, ct_len + ss_len)) ||
|
||||||
|
!this->xof->get_bytes(this->xof, ss_len, this->shared_secret))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cleanup: */
|
||||||
|
memwipe((uint8_t *)W, nb_x_nb * sizeof(uint16_t));
|
||||||
|
memwipe(muprime, mu_len);
|
||||||
|
memwipe(kprime, ss_len);
|
||||||
|
memwipe(Fin_k, ss_len);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static bool set_ciphertext(private_frodo_t *this, chunk_t value)
|
||||||
|
{
|
||||||
|
if (value.len != this->params->ct_len)
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "wrong %N ciphertext size of %u bytes, %u bytes expected",
|
||||||
|
key_exchange_method_names, this->method, value.len,
|
||||||
|
this->params->ct_len);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
this->ciphertext = malloc(value.len);
|
||||||
|
memcpy(this->ciphertext, value.ptr, value.len);
|
||||||
|
|
||||||
|
return decaps_shared_secret(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(key_exchange_t, get_public_key, bool,
|
||||||
|
private_frodo_t *this, chunk_t *value)
|
||||||
|
{
|
||||||
|
/* responder action */
|
||||||
|
if (this->ciphertext)
|
||||||
|
{
|
||||||
|
*value = chunk_clone(
|
||||||
|
chunk_create(this->ciphertext, this->params->ct_len));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initiator action */
|
||||||
|
if (!this->secret_key)
|
||||||
|
{
|
||||||
|
const uint32_t n_x_nb = this->params->n * this->params->nb;
|
||||||
|
const uint32_t log_q = this->params->log_q;
|
||||||
|
const uint32_t seed_A_len = this->params->seed_A_len;
|
||||||
|
const uint32_t ss_len = this->params->ss_len;
|
||||||
|
const uint32_t pk_len = this->params->pk_len;
|
||||||
|
|
||||||
|
uint8_t *pk_seedA, *pk_b, *sk_pos;
|
||||||
|
uint16_t B[n_x_nb], S[n_x_nb], E[n_x_nb];
|
||||||
|
uint8_t randomness[ss_len + ss_len + seed_A_len];
|
||||||
|
uint8_t *randomness_s = &randomness[0];
|
||||||
|
uint8_t *randomness_seedSE = &randomness[ss_len];
|
||||||
|
uint8_t *randomness_z = &randomness[ss_len + ss_len];
|
||||||
|
uint8_t seedSE[1 + ss_len];
|
||||||
|
|
||||||
|
this->secret_key = malloc(this->params->sk_len);
|
||||||
|
pk_seedA = this->public_key;
|
||||||
|
pk_b = this->public_key + seed_A_len;
|
||||||
|
|
||||||
|
/* Do we need an entropy source? */
|
||||||
|
/* TODO */
|
||||||
|
/* Generate the secret value s and the seeds for S, E and seed_A */
|
||||||
|
if (!need_drbg(this) ||
|
||||||
|
!this->drbg->generate(this->drbg, 2*ss_len + seed_A_len, randomness))
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "could not generate randomness");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate seed_A as part of the public key */
|
||||||
|
if (!this->xof->set_seed(this->xof,
|
||||||
|
chunk_create(randomness_z, seed_A_len)) ||
|
||||||
|
!this->xof->get_bytes(this->xof, seed_A_len, pk_seedA))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate S and E, and compute B = A*S + E. Generate A on-the-fly */
|
||||||
|
seedSE[0] = 0x5F;
|
||||||
|
memcpy(&seedSE[1], randomness_seedSE, ss_len);
|
||||||
|
|
||||||
|
if (!this->xof->set_seed(this->xof, chunk_create(seedSE, 1 + ss_len)) ||
|
||||||
|
!this->xof->get_bytes(this->xof,
|
||||||
|
n_x_nb * sizeof(uint16_t), (uint8_t*)S) ||
|
||||||
|
!this->xof->get_bytes(this->xof,
|
||||||
|
n_x_nb * sizeof(uint16_t), (uint8_t*)E))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
frodo_sample_n(this->params, S, n_x_nb);
|
||||||
|
frodo_sample_n(this->params, E, n_x_nb);
|
||||||
|
|
||||||
|
if (!frodo_mul_add_as_plus_e(this->params, B, S, E, this->public_key,
|
||||||
|
this->use_aes))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Encode the second part of the public key */
|
||||||
|
frodo_pack(pk_b, pk_len - seed_A_len, B, n_x_nb, log_q);
|
||||||
|
|
||||||
|
/* Add s, pk and S to the secret key */
|
||||||
|
sk_pos = this->secret_key;
|
||||||
|
memcpy(sk_pos, randomness_s, ss_len);
|
||||||
|
sk_pos += ss_len;
|
||||||
|
memcpy(sk_pos, this->public_key, pk_len);
|
||||||
|
sk_pos += pk_len;
|
||||||
|
memcpy(sk_pos, S, n_x_nb * sizeof(uint16_t));
|
||||||
|
sk_pos += n_x_nb * sizeof(uint16_t);
|
||||||
|
|
||||||
|
/* Add H(pk) to the secret key */
|
||||||
|
if (!this->xof->set_seed(this->xof,
|
||||||
|
chunk_create(this->public_key, pk_len)) ||
|
||||||
|
!this->xof->get_bytes(this->xof, ss_len, sk_pos))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cleanup */
|
||||||
|
memwipe((uint8_t *)S, n_x_nb * sizeof(uint16_t));
|
||||||
|
memwipe((uint8_t *)E, n_x_nb * sizeof(uint16_t));
|
||||||
|
memwipe(randomness, ss_len + ss_len + seed_A_len);
|
||||||
|
memwipe(seedSE, 1 + ss_len);
|
||||||
|
}
|
||||||
|
*value = chunk_clone(chunk_create(this->public_key, this->params->pk_len));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
METHOD(key_exchange_t, get_shared_secret, bool,
|
||||||
|
private_frodo_t *this, chunk_t *secret)
|
||||||
|
{
|
||||||
|
*secret = chunk_clone(
|
||||||
|
chunk_create(this->shared_secret, this->params->ss_len));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(key_exchange_t, set_public_key, bool,
|
||||||
|
private_frodo_t *this, chunk_t value)
|
||||||
|
{
|
||||||
|
/* initiator action */
|
||||||
|
if (this->secret_key)
|
||||||
|
{
|
||||||
|
return set_ciphertext(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* responder action */
|
||||||
|
if (value.len != this->params->pk_len)
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "wrong %N public key size of %u bytes, %u bytes expected",
|
||||||
|
key_exchange_method_names, this->method, value.len,
|
||||||
|
this->params->pk_len);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
memcpy(this->public_key, value.ptr, value.len);
|
||||||
|
|
||||||
|
return need_drbg(this) && encaps_shared_secret(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
METHOD(key_exchange_t, get_method, key_exchange_method_t,
|
||||||
|
private_frodo_t *this)
|
||||||
|
{
|
||||||
|
return this->method;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(key_exchange_t, set_seed, bool,
|
||||||
|
private_frodo_t *this, chunk_t value, drbg_t *drbg)
|
||||||
|
{
|
||||||
|
DESTROY_IF(this->drbg);
|
||||||
|
this->drbg = drbg->get_ref(drbg);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(key_exchange_t, destroy, void,
|
||||||
|
private_frodo_t *this)
|
||||||
|
{
|
||||||
|
DESTROY_IF(this->drbg);
|
||||||
|
this->xof->destroy(this->xof);
|
||||||
|
|
||||||
|
memwipe(this->secret_key, this->params->sk_len);
|
||||||
|
free(this->secret_key);
|
||||||
|
memwipe(this->shared_secret, this->params->ss_len);
|
||||||
|
free(this->shared_secret);
|
||||||
|
free(this->public_key);
|
||||||
|
free(this->ciphertext);
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Described in header.
|
||||||
|
*/
|
||||||
|
frodo_t *frodo_create(key_exchange_method_t method)
|
||||||
|
{
|
||||||
|
private_frodo_t *this;
|
||||||
|
const frodo_params_t *params;
|
||||||
|
frodo_kem_type_t id;
|
||||||
|
bool use_aes;
|
||||||
|
xof_t *xof;
|
||||||
|
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case KE_FRODO_SHAKE_L1:
|
||||||
|
id = FRODO_KEM_L1;
|
||||||
|
use_aes = FALSE;
|
||||||
|
break;
|
||||||
|
case KE_FRODO_SHAKE_L3:
|
||||||
|
id = FRODO_KEM_L3;
|
||||||
|
use_aes = FALSE;
|
||||||
|
break;
|
||||||
|
case KE_FRODO_SHAKE_L5:
|
||||||
|
id = FRODO_KEM_L5;
|
||||||
|
use_aes = FALSE;
|
||||||
|
break;
|
||||||
|
case KE_FRODO_AES_L1:
|
||||||
|
id = FRODO_KEM_L1;
|
||||||
|
use_aes = TRUE;
|
||||||
|
break;
|
||||||
|
case KE_FRODO_AES_L3:
|
||||||
|
id = FRODO_KEM_L3;
|
||||||
|
use_aes = TRUE;
|
||||||
|
break;
|
||||||
|
case KE_FRODO_AES_L5:
|
||||||
|
id = FRODO_KEM_L5;
|
||||||
|
use_aes = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
params = frodo_params_get_by_id(id);
|
||||||
|
|
||||||
|
xof = lib->crypto->create_xof(lib->crypto, params->xof_type);
|
||||||
|
if (!xof)
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "could not instantiate %N", ext_out_function_names,
|
||||||
|
params->xof_type);
|
||||||
|
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,
|
||||||
|
.set_seed = _set_seed,
|
||||||
|
.destroy = _destroy,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.method = method,
|
||||||
|
.use_aes = use_aes,
|
||||||
|
.params = params,
|
||||||
|
.xof = xof,
|
||||||
|
.public_key = malloc(params->pk_len),
|
||||||
|
.shared_secret = malloc(params->ss_len),
|
||||||
|
);
|
||||||
|
|
||||||
|
return &this->public;
|
||||||
|
}
|
47
src/libstrongswan/plugins/frodo/frodo.h
Normal file
47
src/libstrongswan/plugins/frodo/frodo.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Andreas Steffen
|
||||||
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup frodo frodo
|
||||||
|
* @{ @ingroup frodo_p
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FRODO_H_
|
||||||
|
#define FRODO_H_
|
||||||
|
|
||||||
|
typedef struct frodo_t frodo_t;
|
||||||
|
|
||||||
|
#include <library.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quantum-safe key encapsulation implementation using FrodoKEM
|
||||||
|
*/
|
||||||
|
struct frodo_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements key_exchange_t interface.
|
||||||
|
*/
|
||||||
|
key_exchange_t ke;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new frodo_t object.
|
||||||
|
*
|
||||||
|
* @param method key exchange method
|
||||||
|
* @return frodo_t object, NULL if not supported
|
||||||
|
*/
|
||||||
|
frodo_t *frodo_create(key_exchange_method_t method);
|
||||||
|
|
||||||
|
#endif /** FRODO_H_ @}*/
|
111
src/libstrongswan/plugins/frodo/frodo_params.c
Normal file
111
src/libstrongswan/plugins/frodo/frodo_params.c
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (C) Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Andreas Steffen
|
||||||
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "frodo_params.h"
|
||||||
|
|
||||||
|
const uint16_t cdf_table_1[] = { 4643, 13363, 20579, 25843, 29227,
|
||||||
|
31145, 32103, 32525, 32689, 32745,
|
||||||
|
32762, 32766, 32767
|
||||||
|
};
|
||||||
|
const uint16_t cdf_table_3[] = { 5638, 15915, 23689, 28571, 31116,
|
||||||
|
32217, 32613, 32731, 32760, 32766,
|
||||||
|
32767
|
||||||
|
};
|
||||||
|
const uint16_t cdf_table_5[] = { 9142, 23462, 30338, 32361, 32725,
|
||||||
|
32765, 32767
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FrodoKEM parameter definitions
|
||||||
|
*/
|
||||||
|
static const frodo_params_t frodo_params[] = {
|
||||||
|
|
||||||
|
{
|
||||||
|
FRODO_KEM_L1, /* Frodo KEM ID */
|
||||||
|
640, /* Lattice dimension n */
|
||||||
|
8, /* Dimension n_bar */
|
||||||
|
15, /* Logarithm of modulus q */
|
||||||
|
2, /* Extracted bits extr_bits */
|
||||||
|
16, /* Size of seed_A seed_A_len */
|
||||||
|
16, /* Size of shared secret ss_len */
|
||||||
|
9720, /* Size of ciphertext ct_len */
|
||||||
|
9616, /* Size of public key pk_len */
|
||||||
|
19888, /* Size of secret key sk_len */
|
||||||
|
13, /* Size of CDF table cdf_table_len */
|
||||||
|
cdf_table_1, /* CDF table */
|
||||||
|
XOF_SHAKE_128, /* SHAKE XOF */
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
FRODO_KEM_L3, /* Frodo KEM ID */
|
||||||
|
976, /* Lattice dimension n */
|
||||||
|
8, /* Dimension n_bar */
|
||||||
|
16, /* Logarithm of modulus q */
|
||||||
|
3, /* Extracted bits extr_bits */
|
||||||
|
16, /* Size of seed_A seed_A_len */
|
||||||
|
24, /* Size of shared secret ss_len */
|
||||||
|
15744, /* Size of ciphertext ct_len */
|
||||||
|
15632, /* Size of public key pk_len */
|
||||||
|
31296, /* Size of secret key sk_len */
|
||||||
|
11, /* Size of CDF table cdf_table_len */
|
||||||
|
cdf_table_3, /* CDF table */
|
||||||
|
XOF_SHAKE_256, /* SHAKE XOF */
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
FRODO_KEM_L5, /* Frodo KEM ID */
|
||||||
|
1344, /* Lattice dimension n */
|
||||||
|
8, /* Dimension n_bar */
|
||||||
|
16, /* Logarithm of modulus q */
|
||||||
|
4, /* Extracted bits extr_bits */
|
||||||
|
16, /* Size of seed_A seed_A_len */
|
||||||
|
32, /* Size of shared secret ss_len */
|
||||||
|
21632, /* Size of ciphertext ct_len */
|
||||||
|
21520, /* Size of public key pk_len */
|
||||||
|
43088, /* Size of secret key sk_len */
|
||||||
|
7, /* Size of CDF table cdf_table_len */
|
||||||
|
cdf_table_5, /* CDF table */
|
||||||
|
XOF_SHAKE_256, /* SHAKE XOF */
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header.
|
||||||
|
*/
|
||||||
|
const frodo_params_t* frodo_params_get_by_id(frodo_kem_type_t id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < countof(frodo_params); i++)
|
||||||
|
{
|
||||||
|
if (frodo_params[i].id == id)
|
||||||
|
{
|
||||||
|
return &frodo_params[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
124
src/libstrongswan/plugins/frodo/frodo_params.h
Normal file
124
src/libstrongswan/plugins/frodo/frodo_params.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (C) Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Andreas Steffen
|
||||||
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FRODO_PARAMS_H_
|
||||||
|
#define FRODO_PARAMS_H_
|
||||||
|
|
||||||
|
#include <library.h>
|
||||||
|
|
||||||
|
typedef struct frodo_params_t frodo_params_t;
|
||||||
|
typedef enum frodo_kem_type_t frodo_kem_type_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FrodoKEM types with various security strengths
|
||||||
|
*/
|
||||||
|
enum frodo_kem_type_t {
|
||||||
|
FRODO_KEM_L1,
|
||||||
|
FRODO_KEM_L3,
|
||||||
|
FRODO_KEM_L5,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FrodoKEM parameter definitions
|
||||||
|
*/
|
||||||
|
struct frodo_params_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frodo key exchange ID
|
||||||
|
*/
|
||||||
|
const frodo_kem_type_t id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lattice dimension
|
||||||
|
*/
|
||||||
|
const uint32_t n;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dimension n_bar
|
||||||
|
*/
|
||||||
|
const uint32_t nb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logarithm of modulus q
|
||||||
|
*/
|
||||||
|
const uint32_t log_q;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracted bits
|
||||||
|
*/
|
||||||
|
const uint32_t extr_bits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of seed_A
|
||||||
|
*/
|
||||||
|
const uint32_t seed_A_len;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of shared secret
|
||||||
|
*/
|
||||||
|
const uint32_t ss_len;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of ciphertext
|
||||||
|
*/
|
||||||
|
const uint32_t ct_len;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of public key
|
||||||
|
*/
|
||||||
|
const uint32_t pk_len;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of secret key
|
||||||
|
*/
|
||||||
|
const uint32_t sk_len;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of CDF table
|
||||||
|
*/
|
||||||
|
const uint32_t cdf_table_len;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CDF table
|
||||||
|
*/
|
||||||
|
const uint16_t *cdf_table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SHAKE extended output function
|
||||||
|
*/
|
||||||
|
ext_out_function_t xof_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Frodo parameters by Frodo key exchange ID
|
||||||
|
*
|
||||||
|
* @param id Frodo KEM ID
|
||||||
|
* @return Frodo parameters
|
||||||
|
*/
|
||||||
|
const frodo_params_t* frodo_params_get_by_id(frodo_kem_type_t id);
|
||||||
|
|
||||||
|
#endif /** FRODO_PARAMS_H_ @}*/
|
104
src/libstrongswan/plugins/frodo/frodo_plugin.c
Normal file
104
src/libstrongswan/plugins/frodo/frodo_plugin.c
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Andreas Steffen
|
||||||
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "frodo_plugin.h"
|
||||||
|
#include "frodo.h"
|
||||||
|
|
||||||
|
#include <library.h>
|
||||||
|
|
||||||
|
typedef struct private_frodo_plugin_t private_frodo_plugin_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* private data of frodo_plugin
|
||||||
|
*/
|
||||||
|
struct private_frodo_plugin_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* public functions
|
||||||
|
*/
|
||||||
|
frodo_plugin_t public;
|
||||||
|
};
|
||||||
|
|
||||||
|
METHOD(plugin_t, get_name, char*,
|
||||||
|
private_frodo_plugin_t *this)
|
||||||
|
{
|
||||||
|
return "frodo";
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(plugin_t, get_features, int,
|
||||||
|
private_frodo_plugin_t *this, plugin_feature_t *features[])
|
||||||
|
{
|
||||||
|
static plugin_feature_t f[] = {
|
||||||
|
PLUGIN_REGISTER(KE, frodo_create),
|
||||||
|
PLUGIN_PROVIDE(KE, KE_FRODO_SHAKE_L1),
|
||||||
|
PLUGIN_DEPENDS(XOF, XOF_SHAKE_128),
|
||||||
|
PLUGIN_DEPENDS(DRBG, DRBG_CTR_AES256),
|
||||||
|
PLUGIN_DEPENDS(RNG, RNG_TRUE),
|
||||||
|
PLUGIN_PROVIDE(KE, KE_FRODO_SHAKE_L3),
|
||||||
|
PLUGIN_DEPENDS(XOF, XOF_SHAKE_256),
|
||||||
|
PLUGIN_DEPENDS(XOF, XOF_SHAKE_128),
|
||||||
|
PLUGIN_DEPENDS(DRBG, DRBG_CTR_AES256),
|
||||||
|
PLUGIN_DEPENDS(RNG, RNG_TRUE),
|
||||||
|
PLUGIN_PROVIDE(KE, KE_FRODO_SHAKE_L5),
|
||||||
|
PLUGIN_DEPENDS(XOF, XOF_SHAKE_256),
|
||||||
|
PLUGIN_DEPENDS(XOF, XOF_SHAKE_128),
|
||||||
|
PLUGIN_DEPENDS(DRBG, DRBG_CTR_AES256),
|
||||||
|
PLUGIN_DEPENDS(RNG, RNG_TRUE),
|
||||||
|
PLUGIN_PROVIDE(KE, KE_FRODO_AES_L1),
|
||||||
|
PLUGIN_DEPENDS(XOF, XOF_SHAKE_128),
|
||||||
|
PLUGIN_DEPENDS(CRYPTER, ENCR_AES_ECB, 16),
|
||||||
|
PLUGIN_DEPENDS(DRBG, DRBG_CTR_AES256),
|
||||||
|
PLUGIN_DEPENDS(RNG, RNG_TRUE),
|
||||||
|
PLUGIN_PROVIDE(KE, KE_FRODO_AES_L3),
|
||||||
|
PLUGIN_DEPENDS(XOF, XOF_SHAKE_256),
|
||||||
|
PLUGIN_DEPENDS(CRYPTER, ENCR_AES_ECB, 16),
|
||||||
|
PLUGIN_DEPENDS(DRBG, DRBG_CTR_AES256),
|
||||||
|
PLUGIN_DEPENDS(RNG, RNG_TRUE),
|
||||||
|
PLUGIN_PROVIDE(KE, KE_FRODO_AES_L5),
|
||||||
|
PLUGIN_DEPENDS(XOF, XOF_SHAKE_256),
|
||||||
|
PLUGIN_DEPENDS(CRYPTER, ENCR_AES_ECB, 16),
|
||||||
|
PLUGIN_DEPENDS(DRBG, DRBG_CTR_AES256),
|
||||||
|
PLUGIN_DEPENDS(RNG, RNG_TRUE),
|
||||||
|
};
|
||||||
|
*features = f;
|
||||||
|
|
||||||
|
return countof(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(plugin_t, destroy, void,
|
||||||
|
private_frodo_plugin_t *this)
|
||||||
|
{
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* see header file
|
||||||
|
*/
|
||||||
|
plugin_t *frodo_plugin_create()
|
||||||
|
{
|
||||||
|
private_frodo_plugin_t *this;
|
||||||
|
|
||||||
|
INIT(this,
|
||||||
|
.public = {
|
||||||
|
.plugin = {
|
||||||
|
.get_name = _get_name,
|
||||||
|
.get_features = _get_features,
|
||||||
|
.destroy = _destroy,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return &this->public.plugin;
|
||||||
|
}
|
42
src/libstrongswan/plugins/frodo/frodo_plugin.h
Normal file
42
src/libstrongswan/plugins/frodo/frodo_plugin.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Andreas Steffen
|
||||||
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup frodo_p frodo
|
||||||
|
* @ingroup plugins
|
||||||
|
*
|
||||||
|
* @defgroup frodo_plugin frodo_plugin
|
||||||
|
* @{ @ingroup frodo_p
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FRODO_PLUGIN_H_
|
||||||
|
#define FRODO_PLUGIN_H_
|
||||||
|
|
||||||
|
#include <plugins/plugin.h>
|
||||||
|
|
||||||
|
typedef struct frodo_plugin_t frodo_plugin_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin implementing Frodo-based key exchange
|
||||||
|
*/
|
||||||
|
struct frodo_plugin_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* implements plugin interface
|
||||||
|
*/
|
||||||
|
plugin_t plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /** FRODO_PLUGIN_H_ @}*/
|
507
src/libstrongswan/plugins/frodo/frodo_utils.c
Normal file
507
src/libstrongswan/plugins/frodo/frodo_utils.c
Normal file
@ -0,0 +1,507 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (C) Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "frodo_utils.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
void frodo_pack(u_char *out, size_t outlen, uint16_t *in, size_t inlen,
|
||||||
|
u_char lsb)
|
||||||
|
{
|
||||||
|
size_t i = 0; /* whole bytes already filled in */
|
||||||
|
size_t j = 0; /* whole uint16_t already copied */
|
||||||
|
uint16_t w = 0; /* the leftover, not yet copied */
|
||||||
|
u_char bits = 0; /* the number of lsb in w */
|
||||||
|
|
||||||
|
memset(out, 0x00, outlen);
|
||||||
|
|
||||||
|
while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0))))
|
||||||
|
{
|
||||||
|
u_char b = 0; /* bits in out[i] already filled in */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* in: | | |********|********|
|
||||||
|
* ^
|
||||||
|
* j
|
||||||
|
* w : | ****|
|
||||||
|
* ^
|
||||||
|
* bits
|
||||||
|
* out:|**|**|**|**|**|**|**|**|* |
|
||||||
|
* ^^
|
||||||
|
* ib
|
||||||
|
*/
|
||||||
|
while (b < 8)
|
||||||
|
{
|
||||||
|
int nbits = min(8 - b, bits);
|
||||||
|
uint16_t mask = (1 << nbits) - 1;
|
||||||
|
u_char t = (w >> (bits - nbits)) & mask; /* the bits to copy from w to out */
|
||||||
|
|
||||||
|
out[i] = out[i] + (t << (8 - b - nbits));
|
||||||
|
b += nbits;
|
||||||
|
bits -= nbits;
|
||||||
|
|
||||||
|
/* not strictly necessary; mostly for debugging */
|
||||||
|
w &= ~(mask << bits);
|
||||||
|
|
||||||
|
if (bits == 0)
|
||||||
|
{
|
||||||
|
if (j < inlen)
|
||||||
|
{
|
||||||
|
w = in[j];
|
||||||
|
bits = lsb;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break; /* the input vector is exhausted */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (b == 8)
|
||||||
|
{
|
||||||
|
i++; /* out[i] is filled in */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
void frodo_unpack(uint16_t *out, size_t outlen, u_char *in, size_t inlen,
|
||||||
|
u_char lsb)
|
||||||
|
{
|
||||||
|
size_t i = 0; /* whole uint16_t already filled in */
|
||||||
|
size_t j = 0; /* whole bytes already copied */
|
||||||
|
u_char w = 0; /* the leftover, not yet copied */
|
||||||
|
u_char bits = 0; /* the number of lsb bits of w */
|
||||||
|
|
||||||
|
memset(out, 0, outlen * sizeof(uint16_t));
|
||||||
|
|
||||||
|
while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0))))
|
||||||
|
{
|
||||||
|
u_char b = 0; /* bits in out[i] already filled in */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* in: | | | | | | |**|**|...
|
||||||
|
* ^
|
||||||
|
* j
|
||||||
|
* w : | *|
|
||||||
|
* ^
|
||||||
|
* bits
|
||||||
|
* out:| *****| *****| *** | |...
|
||||||
|
* ^ ^
|
||||||
|
* i b
|
||||||
|
*/
|
||||||
|
while (b < lsb)
|
||||||
|
{
|
||||||
|
int nbits = min(lsb - b, bits);
|
||||||
|
uint16_t mask = (1 << nbits) - 1;
|
||||||
|
u_char t = (w >> (bits - nbits)) & mask; /* the bits to copy from w to out */
|
||||||
|
|
||||||
|
out[i] = out[i] + (t << (lsb - b - nbits));
|
||||||
|
b += nbits;
|
||||||
|
bits -= nbits;
|
||||||
|
|
||||||
|
/* not strictly necessary; mostly for debugging */
|
||||||
|
w &= ~(mask << bits);
|
||||||
|
|
||||||
|
if (bits == 0)
|
||||||
|
{
|
||||||
|
if (j < inlen)
|
||||||
|
{
|
||||||
|
w = in[j];
|
||||||
|
bits = 8;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break; /* the input vector is exhausted */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (b == lsb)
|
||||||
|
{
|
||||||
|
i++; /* out[i] is filled in */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
void frodo_sample_n(const frodo_params_t *params, uint16_t *s, size_t n)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
uint8_t sample = 0;
|
||||||
|
uint16_t prnd = s[i] >> 1; /* Drop the least significant bit */
|
||||||
|
uint8_t sign = s[i] & 0x1; /* Pick the least significant bit */
|
||||||
|
|
||||||
|
/* No need to compare with the last value */
|
||||||
|
for (j = 0; j < params->cdf_table_len - 1; j++)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constant time comparison: 1 if CDF_TABLE[j] < s, 0 otherwise.
|
||||||
|
* Uses the fact that CDF_TABLE[j] and s fit in 15 bits
|
||||||
|
*/
|
||||||
|
sample += (uint16_t)(params->cdf_table[j] - prnd) >> 15;
|
||||||
|
}
|
||||||
|
/* Assuming that sign is either 0 or 1, flips sample iff sign = 1 */
|
||||||
|
s[i] = ((-sign) ^ sample) + sign;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate square matrix A by using SHAKE128
|
||||||
|
*/
|
||||||
|
static bool generate_matrix_by_shake(const frodo_params_t *params, uint16_t *A,
|
||||||
|
uint8_t *seed_A)
|
||||||
|
{
|
||||||
|
const uint32_t seed_A_len = params->seed_A_len;
|
||||||
|
const uint32_t n = params->n;
|
||||||
|
|
||||||
|
uint8_t seed_A_separated[2 + seed_A_len];
|
||||||
|
uint16_t *seed_A_origin = (uint16_t*)&seed_A_separated;
|
||||||
|
uint16_t i;
|
||||||
|
bool success = FALSE;
|
||||||
|
xof_t *xof;
|
||||||
|
|
||||||
|
memcpy(&seed_A_separated[2], seed_A, seed_A_len);
|
||||||
|
|
||||||
|
/* Instantiate a SHAKE-128 eXtended Output Function */
|
||||||
|
xof = lib->crypto->create_xof(lib->crypto, XOF_SHAKE_128);
|
||||||
|
if (!xof)
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "could not instantiate %N", ext_out_function_names,
|
||||||
|
XOF_SHAKE_128);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
seed_A_origin[0] = i;
|
||||||
|
|
||||||
|
if (!xof->set_seed(xof, chunk_create(seed_A_separated, 2 + seed_A_len)))
|
||||||
|
{
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (!xof->get_bytes(xof, 2*n, (uint8_t*)(A + i*n)))
|
||||||
|
{
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
success = TRUE;
|
||||||
|
|
||||||
|
err:
|
||||||
|
xof->destroy(xof);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate square matrix A by using AES128
|
||||||
|
*/
|
||||||
|
static bool generate_matrix_by_aes(const frodo_params_t *params, uint16_t *A,
|
||||||
|
uint8_t *seed_A)
|
||||||
|
{
|
||||||
|
const uint32_t n = params->n;
|
||||||
|
const uint32_t A_len = n * n * sizeof(uint16_t);
|
||||||
|
|
||||||
|
crypter_t *crypter;
|
||||||
|
chunk_t A_chunk;
|
||||||
|
bool success = FALSE;
|
||||||
|
uint32_t block_len, step, k;
|
||||||
|
uint16_t i, j;
|
||||||
|
|
||||||
|
memset((uint8_t*)A, 0x00, A_len);
|
||||||
|
|
||||||
|
crypter = lib->crypto->create_crypter(lib->crypto, ENCR_AES_ECB, 16);
|
||||||
|
if (!crypter)
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "could not instantiate AES_ECB-128");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
block_len = crypter->get_block_size(crypter);
|
||||||
|
step = block_len / sizeof(uint16_t);
|
||||||
|
|
||||||
|
if (!crypter->set_key(crypter, chunk_create(seed_A, params->seed_A_len)))
|
||||||
|
{
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ECB encryption */
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < n; j += step)
|
||||||
|
{
|
||||||
|
k = i*n + j;
|
||||||
|
A[k] = i;
|
||||||
|
A[k + 1] = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
A_chunk = chunk_create((uint8_t*)A, A_len);
|
||||||
|
|
||||||
|
if (!crypter->encrypt(crypter, A_chunk, chunk_empty, NULL))
|
||||||
|
{
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
success = TRUE;
|
||||||
|
|
||||||
|
err:
|
||||||
|
crypter->destroy(crypter);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
bool frodo_mul_add_as_plus_e(const frodo_params_t *params, uint16_t *out,
|
||||||
|
uint16_t *s, uint16_t *e, uint8_t *seed_A,
|
||||||
|
bool use_aes)
|
||||||
|
{
|
||||||
|
const uint32_t n = params->n;
|
||||||
|
const uint32_t nb = params->nb;
|
||||||
|
const uint32_t n_x_n = n * n;
|
||||||
|
|
||||||
|
int16_t A[n_x_n];
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
if (use_aes ? !generate_matrix_by_aes (params, A, seed_A) :
|
||||||
|
!generate_matrix_by_shake(params, A, seed_A))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
memcpy(out, e, nb * n * sizeof(uint16_t));
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
/* Matrix multiplication-addition A*s + e */
|
||||||
|
for (k = 0; k < nb; k++)
|
||||||
|
{
|
||||||
|
uint16_t sum = 0;
|
||||||
|
|
||||||
|
for (j = 0; j < n; j++)
|
||||||
|
{
|
||||||
|
sum += A[i*n + j] * s[k*n + j];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adding e. No need to reduce modulo 2^15,
|
||||||
|
* extra bits are taken care of during packing later on.
|
||||||
|
*/
|
||||||
|
out[i*nb + k] += sum;}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
bool frodo_mul_add_sa_plus_e(const frodo_params_t *params, uint16_t *out,
|
||||||
|
uint16_t *s, uint16_t *e, uint8_t *seed_A,
|
||||||
|
bool use_aes)
|
||||||
|
{
|
||||||
|
const uint32_t n = params->n;
|
||||||
|
const uint32_t nb = params->nb;
|
||||||
|
const uint32_t n_x_n = n * n;
|
||||||
|
|
||||||
|
int16_t A[n_x_n];
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
if (use_aes ? !generate_matrix_by_aes (params, A, seed_A) :
|
||||||
|
!generate_matrix_by_shake(params, A, seed_A))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
memcpy(out, e, nb * n * sizeof(uint16_t));
|
||||||
|
|
||||||
|
/* Matrix multiplication-addition A*s + e*/
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
for (k = 0; k < nb; k++)
|
||||||
|
{
|
||||||
|
uint16_t sum = 0;
|
||||||
|
|
||||||
|
for (j = 0; j < n; j++)
|
||||||
|
{
|
||||||
|
sum += A[j*n + i] * s[k*n + j];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adding e. No need to reduce modulo 2^15,
|
||||||
|
* extra bits are taken care of during packing later on.
|
||||||
|
*/
|
||||||
|
out[k*n + i] += sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
void frodo_mul_add_sb_plus_e(const frodo_params_t *params, uint16_t *out,
|
||||||
|
uint16_t *b, uint16_t *s, uint16_t *e)
|
||||||
|
{
|
||||||
|
const uint32_t n = params->n;
|
||||||
|
const uint32_t nb = params->nb;
|
||||||
|
const uint32_t log_q = params->log_q;
|
||||||
|
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
for (k = 0; k < nb; k++)
|
||||||
|
{
|
||||||
|
for (i = 0; i < nb; i++)
|
||||||
|
{
|
||||||
|
out[k*nb + i] = e[k*nb + i];
|
||||||
|
for (j = 0; j < n; j++)
|
||||||
|
{
|
||||||
|
out[k*nb + i] += s[k*n + j] * b[j*nb + i];
|
||||||
|
}
|
||||||
|
out[k*nb + i] = (uint32_t)(out[k*nb + i]) & ((1 << log_q) - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
void frodo_mul_bs(const frodo_params_t *params, uint16_t *out,
|
||||||
|
uint16_t *b, uint16_t *s)
|
||||||
|
{
|
||||||
|
const uint32_t n = params->n;
|
||||||
|
const uint32_t nb = params->nb;
|
||||||
|
const uint32_t log_q = params->log_q;
|
||||||
|
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
for (i = 0; i < nb; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < nb; j++)
|
||||||
|
{
|
||||||
|
out[i*nb + j] = 0;
|
||||||
|
for (k = 0; k < n; k++)
|
||||||
|
{
|
||||||
|
out[i*nb + j] += b[i*n + k] * s[j*n + k];
|
||||||
|
}
|
||||||
|
out[i*nb + j] = (uint32_t)(out[i*nb + j]) & ((1 << log_q) - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
void frodo_add(const frodo_params_t *params, uint16_t *out,
|
||||||
|
uint16_t *a, uint16_t *b)
|
||||||
|
{
|
||||||
|
const uint32_t nb = params->nb;
|
||||||
|
const uint32_t log_q = params->log_q;
|
||||||
|
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
for (i = 0; i < (nb * nb); i++)
|
||||||
|
{
|
||||||
|
out[i] = (a[i] + b[i]) & ((1 << log_q) - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void frodo_sub(const frodo_params_t *params, uint16_t *out,
|
||||||
|
uint16_t *a, uint16_t *b)
|
||||||
|
{
|
||||||
|
const uint32_t nb = params->nb;
|
||||||
|
const uint32_t log_q = params->log_q;
|
||||||
|
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
for (i = 0; i < (nb * nb); i++)
|
||||||
|
{
|
||||||
|
out[i] = (a[i] - b[i]) & ((1 << log_q) - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
void frodo_key_encode(const frodo_params_t *params, uint16_t *out, uint16_t *in)
|
||||||
|
{
|
||||||
|
const uint32_t nb = params->nb;
|
||||||
|
const uint32_t log_q = params->log_q;
|
||||||
|
const uint32_t extr_bits = params->extr_bits;
|
||||||
|
|
||||||
|
u_int i, j, npieces_word = 8;
|
||||||
|
u_int nwords = (nb * nb)/8;
|
||||||
|
uint64_t temp, mask = ((uint64_t)1 << extr_bits) - 1;
|
||||||
|
uint16_t* pos = out;
|
||||||
|
|
||||||
|
for (i = 0; i < nwords; i++)
|
||||||
|
{
|
||||||
|
temp = 0;
|
||||||
|
for(j = 0; j < extr_bits; j++)
|
||||||
|
{
|
||||||
|
temp |= ((uint64_t)((uint8_t*)in)[i*extr_bits + j]) << (8*j);
|
||||||
|
}
|
||||||
|
for (j = 0; j < npieces_word; j++)
|
||||||
|
{
|
||||||
|
*pos = (uint16_t)((temp & mask) << (log_q - extr_bits));
|
||||||
|
temp >>= extr_bits;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
void frodo_key_decode(const frodo_params_t *params, uint16_t *out, uint16_t *in)
|
||||||
|
{
|
||||||
|
const uint32_t nb = params->nb;
|
||||||
|
const uint32_t log_q = params->log_q;
|
||||||
|
const uint32_t extr_bits = params->extr_bits;
|
||||||
|
|
||||||
|
u_int i, j, index = 0, npieces_word = 8;
|
||||||
|
u_int nwords = (nb * nb) / 8;
|
||||||
|
uint16_t temp;
|
||||||
|
u_int maskex = ((uint16_t)1 << extr_bits) - 1;
|
||||||
|
u_int maskq = ((uint16_t)1 << log_q) - 1;
|
||||||
|
uint8_t *pos = (uint8_t*)out;
|
||||||
|
uint64_t templong;
|
||||||
|
|
||||||
|
for (i = 0; i < nwords; i++)
|
||||||
|
{
|
||||||
|
templong = 0;
|
||||||
|
for (j = 0; j < npieces_word; j++)
|
||||||
|
{
|
||||||
|
/* temp = floor(in*2^{-11}+0.5) */
|
||||||
|
temp = ((in[index] & maskq) +
|
||||||
|
(1 << (log_q - extr_bits - 1))) >> (log_q - extr_bits);
|
||||||
|
templong |= ((uint64_t)(temp & maskex)) << (extr_bits * j);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
for(j = 0; j < extr_bits; j++)
|
||||||
|
{
|
||||||
|
pos[i*extr_bits + j] = (templong >> (8*j)) & 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
164
src/libstrongswan/plugins/frodo/frodo_utils.h
Normal file
164
src/libstrongswan/plugins/frodo/frodo_utils.h
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (C) Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FRODO_UTILS_H_
|
||||||
|
#define FRODO_UTILS_H_
|
||||||
|
|
||||||
|
#include "frodo_params.h"
|
||||||
|
|
||||||
|
#include <library.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pack the input uint16 vector into a char output vector,
|
||||||
|
* copying lsb bits from each input element.
|
||||||
|
* If inlen * lsb / 8 > outlen, only outlen * 8 bits are copied.
|
||||||
|
*
|
||||||
|
* @param out
|
||||||
|
* @param outlen
|
||||||
|
* @param in
|
||||||
|
* @param inlen
|
||||||
|
* @param lsb
|
||||||
|
*/
|
||||||
|
void frodo_pack(u_char *out, size_t outlen, uint16_t *in, size_t inlen,
|
||||||
|
u_char lsb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unpack the input char vector into a uint16_t output vector,
|
||||||
|
* copying lsb bits for each output element from input.
|
||||||
|
* outlen must be at least ceil(inlen * 8 / lsb).
|
||||||
|
*
|
||||||
|
* @param out
|
||||||
|
* @param outlen
|
||||||
|
* @param in
|
||||||
|
* @param inlen
|
||||||
|
* @param lsb
|
||||||
|
*/
|
||||||
|
void frodo_unpack(uint16_t *out, size_t outlen, u_char *in, size_t inlen,
|
||||||
|
u_char lsb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills vector s with n samples from the noise distribution which requires
|
||||||
|
* 16 bits to sample. The distribution is specified by its CDF.
|
||||||
|
*
|
||||||
|
* @param params parameter set
|
||||||
|
* @param s pseudo-random values (are overwritten by output)
|
||||||
|
* @param n size of s
|
||||||
|
*/
|
||||||
|
void frodo_sample_n(const frodo_params_t *params, uint16_t *s, size_t n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate-and-multiply: generate matrix A (N x N) row-wise,
|
||||||
|
* multiply by s on the right.
|
||||||
|
*
|
||||||
|
* @param params parameter set
|
||||||
|
* @param out out = A*s + e (N x N_BAR)
|
||||||
|
* @param s array (N x N_BAR)
|
||||||
|
* @param e array (N x N_BAR)
|
||||||
|
* @param seed_A seed for matrix A
|
||||||
|
* @param use_aes if TRUE use AES128 for matrix A, otherwise use SHAKE128
|
||||||
|
* @ret TRUE if successful
|
||||||
|
*/
|
||||||
|
bool frodo_mul_add_as_plus_e(const frodo_params_t *params, uint16_t *out,
|
||||||
|
uint16_t *s, uint16_t *e, uint8_t *seed_A,
|
||||||
|
bool use_aes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate-and-multiply: generate matrix A (N x N) column-wise,
|
||||||
|
*
|
||||||
|
* @param params parameter set
|
||||||
|
* @param out out = s'*A + e' (N_BAR x N)
|
||||||
|
* @param s array (N_BAR x N)
|
||||||
|
* @param e array (N_BAR x N)
|
||||||
|
* @param seed_A seed for matrix A
|
||||||
|
* @param use_aes if TRUE use AES128 for matrix A, otherwise use SHAKE128
|
||||||
|
* @ret TRUE if successful
|
||||||
|
*/
|
||||||
|
bool frodo_mul_add_sa_plus_e(const frodo_params_t *params, uint16_t *out,
|
||||||
|
uint16_t *s, uint16_t *e, uint8_t *seed_A,
|
||||||
|
bool use_aes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiply by s on the left
|
||||||
|
*
|
||||||
|
* @param params parameter set
|
||||||
|
* @param b array (N x N_BAR)
|
||||||
|
* @param s array (N_BAR x N)
|
||||||
|
* @param e array (N_BAR x N_BAR)
|
||||||
|
* @param out out = s*b + e (N_BAR x N_BAR)
|
||||||
|
*/
|
||||||
|
void frodo_mul_add_sb_plus_e(const frodo_params_t *params, uint16_t *out,
|
||||||
|
uint16_t *b, uint16_t *s, uint16_t *e);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiply by s on the right
|
||||||
|
*
|
||||||
|
* @param params parameter set
|
||||||
|
* @param out out = b*s (N_BAR x N_BAR)
|
||||||
|
* @param b array (N_BAR x N),
|
||||||
|
* @param s array (N x N_BAR)
|
||||||
|
*/
|
||||||
|
void frodo_mul_bs(const frodo_params_t *params, uint16_t *out,
|
||||||
|
uint16_t *b, uint16_t *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a and b
|
||||||
|
*
|
||||||
|
* @param params parameter set
|
||||||
|
* @param out c = a + b (N_BAR x N_AR)
|
||||||
|
* @param a array (N_BAR x N_BAR)
|
||||||
|
* @param b array (N_BAR x N_BAR)
|
||||||
|
*/
|
||||||
|
void frodo_add(const frodo_params_t *params, uint16_t *out,
|
||||||
|
uint16_t *a, uint16_t *b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtract a and b
|
||||||
|
*
|
||||||
|
* @param params parameter set
|
||||||
|
* @param out c = a - b (N_BAR x N_AR)
|
||||||
|
* @param a array (N_BAR x N_BAR)
|
||||||
|
* @param b array (N_BAR x N_BAR)
|
||||||
|
*/
|
||||||
|
void frodo_sub(const frodo_params_t *params, uint16_t *out,
|
||||||
|
uint16_t *a, uint16_t *b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode
|
||||||
|
*
|
||||||
|
* @param params parameter set
|
||||||
|
* @param out encoded key
|
||||||
|
* @param in key to be encoded
|
||||||
|
*/
|
||||||
|
void frodo_key_encode(const frodo_params_t *params, uint16_t *out, uint16_t *in);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode
|
||||||
|
*
|
||||||
|
* @param params parameter set
|
||||||
|
* @param out decoded key
|
||||||
|
* @param in key to be decoded
|
||||||
|
*/
|
||||||
|
void frodo_key_decode(const frodo_params_t *params, uint16_t *out, uint16_t *in);
|
||||||
|
|
||||||
|
#endif /** FRODO_UTILS_H_ @}*/
|
Loading…
x
Reference in New Issue
Block a user