|
|
a8e454 |
diff --git a/lib/nettle/int/drbg-aes-self-test.c b/lib/nettle/int/drbg-aes-self-test.c
|
|
|
a8e454 |
index 9c87453..eb62cf0 100644
|
|
|
a8e454 |
--- a/lib/nettle/int/drbg-aes-self-test.c
|
|
|
a8e454 |
+++ b/lib/nettle/int/drbg-aes-self-test.c
|
|
|
a8e454 |
@@ -104,7 +104,8 @@ int drbg_aes_self_test(void)
|
|
|
a8e454 |
struct drbg_aes_ctx test_ctx;
|
|
|
a8e454 |
struct drbg_aes_ctx test_ctx2;
|
|
|
a8e454 |
struct priv_st priv;
|
|
|
a8e454 |
- int ret;
|
|
|
a8e454 |
+ int ret, saved;
|
|
|
a8e454 |
+ uint8_t *tmp;
|
|
|
a8e454 |
unsigned char result[16];
|
|
|
a8e454 |
|
|
|
a8e454 |
memset(&priv, 0, sizeof(priv));
|
|
|
a8e454 |
@@ -119,26 +120,32 @@ int drbg_aes_self_test(void)
|
|
|
a8e454 |
return 0;
|
|
|
a8e454 |
}
|
|
|
a8e454 |
|
|
|
a8e454 |
+ tmp = gnutls_malloc(MAX_DRBG_AES_GENERATE_SIZE+1);
|
|
|
a8e454 |
+ if (tmp == NULL) {
|
|
|
a8e454 |
+ gnutls_assert();
|
|
|
a8e454 |
+ return 0;
|
|
|
a8e454 |
+ }
|
|
|
a8e454 |
+
|
|
|
a8e454 |
for (i = 0; i < sizeof(tv) / sizeof(tv[0]); i++) {
|
|
|
a8e454 |
/* Setup the key. */
|
|
|
a8e454 |
ret =
|
|
|
a8e454 |
drbg_aes_init(&test_ctx, DRBG_AES_SEED_SIZE, tv[i].entropy,
|
|
|
a8e454 |
strlen(tv[i].pstring), (void *)tv[i].pstring);
|
|
|
a8e454 |
if (ret == 0)
|
|
|
a8e454 |
- return 0;
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
|
|
|
a8e454 |
if (drbg_aes_is_seeded(&test_ctx) == 0)
|
|
|
a8e454 |
- return 0;
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
|
|
|
a8e454 |
/* Get and compare the first three results. */
|
|
|
a8e454 |
for (j = 0; j < 3; j++) {
|
|
|
a8e454 |
/* Compute the next value. */
|
|
|
a8e454 |
if (drbg_aes_random(&test_ctx, 16, result) == 0)
|
|
|
a8e454 |
- return 0;
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
|
|
|
a8e454 |
/* Compare it to the known value. */
|
|
|
a8e454 |
if (memcmp(result, tv[i].res[j], 16) != 0) {
|
|
|
a8e454 |
- return 0;
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
}
|
|
|
a8e454 |
}
|
|
|
a8e454 |
|
|
|
a8e454 |
@@ -146,20 +153,72 @@ int drbg_aes_self_test(void)
|
|
|
a8e454 |
drbg_aes_reseed(&test_ctx, DRBG_AES_SEED_SIZE,
|
|
|
a8e454 |
tv[i].entropy, 0, NULL);
|
|
|
a8e454 |
if (ret == 0)
|
|
|
a8e454 |
- return 0;
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
|
|
|
a8e454 |
if (drbg_aes_random(&test_ctx, 16, result) == 0)
|
|
|
a8e454 |
- return 0;
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
|
|
|
a8e454 |
if (memcmp(result, tv[i].res[3], 16) != 0) {
|
|
|
a8e454 |
- return 0;
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
}
|
|
|
a8e454 |
|
|
|
a8e454 |
/* test the error handling of drbg_aes_random() */
|
|
|
a8e454 |
+ saved = test_ctx.reseed_counter;
|
|
|
a8e454 |
test_ctx.reseed_counter = DRBG_AES_RESEED_TIME+1;
|
|
|
a8e454 |
if (drbg_aes_random(&test_ctx, 16, result) != 0) {
|
|
|
a8e454 |
gnutls_assert();
|
|
|
a8e454 |
- return 0;
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
+ }
|
|
|
a8e454 |
+ test_ctx.reseed_counter = saved;
|
|
|
a8e454 |
+
|
|
|
a8e454 |
+ ret = drbg_aes_random(&test_ctx, MAX_DRBG_AES_GENERATE_SIZE+1, tmp);
|
|
|
a8e454 |
+ if (ret == 0) {
|
|
|
a8e454 |
+ gnutls_assert();
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
+ }
|
|
|
a8e454 |
+
|
|
|
a8e454 |
+ /* test the low-level function */
|
|
|
a8e454 |
+ ret = drbg_aes_generate(&test_ctx, MAX_DRBG_AES_GENERATE_SIZE+1, tmp, 0, NULL);
|
|
|
a8e454 |
+ if (ret != 0) {
|
|
|
a8e454 |
+ gnutls_assert();
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
+ }
|
|
|
a8e454 |
+
|
|
|
a8e454 |
+ /* Test of the reseed function for error handling */
|
|
|
a8e454 |
+ ret =
|
|
|
a8e454 |
+ drbg_aes_reseed(&test_ctx, DRBG_AES_SEED_SIZE*2,
|
|
|
a8e454 |
+ (uint8_t*)tv, 0, NULL);
|
|
|
a8e454 |
+ if (ret != 0)
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
+
|
|
|
a8e454 |
+ ret =
|
|
|
a8e454 |
+ drbg_aes_reseed(&test_ctx, DRBG_AES_SEED_SIZE,
|
|
|
a8e454 |
+ tv[i].entropy, DRBG_AES_SEED_SIZE*2, (uint8_t*)tv);
|
|
|
a8e454 |
+ if (ret != 0)
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
+
|
|
|
a8e454 |
+ /* check whether reseed detection works */
|
|
|
a8e454 |
+ if (i==0) {
|
|
|
a8e454 |
+ ret =
|
|
|
a8e454 |
+ drbg_aes_reseed(&test_ctx, DRBG_AES_SEED_SIZE,
|
|
|
a8e454 |
+ tv[i].entropy, 0, NULL);
|
|
|
a8e454 |
+ if (ret == 0)
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
+
|
|
|
a8e454 |
+ saved = test_ctx.reseed_counter;
|
|
|
a8e454 |
+ test_ctx.reseed_counter = DRBG_AES_RESEED_TIME-4;
|
|
|
a8e454 |
+ for (j=0;j<5;j++) {
|
|
|
a8e454 |
+ if (drbg_aes_random(&test_ctx, 1, result) == 0) {
|
|
|
a8e454 |
+ gnutls_assert();
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
+ }
|
|
|
a8e454 |
+ }
|
|
|
a8e454 |
+ /* that should fail */
|
|
|
a8e454 |
+ if (drbg_aes_random(&test_ctx, 1, result) != 0) {
|
|
|
a8e454 |
+ gnutls_assert();
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
+ }
|
|
|
a8e454 |
+ test_ctx.reseed_counter = saved;
|
|
|
a8e454 |
}
|
|
|
a8e454 |
|
|
|
a8e454 |
/* test deinit, which is zeroize_key() */
|
|
|
a8e454 |
@@ -167,9 +226,15 @@ int drbg_aes_self_test(void)
|
|
|
a8e454 |
zeroize_key(&test_ctx, sizeof(test_ctx));
|
|
|
a8e454 |
if (memcmp(&test_ctx, &test_ctx2, sizeof(test_ctx)) == 0) {
|
|
|
a8e454 |
gnutls_assert();
|
|
|
a8e454 |
- return 0;
|
|
|
a8e454 |
+ goto fail;
|
|
|
a8e454 |
}
|
|
|
a8e454 |
+
|
|
|
a8e454 |
+
|
|
|
a8e454 |
}
|
|
|
a8e454 |
|
|
|
a8e454 |
+ free(tmp);
|
|
|
a8e454 |
return 1;
|
|
|
a8e454 |
+ fail:
|
|
|
a8e454 |
+ free(tmp);
|
|
|
a8e454 |
+ return 0;
|
|
|
a8e454 |
}
|
|
|
a8e454 |
diff --git a/lib/nettle/int/drbg-aes.c b/lib/nettle/int/drbg-aes.c
|
|
|
a8e454 |
index 5ff2484..43df5e1 100644
|
|
|
a8e454 |
--- a/lib/nettle/int/drbg-aes.c
|
|
|
a8e454 |
+++ b/lib/nettle/int/drbg-aes.c
|
|
|
a8e454 |
@@ -22,6 +22,7 @@
|
|
|
a8e454 |
|
|
|
a8e454 |
#include <config.h>
|
|
|
a8e454 |
#include <drbg-aes.h>
|
|
|
a8e454 |
+#include <gnutls_errors.h>
|
|
|
a8e454 |
#include <nettle/memxor.h>
|
|
|
a8e454 |
#include <nettle/aes.h>
|
|
|
a8e454 |
#include <minmax.h>
|
|
|
a8e454 |
@@ -67,7 +68,6 @@ drbg_aes_update(struct drbg_aes_ctx *ctx,
|
|
|
a8e454 |
|
|
|
a8e454 |
memcpy(ctx->v, &tmp[DRBG_AES_KEY_SIZE], AES_BLOCK_SIZE);
|
|
|
a8e454 |
|
|
|
a8e454 |
- ctx->reseed_counter = 1;
|
|
|
a8e454 |
ctx->seeded = 1;
|
|
|
a8e454 |
}
|
|
|
a8e454 |
|
|
|
a8e454 |
@@ -93,6 +93,27 @@ drbg_aes_reseed(struct drbg_aes_ctx *ctx,
|
|
|
a8e454 |
memxor(tmp, entropy, entropy_size);
|
|
|
a8e454 |
|
|
|
a8e454 |
drbg_aes_update(ctx, tmp);
|
|
|
a8e454 |
+ ctx->reseed_counter = 1;
|
|
|
a8e454 |
+
|
|
|
a8e454 |
+ return 1;
|
|
|
a8e454 |
+}
|
|
|
a8e454 |
+
|
|
|
a8e454 |
+int drbg_aes_random(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst)
|
|
|
a8e454 |
+{
|
|
|
a8e454 |
+ unsigned p_len;
|
|
|
a8e454 |
+ int left = length;
|
|
|
a8e454 |
+ uint8_t *p = dst;
|
|
|
a8e454 |
+ int ret;
|
|
|
a8e454 |
+
|
|
|
a8e454 |
+ while(left > 0) {
|
|
|
a8e454 |
+ p_len = MIN(MAX_DRBG_AES_GENERATE_SIZE, left);
|
|
|
a8e454 |
+ ret = drbg_aes_generate(ctx, p_len, p, 0, 0);
|
|
|
a8e454 |
+ if (ret == 0)
|
|
|
a8e454 |
+ return ret;
|
|
|
a8e454 |
+
|
|
|
a8e454 |
+ p += p_len;
|
|
|
a8e454 |
+ left -= p_len;
|
|
|
a8e454 |
+ }
|
|
|
a8e454 |
|
|
|
a8e454 |
return 1;
|
|
|
a8e454 |
}
|
|
|
a8e454 |
@@ -106,11 +127,14 @@ int drbg_aes_generate(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst,
|
|
|
a8e454 |
unsigned left;
|
|
|
a8e454 |
|
|
|
a8e454 |
if (ctx->seeded == 0)
|
|
|
a8e454 |
- return 0;
|
|
|
a8e454 |
+ return gnutls_assert_val(0);
|
|
|
a8e454 |
+
|
|
|
a8e454 |
+ if (length > MAX_DRBG_AES_GENERATE_SIZE)
|
|
|
a8e454 |
+ return gnutls_assert_val(0);
|
|
|
a8e454 |
|
|
|
a8e454 |
if (add_size > 0) {
|
|
|
a8e454 |
if (add_size > DRBG_AES_SEED_SIZE)
|
|
|
a8e454 |
- return 0;
|
|
|
a8e454 |
+ return gnutls_assert_val(0);
|
|
|
a8e454 |
memcpy(seed, add, add_size);
|
|
|
a8e454 |
if (add_size != DRBG_AES_SEED_SIZE)
|
|
|
a8e454 |
memset(&seed[add_size], 0, DRBG_AES_SEED_SIZE - add_size);
|
|
|
a8e454 |
@@ -140,7 +164,7 @@ int drbg_aes_generate(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst,
|
|
|
a8e454 |
/* if detected loop */
|
|
|
a8e454 |
if (memcmp(dst, ctx->prev_block, AES_BLOCK_SIZE) == 0) {
|
|
|
a8e454 |
_gnutls_switch_lib_state(LIB_STATE_ERROR);
|
|
|
a8e454 |
- return 0;
|
|
|
a8e454 |
+ return gnutls_assert_val(0);
|
|
|
a8e454 |
}
|
|
|
a8e454 |
|
|
|
a8e454 |
memcpy(ctx->prev_block, dst, AES_BLOCK_SIZE);
|
|
|
a8e454 |
@@ -154,7 +178,7 @@ int drbg_aes_generate(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst,
|
|
|
a8e454 |
/* if detected loop */
|
|
|
a8e454 |
if (memcmp(tmp, ctx->prev_block, AES_BLOCK_SIZE) == 0) {
|
|
|
a8e454 |
_gnutls_switch_lib_state(LIB_STATE_ERROR);
|
|
|
a8e454 |
- return 0;
|
|
|
a8e454 |
+ return gnutls_assert_val(0);
|
|
|
a8e454 |
}
|
|
|
a8e454 |
|
|
|
a8e454 |
memcpy(ctx->prev_block, tmp, AES_BLOCK_SIZE);
|
|
|
a8e454 |
@@ -162,7 +186,7 @@ int drbg_aes_generate(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst,
|
|
|
a8e454 |
}
|
|
|
a8e454 |
|
|
|
a8e454 |
if (ctx->reseed_counter > DRBG_AES_RESEED_TIME)
|
|
|
a8e454 |
- return 0;
|
|
|
a8e454 |
+ return gnutls_assert_val(0);
|
|
|
a8e454 |
ctx->reseed_counter++;
|
|
|
a8e454 |
|
|
|
a8e454 |
drbg_aes_update(ctx, seed);
|
|
|
a8e454 |
diff --git a/lib/nettle/int/drbg-aes.h b/lib/nettle/int/drbg-aes.h
|
|
|
a8e454 |
index eb89be6..72608de 100644
|
|
|
a8e454 |
--- a/lib/nettle/int/drbg-aes.h
|
|
|
a8e454 |
+++ b/lib/nettle/int/drbg-aes.h
|
|
|
a8e454 |
@@ -55,10 +55,13 @@ struct drbg_aes_ctx {
|
|
|
a8e454 |
unsigned reseed_counter;
|
|
|
a8e454 |
};
|
|
|
a8e454 |
|
|
|
a8e454 |
+/* max_number_of_bits_per_request */
|
|
|
a8e454 |
+#define MAX_DRBG_AES_GENERATE_SIZE 65536 /* 2^19 */
|
|
|
a8e454 |
+
|
|
|
a8e454 |
/* This DRBG should be reseeded if reseed_counter exceeds
|
|
|
a8e454 |
* that number. Otherwise drbg_aes_random() will fail.
|
|
|
a8e454 |
*/
|
|
|
a8e454 |
-#define DRBG_AES_RESEED_TIME 65536
|
|
|
a8e454 |
+#define DRBG_AES_RESEED_TIME 16777216
|
|
|
a8e454 |
|
|
|
a8e454 |
/* The entropy provided in these functions should be of
|
|
|
a8e454 |
* size DRBG_AES_SEED_SIZE. Additional data and pers.
|
|
|
a8e454 |
@@ -74,7 +77,10 @@ drbg_aes_reseed(struct drbg_aes_ctx *ctx,
|
|
|
a8e454 |
unsigned entropy_size, const uint8_t *entropy,
|
|
|
a8e454 |
unsigned add_size, const uint8_t* add);
|
|
|
a8e454 |
|
|
|
a8e454 |
-#define drbg_aes_random(ctx, l, dst) drbg_aes_generate(ctx, l, dst, 0, NULL)
|
|
|
a8e454 |
+/* our wrapper for the low-level drbg_aes_generate */
|
|
|
a8e454 |
+int
|
|
|
a8e454 |
+drbg_aes_random(struct drbg_aes_ctx *ctx, unsigned length,
|
|
|
a8e454 |
+ uint8_t * dst);
|
|
|
a8e454 |
|
|
|
a8e454 |
int
|
|
|
a8e454 |
drbg_aes_generate(struct drbg_aes_ctx *ctx, unsigned length,
|
|
|
a8e454 |
diff --git a/tests/rng-fork.c b/tests/rng-fork.c
|
|
|
a8e454 |
index ba9178e..45a18b4 100644
|
|
|
a8e454 |
--- a/tests/rng-fork.c
|
|
|
a8e454 |
+++ b/tests/rng-fork.c
|
|
|
a8e454 |
@@ -53,6 +53,7 @@ void doit(void)
|
|
|
a8e454 |
unsigned char buf1[64];
|
|
|
a8e454 |
unsigned char buf2[64];
|
|
|
a8e454 |
pid_t pid;
|
|
|
a8e454 |
+ unsigned char *tmp;
|
|
|
a8e454 |
int ret;
|
|
|
a8e454 |
FILE *fp;
|
|
|
a8e454 |
unsigned i;
|
|
|
a8e454 |
@@ -119,6 +120,20 @@ void doit(void)
|
|
|
a8e454 |
exit(1);
|
|
|
a8e454 |
}
|
|
|
a8e454 |
}
|
|
|
a8e454 |
+#define TMP_SIZE (65*1024)
|
|
|
a8e454 |
+ tmp = malloc(TMP_SIZE);
|
|
|
a8e454 |
+ if (tmp == NULL) {
|
|
|
a8e454 |
+ fail("memory error\n");
|
|
|
a8e454 |
+ exit(1);
|
|
|
a8e454 |
+ }
|
|
|
a8e454 |
+ for (i = 0; i <= 65539; i++) {
|
|
|
a8e454 |
+ ret = gnutls_rnd(GNUTLS_RND_RANDOM, tmp, TMP_SIZE);
|
|
|
a8e454 |
+ if (ret < 0) {
|
|
|
a8e454 |
+ fail("Error iterating RNG-random more than %u times for %d data\n", i, TMP_SIZE);
|
|
|
a8e454 |
+ exit(1);
|
|
|
a8e454 |
+ }
|
|
|
a8e454 |
+ }
|
|
|
a8e454 |
+ free(tmp);
|
|
|
a8e454 |
|
|
|
a8e454 |
gnutls_global_deinit();
|
|
|
a8e454 |
}
|