cosmopolitan/third_party/mbedtls/ctr_drbg.c

864 lines
30 KiB
C
Raw Normal View History

/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright The Mbed TLS Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 │
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
Add SSL to redbean Your redbean can now interoperate with clients that require TLS crypto. This is accomplished using a protocol polyglot that lets us distinguish between HTTP and HTTPS regardless of the port number. Certificates will be generated automatically, if none are supplied by the user. Footprint increases by only a few hundred kb so redbean in MODY=tiny is now 1.0mb - Add lseek() polyfills for ZIP executable - Automatically polyfill /tmp/FOO paths on NT - Fix readdir() / ftw() / nftw() bugs on Windows - Introduce -B flag for slower SSL that's stronger - Remove mbedtls features Cosmopolitan doesn't need - Have base64 decoder support the uri-safe alternative - Remove Truncated HMAC because it's forbidden by the IETF - Add all the mbedtls test suites and make them go 3x faster - Support opendir() / readdir() / closedir() on ZIP executable - Use Everest for ECDHE-ECDSA because it's so good it's so good - Add tinier implementation of sha1 since it's not worth the rom - Add chi-square monte-carlo mean correlation tests for getrandom() - Source entropy on Windows from the proper interface everyone uses We're continuing to outperform NGINX and other servers on raw message throughput. Using SSL means that instead of 1,000,000 qps you can get around 300,000 qps. However redbean isn't as fast as NGINX yet at SSL handshakes, since redbean can do 2,627 per second and NGINX does 4.3k Right now, the SSL UX story works best if you give your redbean a key signing key since that can be easily generated by openssl using a one liner then redbean will do all the things that are impossibly hard to do like signing ecdsa and rsa certificates that'll work in chrome. We should integrate the let's encrypt acme protocol in the future. Live Demo: https://redbean.justine.lol/ Root Cert: https://redbean.justine.lol/redbean1.crt
2021-06-24 19:31:26 +00:00
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "third_party/mbedtls/common.h"
#include "third_party/mbedtls/ctr_drbg.h"
#include "third_party/mbedtls/error.h"
#include "third_party/mbedtls/platform.h"
/* clang-format off */
2021-06-16 03:18:59 +00:00
asm(".ident\t\"\\n\\n\
Mbed TLS (Apache 2.0)\\n\
Add SSL to redbean Your redbean can now interoperate with clients that require TLS crypto. This is accomplished using a protocol polyglot that lets us distinguish between HTTP and HTTPS regardless of the port number. Certificates will be generated automatically, if none are supplied by the user. Footprint increases by only a few hundred kb so redbean in MODY=tiny is now 1.0mb - Add lseek() polyfills for ZIP executable - Automatically polyfill /tmp/FOO paths on NT - Fix readdir() / ftw() / nftw() bugs on Windows - Introduce -B flag for slower SSL that's stronger - Remove mbedtls features Cosmopolitan doesn't need - Have base64 decoder support the uri-safe alternative - Remove Truncated HMAC because it's forbidden by the IETF - Add all the mbedtls test suites and make them go 3x faster - Support opendir() / readdir() / closedir() on ZIP executable - Use Everest for ECDHE-ECDSA because it's so good it's so good - Add tinier implementation of sha1 since it's not worth the rom - Add chi-square monte-carlo mean correlation tests for getrandom() - Source entropy on Windows from the proper interface everyone uses We're continuing to outperform NGINX and other servers on raw message throughput. Using SSL means that instead of 1,000,000 qps you can get around 300,000 qps. However redbean isn't as fast as NGINX yet at SSL handshakes, since redbean can do 2,627 per second and NGINX does 4.3k Right now, the SSL UX story works best if you give your redbean a key signing key since that can be easily generated by openssl using a one liner then redbean will do all the things that are impossibly hard to do like signing ecdsa and rsa certificates that'll work in chrome. We should integrate the let's encrypt acme protocol in the future. Live Demo: https://redbean.justine.lol/ Root Cert: https://redbean.justine.lol/redbean1.crt
2021-06-24 19:31:26 +00:00
Copyright ARM Limited\\n\
Copyright Mbed TLS Contributors\"");
2021-06-16 03:18:59 +00:00
asm(".include \"libc/disclaimer.inc\"");
/**
* @fileoverview CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
2021-06-15 18:39:36 +00:00
*
* The NIST SP 800-90 DRBGs are described in the following publication.
2021-06-15 18:39:36 +00:00
*
* http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
2021-06-15 18:39:36 +00:00
*/
Add SSL to redbean Your redbean can now interoperate with clients that require TLS crypto. This is accomplished using a protocol polyglot that lets us distinguish between HTTP and HTTPS regardless of the port number. Certificates will be generated automatically, if none are supplied by the user. Footprint increases by only a few hundred kb so redbean in MODY=tiny is now 1.0mb - Add lseek() polyfills for ZIP executable - Automatically polyfill /tmp/FOO paths on NT - Fix readdir() / ftw() / nftw() bugs on Windows - Introduce -B flag for slower SSL that's stronger - Remove mbedtls features Cosmopolitan doesn't need - Have base64 decoder support the uri-safe alternative - Remove Truncated HMAC because it's forbidden by the IETF - Add all the mbedtls test suites and make them go 3x faster - Support opendir() / readdir() / closedir() on ZIP executable - Use Everest for ECDHE-ECDSA because it's so good it's so good - Add tinier implementation of sha1 since it's not worth the rom - Add chi-square monte-carlo mean correlation tests for getrandom() - Source entropy on Windows from the proper interface everyone uses We're continuing to outperform NGINX and other servers on raw message throughput. Using SSL means that instead of 1,000,000 qps you can get around 300,000 qps. However redbean isn't as fast as NGINX yet at SSL handshakes, since redbean can do 2,627 per second and NGINX does 4.3k Right now, the SSL UX story works best if you give your redbean a key signing key since that can be easily generated by openssl using a one liner then redbean will do all the things that are impossibly hard to do like signing ecdsa and rsa certificates that'll work in chrome. We should integrate the let's encrypt acme protocol in the future. Live Demo: https://redbean.justine.lol/ Root Cert: https://redbean.justine.lol/redbean1.crt
2021-06-24 19:31:26 +00:00
/**
* \brief This function initializes the CTR_DRBG context,
* and prepares it for mbedtls_ctr_drbg_seed()
* or mbedtls_ctr_drbg_free().
*
* \note The reseed interval is
* #MBEDTLS_CTR_DRBG_RESEED_INTERVAL by default.
* You can override it by calling
* mbedtls_ctr_drbg_set_reseed_interval().
*
* \param ctx The CTR_DRBG context to initialize.
2021-06-15 18:39:36 +00:00
*/
void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
{
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
2021-06-15 18:39:36 +00:00
/* Indicate that the entropy nonce length is not set explicitly.
* See mbedtls_ctr_drbg_set_nonce_len(). */
ctx->reseed_counter = -1;
ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
}
/*
* This function resets CTR_DRBG context to the state immediately
* after initial call of mbedtls_ctr_drbg_init().
*/
void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_aes_free( &ctx->aes_ctx );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
ctx->reseed_counter = -1;
}
void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
int resistance )
{
ctx->prediction_resistance = resistance;
}
void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
size_t len )
{
ctx->entropy_len = len;
}
int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
size_t len )
{
/* If mbedtls_ctr_drbg_seed() has already been called, it's
* too late. Return the error code that's closest to making sense. */
if( ctx->f_entropy != NULL )
return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
#if SIZE_MAX > INT_MAX
/* This shouldn't be an issue because
* MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
* configuration, but make sure anyway. */
if( len > INT_MAX )
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
#endif
/* For backward compatibility with Mbed TLS <= 2.19, store the
* entropy nonce length in a field that already exists, but isn't
* used until after the initial seeding. */
/* Due to the capping of len above, the value fits in an int. */
ctx->reseed_counter = (int) len;
return( 0 );
}
void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
int interval )
{
ctx->reseed_interval = interval;
}
static int block_cipher_df( unsigned char *output,
const unsigned char *data, size_t data_len )
{
unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
unsigned char *p, *iv;
mbedtls_aes_context aes_ctx;
int ret = 0;
int i, j;
size_t buf_len, use_len;
if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
mbedtls_platform_zeroize( buf, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
2021-06-15 18:39:36 +00:00
MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
mbedtls_aes_init( &aes_ctx );
/*
* Construct IV (16 bytes) and S in buffer
* IV = Counter (in 32-bits) padded to 16 with zeroes
* S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
* data || 0x80
* (Total is padded to a multiple of 16-bytes with zeroes)
*/
p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
*p++ = ( data_len >> 24 ) & 0xff;
*p++ = ( data_len >> 16 ) & 0xff;
*p++ = ( data_len >> 8 ) & 0xff;
*p++ = ( data_len ) & 0xff;
p += 3;
*p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
memcpy( p, data, data_len );
p[data_len] = 0x80;
buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
key[i] = i;
if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
{
goto exit;
}
/*
* Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
*/
for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
{
p = buf;
mbedtls_platform_zeroize( chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
2021-06-15 18:39:36 +00:00
use_len = buf_len;
while( use_len > 0 )
{
for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
chain[i] ^= p[i];
p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
chain, chain ) ) != 0 )
{
goto exit;
}
}
memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
/*
* Update IV
*/
buf[3]++;
}
/*
* Do final encryption with reduced data
*/
if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
{
goto exit;
}
iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
p = output;
for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
{
if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
iv, iv ) ) != 0 )
{
goto exit;
}
memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
}
exit:
mbedtls_aes_free( &aes_ctx );
/*
* tidy up the stack
*/
mbedtls_platform_zeroize( buf, sizeof( buf ) );
mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
mbedtls_platform_zeroize( key, sizeof( key ) );
mbedtls_platform_zeroize( chain, sizeof( chain ) );
if( 0 != ret )
{
/*
* wipe partial seed from memory
*/
mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
}
return( ret );
}
/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
* ctr_drbg_update_internal(ctx, provided_data)
* implements
* CTR_DRBG_Update(provided_data, Key, V)
* with inputs and outputs
* ctx->aes_ctx = Key
* ctx->counter = V
*/
static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
2021-06-15 18:39:36 +00:00
{
unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
unsigned char *p = tmp;
int i, j;
int ret = 0;
mbedtls_platform_zeroize( tmp, MBEDTLS_CTR_DRBG_SEEDLEN );
2021-06-15 18:39:36 +00:00
for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
{
/*
* Increase counter
*/
for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
if( ++ctx->counter[i - 1] != 0 )
break;
/*
* Crypt counter block
*/
if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
ctx->counter, p ) ) != 0 )
{
goto exit;
}
p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
}
for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
tmp[i] ^= data[i];
/*
* Update key and counter
*/
if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
{
goto exit;
}
memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
MBEDTLS_CTR_DRBG_BLOCKSIZE );
exit:
mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
return( ret );
}
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
* mbedtls_ctr_drbg_update(ctx, additional, add_len)
* implements
* CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
* security_strength) -> initial_working_state
* with inputs
* ctx->counter = all-bits-0
* ctx->aes_ctx = context from all-bits-0 key
* additional[:add_len] = entropy_input || nonce || personalization_string
* and with outputs
* ctx = initial_working_state
*/
int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional,
size_t add_len )
{
unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
int ret = MBEDTLS_ERR_THIS_CORRUPTION;
2021-06-15 18:39:36 +00:00
if( add_len == 0 )
return( 0 );
if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
goto exit;
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
goto exit;
exit:
mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
return( ret );
}
/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
* mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
* implements
* CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
* -> new_working_state
* with inputs
* ctx contains working_state
* additional[:len] = additional_input
* and entropy_input comes from calling ctx->f_entropy
* for (ctx->entropy_len + nonce_len) bytes
* and with output
* ctx contains new_working_state
*/
static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional,
size_t len,
size_t nonce_len )
{
unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
size_t seedlen = 0;
int ret = MBEDTLS_ERR_THIS_CORRUPTION;
2021-06-15 18:39:36 +00:00
if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
mbedtls_platform_zeroize( seed, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
2021-06-15 18:39:36 +00:00
/* Gather entropy_len bytes of entropy to seed state. */
if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
{
return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
}
seedlen += ctx->entropy_len;
/* Gather entropy for a nonce if requested. */
if( nonce_len != 0 )
{
if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
{
return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
}
seedlen += nonce_len;
}
/* Add additional data if provided. */
if( additional != NULL && len != 0 )
{
memcpy( seed + seedlen, additional, len );
seedlen += len;
}
/* Reduce to 384 bits. */
if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
goto exit;
/* Update state. */
if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
goto exit;
ctx->reseed_counter = 1;
exit:
mbedtls_platform_zeroize( seed, sizeof( seed ) );
return( ret );
}
int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
const void *additional, size_t len )
2021-06-15 18:39:36 +00:00
{
return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
}
/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
* is sufficient to achieve the maximum security strength given the key
* size and entropy length. If there is enough entropy in the initial
* call to the entropy function to serve as both the entropy input and
* the nonce, don't make a second call to get a nonce. */
static size_t good_nonce_len( size_t entropy_len )
{
if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
return( 0 );
else
return( ( entropy_len + 1 ) / 2 );
}
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
* mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
* implements
* CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
* security_strength) -> initial_working_state
* with inputs
* custom[:len] = nonce || personalization_string
* where entropy_input comes from f_entropy for ctx->entropy_len bytes
* and with outputs
* ctx = initial_working_state
*/
int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
int (*f_entropy)(void *, unsigned char *, size_t),
void *p_entropy,
const void *custom,
2021-06-15 18:39:36 +00:00
size_t len )
{
int ret = MBEDTLS_ERR_THIS_CORRUPTION;
2021-06-15 18:39:36 +00:00
unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
size_t nonce_len;
mbedtls_platform_zeroize( key, MBEDTLS_CTR_DRBG_KEYSIZE );
2021-06-15 18:39:36 +00:00
mbedtls_aes_init( &ctx->aes_ctx );
ctx->f_entropy = f_entropy;
ctx->p_entropy = p_entropy;
if( ctx->entropy_len == 0 )
ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
/* ctx->reseed_counter contains the desired amount of entropy to
* grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
* If it's -1, indicating that the entropy nonce length was not set
* explicitly, use a sufficiently large nonce for security. */
nonce_len = ( ctx->reseed_counter >= 0 ?
(size_t) ctx->reseed_counter :
good_nonce_len( ctx->entropy_len ) );
/* Initialize with an empty key. */
if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
{
return( ret );
}
/* Do the initial seeding. */
if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
nonce_len ) ) != 0 )
{
return( ret );
}
return( 0 );
}
/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
* mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
* implements
* CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
* -> working_state_after_reseed
* if required, then
* CTR_DRBG_Generate(working_state_after_reseed,
* requested_number_of_bits, additional_input)
* -> status, returned_bits, new_working_state
* with inputs
* ctx contains working_state
* requested_number_of_bits = 8 * output_len
* additional[:add_len] = additional_input
* and entropy_input comes from calling ctx->f_entropy
* and with outputs
* status = SUCCESS (this function does the reseed internally)
* returned_bits = output[:output_len]
* ctx contains new_working_state
*/
int mbedtls_ctr_drbg_random_with_add( void *p_rng,
unsigned char *output, size_t output_len,
const unsigned char *additional, size_t add_len )
{
int ret = 0;
mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
unsigned char *p = output;
unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
int i;
size_t use_len;
if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
mbedtls_platform_zeroize( add_input, MBEDTLS_CTR_DRBG_SEEDLEN );
2021-06-15 18:39:36 +00:00
if( ctx->reseed_counter > ctx->reseed_interval ||
ctx->prediction_resistance )
{
if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
{
return( ret );
}
add_len = 0;
}
if( add_len > 0 )
{
if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
goto exit;
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
goto exit;
}
while( output_len > 0 )
{
/*
* Increase counter
*/
for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
if( ++ctx->counter[i - 1] != 0 )
break;
/*
* Crypt counter block
*/
if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
ctx->counter, tmp ) ) != 0 )
{
goto exit;
}
use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
/*
* Copy random block to destination
*/
memcpy( p, tmp, use_len );
p += use_len;
output_len -= use_len;
}
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
goto exit;
ctx->reseed_counter++;
exit:
mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
return( ret );
}
int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
size_t output_len )
{
mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
Add SSL to redbean Your redbean can now interoperate with clients that require TLS crypto. This is accomplished using a protocol polyglot that lets us distinguish between HTTP and HTTPS regardless of the port number. Certificates will be generated automatically, if none are supplied by the user. Footprint increases by only a few hundred kb so redbean in MODY=tiny is now 1.0mb - Add lseek() polyfills for ZIP executable - Automatically polyfill /tmp/FOO paths on NT - Fix readdir() / ftw() / nftw() bugs on Windows - Introduce -B flag for slower SSL that's stronger - Remove mbedtls features Cosmopolitan doesn't need - Have base64 decoder support the uri-safe alternative - Remove Truncated HMAC because it's forbidden by the IETF - Add all the mbedtls test suites and make them go 3x faster - Support opendir() / readdir() / closedir() on ZIP executable - Use Everest for ECDHE-ECDSA because it's so good it's so good - Add tinier implementation of sha1 since it's not worth the rom - Add chi-square monte-carlo mean correlation tests for getrandom() - Source entropy on Windows from the proper interface everyone uses We're continuing to outperform NGINX and other servers on raw message throughput. Using SSL means that instead of 1,000,000 qps you can get around 300,000 qps. However redbean isn't as fast as NGINX yet at SSL handshakes, since redbean can do 2,627 per second and NGINX does 4.3k Right now, the SSL UX story works best if you give your redbean a key signing key since that can be easily generated by openssl using a one liner then redbean will do all the things that are impossibly hard to do like signing ecdsa and rsa certificates that'll work in chrome. We should integrate the let's encrypt acme protocol in the future. Live Demo: https://redbean.justine.lol/ Root Cert: https://redbean.justine.lol/redbean1.crt
2021-06-24 19:31:26 +00:00
return mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
2021-06-15 18:39:36 +00:00
}
#if defined(MBEDTLS_FS_IO)
int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
const char *path )
{
int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
FILE *f;
unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
if( ( f = fopen( path, "wb" ) ) == NULL )
return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
goto exit;
if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
MBEDTLS_CTR_DRBG_MAX_INPUT )
{
ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
}
else
{
ret = 0;
}
exit:
mbedtls_platform_zeroize( buf, sizeof( buf ) );
fclose( f );
return( ret );
}
int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
const char *path )
{
int ret = 0;
FILE *f = NULL;
size_t n;
unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
unsigned char c;
if( ( f = fopen( path, "rb" ) ) == NULL )
return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
n = fread( buf, 1, sizeof( buf ), f );
if( fread( &c, 1, 1, f ) != 0 )
{
ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
goto exit;
}
if( n == 0 || ferror( f ) )
{
ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
goto exit;
}
fclose( f );
f = NULL;
ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
exit:
mbedtls_platform_zeroize( buf, sizeof( buf ) );
if( f != NULL )
fclose( f );
if( ret != 0 )
return( ret );
return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
}
#endif /* MBEDTLS_FS_IO */
#if defined(MBEDTLS_SELF_TEST)
/* The CTR_DRBG NIST test vectors used here are available at
* https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
*
* The parameters used to derive the test data are:
*
* [AES-128 use df]
* [PredictionResistance = True/False]
* [EntropyInputLen = 128]
* [NonceLen = 64]
* [PersonalizationStringLen = 128]
* [AdditionalInputLen = 0]
* [ReturnedBitsLen = 512]
*
* [AES-256 use df]
* [PredictionResistance = True/False]
* [EntropyInputLen = 256]
* [NonceLen = 128]
* [PersonalizationStringLen = 256]
* [AdditionalInputLen = 0]
* [ReturnedBitsLen = 512]
*
*/
#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
static const unsigned char entropy_source_pr[] =
{ 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
static const unsigned char entropy_source_nopr[] =
{ 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
static const unsigned char pers_pr[] =
{ 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
static const unsigned char pers_nopr[] =
{ 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
static const unsigned char result_pr[] =
{ 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
static const unsigned char result_nopr[] =
{ 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
static const unsigned char entropy_source_pr[] =
{ 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
static const unsigned char entropy_source_nopr[] =
{ 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
static const unsigned char pers_pr[] =
{ 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
static const unsigned char pers_nopr[] =
{ 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
static const unsigned char result_pr[] =
{ 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
static const unsigned char result_nopr[] =
{ 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
static size_t test_offset;
static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
size_t len )
{
const unsigned char *p = data;
memcpy( buf, p + test_offset, len );
test_offset += len;
return( 0 );
}
#define CHK( c ) if( (c) != 0 ) \
{ \
if( verbose != 0 ) \
mbedtls_printf( "failed\n" ); \
return( 1 ); \
}
#define SELF_TEST_OUPUT_DISCARD_LENGTH 64
/*
* Checkup routine
*/
int mbedtls_ctr_drbg_self_test( int verbose )
{
mbedtls_ctr_drbg_context ctx;
unsigned char buf[ sizeof( result_pr ) ];
mbedtls_ctr_drbg_init( &ctx );
/*
* Based on a NIST CTR_DRBG test vector (PR = True)
*/
if( verbose != 0 )
mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
test_offset = 0;
mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
CHK( mbedtls_ctr_drbg_seed( &ctx,
ctr_drbg_self_test_entropy,
(void *) entropy_source_pr,
pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
mbedtls_ctr_drbg_free( &ctx );
if( verbose != 0 )
mbedtls_printf( "passed\n" );
/*
* Based on a NIST CTR_DRBG test vector (PR = FALSE)
*/
if( verbose != 0 )
mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
mbedtls_ctr_drbg_init( &ctx );
test_offset = 0;
mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
CHK( mbedtls_ctr_drbg_seed( &ctx,
ctr_drbg_self_test_entropy,
(void *) entropy_source_nopr,
pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
mbedtls_ctr_drbg_free( &ctx );
if( verbose != 0 )
mbedtls_printf( "passed\n" );
if( verbose != 0 )
mbedtls_printf( "\n" );
return( 0 );
}
Add SSL to redbean Your redbean can now interoperate with clients that require TLS crypto. This is accomplished using a protocol polyglot that lets us distinguish between HTTP and HTTPS regardless of the port number. Certificates will be generated automatically, if none are supplied by the user. Footprint increases by only a few hundred kb so redbean in MODY=tiny is now 1.0mb - Add lseek() polyfills for ZIP executable - Automatically polyfill /tmp/FOO paths on NT - Fix readdir() / ftw() / nftw() bugs on Windows - Introduce -B flag for slower SSL that's stronger - Remove mbedtls features Cosmopolitan doesn't need - Have base64 decoder support the uri-safe alternative - Remove Truncated HMAC because it's forbidden by the IETF - Add all the mbedtls test suites and make them go 3x faster - Support opendir() / readdir() / closedir() on ZIP executable - Use Everest for ECDHE-ECDSA because it's so good it's so good - Add tinier implementation of sha1 since it's not worth the rom - Add chi-square monte-carlo mean correlation tests for getrandom() - Source entropy on Windows from the proper interface everyone uses We're continuing to outperform NGINX and other servers on raw message throughput. Using SSL means that instead of 1,000,000 qps you can get around 300,000 qps. However redbean isn't as fast as NGINX yet at SSL handshakes, since redbean can do 2,627 per second and NGINX does 4.3k Right now, the SSL UX story works best if you give your redbean a key signing key since that can be easily generated by openssl using a one liner then redbean will do all the things that are impossibly hard to do like signing ecdsa and rsa certificates that'll work in chrome. We should integrate the let's encrypt acme protocol in the future. Live Demo: https://redbean.justine.lol/ Root Cert: https://redbean.justine.lol/redbean1.crt
2021-06-24 19:31:26 +00:00
#endif /* MBEDTLS_SELF_TEST */