RNG tests based on FIPS 140-1
This commit is contained in:
parent
2241a29571
commit
f6035833fa
|
@ -19,7 +19,8 @@ libstrongswan_unit_tester_la_SOURCES = unit_tester.c unit_tester.h tests.h \
|
|||
tests/test_aes.c \
|
||||
tests/test_chunk.c \
|
||||
tests/test_pool.c \
|
||||
tests/test_agent.c
|
||||
tests/test_agent.c \
|
||||
tests/test_rng.c
|
||||
|
||||
libstrongswan_unit_tester_la_LDFLAGS = -module
|
||||
|
||||
|
|
|
@ -33,10 +33,11 @@ DEFINE_TEST("SQLite operations", test_sqlite, FALSE)
|
|||
DEFINE_TEST("mutex primitive", test_mutex, FALSE)
|
||||
DEFINE_TEST("RSA key generation", test_rsa_gen, FALSE)
|
||||
DEFINE_TEST("RSA subjectPublicKeyInfo loading", test_rsa_load_any, FALSE)
|
||||
DEFINE_TEST("X509 certificate", test_cert_x509, TRUE)
|
||||
DEFINE_TEST("X509 certificate", test_cert_x509, FALSE)
|
||||
DEFINE_TEST("Mediation database key fetch", test_med_db, FALSE)
|
||||
DEFINE_TEST("AES-128 encryption", test_aes128, FALSE)
|
||||
DEFINE_TEST("AES-XCBC", test_aes_xcbc, FALSE)
|
||||
DEFINE_TEST("Base64 converter", test_chunk_base64, FALSE)
|
||||
DEFINE_TEST("IP pool", test_pool, FALSE)
|
||||
DEFINE_TEST("SSH agent", test_agent, FALSE)
|
||||
DEFINE_TEST("RNG quality", test_rng, FALSE)
|
||||
|
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <daemon.h>
|
||||
#include <library.h>
|
||||
#include <utils/mutex.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static bool test_monobit(chunk_t data)
|
||||
{
|
||||
int i, j, bits = 0;
|
||||
|
||||
for (i = 0; i < data.len; i++)
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
if (data.ptr[i] & (1<<j))
|
||||
{
|
||||
bits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
DBG1(DBG_CFG, " Monobit: %d/%d bits set", bits, data.len * 8);
|
||||
if (bits > 9654 && bits < 10346)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool test_poker(chunk_t data)
|
||||
{
|
||||
int i, counter[16];
|
||||
double sum = 0.0;
|
||||
|
||||
memset(counter, 0, sizeof(counter));
|
||||
|
||||
for (i = 0; i < data.len; i++)
|
||||
{
|
||||
counter[data.ptr[i] & 0x0F]++;
|
||||
counter[(data.ptr[i] & 0xF0) >> 4]++;
|
||||
}
|
||||
|
||||
for (i = 0; i < countof(counter); i++)
|
||||
{
|
||||
sum += (counter[i] * counter[i]) / 5000.0 * 16.0;
|
||||
}
|
||||
sum -= 5000.0;
|
||||
DBG1(DBG_CFG, " Poker: %f", sum);
|
||||
if (sum > 1.03 && sum < 57.4)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool test_runs(chunk_t data)
|
||||
{
|
||||
int i, j, zero_runs[7], one_runs[7], zero = 0, one = 0, longrun = 0;
|
||||
bool ok = TRUE;
|
||||
|
||||
memset(one_runs, 0, sizeof(zero_runs));
|
||||
memset(zero_runs, 0, sizeof(one_runs));
|
||||
|
||||
for (i = 0; i < data.len; i++)
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
if (data.ptr[i] & (1<<j))
|
||||
{
|
||||
if (one)
|
||||
{
|
||||
if (++one >= 34)
|
||||
{
|
||||
longrun++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
zero_runs[min(6, zero)]++;
|
||||
zero = 0;
|
||||
one = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (zero)
|
||||
{
|
||||
if (++zero >= 34)
|
||||
{
|
||||
longrun++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
one_runs[min(6, one)]++;
|
||||
one = 0;
|
||||
zero = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DBG1(DBG_CFG, " Runs: zero: %d/%d/%d/%d/%d/%d, one: %d/%d/%d/%d/%d/%d, "
|
||||
"longruns: %d",
|
||||
zero_runs[1], zero_runs[2], zero_runs[3],
|
||||
zero_runs[4], zero_runs[5], zero_runs[6],
|
||||
one_runs[1], one_runs[2], one_runs[3],
|
||||
one_runs[4], one_runs[5], one_runs[6],
|
||||
longrun);
|
||||
|
||||
if (longrun)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 1; i < countof(zero_runs); i++)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
ok &= zero_runs[i] > 2267 && zero_runs[i] < 2733;
|
||||
ok &= one_runs[i] > 2267 && one_runs[i] < 2733;
|
||||
break;
|
||||
case 2:
|
||||
ok &= zero_runs[i] > 1079 && zero_runs[i] < 1421;
|
||||
ok &= one_runs[i] > 1079 && one_runs[i] < 1421;
|
||||
break;
|
||||
case 3:
|
||||
ok &= zero_runs[i] > 502 && zero_runs[i] < 748;
|
||||
ok &= one_runs[i] > 502 && one_runs[i] < 748;
|
||||
break;
|
||||
case 4:
|
||||
ok &= zero_runs[i] > 223 && zero_runs[i] < 402;
|
||||
ok &= one_runs[i] > 223 && one_runs[i] < 402;
|
||||
break;
|
||||
case 5:
|
||||
ok &= zero_runs[i] > 90 && zero_runs[i] < 223;
|
||||
ok &= one_runs[i] > 90 && one_runs[i] < 223;
|
||||
break;
|
||||
case 6:
|
||||
ok &= zero_runs[i] > 90 && zero_runs[i] < 223;
|
||||
ok &= one_runs[i] > 90 && one_runs[i] < 223;
|
||||
break;
|
||||
}
|
||||
if (!ok)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool test_rng_quality(rng_quality_t quality)
|
||||
{
|
||||
rng_t *rng;
|
||||
chunk_t chunk;
|
||||
|
||||
rng = lib->crypto->create_rng(lib->crypto, quality);
|
||||
if (!rng)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
DBG1(DBG_CFG, "%N", rng_quality_names, quality);
|
||||
rng->allocate_bytes(rng, 2500, &chunk);
|
||||
|
||||
if (!test_monobit(chunk))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!test_poker(chunk))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!test_runs(chunk))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
free(chunk.ptr);
|
||||
rng->destroy(rng);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* run a test using given values
|
||||
*/
|
||||
bool test_rng()
|
||||
{
|
||||
if (!test_rng_quality(RNG_WEAK))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!test_rng_quality(RNG_STRONG))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!test_rng_quality(RNG_REAL))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue