| * "counter". The function then returns the sum of all produced |
* "counter". The function then returns the sum of all produced |
| * 32-bit words, in an "unum32". That sum prevents the compiler from |
* 32-bit words, in an "unum32". That sum prevents the compiler from |
| * optimizing out part of the computation. |
* optimizing out part of the computation. |
| |
* |
| |
* If SOSEMANUK_ECRYPT is defined, the input and output buffers are |
| |
* provided also, and this function performs the XOR. The input and |
| |
* output buffers are assumed to be 32-bit aligned. |
| */ |
*/ |
| #if defined SOSEMANUK_ECRYPT |
#if defined SOSEMANUK_ECRYPT |
| static void |
static void |
| sosemanuk_internal(ECRYPT_ctx *rc, u8 *dst) |
sosemanuk_internal(ECRYPT_ctx *rc, const u32 *src, u32 *dst) |
| #elif defined SOSEMANUK_SPEED |
#elif defined SOSEMANUK_SPEED |
| static unum32 |
static unum32 |
| sosemanuk_internal(sosemanuk_run_context *rc, unsigned long counter) |
sosemanuk_internal(sosemanuk_run_context *rc, unsigned long counter) |
| #else |
#else |
| |
|
| #ifdef SOSEMANUK_ECRYPT |
#ifdef SOSEMANUK_ECRYPT |
| #define OUTWORD_BASE dst |
#define SRD(S, x0, x1, x2, x3, ooff) do { \ |
| |
PSPIN(u0, u1, u2, u3); \ |
| |
S(u0, u1, u2, u3, u4); \ |
| |
PSPOUT(u ## x0, u ## x1, u ## x2, u ## x3); \ |
| |
dst[(ooff / 4)] = src[(ooff / 4)] \ |
| |
^ U32TO32_LITTLE(u ## x0 ^ v0); \ |
| |
dst[(ooff / 4) + 1] = src[(ooff / 4) + 1] \ |
| |
^ U32TO32_LITTLE(u ## x1 ^ v1); \ |
| |
dst[(ooff / 4) + 2] = src[(ooff / 4) + 2] \ |
| |
^ U32TO32_LITTLE(u ## x2 ^ v2); \ |
| |
dst[(ooff / 4) + 3] = src[(ooff / 4) + 3] \ |
| |
^ U32TO32_LITTLE(u ## x3 ^ v3); \ |
| |
POUT((unsigned char *)dst + ooff); \ |
| |
} while (0) |
| #else |
#else |
| #define OUTWORD_BASE (rc->buf) |
#define OUTWORD_BASE (rc->buf) |
| #endif |
|
| |
|
| #define SRD(S, x0, x1, x2, x3, ooff) do { \ |
#define SRD(S, x0, x1, x2, x3, ooff) do { \ |
| PSPIN(u0, u1, u2, u3); \ |
PSPIN(u0, u1, u2, u3); \ |
| S(u0, u1, u2, u3, u4); \ |
S(u0, u1, u2, u3, u4); \ |
| encode32le(OUTWORD_BASE + ooff + 12, u ## x3 ^ v3); \ |
encode32le(OUTWORD_BASE + ooff + 12, u ## x3 ^ v3); \ |
| POUT(OUTWORD_BASE + ooff); \ |
POUT(OUTWORD_BASE + ooff); \ |
| } while (0) |
} while (0) |
| |
#endif |
| |
|
| #endif |
#endif |
| |
|
| #endif |
#endif |
| } |
} |
| |
|
| |
#if !defined SOSEMANUK_ECRYPT && !defined SOSEMANUK_SPEED |
| |
|
| /* |
/* |
| * Combine buffers in1[] and in2[] by XOR, result in out[]. The length |
* Combine buffers in1[] and in2[] by XOR, result in out[]. The length |
| * is "data_len" (in bytes). Partial overlap of out[] with either in1[] |
* is "data_len" (in bytes). Partial overlap of out[] with either in1[] |
| * or in2[] is not allowed. Total overlap (out == in1 and/or out == in2) |
* or in2[] is not allowed. Total overlap (out == in1 and/or out == in2) |
| * is allowed. |
* is allowed. |
| |
* |
| |
* This function tries to be smart and to perform 32-bit accesses whenever |
| |
* safe (aligned pointers). According to the Holy Standard From ISO, this |
| |
* is heretic; but it works everywhere (hopefully). |
| */ |
*/ |
| static INLINE void |
static INLINE void |
| xorbuf(const unsigned char *in1, const unsigned char *in2, |
xorbuf(const unsigned char *in1, const unsigned char *in2, |
| unsigned char *out, size_t data_len) |
unsigned char *out, size_t data_len) |
| { |
{ |
| |
unum32 *s1, *s2, *d; |
| |
size_t tl; |
| |
|
| |
if (!(((unsigned)in1 | (unsigned)in2 | (unsigned)out) & 0x03)) { |
| |
s1 = (unum32 *)in1; |
| |
s2 = (unum32 *)in2; |
| |
d = (unum32 *)out; |
| |
tl = data_len >> 2; |
| |
while (tl -- > 0) |
| |
*d ++ = *s1 ++ ^ *s2 ++; |
| |
|
| |
switch (data_len & (size_t)0x03) { |
| |
case 0x03: |
| |
out[data_len - 3] = |
| |
in1[data_len - 3] ^ in2[data_len - 3]; |
| |
/* fall through */ |
| |
case 0x02: |
| |
out[data_len - 2] = |
| |
in1[data_len - 2] ^ in2[data_len - 2]; |
| |
/* fall through */ |
| |
case 0x01: |
| |
out[data_len - 1] = |
| |
in1[data_len - 1] ^ in2[data_len - 1]; |
| |
} |
| |
} else { |
| while (data_len -- > 0) |
while (data_len -- > 0) |
| *out ++ = *in1 ++ ^ *in2 ++; |
*out ++ = *in1 ++ ^ *in2 ++; |
| } |
} |
| |
} |
| |
|
| |
#endif |
| |
|
| /* ======================================================================== */ |
/* ======================================================================== */ |
| /* |
/* |
| (void)action; |
(void)action; |
| |
|
| while (msglen > 0) { |
while (msglen > 0) { |
| unsigned char tbuf[ECRYPT_BLOCKLENGTH]; |
u32 ibuf[ECRYPT_BLOCKLENGTH / 4]; |
| |
u32 obuf[ECRYPT_BLOCKLENGTH / 4]; |
| size_t len; |
size_t len; |
| |
|
| sosemanuk_internal(ctx, tbuf); |
len = sizeof ibuf; |
| len = sizeof tbuf; |
|
| if (len > msglen) |
if (len > msglen) |
| len = msglen; |
len = msglen; |
| xorbuf(input, tbuf, output, len); |
memcpy(ibuf, input, len); |
| |
sosemanuk_internal(ctx, ibuf, obuf); |
| |
memcpy(output, obuf, len); |
| input += len; |
input += len; |
| output += len; |
output += len; |
| msglen -= len; |
msglen -= len; |
| void |
void |
| ECRYPT_keystream_bytes(ECRYPT_ctx *ctx, u8 *keystream, u32 length) |
ECRYPT_keystream_bytes(ECRYPT_ctx *ctx, u8 *keystream, u32 length) |
| { |
{ |
| |
static const u32 zb[ECRYPT_BLOCKLENGTH]; |
| |
|
| while (length > 0) { |
while (length > 0) { |
| |
u32 tbuf[ECRYPT_BLOCKLENGTH / 4]; |
| |
|
| |
sosemanuk_internal(ctx, zb, tbuf); |
| if (length >= ECRYPT_BLOCKLENGTH) { |
if (length >= ECRYPT_BLOCKLENGTH) { |
| sosemanuk_internal(ctx, keystream); |
memcpy(keystream, tbuf, ECRYPT_BLOCKLENGTH); |
| keystream += ECRYPT_BLOCKLENGTH; |
keystream += ECRYPT_BLOCKLENGTH; |
| length -= ECRYPT_BLOCKLENGTH; |
length -= ECRYPT_BLOCKLENGTH; |
| } else { |
} else { |
| unsigned char tbuf[ECRYPT_BLOCKLENGTH]; |
|
| |
|
| sosemanuk_internal(ctx, tbuf); |
|
| memcpy(keystream, tbuf, length); |
memcpy(keystream, tbuf, length); |
| return; |
return; |
| } |
} |
| (void)action; |
(void)action; |
| |
|
| while (blocks -- > 0) { |
while (blocks -- > 0) { |
| unsigned char tbuf[ECRYPT_BLOCKLENGTH]; |
sosemanuk_internal(ctx, (u32 *)input, (u32 *)output); |
| |
|
| sosemanuk_internal(ctx, tbuf); |
|
| xorbuf(input, tbuf, output, ECRYPT_BLOCKLENGTH); |
|
| input += ECRYPT_BLOCKLENGTH; |
input += ECRYPT_BLOCKLENGTH; |
| output += ECRYPT_BLOCKLENGTH; |
output += ECRYPT_BLOCKLENGTH; |
| } |
} |
| void |
void |
| ECRYPT_keystream_blocks(ECRYPT_ctx *ctx, u8 *keystream, u32 blocks) |
ECRYPT_keystream_blocks(ECRYPT_ctx *ctx, u8 *keystream, u32 blocks) |
| { |
{ |
| |
static const u32 zb[ECRYPT_BLOCKLENGTH / 4]; |
| |
|
| while (blocks -- > 0) { |
while (blocks -- > 0) { |
| sosemanuk_internal(ctx, keystream); |
sosemanuk_internal(ctx, zb, (u32 *)keystream); |
| keystream += ECRYPT_BLOCKLENGTH; |
keystream += ECRYPT_BLOCKLENGTH; |
| } |
} |
| } |
} |