/* Editor Settings: expandtabs and use 4 spaces for indentation
* ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: *
* -*- mode: c, c-basic-offset: 4 -*- */
/*
* Copyright Likewise Software 2004-2008
* All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the license, or (at
* your option) any later version.
*
* This library 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 Lesser
* General Public License for more details. You should have received a copy
* of the GNU Lesser General Public License along with this program. If
* not, see .
*
* LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
* TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
* WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
* TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
* LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU
* HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
* TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
* license@likewisesoftware.com
*/
#include
#include
#include
#include
static const
UINT8 padding[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static void md4transform(struct md4context *ctx);
static void enc(unsigned char *out, unsigned int *in, size_t len)
{
int i, j;
for (i = 0, j = 0; j < len; i++, j+=4) {
out[j] = (unsigned char)(in[i] & 0xff);
out[j+1] = (unsigned char)((in[i] >> 8) & 0xff);
out[j+2] = (unsigned char)((in[i] >> 16) & 0xff);
out[j+3] = (unsigned char)((in[i] >> 24) & 0xff);
}
}
static void dec(unsigned int *out, unsigned char *in, size_t len)
{
int i, j;
for (i = 0, j = 0; j < len; i++, j+=4) {
out[i] = (unsigned int)in[j] |
((unsigned int)in[j+1]) << 8 |
((unsigned int)in[j+2]) << 16 |
((unsigned int)in[j+3]) << 24;
}
}
void md4init(struct md4context *ctx)
{
if (!ctx) return;
ctx->A = 0x67452301;
ctx->B = 0xefcdab89;
ctx->C = 0x98badcfe;
ctx->D = 0x10325476;
ctx->count[0] = 0;
ctx->count[1] = 0;
memset(ctx->block, 0, sizeof(ctx->block));
}
void md4update(struct md4context *ctx, const unsigned char *buf,
size_t len)
{
int i, index, block_len;
index = (int)((ctx->count[0] >> 3) & 0x3f);
ctx->count[0] += len * 8;
if (ctx->count[0] < len * 8) ctx->count[1]++;
ctx->count[1] += len >> (32-8);
block_len = 64 - index;
if (len >= block_len) {
memcpy(&ctx->block[index], buf, block_len);
md4transform(ctx);
for (i = block_len; i + 63 < len; i+=64) {
memcpy(ctx->block, &buf[i], sizeof(ctx->block));
md4transform(ctx);
}
index = 0;
} else {
i = 0;
}
memcpy(&ctx->block[index], &buf[i], len - i);
}
static void md4transform(struct md4context *ctx)
{
unsigned int A, B, C, D;
int i, j;
unsigned int X[16] = {0};
for (i = 0, j = 0; i < sizeof(X) / sizeof(X[0]); i++, j+=4) {
dec(&X[i], &ctx->block[j], 4);
}
A = ctx->A;
B = ctx->B;
C = ctx->C;
D = ctx->D;
#define LROT(v, n) (((v) << (n)) | ((v) >> (32-(n))))
/* Round 1 */
#define F(x, y, z) (((x)&(y)) | ((~x)&(z)))
#define Fx(a,b,c,d, k,s) ((a) = LROT(((a) + F((b),(c),(d)) + X[k]), s))
Fx(A,B,C,D, 0, 3);
Fx(D,A,B,C, 1, 7);
Fx(C,D,A,B, 2,11);
Fx(B,C,D,A, 3,19);
Fx(A,B,C,D, 4, 3);
Fx(D,A,B,C, 5, 7);
Fx(C,D,A,B, 6,11);
Fx(B,C,D,A, 7,19);
Fx(A,B,C,D, 8, 3);
Fx(D,A,B,C, 9, 7);
Fx(C,D,A,B, 10,11);
Fx(B,C,D,A, 11,19);
Fx(A,B,C,D, 12, 3);
Fx(D,A,B,C, 13, 7);
Fx(C,D,A,B, 14,11);
Fx(B,C,D,A, 15,19);
/* Round 2 */
#define G(x, y, z) (((x)&(y)) | ((x)&(z)) | ((y)&(z)))
#define Gx(a,b,c,d, k,s) ((a) = LROT(((a) + G((b),(c),(d)) + X[k] + 0x5A827999), s))
Gx(A,B,C,D, 0, 3);
Gx(D,A,B,C, 4, 5);
Gx(C,D,A,B, 8, 9);
Gx(B,C,D,A, 12,13);
Gx(A,B,C,D, 1, 3);
Gx(D,A,B,C, 5, 5);
Gx(C,D,A,B, 9, 9);
Gx(B,C,D,A, 13,13);
Gx(A,B,C,D, 2, 3);
Gx(D,A,B,C, 6, 5);
Gx(C,D,A,B, 10, 9);
Gx(B,C,D,A, 14,13);
Gx(A,B,C,D, 3, 3);
Gx(D,A,B,C, 7, 5);
Gx(C,D,A,B, 11, 9);
Gx(B,C,D,A, 15,13);
/* Round 3 */
#define H(x, y, z) ((x)^(y)^(z))
#define Hx(a,b,c,d, k,s) ((a) = LROT(((a) + H((b),(c),(d)) + X[k] + 0x6ED9EBA1), s))
Hx(A,B,C,D, 0, 3);
Hx(D,A,B,C, 8, 9);
Hx(C,D,A,B, 4,11);
Hx(B,C,D,A, 12,15);
Hx(A,B,C,D, 2, 3);
Hx(D,A,B,C, 10, 9);
Hx(C,D,A,B, 6,11);
Hx(B,C,D,A, 14,15);
Hx(A,B,C,D, 1, 3);
Hx(D,A,B,C, 9, 9);
Hx(C,D,A,B, 5,11);
Hx(B,C,D,A, 13,15);
Hx(A,B,C,D, 3, 3);
Hx(D,A,B,C, 11, 9);
Hx(C,D,A,B, 7,11);
Hx(B,C,D,A, 15,15);
ctx->A += A;
ctx->B += B;
ctx->C += C;
ctx->D += D;
memset(X, 0, sizeof(X));
}
void md4final(struct md4context *ctx, unsigned char digest[16])
{
unsigned char b[8];
unsigned int index, padding_len;
enc(b, ctx->count, sizeof(b));
index = (unsigned int)((ctx->count[0] >> 3) & 0x3f);
padding_len = (index < 56) ? (56 - index) : (120 - index);
md4update(ctx, padding, padding_len);
md4update(ctx, b, sizeof(b));
enc(&digest[0], &ctx->A, 4);
enc(&digest[4], &ctx->B, 4);
enc(&digest[8], &ctx->C, 4);
enc(&digest[12], &ctx->D, 4);
memset(ctx, 0, sizeof(*ctx));
}
void md4(unsigned char out[16], const unsigned char *in, size_t len)
{
struct md4context ctx;
md4init(&ctx);
md4update(&ctx, in, len);
md4final(&ctx, out);
memset(&ctx, 0, sizeof(struct md4context));
}
/*
local variables:
mode: c
c-basic-offset: 4
indent-tabs-mode: nil
tab-width: 4
end:
*/