unify the prng's export() functions

This also makes fortuna_export() compliant to the "Write seed file"
behavior of the original paper.
This commit is contained in:
Steffen Jaeckel 2018-03-22 17:50:42 +01:00
parent 979a36b9bb
commit 4fb3a6468e
6 changed files with 31 additions and 146 deletions

View File

@ -212,6 +212,31 @@ int register_all_prngs(void);
int prng_is_valid(int idx);
LTC_MUTEX_PROTO(ltc_prng_mutex)
#ifdef LTC_SOURCE
/* internal helper functions */
#define _LTC_PRNG_EXPORT(which) \
int which ## _export(unsigned char *out, unsigned long *outlen, prng_state *prng) \
{ \
unsigned long len = which ## _desc.export_size; \
\
LTC_ARGCHK(prng != NULL); \
LTC_ARGCHK(out != NULL); \
LTC_ARGCHK(outlen != NULL); \
\
if (*outlen < len) { \
*outlen = len; \
return CRYPT_BUFFER_OVERFLOW; \
} \
\
if (which ## _read(out, len, prng) != len) { \
return CRYPT_ERROR_READPRNG; \
} \
\
*outlen = len; \
return CRYPT_OK; \
}
#endif
/* Slow RNG you **might** be able to use to seed a PRNG with. Be careful as this
* might not work on all platforms as planned
*/

View File

@ -150,26 +150,7 @@ int chacha20_prng_done(prng_state *prng)
@param prng The PRNG to export
@return CRYPT_OK if successful
*/
int chacha20_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
{
unsigned long len = chacha20_prng_desc.export_size;
LTC_ARGCHK(prng != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
if (*outlen < len) {
*outlen = len;
return CRYPT_BUFFER_OVERFLOW;
}
if (chacha20_prng_read(out, len, prng) != len) {
return CRYPT_ERROR_READPRNG;
}
*outlen = len;
return CRYPT_OK;
}
_LTC_PRNG_EXPORT(chacha20_prng)
/**
Import a PRNG state

View File

@ -37,7 +37,7 @@ we reseed automatically when len(pool0) >= 64 or every LTC_FORTUNA_WD calls to t
const struct ltc_prng_descriptor fortuna_desc = {
"fortuna",
(32 * LTC_FORTUNA_POOLS), /* default: 1024 */
64,
&fortuna_start,
&fortuna_add_entropy,
&fortuna_ready,
@ -337,71 +337,7 @@ LBL_UNLOCK:
@param prng The PRNG to export
@return CRYPT_OK if successful
*/
int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
{
int x, err;
hash_state *md;
unsigned long len = fortuna_desc.export_size;
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(prng != NULL);
LTC_MUTEX_LOCK(&prng->lock);
if (!prng->ready) {
err = CRYPT_ERROR;
goto LBL_UNLOCK;
}
/* we'll write bytes for s&g's */
if (*outlen < len) {
*outlen = len;
err = CRYPT_BUFFER_OVERFLOW;
goto LBL_UNLOCK;
}
md = XMALLOC(sizeof(hash_state));
if (md == NULL) {
err = CRYPT_MEM;
goto LBL_UNLOCK;
}
/* to emit the state we copy each pool, terminate it then hash it again so
* an attacker who sees the state can't determine the current state of the PRNG
*/
for (x = 0; x < LTC_FORTUNA_POOLS; x++) {
/* copy the PRNG */
XMEMCPY(md, &(prng->fortuna.pool[x]), sizeof(*md));
/* terminate it */
if ((err = sha256_done(md, out+x*32)) != CRYPT_OK) {
goto LBL_ERR;
}
/* now hash it */
if ((err = sha256_init(md)) != CRYPT_OK) {
goto LBL_ERR;
}
if ((err = sha256_process(md, out+x*32, 32)) != CRYPT_OK) {
goto LBL_ERR;
}
if ((err = sha256_done(md, out+x*32)) != CRYPT_OK) {
goto LBL_ERR;
}
}
*outlen = len;
err = CRYPT_OK;
LBL_ERR:
#ifdef LTC_CLEAN_STACK
zeromem(md, sizeof(*md));
#endif
XFREE(md);
LBL_UNLOCK:
LTC_MUTEX_UNLOCK(&prng->lock);
return err;
}
_LTC_PRNG_EXPORT(fortuna)
/**
Import a PRNG state

View File

@ -153,26 +153,7 @@ int rc4_done(prng_state *prng)
@param prng The PRNG to export
@return CRYPT_OK if successful
*/
int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
{
unsigned long len = rc4_desc.export_size;
LTC_ARGCHK(prng != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
if (*outlen < len) {
*outlen = len;
return CRYPT_BUFFER_OVERFLOW;
}
if (rc4_read(out, len, prng) != len) {
return CRYPT_ERROR_READPRNG;
}
*outlen = len;
return CRYPT_OK;
}
_LTC_PRNG_EXPORT(rc4)
/**
Import a PRNG state

View File

@ -152,26 +152,7 @@ int sober128_done(prng_state *prng)
@param prng The PRNG to export
@return CRYPT_OK if successful
*/
int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
{
unsigned long len = sober128_desc.export_size;
LTC_ARGCHK(prng != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
if (*outlen < len) {
*outlen = len;
return CRYPT_BUFFER_OVERFLOW;
}
if (sober128_read(out, len, prng) != len) {
return CRYPT_ERROR_READPRNG;
}
*outlen = len;
return CRYPT_OK;
}
_LTC_PRNG_EXPORT(sober128)
/**
Import a PRNG state

View File

@ -273,26 +273,7 @@ int yarrow_done(prng_state *prng)
@param prng The PRNG to export
@return CRYPT_OK if successful
*/
int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
{
unsigned long len = yarrow_desc.export_size;
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(prng != NULL);
if (*outlen < len) {
*outlen = len;
return CRYPT_BUFFER_OVERFLOW;
}
if (yarrow_read(out, len, prng) != len) {
return CRYPT_ERROR_READPRNG;
}
*outlen = len;
return CRYPT_OK;
}
_LTC_PRNG_EXPORT(yarrow)
/**
Import a PRNG state