@@ -25,6 +25,15 @@
#define DEFAULT_PRNG_KSZ 16
#define DEFAULT_BLK_SZ 16
+#define BLK_INTS ((DEFAULT_BLK_SZ + 3) / 4)
+#define BLK_LONGS ((DEFAULT_BLK_SZ + 7) / 8)
+
+/* An aligned buffer thant can be accessed various ways */
+union cipherblock {
+ u8 b[DEFAULT_BLK_SZ];
+ u32 i[BLK_INTS];
+ u64 l[BLK_LONGS];
+};
/*
* Flags for the prng_context flags field
@@ -47,15 +56,15 @@ struct prng_context {
spinlock_t prng_lock;
u8 flags;
u8 rand_read_pos;
- u8 rand_data[DEFAULT_BLK_SZ];
- u8 DT[DEFAULT_BLK_SZ];
- u8 V[DEFAULT_BLK_SZ];
+ union cipherblock rand_data;
+ union cipherblock DT;
+ union cipherblock V;
struct crypto_cipher *tfm;
};
static int dbg;
-static void hexdump(char const *note, const u8 buf[DEFAULT_BLK_SZ])
+static void hexdump(char const *note, const union cipherblock *buf)
{
if (dbg) {
printk(KERN_CRIT "%s = %" __stringify(DEFAULT_BLK_SZ) "phN",
@@ -68,11 +77,11 @@ if (dbg)\
printk(format, ##args);\
} while (0)
-static void xor_block(const u8 in[DEFAULT_BLK_SZ], u8 out[DEFAULT_BLK_SZ])
+static void xor_block(const u64 in[BLK_LONGS], u64 out[BLK_LONGS])
{
int i;
- for (i = 0; i < DEFAULT_BLK_SZ; i++)
+ for (i = 0; i < BLK_LONGS; i++)
out[i] ^= in[i];
}
@@ -83,20 +92,20 @@ static void xor_block(const u8 in[DEFAULT_BLK_SZ], u8 out[DEFAULT_BLK_SZ])
static int _get_more_prng_bytes(struct prng_context *ctx, bool cont_test)
{
int i;
- u8 tmp[DEFAULT_BLK_SZ];
+ union cipherblock tmp;
dbgprint(KERN_CRIT "Calling _get_more_prng_bytes for context %p\n",
ctx);
- hexdump("DT", ctx->DT);
- hexdump("V", ctx->V);
+ hexdump("DT", &ctx->DT);
+ hexdump("V", &ctx->V);
/*
* Start by encrypting the counter value
* This gives us an intermediate value I (stored in tmp)
*/
- crypto_cipher_encrypt_one(ctx->tfm, tmp, ctx->DT);
- hexdump("I", tmp);
+ crypto_cipher_encrypt_one(ctx->tfm, tmp.b, ctx->DT.b);
+ hexdump("I", &tmp);
/*
* Next xor I with our secret vector V. Encrypt that result
@@ -104,16 +113,16 @@ static int _get_more_prng_bytes(struct prng_context *ctx, bool cont_test)
* keep that output in ctx->V for the moment; we need the
* previous rand_data for ons more thing.
*/
- xor_block(tmp, ctx->V);
- hexdump("V^I", ctx->V);
- crypto_cipher_encrypt_one(ctx->tfm, ctx->V, ctx->V);
- hexdump("R", ctx->V);
+ xor_block(tmp.l, ctx->V.l);
+ hexdump("V^I", &ctx->V);
+ crypto_cipher_encrypt_one(ctx->tfm, ctx->V.b, ctx->V.b);
+ hexdump("R", &ctx->V);
/*
* Check that we didn't produce the same random data that we
* did last time around.
*/
- if (!memcmp(ctx->V, ctx->rand_data, DEFAULT_BLK_SZ)) {
+ if (!memcmp(ctx->V.b, ctx->rand_data.b, DEFAULT_BLK_SZ)) {
if (cont_test) {
panic("cprng %p Failed repetition check!\n", ctx);
}
@@ -126,27 +135,27 @@ static int _get_more_prng_bytes(struct prng_context *ctx, bool cont_test)
/*
* Okay, the new data is okay, copy it to the buffer.
*/
- memcpy(ctx->rand_data, ctx->V, DEFAULT_BLK_SZ);
+ ctx->rand_data = ctx->V;
/*
* Lastly xor the random data with I and encrypt that to obtain
* a new secret vector V.
*/
- xor_block(tmp, ctx->V);
- hexdump("R^I", ctx->V);
- memzero_explicit(tmp, DEFAULT_BLK_SZ);
- crypto_cipher_encrypt_one(ctx->tfm, ctx->V, ctx->V);
- hexdump("V'", ctx->V);
+ xor_block(tmp.l, ctx->V.l);
+ hexdump("R^I", &ctx->V);
+ memzero_explicit(tmp.b, DEFAULT_BLK_SZ);
+ crypto_cipher_encrypt_one(ctx->tfm, ctx->V.b, ctx->V.b);
+ hexdump("V'", &ctx->V);
/*
* Now update our DT value
*/
for (i = DEFAULT_BLK_SZ - 1; i >= 0; i--) {
- ctx->DT[i] += 1;
- if (ctx->DT[i] != 0)
+ ctx->DT.b[i] += 1;
+ if (ctx->DT.b[i] != 0)
break;
}
- hexdump("DT'", ctx->DT);
+ hexdump("DT'", &ctx->DT);
dbgprint("Returning new block for context %p\n", ctx);
@@ -175,7 +184,7 @@ static int get_prng_bytes(u8 *buf, unsigned int nbytes,
/* Leading partial block */
unsigned int avail = DEFAULT_BLK_SZ - read_pos;
- memcpy(ptr, ctx->rand_data + read_pos, avail);
+ memcpy(ptr, ctx->rand_data.b + read_pos, avail);
ptr += avail;
byte_count -= avail;
read_pos = 0;
@@ -188,14 +197,14 @@ static int get_prng_bytes(u8 *buf, unsigned int nbytes,
}
if (byte_count < DEFAULT_BLK_SZ)
break;
- memcpy(ptr, ctx->rand_data, DEFAULT_BLK_SZ);
+ memcpy(ptr, ctx->rand_data.b, DEFAULT_BLK_SZ);
ptr += DEFAULT_BLK_SZ;
byte_count -= DEFAULT_BLK_SZ;
}
}
/* The final partial block; read_pos + byte_count <= DEFAULT_BLK_SZ */
- memcpy(ptr, ctx->rand_data + read_pos, byte_count);
+ memcpy(ptr, ctx->rand_data.b + read_pos, byte_count);
ctx->rand_read_pos = read_pos + byte_count;
err = nbytes;
@@ -220,13 +229,13 @@ static int reset_prng_context(struct prng_context *ctx, const u8 *key,
ctx->flags |= PRNG_NEED_RESET;
ctx->rand_read_pos = DEFAULT_BLK_SZ;
- memset(ctx->rand_data, 0, DEFAULT_BLK_SZ);
+ memset(ctx->rand_data.b, 0, DEFAULT_BLK_SZ);
if (!DT)
- DT = ctx->rand_data; /* Use all-zeros if NULL */
+ DT = ctx->rand_data.b; /* Use all-zeros if NULL */
- memcpy(ctx->DT, DT, DEFAULT_BLK_SZ);
- memcpy(ctx->V, V, DEFAULT_BLK_SZ);
+ memcpy(ctx->DT.b, DT, DEFAULT_BLK_SZ);
+ memcpy(ctx->V.b, V, DEFAULT_BLK_SZ);
ret = crypto_cipher_setkey(ctx->tfm, key, klen);
if (ret) {
This ensures alignment and makes xor_block more efficient, but it's mostly in preparation for later changes. Signed-off-by: George Spelvin <linux@horizon.com> --- crypto/ansi_cprng.c | 73 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 32 deletions(-)