|
- //
- // rng.c
- //
- // Created by Bassham, Lawrence E (Fed) on 8/29/17.
- // Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved.
- // Modified for PQClean by Sebastian Verschoor
- //
-
- #include "nistseedexpander.h"
- #include "aes.h"
- #include <string.h>
-
- /*
- seedexpander_init()
- ctx - stores the current state of an instance of the seed expander
- seed - a 32 byte random value
- diversifier - an 8 byte diversifier
- maxlen - maximum number of bytes (less than 2**32) generated under this seed and diversifier
- */
- int
- seedexpander_init(AES_XOF_struct *ctx,
- const uint8_t *seed,
- const uint8_t *diversifier,
- size_t maxlen)
- {
- ctx->length_remaining = maxlen;
-
- memcpy(ctx->key, seed, 32);
- memcpy(ctx->ctr, diversifier, 8);
-
- ctx->ctr[11] = maxlen % 256;
- maxlen >>= 8;
- ctx->ctr[10] = maxlen % 256;
- maxlen >>= 8;
- ctx->ctr[9] = maxlen % 256;
- maxlen >>= 8;
- ctx->ctr[8] = maxlen % 256;
- memset(ctx->ctr+12, 0x00, 4);
-
- ctx->buffer_pos = 16;
- memset(ctx->buffer, 0x00, 16);
-
- return RNG_SUCCESS;
- }
-
- static void AES256_ECB(uint8_t *key, uint8_t *ctr, uint8_t *buffer) {
- aes256ctx ctx;
- aes256_ecb_keyexp(&ctx, key);
- aes256_ecb(buffer, ctr, 1, &ctx);
- aes256_ctx_release(&ctx);
- }
-
- /*
- seedexpander()
- ctx - stores the current state of an instance of the seed expander
- x - returns the XOF data
- xlen - number of bytes to return
- */
- int
- seedexpander(AES_XOF_struct *ctx, uint8_t *x, size_t xlen)
- {
- size_t offset;
-
- if ( x == NULL ) {
- return RNG_BAD_OUTBUF;
- }
- if ( xlen >= ctx->length_remaining ) {
- return RNG_BAD_REQ_LEN;
- }
-
- ctx->length_remaining -= xlen;
-
- offset = 0;
- while ( xlen > 0 ) {
- if ( xlen <= (16-ctx->buffer_pos) ) { // buffer has what we need
- memcpy(x+offset, ctx->buffer+ctx->buffer_pos, xlen);
- ctx->buffer_pos += xlen;
-
- return RNG_SUCCESS;
- }
-
- // take what's in the buffer
- memcpy(x+offset, ctx->buffer+ctx->buffer_pos, 16-ctx->buffer_pos);
- xlen -= 16-ctx->buffer_pos;
- offset += 16-ctx->buffer_pos;
-
- AES256_ECB(ctx->key, ctx->ctr, ctx->buffer);
- ctx->buffer_pos = 0;
-
- //increment the counter
- for (size_t i=15; i>=12; i--) {
- if ( ctx->ctr[i] == 0xff ) {
- ctx->ctr[i] = 0x00;
- } else {
- ctx->ctr[i]++;
- break;
- }
- }
-
- }
-
- return RNG_SUCCESS;
- }
|