Commit 58ae58cd authored by Niels Möller's avatar Niels Möller

Reapplied optimizations (150% speedup on x86_32) and other fixes,

relicensing them as LGPL.
* blowfish.c (do_encrypt): Renamed, to...
(encrypt): ...new name.
(F): Added context argument. Shift input explicitly, instead of
reading individual bytes via memory.
(R): Added context argument.
(encrypt): Deleted a bunch of local variables. Using the context
pointer for everything should consume less registers.
(decrypt): Likewise.
(initial_ctx): Arrange constants into a struct, to simplify key setup.
(blowfish_set_key): Some simplification.

Rev: nettle/ChangeLog:1.123
Rev: nettle/blowfish.c:1.5
parent 8ce0ab12
2010-11-26 Niels Mller <nisse@lysator.liu.se>
Reapplied optimizations (150% speedup on x86_32) and other fixes,
relicensing them as LGPL.
* blowfish.c (do_encrypt): Renamed, to...
(encrypt): ...new name.
(F): Added context argument. Shift input explicitly, instead of
reading individual bytes via memory.
(R): Added context argument.
(encrypt): Deleted a bunch of local variables. Using the context
pointer for everything should consume less registers.
(decrypt): Likewise.
(initial_ctx): Arrange constants into a struct, to simplify key
setup.
(blowfish_set_key): Some simplification.
2010-11-26 Simon Josefsson <simon@josefsson.org>
* blowfish.c: New version ported from libgcrypt. License changed
......@@ -323,7 +339,7 @@
* blowfish.c (initial_ctx): Deleted status value.
(blowfish_encrypt): Ignore status attribute.
(blowfish_decrypt): Likewise.
(blowfish_set_key): return result from weak key check, without
(blowfish_set_key): Return result from weak key check, without
setting the status attribute.
* blowfish.h (enum blowfish_error): Deleted.
......
......@@ -48,7 +48,10 @@
#include "macros.h"
/* precomputed S boxes */
static const uint32_t ks0[256] = {
static const struct blowfish_ctx
initial_ctx = {
{
{ /* ks0 */
0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96,
0xBA7C9045, 0xF12C7F99, 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, 0x0D95748F, 0x728EB658,
......@@ -92,9 +95,8 @@ static const uint32_t ks0[256] = {
0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, 0x08BA6FB5, 0x571BE91F,
0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A
};
static const uint32_t ks1[256] = {
},
{ /* ks1 */
0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D,
0x9CEE60B8, 0x8FEDB266, 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65,
......@@ -138,9 +140,8 @@ static const uint32_t ks1[256] = {
0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, 0xDB73DBD3, 0x105588CD,
0x675FDA79, 0xE3674340, 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7
};
static const uint32_t ks2[256] = {
},
{ /* ks2 */
0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, 0x411520F7, 0x7602D4F7,
0xBCF46B2E, 0xD4A20068, 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, 0x4D95FC1D, 0x96B591AF,
......@@ -184,9 +185,8 @@ static const uint32_t ks2[256] = {
0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, 0x1E50EF5E, 0xB161E6F8,
0xA28514D9, 0x6C51133C, 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0
};
static const uint32_t ks3[256] = {
},
{ /* ks3 */
0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, 0x5CB0679E, 0x4FA33742,
0xD3822740, 0x99BC9BBE, 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, 0x5748AB2F, 0xBC946E79,
......@@ -230,57 +230,55 @@ static const uint32_t ks3[256] = {
0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, 0x1948C25C, 0x02FB8A8C,
0x01C36AE4, 0xD6EBE1F9, 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6
};
static const uint32_t ps[_BLOWFISH_ROUNDS + 2] = {
}
},
{ /* ps */
0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0,
0x082EFA98, 0xEC4E6C89, 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, 0x9216D5D9, 0x8979FB1B
}
};
#ifdef WORDS_BIGENDIAN
#define F(x) ((( s0[((uint8_t*)&x)[0]] + s1[((uint8_t*)&x)[1]]) \
^ s2[((uint8_t*)&x)[2]]) + s3[((uint8_t*)&x)[3]] )
#else
#define F(x) ((( s0[((uint8_t*)&x)[3]] + s1[((uint8_t*)&x)[2]]) \
^ s2[((uint8_t*)&x)[1]]) + s3[((uint8_t*)&x)[0]] )
#endif
#define R(l,r,i) do { l ^= p[i]; r ^= F(l); } while(0)
/* It's unfortunate to have to pick the bytes apart in the round
* function. Werner's gnupg/libgcrypt code took the address of x, and
* then read the individual bytes depending on the endianness. But
* since xr and xl ought to live in registers, copying via memory is a
* bad idea. */
#define F(c, x) \
((( (c->s[0][(x>>24) &0xff] + c->s[1][(x>>16) & 0xff]) \
^ c->s[2][(x>>8) & 0xff]) + c->s[3][x & 0xff]) & 0xffffffff)
#define R(c, l,r,i) do { l ^= c->p[i]; r ^= F(c,l); } while(0)
static void
do_encrypt (const struct blowfish_ctx *ctx, uint32_t * ret_xl,
encrypt (const struct blowfish_ctx *ctx, uint32_t * ret_xl,
uint32_t * ret_xr)
{
uint32_t xl, xr;
const uint32_t *s0, *s1, *s2, *s3, *p;
xl = *ret_xl;
xr = *ret_xr;
p = ctx->p;
s0 = ctx->s[0];
s1 = ctx->s[1];
s2 = ctx->s[2];
s3 = ctx->s[3];
R (xl, xr, 0);
R (xr, xl, 1);
R (xl, xr, 2);
R (xr, xl, 3);
R (xl, xr, 4);
R (xr, xl, 5);
R (xl, xr, 6);
R (xr, xl, 7);
R (xl, xr, 8);
R (xr, xl, 9);
R (xl, xr, 10);
R (xr, xl, 11);
R (xl, xr, 12);
R (xr, xl, 13);
R (xl, xr, 14);
R (xr, xl, 15);
xl ^= p[_BLOWFISH_ROUNDS];
xr ^= p[_BLOWFISH_ROUNDS + 1];
R (ctx, xl, xr, 0);
R (ctx, xr, xl, 1);
R (ctx, xl, xr, 2);
R (ctx, xr, xl, 3);
R (ctx, xl, xr, 4);
R (ctx, xr, xl, 5);
R (ctx, xl, xr, 6);
R (ctx, xr, xl, 7);
R (ctx, xl, xr, 8);
R (ctx, xr, xl, 9);
R (ctx, xl, xr, 10);
R (ctx, xr, xl, 11);
R (ctx, xl, xr, 12);
R (ctx, xr, xl, 13);
R (ctx, xl, xr, 14);
R (ctx, xr, xl, 15);
xl ^= ctx->p[_BLOWFISH_ROUNDS];
xr ^= ctx->p[_BLOWFISH_ROUNDS + 1];
*ret_xl = xr;
*ret_xr = xl;
......@@ -290,35 +288,29 @@ static void
decrypt (const struct blowfish_ctx *ctx, uint32_t * ret_xl, uint32_t * ret_xr)
{
uint32_t xl, xr;
const uint32_t *s0, *s1, *s2, *s3, *p;
xl = *ret_xl;
xr = *ret_xr;
p = ctx->p;
s0 = ctx->s[0];
s1 = ctx->s[1];
s2 = ctx->s[2];
s3 = ctx->s[3];
R (xl, xr, 17);
R (xr, xl, 16);
R (xl, xr, 15);
R (xr, xl, 14);
R (xl, xr, 13);
R (xr, xl, 12);
R (xl, xr, 11);
R (xr, xl, 10);
R (xl, xr, 9);
R (xr, xl, 8);
R (xl, xr, 7);
R (xr, xl, 6);
R (xl, xr, 5);
R (xr, xl, 4);
R (xl, xr, 3);
R (xr, xl, 2);
xl ^= p[1];
xr ^= p[0];
R (ctx, xl, xr, 17);
R (ctx, xr, xl, 16);
R (ctx, xl, xr, 15);
R (ctx, xr, xl, 14);
R (ctx, xl, xr, 13);
R (ctx, xr, xl, 12);
R (ctx, xl, xr, 11);
R (ctx, xr, xl, 10);
R (ctx, xl, xr, 9);
R (ctx, xr, xl, 8);
R (ctx, xl, xr, 7);
R (ctx, xr, xl, 6);
R (ctx, xl, xr, 5);
R (ctx, xr, xl, 4);
R (ctx, xl, xr, 3);
R (ctx, xr, xl, 2);
xl ^= ctx->p[1];
xr ^= ctx->p[0];
*ret_xl = xr;
*ret_xr = xl;
......@@ -337,7 +329,7 @@ blowfish_encrypt (const struct blowfish_ctx *ctx,
d1 = src[0] << 24 | src[1] << 16 | src[2] << 8 | src[3];
d2 = src[4] << 24 | src[5] << 16 | src[6] << 8 | src[7];
do_encrypt (ctx, &d1, &d2);
encrypt (ctx, &d1, &d2);
dst[0] = (d1 >> 24) & 0xff;
dst[1] = (d1 >> 16) & 0xff;
dst[2] = (d1 >> 8) & 0xff;
......@@ -378,29 +370,12 @@ blowfish_set_key (struct blowfish_ctx *ctx,
int i, j;
uint32_t data, datal, datar;
for (i = 0; i < _BLOWFISH_ROUNDS + 2; i++)
ctx->p[i] = ps[i];
for (i = 0; i < 256; i++)
{
ctx->s[0][i] = ks0[i];
ctx->s[1][i] = ks1[i];
ctx->s[2][i] = ks2[i];
ctx->s[3][i] = ks3[i];
}
*ctx = initial_ctx;
for (i = j = 0; i < _BLOWFISH_ROUNDS + 2; i++)
{
#ifdef WORDS_BIGENDIAN
((uint8_t *) & data)[0] = key[j];
((uint8_t *) & data)[1] = key[(j + 1) % length];
((uint8_t *) & data)[2] = key[(j + 2) % length];
((uint8_t *) & data)[3] = key[(j + 3) % length];
#else
((uint8_t *) & data)[3] = key[j];
((uint8_t *) & data)[2] = key[(j + 1) % length];
((uint8_t *) & data)[1] = key[(j + 2) % length];
((uint8_t *) & data)[0] = key[(j + 3) % length];
#endif
data = (key[j] << 24) | (key[(j+1) % length] << 16)
| (key[(j+2) % length] << 8) | key[(j+3) % length];
ctx->p[i] ^= data;
j = (j + 4) % length;
}
......@@ -408,36 +383,19 @@ blowfish_set_key (struct blowfish_ctx *ctx,
datal = datar = 0;
for (i = 0; i < _BLOWFISH_ROUNDS + 2; i += 2)
{
do_encrypt (ctx, &datal, &datar);
encrypt (ctx, &datal, &datar);
ctx->p[i] = datal;
ctx->p[i + 1] = datar;
}
for (j = 0; j < 4; j++)
for (i = 0; i < 256; i += 2)
{
do_encrypt (ctx, &datal, &datar);
ctx->s[0][i] = datal;
ctx->s[0][i + 1] = datar;
}
for (i = 0; i < 256; i += 2)
{
do_encrypt (ctx, &datal, &datar);
ctx->s[1][i] = datal;
ctx->s[1][i + 1] = datar;
}
for (i = 0; i < 256; i += 2)
{
do_encrypt (ctx, &datal, &datar);
ctx->s[2][i] = datal;
ctx->s[2][i + 1] = datar;
}
for (i = 0; i < 256; i += 2)
{
do_encrypt (ctx, &datal, &datar);
ctx->s[3][i] = datal;
ctx->s[3][i + 1] = datar;
encrypt (ctx, &datal, &datar);
ctx->s[j][i] = datal;
ctx->s[j][i + 1] = datar;
}
/* Check for weak key. A weak key is a key in which a value in
the P-array (here c) occurs more than once per table. */
for (i = 0; i < 255; i++)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment