From: Andreas Steffen Date: Wed, 3 Aug 2016 12:46:08 +0000 (+0200) Subject: xof: Added ChaCha20 stream as XOF X-Git-Tag: 5.5.1dr1~1^2~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1fddb0b92ef2e4ee4fb23da2c4badc70620df1dc;p=thirdparty%2Fstrongswan.git xof: Added ChaCha20 stream as XOF --- diff --git a/src/libstrongswan/crypto/xofs/xof.c b/src/libstrongswan/crypto/xofs/xof.c index 5a78271ad8..3c5b5d6eda 100644 --- a/src/libstrongswan/crypto/xofs/xof.c +++ b/src/libstrongswan/crypto/xofs/xof.c @@ -15,12 +15,13 @@ #include "xof.h" -ENUM(ext_out_function_names, XOF_UNDEFINED, XOF_MGF1_SHA512, +ENUM(ext_out_function_names, XOF_UNDEFINED, XOF_CHACHA20, "XOF_UNDEFINED", "XOF_SHAKE128", "XOF_SHAKE256", "XOF_MGF1_SHA1", "XOF_MGF1_SHA256", - "XOF_MGF1_SHA512" + "XOF_MGF1_SHA512", + "XOF_CHACHA20" ); diff --git a/src/libstrongswan/crypto/xofs/xof.h b/src/libstrongswan/crypto/xofs/xof.h index 11ef086ece..e8acda31a1 100644 --- a/src/libstrongswan/crypto/xofs/xof.h +++ b/src/libstrongswan/crypto/xofs/xof.h @@ -41,6 +41,8 @@ enum ext_out_function_t { XOF_MGF1_SHA256, /** RFC 2437 PKCS#1 */ XOF_MGF1_SHA512, + /** RFC 7539 ChaCha20 */ + XOF_CHACHA20, }; /** diff --git a/src/libstrongswan/plugins/chapoly/Makefile.am b/src/libstrongswan/plugins/chapoly/Makefile.am index 1753de0c76..d6d577c86b 100644 --- a/src/libstrongswan/plugins/chapoly/Makefile.am +++ b/src/libstrongswan/plugins/chapoly/Makefile.am @@ -15,7 +15,8 @@ libstrongswan_chapoly_la_SOURCES = \ chapoly_plugin.h chapoly_plugin.c \ chapoly_drv.h chapoly_drv.c \ chapoly_drv_portable.h chapoly_drv_portable.c \ - chapoly_aead.h chapoly_aead.c + chapoly_aead.h chapoly_aead.c \ + chapoly_xof.h chapoly_xof.c noinst_LTLIBRARIES += libchapoly-drv-ssse3.la libchapoly_drv_ssse3_la_SOURCES = chapoly_drv_ssse3.h chapoly_drv_ssse3.c diff --git a/src/libstrongswan/plugins/chapoly/chapoly_plugin.c b/src/libstrongswan/plugins/chapoly/chapoly_plugin.c index 02e7121d6e..447960bd03 100644 --- a/src/libstrongswan/plugins/chapoly/chapoly_plugin.c +++ b/src/libstrongswan/plugins/chapoly/chapoly_plugin.c @@ -15,6 +15,7 @@ #include "chapoly_plugin.h" #include "chapoly_aead.h" +#include "chapoly_xof.h" #include @@ -43,6 +44,8 @@ METHOD(plugin_t, get_features, int, static plugin_feature_t f[] = { PLUGIN_REGISTER(AEAD, chapoly_aead_create), PLUGIN_PROVIDE(AEAD, ENCR_CHACHA20_POLY1305, 32), + PLUGIN_REGISTER(XOF, chapoly_xof_create), + PLUGIN_PROVIDE(XOF, XOF_CHACHA20), }; *features = f; return countof(f); diff --git a/src/libstrongswan/plugins/chapoly/chapoly_xof.c b/src/libstrongswan/plugins/chapoly/chapoly_xof.c new file mode 100644 index 0000000000..db5598428b --- /dev/null +++ b/src/libstrongswan/plugins/chapoly/chapoly_xof.c @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2016 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 . + * + * 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 "chapoly_xof.h" +#include "chapoly_drv.h" + +typedef struct private_chapoly_xof_t private_chapoly_xof_t; + +/** + * Private data of an chapoly_xof_t object. + */ +struct private_chapoly_xof_t { + + /** + * Public chapoly_xof_t interface. + */ + chapoly_xof_t public; + + /** + * Latest block of the ChaCha20 stream. + */ + uint8_t stream[CHACHA_BLOCK_SIZE]; + + /** + * Index pointing to the current position in the stream + */ + u_int stream_index; + + /** + * Driver backend + */ + chapoly_drv_t *drv; +}; + +METHOD(xof_t, get_bytes, bool, + private_chapoly_xof_t *this, size_t out_len, uint8_t *buffer) +{ + size_t index = 0, len, blocks; + + /* empty the stream buffer first */ + len = min(out_len, CHACHA_BLOCK_SIZE - this->stream_index); + if (len) + { + memcpy(buffer + index, this->stream + this->stream_index, len); + index += len; + this->stream_index += len; + } + + /* copy whole stream blocks directly to output buffer */ + blocks = (out_len - index) / CHACHA_BLOCK_SIZE; + while (blocks--) + { + if (!this->drv->chacha(this->drv, buffer + index)) + { + return FALSE; + } + index += CHACHA_BLOCK_SIZE; + } + + /* refill the stream buffer if some more output bytes are needed */ + len = out_len - index; + if (len) + { + if (!this->drv->chacha(this->drv, this->stream)) + { + return FALSE; + } + memcpy(buffer + index, this->stream, len); + this->stream_index = len; + } + + return TRUE; +} + +METHOD(xof_t, allocate_bytes, bool, + private_chapoly_xof_t *this, size_t out_len, chunk_t *chunk) +{ + *chunk = chunk_alloc(out_len); + + if (!get_bytes(this, out_len, chunk->ptr)) + { + chunk_free(chunk); + return FALSE; + } + + return TRUE; +} + +METHOD(xof_t, get_block_size, size_t, + private_chapoly_xof_t *this) +{ + return CHACHA_BLOCK_SIZE; +} + +METHOD(xof_t, get_seed_size, size_t, + private_chapoly_xof_t *this) +{ + return CHACHA_KEY_SIZE + CHACHA_SALT_SIZE + CHACHA_IV_SIZE; +} + +METHOD(xof_t, set_seed, bool, + private_chapoly_xof_t *this, chunk_t seed) +{ + this->stream_index = CHACHA_BLOCK_SIZE; + + return seed.len == get_seed_size(this) && + this->drv->set_key(this->drv, "expand 32-byte k", + seed.ptr, seed.ptr + CHACHA_KEY_SIZE) && + this->drv->init(this->drv, + seed.ptr + CHACHA_KEY_SIZE + CHACHA_SALT_SIZE); +} + +METHOD(xof_t, destroy, void, + private_chapoly_xof_t *this) +{ + this->drv->destroy(this->drv); + free(this); +} + +/** + * See header + */ +chapoly_xof_t *chapoly_xof_create(ext_out_function_t algorithm) +{ + private_chapoly_xof_t *this; + chapoly_drv_t *drv; + + if (algorithm != XOF_CHACHA20) + { + return NULL; + } + + drv = chapoly_drv_probe(); + if (!drv) + { + return NULL; + } + + INIT(this, + .public = { + .xof_interface = { + .get_bytes = _get_bytes, + .allocate_bytes = _allocate_bytes, + .get_block_size = _get_block_size, + .get_seed_size = _get_seed_size, + .set_seed = _set_seed, + .destroy = _destroy, + }, + }, + .drv = drv, + ); + + return &this->public; +} diff --git a/src/libstrongswan/plugins/chapoly/chapoly_xof.h b/src/libstrongswan/plugins/chapoly/chapoly_xof.h new file mode 100644 index 0000000000..cd0586fad6 --- /dev/null +++ b/src/libstrongswan/plugins/chapoly/chapoly_xof.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2016 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 . + * + * 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 chapoly_xof chapoly_xof + * @{ @ingroup chapoly + */ + +#ifndef CHAPOLY_XOF_H_ +#define CHAPOLY_XOF_H_ + +#include + +typedef struct chapoly_xof_t chapoly_xof_t; + +/** + * ChaCha20 XOF implementation + * + * Based on RFC 7539 ChaCha20 stream initialized with block counter = 1 + */ +struct chapoly_xof_t { + + /** + * Generic xof_t interface for this Extended Output Function (XOF). + */ + xof_t xof_interface; +}; + +/** + * Create a chapoly_xof instance. + * + * @param algorithm XOF_CHACHA20 + * @return chapoly_xof_t object, NULL if not supported + */ +chapoly_xof_t *chapoly_xof_create(ext_out_function_t algorithm); + +#endif /** CHAPOLY_XOF_H_ @}*/ diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.am b/src/libstrongswan/plugins/test_vectors/Makefile.am index 88c023f42f..c29b6fd1e2 100644 --- a/src/libstrongswan/plugins/test_vectors/Makefile.am +++ b/src/libstrongswan/plugins/test_vectors/Makefile.am @@ -20,6 +20,7 @@ libstrongswan_test_vectors_la_SOURCES = \ test_vectors/aes_ccm.c \ test_vectors/aes_gcm.c \ test_vectors/chacha20poly1305.c \ + test_vectors/chacha20_xof.c \ test_vectors/blowfish.c \ test_vectors/camellia_cbc.c \ test_vectors/camellia_ctr.c \ diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors.h b/src/libstrongswan/plugins/test_vectors/test_vectors.h index 309040c98e..43633e3ff1 100644 --- a/src/libstrongswan/plugins/test_vectors/test_vectors.h +++ b/src/libstrongswan/plugins/test_vectors/test_vectors.h @@ -268,6 +268,10 @@ TEST_VECTOR_XOF(shake_256_64) TEST_VECTOR_XOF(shake_256_135) TEST_VECTOR_XOF(shake_256_136) TEST_VECTOR_XOF(shake_256_255) +TEST_VECTOR_XOF(chacha20_xof_1) +TEST_VECTOR_XOF(chacha20_xof_2) +TEST_VECTOR_XOF(chacha20_xof_3) +TEST_VECTOR_XOF(chacha20_xof_4) TEST_VECTOR_RNG(rng_monobit_1) TEST_VECTOR_RNG(rng_monobit_2) diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors/chacha20_xof.c b/src/libstrongswan/plugins/test_vectors/test_vectors/chacha20_xof.c new file mode 100644 index 0000000000..2c602c6a3b --- /dev/null +++ b/src/libstrongswan/plugins/test_vectors/test_vectors/chacha20_xof.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2016 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 Licenseor (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be usefulbut + * 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 + +/** + * ChaCha20 Stream Test Vector from RFC 7539, Section 2.3.2 + */ +xof_test_vector_t chacha20_xof_1 = { + .alg = XOF_CHACHA20, .len = 44, + .seed = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x00\x00\x00\x09\x00\x00\x00\x4a\x00\x00\x00\x00", + .out_len = 64, + .out = "\x10\xf1\xe7\xe4\xd1\x3b\x59\x15\x50\x0f\xdd\x1f\xa3\x20\x71\xc4" + "\xc7\xd1\xf4\xc7\x33\xc0\x68\x03\x04\x22\xaa\x9a\xc3\xd4\x6c\x4e" + "\xd2\x82\x64\x46\x07\x9f\xaa\x09\x14\xc2\xd7\x05\xd9\x8b\x02\xa2" + "\xb5\x12\x9c\xd1\xde\x16\x4e\xb9\xcb\xd0\x83\xe8\xa2\x50\x3c\x4e" +}; + +/** + * ChaCha20 Stream Test Vector from RFC 7539, Section 2.4.2 + */ +xof_test_vector_t chacha20_xof_2 = { + .alg = XOF_CHACHA20, .len = 44, + .seed = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x00\x00\x00\x00\x00\x00\x00\x4a\x00\x00\x00\x00", + .out_len = 114, + .out = "\x22\x4f\x51\xf3\x40\x1b\xd9\xe1\x2f\xde\x27\x6f\xb8\x63\x1d\xed" + "\x8c\x13\x1f\x82\x3d\x2c\x06\xe2\x7e\x4f\xca\xec\x9e\xf3\xcf\x78" + "\x8a\x3b\x0a\xa3\x72\x60\x0a\x92\xb5\x79\x74\xcd\xed\x2b\x93\x34" + "\x79\x4c\xba\x40\xc6\x3e\x34\xcd\xea\x21\x2c\x4c\xf0\x7d\x41\xb7" + "\x69\xa6\x74\x9f\x3f\x63\x0f\x41\x22\xca\xfe\x28\xec\x4d\xc4\x7e" + "\x26\xd4\x34\x6d\x70\xb9\x8c\x73\xf3\xe9\xc5\x3a\xc4\x0c\x59\x45" + "\x39\x8b\x6e\xda\x1a\x83\x2c\x89\xc1\x67\xea\xcd\x90\x1d\x7e\x2b" + "\xf3\x63" +}; + +/** + * ChaCha20 Stream Test Vector #2 from RFC 7539, Section A1. + */ +xof_test_vector_t chacha20_xof_3 = { + .alg = XOF_CHACHA20, .len = 44, + .seed = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + .out_len = 64, + .out = "\x9f\x07\xe7\xbe\x55\x51\x38\x7a\x98\xba\x97\x7c\x73\x2d\x08\x0d" + "\xcb\x0f\x29\xa0\x48\xe3\x65\x69\x12\xc6\x53\x3e\x32\xee\x7a\xed" + "\x29\xb7\x21\x76\x9c\xe6\x4e\x43\xd5\x71\x33\xb0\x74\xd8\x39\xd5" + "\x31\xed\x1f\x28\x51\x0a\xfb\x45\xac\xe1\x0a\x1f\x4b\x79\x4d\x6f" +}; + +/** + * ChaCha20 Stream Test Vector #3 from RFC 7539, Section A1. + */ +xof_test_vector_t chacha20_xof_4 = { + .alg = XOF_CHACHA20, .len = 44, + .seed = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + .out_len = 64, + .out = "\x3a\xeb\x52\x24\xec\xf8\x49\x92\x9b\x9d\x82\x8d\xb1\xce\xd4\xdd" + "\x83\x20\x25\xe8\x01\x8b\x81\x60\xb8\x22\x84\xf3\xc9\x49\xaa\x5a" + "\x8e\xca\x00\xbb\xb4\xa7\x3b\xda\xd1\x92\xb5\xc4\x2f\x73\xf2\xfd" + "\x4e\x27\x36\x44\xc8\xb3\x61\x25\xa6\x4a\xdd\xeb\x00\x6c\x13\xa0" +}; +