Path: blob/main/contrib/bearssl/src/rand/aesctr_drbg.c
39507 views
/*1* Copyright (c) 2018 Thomas Pornin <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining4* a copy of this software and associated documentation files (the5* "Software"), to deal in the Software without restriction, including6* without limitation the rights to use, copy, modify, merge, publish,7* distribute, sublicense, and/or sell copies of the Software, and to8* permit persons to whom the Software is furnished to do so, subject to9* the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*/2324#include "inner.h"2526/* see bearssl_rand.h */27void28br_aesctr_drbg_init(br_aesctr_drbg_context *ctx,29const br_block_ctr_class *aesctr,30const void *seed, size_t len)31{32unsigned char tmp[16];3334ctx->vtable = &br_aesctr_drbg_vtable;35memset(tmp, 0, sizeof tmp);36aesctr->init(&ctx->sk.vtable, tmp, 16);37ctx->cc = 0;38br_aesctr_drbg_update(ctx, seed, len);39}4041/* see bearssl_rand.h */42void43br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx, void *out, size_t len)44{45unsigned char *buf;46unsigned char iv[12];4748buf = out;49memset(iv, 0, sizeof iv);50while (len > 0) {51size_t clen;5253/*54* We generate data by blocks of at most 65280 bytes. This55* allows for unambiguously testing the counter overflow56* condition; also, it should work on 16-bit architectures57* (where 'size_t' is 16 bits only).58*/59clen = len;60if (clen > 65280) {61clen = 65280;62}6364/*65* We make sure that the counter won't exceed the configured66* limit.67*/68if ((uint32_t)(ctx->cc + ((clen + 15) >> 4)) > 32768) {69clen = (32768 - ctx->cc) << 4;70if (clen > len) {71clen = len;72}73}7475/*76* Run CTR.77*/78memset(buf, 0, clen);79ctx->cc = ctx->sk.vtable->run(&ctx->sk.vtable,80iv, ctx->cc, buf, clen);81buf += clen;82len -= clen;8384/*85* Every 32768 blocks, we force a state update.86*/87if (ctx->cc >= 32768) {88br_aesctr_drbg_update(ctx, NULL, 0);89}90}91}9293/* see bearssl_rand.h */94void95br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, const void *seed, size_t len)96{97/*98* We use a Hirose construction on AES-256 to make a hash function.99* Function definition:100* - running state consists in two 16-byte blocks G and H101* - initial values of G and H are conventional102* - there is a fixed block-sized constant C103* - for next data block m:104* set AES key to H||m105* G' = E(G) xor G106* H' = E(G xor C) xor G xor C107* G <- G', H <- H'108* - once all blocks have been processed, output is H||G109*110* Constants:111* G_init = B6 B6 ... B6112* H_init = A5 A5 ... A5113* C = 01 00 ... 00114*115* With this hash function h(), we compute the new state as116* follows:117* - produce a state-dependent value s as encryption of an118* all-one block with AES and the current key119* - compute the new key as the first 128 bits of h(s||seed)120*121* Original Hirose article:122* https://www.iacr.org/archive/fse2006/40470213/40470213.pdf123*/124125unsigned char s[16], iv[12];126unsigned char G[16], H[16];127int first;128129/*130* Use an all-one IV to get a fresh output block that depends on the131* current seed.132*/133memset(iv, 0xFF, sizeof iv);134memset(s, 0, 16);135ctx->sk.vtable->run(&ctx->sk.vtable, iv, 0xFFFFFFFF, s, 16);136137/*138* Set G[] and H[] to conventional start values.139*/140memset(G, 0xB6, sizeof G);141memset(H, 0x5A, sizeof H);142143/*144* Process the concatenation of the current state and the seed145* with the custom hash function.146*/147first = 1;148for (;;) {149unsigned char tmp[32];150unsigned char newG[16];151152/*153* Assemble new key H||m into tmp[].154*/155memcpy(tmp, H, 16);156if (first) {157memcpy(tmp + 16, s, 16);158first = 0;159} else {160size_t clen;161162if (len == 0) {163break;164}165clen = len < 16 ? len : 16;166memcpy(tmp + 16, seed, clen);167memset(tmp + 16 + clen, 0, 16 - clen);168seed = (const unsigned char *)seed + clen;169len -= clen;170}171ctx->sk.vtable->init(&ctx->sk.vtable, tmp, 32);172173/*174* Compute new G and H values.175*/176memcpy(iv, G, 12);177memcpy(newG, G, 16);178ctx->sk.vtable->run(&ctx->sk.vtable, iv,179br_dec32be(G + 12), newG, 16);180iv[0] ^= 0x01;181memcpy(H, G, 16);182H[0] ^= 0x01;183ctx->sk.vtable->run(&ctx->sk.vtable, iv,184br_dec32be(G + 12), H, 16);185memcpy(G, newG, 16);186}187188/*189* Output hash value is H||G. We truncate it to its first 128 bits,190* i.e. H; that's our new AES key.191*/192ctx->sk.vtable->init(&ctx->sk.vtable, H, 16);193ctx->cc = 0;194}195196/* see bearssl_rand.h */197const br_prng_class br_aesctr_drbg_vtable = {198sizeof(br_aesctr_drbg_context),199(void (*)(const br_prng_class **, const void *, const void *, size_t))200&br_aesctr_drbg_init,201(void (*)(const br_prng_class **, void *, size_t))202&br_aesctr_drbg_generate,203(void (*)(const br_prng_class **, const void *, size_t))204&br_aesctr_drbg_update205};206207208