diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2014-03-11 20:48:48 +0100 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2014-03-11 20:48:48 +0100 |
commit | 15fb7904f4431a6e7c305fd08732458f7f885e7e (patch) | |
tree | c93b60ee813af70509f00f34e29ebec311762427 /src/libstrongswan/plugins/ntru/ntru_drbg.c | |
parent | 5313d2d78ca150515f7f5eb39801c100690b6b29 (diff) | |
download | vyos-strongswan-15fb7904f4431a6e7c305fd08732458f7f885e7e.tar.gz vyos-strongswan-15fb7904f4431a6e7c305fd08732458f7f885e7e.zip |
Imported Upstream version 5.1.2
Diffstat (limited to 'src/libstrongswan/plugins/ntru/ntru_drbg.c')
-rw-r--r-- | src/libstrongswan/plugins/ntru/ntru_drbg.c | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/ntru/ntru_drbg.c b/src/libstrongswan/plugins/ntru/ntru_drbg.c new file mode 100644 index 000000000..181a58939 --- /dev/null +++ b/src/libstrongswan/plugins/ntru/ntru_drbg.c @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2013 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 "ntru_drbg.h" + +#include <utils/debug.h> +#include <utils/test.h> + +#define MAX_STRENGTH_BITS 256 +#define MAX_DRBG_REQUESTS 0xfffffffe + +typedef struct private_ntru_drbg_t private_ntru_drbg_t; + +/** + * Private data of an ntru_drbg_t object. + */ +struct private_ntru_drbg_t { + /** + * Public ntru_drbg_t interface. + */ + ntru_drbg_t public; + + /** + * Security strength in bits of the DRBG + */ + u_int32_t strength; + + /** + * Number of requests for pseudorandom bits + */ + u_int32_t reseed_counter; + + /** + * Maximum number of requests for pseudorandom bits + */ + u_int32_t max_requests; + + /** + * True entropy source + */ + rng_t *entropy; + + /** + * HMAC-SHA256 + */ + signer_t *hmac; + + /** + * Internal state of HMAC-SHA256: key + */ + chunk_t key; + + /** + * Internal state of HMAC-SHA256: value + */ + chunk_t value; + +}; + +/** + * Update the internal state of the HMAC_DRBG + */ +static bool update(private_ntru_drbg_t *this, chunk_t data) +{ + chunk_t ch_00 = chunk_from_chars(0x00); + chunk_t ch_01 = chunk_from_chars(0x01); + + if (!this->hmac->set_key(this->hmac, this->key) || + !this->hmac->get_signature(this->hmac, this->value, NULL) || + !this->hmac->get_signature(this->hmac, ch_00, NULL) || + !this->hmac->get_signature(this->hmac, data, this->key.ptr) || + !this->hmac->set_key(this->hmac, this->key) || + !this->hmac->get_signature(this->hmac, this->value, + this->value.ptr)) + { + return FALSE; + } + + if (data.len > 0) + { + if (!this->hmac->set_key(this->hmac, this->key) || + !this->hmac->get_signature(this->hmac, this->value, NULL) || + !this->hmac->get_signature(this->hmac, ch_01, NULL) || + !this->hmac->get_signature(this->hmac, data, this->key.ptr) || + !this->hmac->set_key(this->hmac, this->key) || + !this->hmac->get_signature(this->hmac, this->value, + this->value.ptr)) + { + return FALSE; + } + } + DBG4(DBG_LIB, "HMAC_DRBG V: %B", &this->value); + DBG4(DBG_LIB, "HMAC_DRBG K: %B", &this->key); + + return TRUE; +} + +METHOD(ntru_drbg_t, get_strength, u_int32_t, + private_ntru_drbg_t *this) +{ + return this->strength; +} + +METHOD(ntru_drbg_t, reseed, bool, + private_ntru_drbg_t *this) +{ + chunk_t seed; + + seed = chunk_alloc(this->strength / BITS_PER_BYTE); + DBG2(DBG_LIB, "DRBG requests %u bytes of entropy", seed.len); + + if (!this->entropy->get_bytes(this->entropy, seed.len, seed.ptr)) + { + chunk_free(&seed); + return FALSE; + } + if (!update(this, seed)) + { + chunk_free(&seed); + return FALSE; + } + chunk_clear(&seed); + this->reseed_counter = 1; + + return TRUE; +} + +METHOD(ntru_drbg_t, generate, bool, + private_ntru_drbg_t *this, u_int32_t strength, u_int32_t len, u_int8_t *out) +{ + size_t delta; + chunk_t output; + + DBG2(DBG_LIB, "DRBG generates %u pseudorandom bytes", len); + if (!out || len == 0) + { + return FALSE; + } + output = chunk_create(out, len); + + if (this->reseed_counter > this->max_requests) + { + if (!reseed(this)) + { + return FALSE; + } + } + while (len) + { + if (!this->hmac->get_signature(this->hmac, this->value, + this->value.ptr)) + { + return FALSE; + } + delta = min(len, this->value.len); + memcpy(out, this->value.ptr, delta); + len -= delta; + out += delta; + } + DBG4(DBG_LIB, "HMAC_DRBG Out: %B", &output); + + if (!update(this, chunk_empty)) + { + return FALSE; + } + this->reseed_counter++; + + return TRUE; +} + +METHOD(ntru_drbg_t, destroy, void, + private_ntru_drbg_t *this) +{ + this->hmac->destroy(this->hmac); + chunk_clear(&this->key); + chunk_clear(&this->value); + free(this); +} + +/* + * Described in header. + */ +ntru_drbg_t *ntru_drbg_create(u_int32_t strength, chunk_t pers_str, + rng_t *entropy) +{ + private_ntru_drbg_t *this; + chunk_t seed; + signer_t *hmac; + size_t entropy_len; + u_int32_t max_requests; + + if (strength > MAX_STRENGTH_BITS) + { + return NULL; + } + if (strength <= 112) + { + strength = 112; + } + else if (strength <= 128) + { + strength = 128; + } + else if (strength <= 192) + { + strength = 192; + } + else + { + strength = 256; + } + + hmac = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_SHA2_256_256); + if (!hmac) + { + DBG1(DBG_LIB, "could not instantiate HMAC-SHA256"); + return NULL; + } + + max_requests = lib->settings->get_int(lib->settings, + "%s.plugins.ntru.max_drbg_requests", + MAX_DRBG_REQUESTS, lib->ns); + + INIT(this, + .public = { + .get_strength = _get_strength, + .reseed = _reseed, + .generate = _generate, + .destroy = _destroy, + }, + .strength = strength, + .entropy = entropy, + .hmac = hmac, + .key = chunk_alloc(hmac->get_key_size(hmac)), + .value = chunk_alloc(hmac->get_block_size(hmac)), + .max_requests = max_requests, + .reseed_counter = 1, + ); + + memset(this->key.ptr, 0x00, this->key.len); + memset(this->value.ptr, 0x01, this->value.len); + + entropy_len = (strength + strength/2) / BITS_PER_BYTE; + seed = chunk_alloc(entropy_len + pers_str.len); + DBG2(DBG_LIB, "DRBG requests %u bytes of entropy", entropy_len); + + if (!this->entropy->get_bytes(this->entropy, entropy_len, seed.ptr)) + { + chunk_free(&seed); + destroy(this); + return NULL; + } + memcpy(seed.ptr + entropy_len, pers_str.ptr, pers_str.len); + DBG4(DBG_LIB, "seed: %B", &seed); + + if (!update(this, seed)) + { + chunk_free(&seed); + destroy(this); + return NULL; + } + chunk_clear(&seed); + + return &this->public; +} + +EXPORT_FUNCTION_FOR_TESTS(ntru, ntru_drbg_create); |