From 075bcf453371e1b3f7b6ca72b4080eefbe1be3f7 Mon Sep 17 00:00:00 2001 From: rasky Date: Wed, 29 Sep 2010 15:24:43 +0000 Subject: [PATCH] SEC: Add ANSI X9.17 PRNG. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4352 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/sec/prng/x917.c | 126 +++++++++++++++++++++++++++++++++++++++++ bertos/sec/prng/x917.h | 58 +++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 bertos/sec/prng/x917.c create mode 100644 bertos/sec/prng/x917.h diff --git a/bertos/sec/prng/x917.c b/bertos/sec/prng/x917.c new file mode 100644 index 00000000..2ffba3aa --- /dev/null +++ b/bertos/sec/prng/x917.c @@ -0,0 +1,126 @@ +/** + * \file + * + * + * \brief ANSI X9.17 PRNG implementation + * \author Giovanni Bajo + * + */ + +#include "x917.h" +#include +#include +#include "hw/hw_timer.h" + +static void x917_next(X917Context *ctx, BlockCipher *cipher, uint8_t *out) +{ + const size_t blen = cipher_block_len(cipher); + + union + { + uint8_t bytes[blen]; + struct + { + time_t t0; + hptime_t t1; + } data; + } DT; + + ASSERT(sizeof(DT.bytes) >= sizeof(ticks_t) + sizeof(hptime_t)); + + DT.data.t0 = timer_clock(); + DT.data.t1 = timer_hw_hpread(); + + cipher_ecb_encrypt(cipher, DT.bytes); + + xor_block(out, DT.bytes, ctx->state, blen); + cipher_ecb_encrypt(cipher, out); + + xor_block(ctx->state, DT.bytes, out, blen); + cipher_ecb_encrypt(cipher, ctx->state); + + PURGE(DT.bytes); +} + + +static void x917_generate(PRNG *ctx_, uint8_t *data, size_t len) +{ + X917Context *ctx = (X917Context *)ctx_; + BlockCipher *cipher = AES128_stackinit(); + + const size_t blen = cipher_block_len(cipher); + uint8_t temp[blen]; + + ASSERT(len); + ASSERT(sizeof(ctx->state) >= blen); + ASSERT(sizeof(ctx->key) >= cipher_key_len(cipher)); + + cipher_set_key(cipher, ctx->key); + + while (len) + { + size_t L = MIN(blen, len); + x917_next(ctx, cipher, temp); + memcpy(data, temp, L); + len -= L; + data += L; + } +} + +static void x917_reseed(PRNG *ctx_, const uint8_t *seed) +{ + // The X9.17 standard does not specify reseeding. To avoid external + // dependencies, we implement it this way: + // * Generate a new random block, xor it with the first part + // of the seed, and use the result as new seed. + // * Generate and throw away a block to update the state. + X917Context *ctx = (X917Context *)ctx_; + + size_t klen = sizeof(ctx->key); + size_t blen = sizeof(ctx->state); + + uint8_t buf[klen]; + x917_generate(ctx_, buf, klen); + + xor_block(ctx->key, buf, seed, klen); + xor_block(ctx->state, ctx->state, seed+klen, blen); + + PURGE(buf); +} + +/*********************************************************************/ + +void x917_init(X917Context *ctx) +{ + ctx->rng.reseed = x917_reseed; + ctx->rng.generate = x917_generate; + ctx->rng.seed_len = sizeof(ctx->key) + sizeof(ctx->state); +} diff --git a/bertos/sec/prng/x917.h b/bertos/sec/prng/x917.h new file mode 100644 index 00000000..a5cc94d5 --- /dev/null +++ b/bertos/sec/prng/x917.h @@ -0,0 +1,58 @@ +/** + * \file + * + * + * \brief ANSI X9.17 PRNG implementation + * \author Giovanni Bajo + * + */ + +#ifndef SEC_PRNG_X917_H +#define SEC_PRNG_X917_H + +#include +#include + +typedef struct X917Context +{ + PRNG rng; + uint8_t key[16]; + uint8_t state[16]; + +} X917Context; + +void x917_init(X917Context *ctx); + +#define x917_stackinit(...) \ + ({ X917Context *ctx = alloca(sizeof(X917Context)); x917_init(ctx, ##__VA_ARGS__); &ctx->rng; }) + + +#endif /* SEC_CSPRNG_X917_H */ -- 2.25.1