]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
replaced the ANSI X9.31 RNG with the SP800-90A DRBG-AES-CTR rng.
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 17 Jan 2014 09:35:00 +0000 (10:35 +0100)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 17 Jan 2014 10:07:15 +0000 (11:07 +0100)
lib/nettle/int/drbg-aes-self-test.c
lib/nettle/int/drbg-aes.c
lib/nettle/int/drbg-aes.h
lib/nettle/rnd-common.c
lib/nettle/rnd-common.h
lib/nettle/rnd-fips.c
lib/nettle/rnd.c

index ac6e8aa72a7fdd57c38b75a2d1696a501b0b9aec..99b9a8a498c0552b29af1eefb0346c47be85ab37 100644 (file)
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-/* This is a known-answer test for the DRBG-AES. The test vectors
- * and test structures are taken from libgcrypt's DRBG-AES implementation.
- * We differ however, in the fact we always discard an AES block when
- * the key is changed. That's why the 2nd and 3rd test vectors differ
- * from libgcrypt's vectors by 1.
+/* This is a known-answer test for the DRBG-CTR-AES. 
  */
 
 #include <config.h>
 #include <drbg-aes.h>
 #include <string.h>
+#include <stdio.h>
 
 struct self_test_st {
-       const uint8_t key[16];
-       const uint8_t dt[16];
-       const uint8_t v[16];
-       const uint8_t r[3][16];
+       const uint8_t entropy[DRBG_AES_SEED_SIZE];
+       const char* pstring;
+       const uint8_t res[4][16];
 };
 
 struct priv_st {
        struct drbg_aes_ctx *ctx;
-       const uint8_t *dt;
-       unsigned counter;
 };
 
-static int get_dt(void *_priv, uint8_t dt[AES_BLOCK_SIZE])
-{
-       struct priv_st *priv = _priv;
-
-       memcpy(dt, priv->dt, AES_BLOCK_SIZE);
-
-       dt[12] = priv->counter >> 24;
-       dt[13] = priv->counter >> 16;
-       dt[14] = priv->counter >> 8;
-       dt[15] = priv->counter;
-
-       priv->counter++;
-
-       return 1;
-}
-
-/* Run a Know-Answer-Test using a dedicated test context.  Note that
-   we can't use the samples from the NISR RNGVS document because they
-   don't take the requirement to throw away the first block and use
-   that for duplicate check in account.  Thus we made up our own test
-   vectors. */
+/* Run a Know-Answer-Test using a dedicated test context. */
 int drbg_aes_self_test(void)
 {
        static const struct self_test_st tv[] = {
-               {
+                {
+                 .entropy =
                 {0xb9, 0xca, 0x7f, 0xd6, 0xa0, 0xf5, 0xd3, 0x42,
-                 0x19, 0x6d, 0x84, 0x91, 0x76, 0x1c, 0x3b, 0xbe},
-                {0x48, 0xb2, 0x82, 0x98, 0x68, 0xc2, 0x80, 0x00,
+                 0x19, 0x6d, 0x84, 0x91, 0x76, 0x1c, 0x3b, 0xbe,
+                 0x48, 0xb2, 0x82, 0x98, 0x68, 0xc2, 0x80, 0x00,
+                 0x19, 0x6d, 0x84, 0x91, 0x76, 0x1c, 0x3b, 0xbe,
+                 0x48, 0xb2, 0x82, 0x98, 0x68, 0xc2, 0x80, 0x00,
                  0x00, 0x00, 0x28, 0x18, 0x00, 0x00, 0x25, 0x00},
-                {0x52, 0x17, 0x8d, 0x29, 0xa2, 0xd5, 0x84, 0x12,
-                 0x9d, 0x89, 0x9a, 0x45, 0x82, 0x02, 0xf7, 0x77},
-                {
-                 {0x42, 0x9c, 0x08, 0x3d, 0x82, 0xf4, 0x8a, 0x40,
-                  0x66, 0xb5, 0x49, 0x27, 0xab, 0x42, 0xc7, 0xc3},
-                 {0x0e, 0xb7, 0x61, 0x3c, 0xfe, 0xb0, 0xbe, 0x73,
-                  0xf7, 0x6e, 0x6d, 0x6f, 0x1d, 0xa3, 0x14, 0xfa},
-                 {0xbb, 0x4b, 0xc1, 0x0e, 0xc5, 0xfb, 0xcd, 0x46,
-                  0xbe, 0x28, 0x61, 0xe7, 0x03, 0x2b, 0x37, 0x7d}
+                .pstring = "test test test",
+                .res = {
+                 {0xb9, 0x4b, 0x00, 0x40, 0x5d, 0x10, 0x58, 0x84, 
+                  0x97, 0x85, 0x5d, 0x49, 0x4f, 0x66, 0x4f, 0xa3},
+                 {0xe8, 0x34, 0xae, 0x3e, 0x26, 0x36, 0xe0, 0x6e, 
+                  0xb7, 0x15, 0x97, 0xc3, 0xf4, 0x7c, 0x98, 0xb0},
+                 {0x8b, 0xf3, 0x85, 0xe9, 0x2b, 0x7f, 0x99, 0x7f, 
+                  0x76, 0x97, 0x8b, 0x60, 0x25, 0x0a, 0x80, 0x60},
+                 {0x4d, 0xfd, 0x8c, 0xc0, 0x5a, 0x20, 0xc8, 0x2d,
+                  0x5c, 0x33, 0x7f, 0x1c, 0x90, 0xa0, 0xe4, 0xa7}
                  }
                 },
-               {
-                {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-                {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-                {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
                 {
-                 {0xc8, 0xd1, 0xe5, 0x11, 0x59, 0x52, 0xf7, 0xfa,
-                  0x37, 0x38, 0xb4, 0xc5, 0xce, 0xb2, 0xb0, 0x9a},
-                 {0x0d, 0x9c, 0xc5, 0x0d, 0x16, 0xe1, 0xbc, 0xed,
-                  0xcf, 0x60, 0x62, 0x09, 0x9d, 0x20, 0x83, 0x7e},
-                 {0x6f, 0x39, 0xe0, 0xcb, 0x76, 0x7c, 0x0d, 0xeb,
-                  0xff, 0xa0, 0x0e, 0x54, 0xe8, 0x9b, 0xa6, 0x79}
+                .entropy = {
+                 0xb9, 0xca, 0x7f, 0xd6, 0xa0, 0xf5, 0xd3, 0x42,
+                 0x19, 0x6d, 0x84, 0x91, 0x76, 0x1c, 0x3b, 0xbe,
+                 0x48, 0xb2, 0x82, 0x98, 0x68, 0xc2, 0x80, 0x00,
+                 0x19, 0x6d, 0x84, 0x91, 0x76, 0x1c, 0x3b, 0xbe,
+                 0x48, 0xb2, 0x82, 0x98, 0x68, 0xc2, 0x80, 0x00,
+                 0x00, 0x00, 0x28, 0x18, 0x00, 0x00, 0x25, 0x00},
+                .pstring = "tost tost test",
+                .res = {
+                 {0x12, 0x54, 0x35, 0x0f, 0x48, 0x7b, 0x6b, 0xed, 
+                  0x2b, 0x3a, 0x2f, 0xa5, 0x53, 0x2c, 0x7b, 0xcb},
+                 {0x39, 0x7a, 0x88, 0xd7, 0x56, 0xf2, 0xd0, 0x64, 
+                  0x37, 0xa0, 0x8f, 0xf9, 0x64, 0xb2, 0x2b, 0x2b},
+                 {0x4f, 0x12, 0x38, 0x71, 0x64, 0x90, 0xae, 0xb3, 
+                  0xea, 0x1e, 0x01, 0xee, 0x2b, 0x03, 0x4a, 0xd3},
+                 {0x9a, 0x0a, 0x9f, 0x42, 0x9b, 0x3f, 0xea, 0x63, 
+                  0x84, 0xdb, 0xf2, 0x7b, 0x96, 0x38, 0x86, 0x41}
                  }
                 },
-               {
-                {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-                 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
-                {0x80, 0x00, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03,
-                 0xa0, 0x20, 0xa1, 0x21, 0xa2, 0x22, 0xa3, 0x23},
-                {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
                 {
-                 {0x7a, 0x14, 0x76, 0x77, 0x95, 0x17, 0x7e, 0xc8,
-                  0x92, 0xe8, 0xdd, 0x15, 0xcb, 0x1f, 0xbc, 0xb1},
-                 {0x25, 0x3e, 0x2e, 0xa2, 0x41, 0x1b, 0xdd, 0xf5,
-                  0x21, 0x48, 0x41, 0x71, 0xb3, 0x8d, 0x2f, 0x4c},
-                 {0xc3, 0xa0, 0x56, 0xc4, 0x98, 0x56, 0xe7, 0xa5,
-                  0x19, 0x42, 0x73, 0x43, 0xdc, 0x07, 0xe0, 0x7f}
+                .entropy = {
+                  0x42, 0x9c, 0x08, 0x3d, 0x82, 0xf4, 0x8a, 0x40,
+                  0x66, 0xb5, 0x49, 0x27, 0xab, 0x42, 0xc7, 0xc3,
+                  0x0e, 0xb7, 0x61, 0x3c, 0xfe, 0xb0, 0xbe, 0x73,
+                  0xf7, 0x6e, 0x6d, 0x6f, 0x1d, 0xa3, 0x14, 0xfa,
+                  0xbb, 0x4b, 0xc1, 0x0e, 0xc5, 0xfb, 0xcd, 0x46,
+                  0xbe, 0x28, 0x61, 0xe7, 0x03, 0x2b, 0x37, 0x7d},
+                .pstring = "one two",
+                .res = {
+                 {0x82, 0x6e, 0x20, 0xf2, 0x85, 0xc2, 0xf7, 0xc7, 
+                  0x90, 0x1f, 0xff, 0x83, 0x6b, 0xaf, 0xaa, 0xd3},
+                 {0x84, 0x4a, 0x39, 0x8a, 0xfe, 0xc0, 0x77, 0x30, 
+                  0xf5, 0xed, 0x11, 0xa2, 0xd2, 0x20, 0xf5, 0x6c},
+                 {0x83, 0x49, 0xd3, 0x41, 0x50, 0xd7, 0xc2, 0x81, 
+                  0x1a, 0xdc, 0x42, 0x62, 0x49, 0xf5, 0xf9, 0x56},
+                 {0xd2, 0xf2, 0x0d, 0xee, 0x9c, 0x63, 0xe6, 0xcc, 
+                  0xc6, 0x41, 0x32, 0x27, 0xe0, 0xe0, 0x93, 0x85}
                  }
-                }
+                },
        };
        unsigned i, j;
        struct drbg_aes_ctx test_ctx;
@@ -125,20 +111,11 @@ int drbg_aes_self_test(void)
 
        for (i = 0; i < sizeof(tv) / sizeof(tv[0]); i++) {
                /* Setup the key.  */
-               ret = drbg_aes_set_key(&test_ctx, 16, tv[i].key);
+               ret = drbg_aes_init(&test_ctx, DRBG_AES_SEED_SIZE, tv[i].entropy,
+                       strlen(tv[i].pstring), (void*)tv[i].pstring);
                if (ret == 0)
                        return 0;
 
-               priv.dt = tv[i].dt;
-               priv.counter =
-                   ((tv[i].dt[12] << 24) | (tv[i].dt[13] << 16) | (tv[i].
-                                                                   dt[14]
-                                                                   << 8) |
-                    (tv[i].dt[15]));
-
-               /* Setup the seed.  */
-               drbg_aes_seed(&test_ctx, tv[i].v, &priv, get_dt);
-
                if (drbg_aes_is_seeded(&test_ctx) == 0)
                        return 0;
 
@@ -150,8 +127,21 @@ int drbg_aes_self_test(void)
                                return 0;
 
                        /* Compare it to the known value.  */
-                       if (memcmp(result, tv[i].r[j], 16) != 0)
+                       if (memcmp(result, tv[i].res[j], 16) != 0) {
                                return 0;
+                       }
+               }
+
+               ret = drbg_aes_reseed(&test_ctx, DRBG_AES_SEED_SIZE, tv[i].entropy,
+                       0, NULL);
+               if (ret == 0)
+                       return 0;
+
+               if (drbg_aes_random(&test_ctx, 16, result) == 0)
+                       return 0;
+
+               if (memcmp(result, tv[i].res[3], 16) != 0) {
+                       return 0;
                }
        }
 
index e70a655de901ed7268e5aceb1dcfb4311e9a7d96..f02d14a1e06432eec91544ad7a356a5998b33862 100644 (file)
 #include <config.h>
 #include <drbg-aes.h>
 #include <nettle/memxor.h>
+#include <minmax.h>
 #include <string.h>
 #include <stdio.h>
 
 int
-drbg_aes_set_key(struct drbg_aes_ctx *ctx, unsigned length,
-                const uint8_t * key)
+drbg_aes_init(struct drbg_aes_ctx *ctx,
+             unsigned entropy_size, const uint8_t * entropy,
+             unsigned pstring_size, const uint8_t * pstring)
 {
-       if (length != 16 && length != 24 && length != 32)
-               return 0;
-
-       aes_set_encrypt_key(&ctx->key, length, key);
-       ctx->seeded = 0;
-       ctx->reseed_counter = 0;
-       ctx->prev_block_present = 0;
+       memset(ctx, 0, sizeof(*ctx));
 
-       return 1;
+       return drbg_aes_reseed(ctx, entropy_size, entropy,
+                              pstring_size, pstring);
 }
 
-/* Set's V value */
-void
-drbg_aes_seed(struct drbg_aes_ctx *ctx, const uint8_t seed[AES_BLOCK_SIZE],
-       void *dt_priv, aes_dt dt_func)
+/* Sets V and key based on pdata */
+static void
+drbg_aes_update(struct drbg_aes_ctx *ctx,
+               unsigned pdata_size, const uint8_t * pdata)
 {
-       memcpy(ctx->v, seed, AES_BLOCK_SIZE);
-       
-       dt_func(dt_priv, ctx->dt);
-       
-       ctx->reseed_counter = 0;
+       unsigned len = 0;
+       uint8_t tmp[DRBG_AES_SEED_SIZE];
+       uint8_t *t = tmp;
+
+       while (len < DRBG_AES_SEED_SIZE) {
+               INCREMENT(sizeof(ctx->v), ctx->v);
+               aes_encrypt(&ctx->key, AES_BLOCK_SIZE, t, ctx->v);
+               t += AES_BLOCK_SIZE;
+               len += AES_BLOCK_SIZE;
+       }
+
+       memxor(tmp, pdata, DRBG_AES_SEED_SIZE);
+
+       aes_set_encrypt_key(&ctx->key, DRBG_AES_KEY_SIZE, tmp);
+
+       ctx->prev_block_present = 0;
+
+       memcpy(ctx->v, &tmp[AES_BLOCK_SIZE], AES_BLOCK_SIZE);
+
+       ctx->reseed_counter = 1;
        ctx->seeded = 1;
 }
+
 int
-drbg_aes_random(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst)
+drbg_aes_reseed(struct drbg_aes_ctx *ctx,
+               unsigned entropy_size, const uint8_t * entropy,
+               unsigned add_size, const uint8_t * add)
+{
+       uint8_t tmp[DRBG_AES_SEED_SIZE];
+       unsigned len = 0;
+
+       if (add_size > DRBG_AES_SEED_SIZE || entropy_size != DRBG_AES_SEED_SIZE)
+               return 0;
+
+       if (add_size <= DRBG_AES_SEED_SIZE && add_size > 0) {
+               memcpy(tmp, add, add_size);
+               len = add_size;
+       }
+
+       if (len != DRBG_AES_SEED_SIZE)
+               memset(&tmp[len], 0, DRBG_AES_SEED_SIZE - len);
+
+       memxor(tmp, entropy, entropy_size);
+
+       drbg_aes_update(ctx, DRBG_AES_SEED_SIZE, tmp);
+
+       return 1;
+}
+
+/* we don't use additional input */
+int drbg_aes_random(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst)
 {
-       uint8_t intermediate[AES_BLOCK_SIZE];
        uint8_t tmp[AES_BLOCK_SIZE];
        unsigned left;
 
@@ -67,60 +104,30 @@ drbg_aes_random(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst)
        /* Throw the first block generated. FIPS 140-2 requirement 
         */
        if (ctx->prev_block_present == 0) {
-               /* I = AES_K(dt) */
-               aes_encrypt(&ctx->key, AES_BLOCK_SIZE, intermediate, ctx->dt);
-
-               /* tmp = I XOR V */
-               memxor3(tmp, ctx->v, intermediate, AES_BLOCK_SIZE);
-
-               /* dst = R = AES_K(I XOR V) */
-               aes_encrypt(&ctx->key, AES_BLOCK_SIZE, ctx->prev_block,
-                           tmp);
-
-               /* V = AES_K(R XOR I) */
-               memxor3(tmp, ctx->prev_block, intermediate,
-                       AES_BLOCK_SIZE);
-               aes_encrypt(&ctx->key, AES_BLOCK_SIZE, ctx->v, tmp);
+               INCREMENT(sizeof(ctx->v), ctx->v);
+               aes_encrypt(&ctx->key, AES_BLOCK_SIZE, ctx->prev_block, ctx->v);
 
                ctx->prev_block_present = 1;
-               
-               INCREMENT(sizeof(ctx->dt), ctx->dt);
        }
 
        /* Perform the actual encryption */
        for (left = length; left >= AES_BLOCK_SIZE;
             left -= AES_BLOCK_SIZE, dst += AES_BLOCK_SIZE) {
 
-               /* I = AES_K(dt) */
-               aes_encrypt(&ctx->key, AES_BLOCK_SIZE, intermediate, ctx->dt);
-
-               /* tmp = I XOR V */
-               memxor3(tmp, ctx->v, intermediate, AES_BLOCK_SIZE);
-
-               /* dst = R = AES_K(I XOR V) */
-               aes_encrypt(&ctx->key, AES_BLOCK_SIZE, dst, tmp);
+               INCREMENT(sizeof(ctx->v), ctx->v);
+               aes_encrypt(&ctx->key, AES_BLOCK_SIZE, dst, ctx->v);
 
                /* if detected loop */
                if (memcmp(dst, ctx->prev_block, AES_BLOCK_SIZE) == 0)
                        return 0;
 
                memcpy(ctx->prev_block, dst, AES_BLOCK_SIZE);
-
-               /* V = AES_K(R XOR I) */
-               memxor3(tmp, dst, intermediate, AES_BLOCK_SIZE);
-               aes_encrypt(&ctx->key, AES_BLOCK_SIZE, ctx->v, tmp);
-               
-               INCREMENT(sizeof(ctx->dt), ctx->dt);
        }
 
        if (left > 0) {         /* partial fill */
 
-               /* I = AES_K(dt) */
-               aes_encrypt(&ctx->key, AES_BLOCK_SIZE, intermediate, ctx->dt);
-               memxor3(tmp, ctx->v, intermediate, AES_BLOCK_SIZE);
-
-               /* tmp = R = AES_K(I XOR V) */
-               aes_encrypt(&ctx->key, AES_BLOCK_SIZE, tmp, tmp);
+               INCREMENT(sizeof(ctx->v), ctx->v);
+               aes_encrypt(&ctx->key, AES_BLOCK_SIZE, tmp, ctx->v);
 
                /* if detected loop */
                if (memcmp(tmp, ctx->prev_block, AES_BLOCK_SIZE) == 0)
@@ -128,14 +135,8 @@ drbg_aes_random(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst)
 
                memcpy(ctx->prev_block, tmp, AES_BLOCK_SIZE);
                memcpy(dst, tmp, left);
-
-               /* V = AES_K(R XOR I) */
-               memxor(tmp, intermediate, AES_BLOCK_SIZE);
-               aes_encrypt(&ctx->key, AES_BLOCK_SIZE, ctx->v, tmp);
-               
-               INCREMENT(sizeof(ctx->dt), ctx->dt);
        }
-       
+
        if (ctx->reseed_counter > DRBG_AES_RESEED_TIME)
                return 0;
        ctx->reseed_counter++;
index 9454fd01e88b75c9983bebfbfb459365944cb9f5..1c6ff5974c4046f0c82d9f1653f7651287bcc8c3 100644 (file)
         ;                                       \
   } while (0)
 
-/* This is the AES-based random-number generator from ANSI X9.31 
- * Appendix A.2.4. Note that the DT value from the document is obtained
- * during seeding. Then it is used as an 128-bit counter which is
- * incremented on block encrypted in drbg_aes_random().
+#define DRBG_AES_KEY_SIZE 32
+#define DRBG_AES_SEED_SIZE (AES_BLOCK_SIZE+DRBG_AES_KEY_SIZE)
+
+/* This is the CTR-AES-256-based random-number generator from SP800-90A.
  */
 struct drbg_aes_ctx {
        unsigned seeded;
-       /* The current key and counter block */
+       /* The current key */
        struct aes_ctx key;
-       uint8_t v[AES_BLOCK_SIZE];
 
-       /* An initial value based on timestamp */
-       uint8_t dt[AES_BLOCK_SIZE];
+       uint8_t v[AES_BLOCK_SIZE];
 
        unsigned prev_block_present;
        uint8_t prev_block[AES_BLOCK_SIZE];
@@ -58,22 +56,23 @@ struct drbg_aes_ctx {
 };
 
 /* This DRBG should be reseeded if reseed_counter exceeds
- * that number.
+ * that number. Otherwise drbg_aes_random() will fail.
  */
 #define DRBG_AES_RESEED_TIME 65536
 
-typedef int (*aes_dt) (void *priv, uint8_t dt[AES_BLOCK_SIZE]);
-
-/* should return zero on error */
+/* The entropy provided in these functions should be of
+ * size DRBG_AES_SEED_SIZE. Additional data and pers.
+ * string may be <= DRBG_AES_SEED_SIZE.
+ */
 int
-drbg_aes_set_key(struct drbg_aes_ctx *ctx, unsigned length,
-                const uint8_t * key);
+drbg_aes_init(struct drbg_aes_ctx *ctx, 
+       unsigned entropy_size, const uint8_t *entropy, 
+       unsigned pstring_size, const uint8_t* pstring);
 
-/* Set's V value */
-void
-drbg_aes_seed(struct drbg_aes_ctx *ctx,
-             const uint8_t seed[AES_BLOCK_SIZE],
-             void *dt_priv, aes_dt dt);
+int
+drbg_aes_reseed(struct drbg_aes_ctx *ctx, 
+       unsigned entropy_size, const uint8_t *entropy, 
+       unsigned add_size, const uint8_t* add);
 
 int
 drbg_aes_random(struct drbg_aes_ctx *ctx, unsigned length,
index 69cb04577f5561b56eb0342f7992d0ecca2360e3..db64bb0e58c05b334dbf5285678d9bb54600f992 100644 (file)
@@ -211,51 +211,11 @@ void _rnd_system_entropy_deinit(void)
 }
 #endif
 
-/* Get the DT vector for use with the core PRNG function. 
-
-   Buffer:       00112233445566778899AABBCCDDEEFF
-                 !--+---!!--+---!!--+---!!--+---!
-   seconds ---------/      |        |       |
-   nanoseconds ------------/        |       |
-                                    |       |
-   counter  ------------------------/       |
-   hash    --------------------------------/
-
-   hash is a hash of all the event values (including rusage when present,
-   and pid), and counter is a 32-bit running counter.
-   
-   The output number will be always unique if this function is called 
-   less than 2^32 times per nanosecond.
-    
-   This function is used to get an initial value for the DT of DRBG-AES
-   which is later being incremented.
-*/
-static int
-get_dt(void* priv, uint8_t dt[AES_BLOCK_SIZE])
+#define PSTRING "gnutls-rng"
+#define PSTRING_SIZE (sizeof(PSTRING)-1)
+int drbg_init(struct drbg_aes_ctx *ctx)
 {
-       struct event_st event;
-       uint32_t secs, usecs;
-       uint32_t v1, v2;
-
-       _rnd_get_event(&event);
-       secs = event.now.tv_sec;
-       usecs = event.now.tv_nsec;
-       /* v2 is a hash of all values including rusage -when present
-        * and getpid(). */
-       v1 = event.count;
-       v2 = hash_pjw_bare(&event, sizeof(event));
-       
-       memcpy(dt, &secs, 4);
-       memcpy(dt+4, &usecs, 4);
-       memcpy(dt+8, &v1, 4);
-       memcpy(dt+12, &v2, 4);
-       
-       return 1;
-}
-
-int drbg_generate_key(struct drbg_aes_ctx *ctx)
-{
-       uint8_t buffer[FIPS140_RND_KEY_SIZE];
+       uint8_t buffer[DRBG_AES_SEED_SIZE];
        int ret;
 
        /* Get a key from the standard RNG or from the entropy source.  */
@@ -263,7 +223,7 @@ int drbg_generate_key(struct drbg_aes_ctx *ctx)
        if (ret < 0)
                return gnutls_assert_val(ret);
 
-       ret = drbg_aes_set_key(ctx, sizeof(buffer), buffer);
+       ret = drbg_aes_init(ctx, sizeof(buffer), buffer, PSTRING_SIZE, (void*)PSTRING);
        if (ret == 0)
                return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED);
 
@@ -272,10 +232,10 @@ int drbg_generate_key(struct drbg_aes_ctx *ctx)
        return 0;
 }
 
-/* Reseed a generator.  This is also used for the initial seeding. */
+/* Reseed a generator. */
 int drbg_reseed(struct drbg_aes_ctx *ctx)
 {
-       uint8_t buffer[AES_BLOCK_SIZE];
+       uint8_t buffer[DRBG_AES_SEED_SIZE];
        int ret;
 
        /* The other two generators are seeded from /dev/random.  */
@@ -283,7 +243,7 @@ int drbg_reseed(struct drbg_aes_ctx *ctx)
        if (ret < 0)
                return gnutls_assert_val(ret);
 
-       drbg_aes_seed(ctx, buffer, NULL, get_dt);
+       drbg_aes_reseed(ctx, sizeof(buffer), buffer, 0, NULL);
 
        return 0;
 }
index 12123900028f7e02306a8ef7f5e8d9c68b3733b8..595c193bb904030a156162da063b6e22d87a2e60 100644 (file)
@@ -58,4 +58,4 @@ typedef int (*get_entropy_func)(void* rnd, size_t size);
 extern get_entropy_func _rnd_get_system_entropy;
 
 int drbg_reseed(struct drbg_aes_ctx *ctx);
-int drbg_generate_key(struct drbg_aes_ctx *ctx);
+int drbg_init(struct drbg_aes_ctx *ctx);
index d28bb685e6afba349ad8412b79f92d069cd7b18b..4e26ac6d5beb78c2fbbd9a9c7a0fff5364143b26 100644 (file)
@@ -1,4 +1,4 @@
-/* random-fips.c - FIPS140-2 random number generator
+/*
  * Copyright (C) 2013 Red Hat
  *
  * This file is part of GnuTLS.
 #include <locks.h>
 #include <rnd-common.h>
 
+/* This provides a random generator for gnutls. It uses
+ * three instances of the DRBG-AES-CTR generator, one for
+ * each level of randomness. It uses /dev/urandom for their
+ * seeding.
+ */
+
 #define RND_LOCK if (gnutls_mutex_lock(&rnd_mutex)!=0) abort()
 #define RND_UNLOCK if (gnutls_mutex_unlock(&rnd_mutex)!=0) abort()
 
@@ -46,21 +52,21 @@ struct fips_ctx {
 #endif
 };
 
-static int _rngfips_reinit(struct fips_ctx* fctx);
+static int _rngfips_ctx_reinit(struct fips_ctx *fctx);
+static int _rngfips_ctx_init(struct fips_ctx *fctx);
 
-
-static int get_random(struct drbg_aes_ctx *ctx, struct fips_ctx* fctx,
-                       void *buffer, size_t length)
+static int get_random(struct drbg_aes_ctx *ctx, struct fips_ctx *fctx,
+                     void *buffer, size_t length)
 {
        int ret;
 
        if (ctx->reseed_counter > DRBG_AES_RESEED_TIME
 #ifdef HAVE_GETPID
-               || fctx->pid != getpid()
+           || fctx->pid != getpid()
 #endif
-               ) {
+           ) {
 
-               ret = _rngfips_reinit(fctx);
+               ret = _rngfips_ctx_reinit(fctx);
                if (ret < 0)
                        return gnutls_assert_val(ret);
        }
@@ -72,33 +78,46 @@ static int get_random(struct drbg_aes_ctx *ctx, struct fips_ctx* fctx,
        return 0;
 }
 
-static int _rngfips_reinit(struct fips_ctx* fctx)
+static int _rngfips_ctx_init(struct fips_ctx *fctx)
 {
-int ret;
+       int ret;
 
        /* strong */
-       ret = drbg_generate_key(&fctx->strong_context);
+       ret = drbg_init(&fctx->strong_context);
        if (ret < 0)
                return gnutls_assert_val(ret);
-       
-       ret = drbg_reseed(&fctx->strong_context);
+
+       /* normal */
+       ret = drbg_init(&fctx->normal_context);
        if (ret < 0)
                return gnutls_assert_val(ret);
 
-       /* normal */
-       ret = drbg_generate_key(&fctx->normal_context);
+       /* nonce */
+       ret = drbg_init(&fctx->nonce_context);
        if (ret < 0)
                return gnutls_assert_val(ret);
-       
-       ret = drbg_reseed(&fctx->normal_context);
+
+#ifdef HAVE_GETPID
+       fctx->pid = getpid();
+#endif
+       return 0;
+}
+
+static int _rngfips_ctx_reinit(struct fips_ctx *fctx)
+{
+       int ret;
+
+       /* strong */
+       ret = drbg_reseed(&fctx->strong_context);
        if (ret < 0)
                return gnutls_assert_val(ret);
 
-       /* nonce */
-       ret = drbg_generate_key(&fctx->nonce_context);
+       /* normal */
+       ret = drbg_reseed(&fctx->normal_context);
        if (ret < 0)
                return gnutls_assert_val(ret);
-       
+
+       /* nonce */
        ret = drbg_reseed(&fctx->nonce_context);
        if (ret < 0)
                return gnutls_assert_val(ret);
@@ -106,16 +125,15 @@ int ret;
 #ifdef HAVE_GETPID
        fctx->pid = getpid();
 #endif
-
        return 0;
 }
 
 /* Initialize this random subsystem. */
-static int _rngfips_init(void** _ctx)
+static int _rngfips_init(void **_ctx)
 {
 /* Basic initialization is required to initialize mutexes and
    do a few checks on the implementation.  */
-       struct fips_ctxctx;
+       struct fips_ctx *ctx;
        int ret;
 
        ret = _rnd_system_entropy_init();
@@ -130,7 +148,7 @@ static int _rngfips_init(void** _ctx)
        if (ret < 0)
                return gnutls_assert_val(ret);
 
-       ret = _rngfips_reinit(ctx);
+       ret = _rngfips_ctx_init(ctx);
        if (ret < 0)
                return gnutls_assert_val(ret);
 
@@ -139,29 +157,28 @@ static int _rngfips_init(void** _ctx)
        return 0;
 }
 
-static int
-_rngfips_rnd(void *_ctx, int level, void *buffer, size_t length)
+static int _rngfips_rnd(void *_ctx, int level, void *buffer, size_t length)
 {
-struct fips_ctx* ctx = _ctx;
-int ret;
+       struct fips_ctx *ctx = _ctx;
+       int ret;
 
        RND_LOCK;
-       switch(level) {
-               case GNUTLS_RND_RANDOM:
-                       ret = get_random(&ctx->normal_context, ctx, buffer, length);
-               case GNUTLS_RND_KEY:
-                       ret = get_random(&ctx->strong_context, ctx, buffer, length);
-               default:
-                       ret = get_random(&ctx->nonce_context, ctx, buffer, length);
+       switch (level) {
+       case GNUTLS_RND_RANDOM:
+               ret = get_random(&ctx->normal_context, ctx, buffer, length);
+       case GNUTLS_RND_KEY:
+               ret = get_random(&ctx->strong_context, ctx, buffer, length);
+       default:
+               ret = get_random(&ctx->nonce_context, ctx, buffer, length);
        }
        RND_UNLOCK;
-       
+
        return ret;
 }
 
-static void _rngfips_deinit(void * _ctx)
+static void _rngfips_deinit(void *_ctx)
 {
-       struct fips_ctxctx = _ctx;
+       struct fips_ctx *ctx = _ctx;
 
        gnutls_mutex_deinit(&rnd_mutex);
        rnd_mutex = NULL;
@@ -179,7 +196,7 @@ static void _rngfips_refresh(void *_ctx)
 static int selftest_kat(void)
 {
        int ret;
-       
+
        RND_LOCK;
        ret = drbg_aes_self_test();
        RND_UNLOCK;
@@ -189,7 +206,7 @@ static int selftest_kat(void)
                return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED);
        } else
                _gnutls_debug_log("DRBG-AES self test succeeded\n");
-               
+
        return 0;
 }
 
index 4f8933c36293538bcae7ee4ccff77d75a4babba8..f967515bcdbd24e30198a36d407eafe80ad25ddf 100644 (file)
@@ -195,11 +195,7 @@ static int wrap_nettle_rnd_init(void **ctx)
        yarrow256_slow_reseed(&yctx);
        
        /* initialize the nonce RNG */
-       ret = drbg_generate_key(&nonce_ctx);
-       if (ret < 0)
-               return gnutls_assert_val(ret);
-
-       ret = drbg_reseed(&nonce_ctx);
+       ret = drbg_init(&nonce_ctx);
        if (ret < 0)
                return gnutls_assert_val(ret);
 
@@ -244,10 +240,6 @@ wrap_nettle_rnd(void *_ctx, int level, void *data, size_t datasize)
        if (level == GNUTLS_RND_NONCE) {
                if (reseed != 0) {
                        /* reseed nonce */
-                       ret = drbg_generate_key(&nonce_ctx);
-                       if (ret < 0)
-                               return gnutls_assert_val(ret);
-
                        ret = drbg_reseed(&nonce_ctx);
                        if (ret < 0)
                                return gnutls_assert_val(ret);