1 // 2 // rng.c 3 // 4 // Created by Bassham, Lawrence E (Fed) on 8/29/17. 5 // Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. 6 // SPDX-License-Identifier: Unknown 7 // Modified for PQClean by Sebastian Verschoor 8 // 9 10 #include "nistseedexpander.h" 11 #include "aes.h" 12 #include <string.h> 13 14 /* 15 seedexpander_init() 16 ctx - stores the current state of an instance of the seed expander 17 seed - a 32 byte random value 18 diversifier - an 8 byte diversifier 19 maxlen - maximum number of bytes (less than 2**32) generated under this seed and diversifier 20 */ 21 int 22 seedexpander_init(AES_XOF_struct *ctx, 23 const uint8_t *seed, 24 const uint8_t *diversifier, 25 size_t maxlen) { 26 ctx->length_remaining = maxlen; 27 28 memcpy(ctx->key, seed, 32); 29 memcpy(ctx->ctr, diversifier, 8); 30 31 ctx->ctr[11] = (uint8_t) (maxlen % 256); 32 maxlen >>= 8; 33 ctx->ctr[10] = (uint8_t) (maxlen % 256); 34 maxlen >>= 8; 35 ctx->ctr[9] = (uint8_t) (maxlen % 256); 36 maxlen >>= 8; 37 ctx->ctr[8] = (uint8_t) (maxlen % 256); 38 memset(ctx->ctr + 12, 0x00, 4); 39 40 ctx->buffer_pos = 16; 41 memset(ctx->buffer, 0x00, 16); 42 43 return RNG_SUCCESS; 44 } 45 46 static void AES256_ECB(uint8_t *key, uint8_t *ctr, uint8_t *buffer) { 47 aes256ctx ctx; 48 aes256_ecb_keyexp(&ctx, key); 49 aes256_ecb(buffer, ctr, 1, &ctx); 50 aes256_ctx_release(&ctx); 51 } 52 53 /* 54 seedexpander() 55 ctx - stores the current state of an instance of the seed expander 56 x - returns the XOF data 57 xlen - number of bytes to return 58 */ 59 int 60 seedexpander(AES_XOF_struct *ctx, uint8_t *x, size_t xlen) { 61 size_t offset; 62 63 if ( x == NULL ) { 64 return RNG_BAD_OUTBUF; 65 } 66 if ( xlen >= ctx->length_remaining ) { 67 return RNG_BAD_REQ_LEN; 68 } 69 70 ctx->length_remaining -= xlen; 71 72 offset = 0; 73 while ( xlen > 0 ) { 74 if ( xlen <= (16 - ctx->buffer_pos) ) { // buffer has what we need 75 memcpy(x + offset, ctx->buffer + ctx->buffer_pos, xlen); 76 ctx->buffer_pos += xlen; 77 78 return RNG_SUCCESS; 79 } 80 81 // take what's in the buffer 82 memcpy(x + offset, ctx->buffer + ctx->buffer_pos, 16 - ctx->buffer_pos); 83 xlen -= 16 - ctx->buffer_pos; 84 offset += 16 - ctx->buffer_pos; 85 86 AES256_ECB(ctx->key, ctx->ctr, ctx->buffer); 87 ctx->buffer_pos = 0; 88 89 //increment the counter 90 for (size_t i = 15; i >= 12; i--) { 91 if ( ctx->ctr[i] == 0xff ) { 92 ctx->ctr[i] = 0x00; 93 } else { 94 ctx->ctr[i]++; 95 break; 96 } 97 } 98 99 } 100 101 return RNG_SUCCESS; 102 } 103