Skip to content

Commit

Permalink
crypto: testmgr - add helpers for fuzzing against generic implementation
Browse files Browse the repository at this point in the history
Add some helper functions in preparation for fuzz testing algorithms
against their generic implementation.

Signed-off-by: Eric Biggers <[email protected]>
Signed-off-by: Herbert Xu <[email protected]>
  • Loading branch information
ebiggers authored and herbertx committed Apr 18, 2019
1 parent 951d133 commit f2bb770
Showing 1 changed file with 128 additions and 0 deletions.
128 changes: 128 additions & 0 deletions crypto/testmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ struct kpp_test_suite {

struct alg_test_desc {
const char *alg;
const char *generic_driver;
int (*test)(const struct alg_test_desc *desc, const char *driver,
u32 type, u32 mask);
int fips_allowed; /* set if alg is allowed in fips mode */
Expand Down Expand Up @@ -745,6 +746,91 @@ static int build_cipher_test_sglists(struct cipher_test_sglists *tsgls,
}

#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS

/* Generate a random length in range [0, max_len], but prefer smaller values */
static unsigned int generate_random_length(unsigned int max_len)
{
unsigned int len = prandom_u32() % (max_len + 1);

switch (prandom_u32() % 4) {
case 0:
return len % 64;
case 1:
return len % 256;
case 2:
return len % 1024;
default:
return len;
}
}

/* Sometimes make some random changes to the given data buffer */
static void mutate_buffer(u8 *buf, size_t count)
{
size_t num_flips;
size_t i;
size_t pos;

/* Sometimes flip some bits */
if (prandom_u32() % 4 == 0) {
num_flips = min_t(size_t, 1 << (prandom_u32() % 8), count * 8);
for (i = 0; i < num_flips; i++) {
pos = prandom_u32() % (count * 8);
buf[pos / 8] ^= 1 << (pos % 8);
}
}

/* Sometimes flip some bytes */
if (prandom_u32() % 4 == 0) {
num_flips = min_t(size_t, 1 << (prandom_u32() % 8), count);
for (i = 0; i < num_flips; i++)
buf[prandom_u32() % count] ^= 0xff;
}
}

/* Randomly generate 'count' bytes, but sometimes make them "interesting" */
static void generate_random_bytes(u8 *buf, size_t count)
{
u8 b;
u8 increment;
size_t i;

if (count == 0)
return;

switch (prandom_u32() % 8) { /* Choose a generation strategy */
case 0:
case 1:
/* All the same byte, plus optional mutations */
switch (prandom_u32() % 4) {
case 0:
b = 0x00;
break;
case 1:
b = 0xff;
break;
default:
b = (u8)prandom_u32();
break;
}
memset(buf, b, count);
mutate_buffer(buf, count);
break;
case 2:
/* Ascending or descending bytes, plus optional mutations */
increment = (u8)prandom_u32();
b = (u8)prandom_u32();
for (i = 0; i < count; i++, b += increment)
buf[i] = b;
mutate_buffer(buf, count);
break;
default:
/* Fully random bytes */
for (i = 0; i < count; i++)
buf[i] = (u8)prandom_u32();
}
}

static char *generate_random_sgl_divisions(struct test_sg_division *divs,
size_t max_divs, char *p, char *end,
bool gen_flushes, u32 req_flags)
Expand Down Expand Up @@ -899,6 +985,48 @@ static void crypto_reenable_simd_for_test(void)
__this_cpu_write(crypto_simd_disabled_for_test, false);
preempt_enable();
}

/*
* Given an algorithm name, build the name of the generic implementation of that
* algorithm, assuming the usual naming convention. Specifically, this appends
* "-generic" to every part of the name that is not a template name. Examples:
*
* aes => aes-generic
* cbc(aes) => cbc(aes-generic)
* cts(cbc(aes)) => cts(cbc(aes-generic))
* rfc7539(chacha20,poly1305) => rfc7539(chacha20-generic,poly1305-generic)
*
* Return: 0 on success, or -ENAMETOOLONG if the generic name would be too long
*/
static int build_generic_driver_name(const char *algname,
char driver_name[CRYPTO_MAX_ALG_NAME])
{
const char *in = algname;
char *out = driver_name;
size_t len = strlen(algname);

if (len >= CRYPTO_MAX_ALG_NAME)
goto too_long;
do {
const char *in_saved = in;

while (*in && *in != '(' && *in != ')' && *in != ',')
*out++ = *in++;
if (*in != '(' && in > in_saved) {
len += 8;
if (len >= CRYPTO_MAX_ALG_NAME)
goto too_long;
memcpy(out, "-generic", 8);
out += 8;
}
} while ((*out++ = *in++) != '\0');
return 0;

too_long:
pr_err("alg: generic driver name for \"%s\" would be too long\n",
algname);
return -ENAMETOOLONG;
}
#else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
static void crypto_disable_simd_for_test(void)
{
Expand Down

0 comments on commit f2bb770

Please sign in to comment.