tags 328923 + patch thanks Hi,
Attached is a patch to remove the offending code: - md4c.c has been replaced with a GPLed implementation from Samba, by Andrew Tridgell. - md5c.c has been replaced by a free reimplementation (at least it looks DFSG-free for me) by L. Peter Deutsch. - logwtmp.c has simply been removed, it was redundant. opie compiles and links with the patch (and it looks rather trivial), but I have not actually tested it, as I don't run opie myself. /* Steinar */ -- Homepage: http://www.sesse.net/
diff -Nur opie-2.32/libopie/hash.c ../opie-2.32/libopie/hash.c --- opie-2.32/libopie/hash.c 1998-01-02 00:53:52.000000000 +0100 +++ ../opie-2.32/libopie/hash.c 2006-07-16 01:26:29.000000000 +0200 @@ -39,24 +39,21 @@ #endif /* 0 */ case 4: { - struct opiemdx_ctx mdx; UINT4 mdx_tmp[4]; - opiemd4init(&mdx); - opiemd4update(&mdx, (unsigned char *)x, 8); - opiemd4final((unsigned char *)mdx_tmp, &mdx); + mdfour((unsigned char *)mdx_tmp, (unsigned char *)x, 8); results[0] = mdx_tmp[0] ^ mdx_tmp[2]; results[1] = mdx_tmp[1] ^ mdx_tmp[3]; }; break; case 5: { - struct opiemdx_ctx mdx; + md5_state_t mdx; UINT4 mdx_tmp[4]; - opiemd5init(&mdx); - opiemd5update(&mdx, (unsigned char *)x, 8); - opiemd5final((unsigned char *)mdx_tmp, &mdx); + md5_init(&mdx); + md5_append(&mdx, (unsigned char *)x, 8); + md5_finish(&mdx, (unsigned char *)mdx_tmp); results[0] = mdx_tmp[0] ^ mdx_tmp[2]; results[1] = mdx_tmp[1] ^ mdx_tmp[3]; }; diff -Nur opie-2.32/libopie/hashlen.c ../opie-2.32/libopie/hashlen.c --- opie-2.32/libopie/hashlen.c 1998-01-02 00:53:53.000000000 +0100 +++ ../opie-2.32/libopie/hashlen.c 2006-07-16 01:26:29.000000000 +0200 @@ -17,7 +17,6 @@ VOIDRET opiehashlen FUNCTION((algorithm, in, out, n), int algorithm AND VOIDPTR in AND VOIDPTR out AND int n) { UINT4 *results = (UINT4 *)out; - struct opiemdx_ctx mdx; UINT4 mdx_tmp[4]; #if 0 SHA_INFO sha; @@ -34,18 +33,19 @@ break; #endif /* 0 */ case 4: - opiemd4init(&mdx); - opiemd4update(&mdx, (unsigned char *)in, n); - opiemd4final((unsigned char *)mdx_tmp, &mdx); + mdfour((unsigned char *)mdx_tmp, (unsigned char *)in, n); results[0] = mdx_tmp[0] ^ mdx_tmp[2]; results[1] = mdx_tmp[1] ^ mdx_tmp[3]; break; case 5: - opiemd5init(&mdx); - opiemd5update(&mdx, (unsigned char *)in, n); - opiemd5final((unsigned char *)mdx_tmp, &mdx); + { + md5_state_t mdx; + md5_init(&mdx); + md5_append(&mdx, (unsigned char *)in, n); + md5_finish(&mdx, (unsigned char *)mdx_tmp); results[0] = mdx_tmp[0] ^ mdx_tmp[2]; results[1] = mdx_tmp[1] ^ mdx_tmp[3]; break; + } } } diff -Nur opie-2.32/libopie/login.c ../opie-2.32/libopie/login.c --- opie-2.32/libopie/login.c 1998-01-02 00:53:54.000000000 +0100 +++ ../opie-2.32/libopie/login.c 2006-07-16 01:26:29.000000000 +0200 @@ -96,8 +96,7 @@ #endif /* !DISABLE_UTMP */ dowtmp: - opielogwtmp(line, name, host); - opielogwtmp(NULL, NULL, NULL); + logwtmp(line, name, host); dosetlogin: #if HAVE_SETLOGIN diff -Nur opie-2.32/libopie/Makefile.in ../opie-2.32/libopie/Makefile.in --- opie-2.32/libopie/Makefile.in 1998-01-02 00:53:49.000000000 +0100 +++ ../opie-2.32/libopie/Makefile.in 2006-07-16 01:26:29.000000000 +0200 @@ -12,7 +12,7 @@ # Modified by cmetz for OPIE 2.31. Added logwtmp.o # Created by cmetz for OPIE 2.3 using old Makefiles as a guide. -OBJS=md4c.o md5c.o atob8.o btoa8.o btoh.o challenge.o getsequence.o hash.o hashlen.o keycrunch.o lock.o lookup.o newseed.o parsechallenge.o passcheck.o passwd.o randomchallenge.o readpass.o unlock.o verify.o version.o btoe.o accessfile.o generator.o insecure.o getutmpentry.o readrec.o writerec.o login.o open.o logwtmp.o # sha.o +OBJS=md4c.o md5c.o atob8.o btoa8.o btoh.o challenge.o getsequence.o hash.o hashlen.o keycrunch.o lock.o lookup.o newseed.o parsechallenge.o passcheck.o passwd.o randomchallenge.o readpass.o unlock.o verify.o version.o btoe.o accessfile.o generator.o insecure.o getutmpentry.o readrec.o writerec.o login.o open.o # sha.o [EMAIL PROTECTED]@ CFLAGS=$(CFL) -I.. diff -Nur opie-2.32/libopie/md4c.c ../opie-2.32/libopie/md4c.c --- opie-2.32/libopie/md4c.c 1998-01-02 00:53:54.000000000 +0100 +++ ../opie-2.32/libopie/md4c.c 2006-07-16 01:26:29.000000000 +0200 @@ -1,267 +1,172 @@ -/* md4c.c: "RSA Data Security, Inc. MD4 Message-Digest Algorithm" +/* + Unix SMB/Netbios implementation. + Version 1.9. + a implementation of MD4 designed for use in the SMB authentication protocol + Copyright (C) Andrew Tridgell 1997 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +/* NOTE: This code makes no attempt to be fast! -%%% portions-copyright-cmetz-96 -Portions of this software are Copyright 1996-1998 by Craig Metz, All Rights -Reserved. The Inner Net License Version 2 applies to these portions of -the software. -You should have received a copy of the license with this software. If -you didn't get a copy, you may request one from <[EMAIL PROTECTED]>. - -Portions of this software are Copyright 1995 by Randall Atkinson and Dan -McDonald, All Rights Reserved. All Rights under this copyright are assigned -to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and -License Agreement applies to this software. - - History: - - Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. - Use the real memcpy() and memset(). Use unified context - structure. - Modified at NRL for OPIE 2.0. - Originally from RSADSI reference code. + It assumes that a int is at least 32 bits long */ -/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. +#include <string.h> - License to copy and use this software is granted provided that it - is identified as the "RSA Data Security, Inc. MD4 Message-Digest - Algorithm" in all material mentioning or referencing this software - or this function. - - License is also granted to make and use derivative works provided - that such works are identified as "derived from the RSA Data - Security, Inc. MD4 Message-Digest Algorithm" in all material - mentioning or referencing the derived work. - - RSA Data Security, Inc. makes no representations concerning either - the merchantability of this software or the suitability of this - software for any particular purpose. It is provided "as is" - without express or implied warranty of any kind. - - These notices must be retained in any copies of any part of this - documentation and/or software. - */ - -#include "opie_cfg.h" -#include "opie.h" - -/* Constants for MD4Transform routine. - */ -#define S11 3 -#define S12 7 -#define S13 11 -#define S14 19 -#define S21 3 -#define S22 5 -#define S23 9 -#define S24 13 -#define S31 3 -#define S32 9 -#define S33 11 -#define S34 15 - -static VOIDRET MD4Transform __P((UINT4[4], unsigned char[64])); -static VOIDRET Encode __P((unsigned char *, UINT4 *, unsigned int)); -static VOIDRET Decode __P((UINT4 *, unsigned char *, unsigned int)); +typedef unsigned int uint32; -static unsigned char 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 -}; - -/* F, G and H are basic MD4 functions. - */ -#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) - -/* ROTATE_LEFT rotates x left n bits. - */ -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) - -/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ -/* Rotation is separate from addition to prevent recomputation */ - -#define FF(a, b, c, d, x, s) { \ - (a) += F ((b), (c), (d)) + (x); \ - (a) = ROTATE_LEFT ((a), (s)); \ - } -#define GG(a, b, c, d, x, s) { \ - (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \ - (a) = ROTATE_LEFT ((a), (s)); \ - } -#define HH(a, b, c, d, x, s) { \ - (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \ - (a) = ROTATE_LEFT ((a), (s)); \ - } - -/* MD4 initialization. Begins an MD4 operation, writing a new context. - */ -VOIDRET opiemd4init FUNCTION((context), struct opiemdx_ctx *context) -{ - context->count[0] = context->count[1] = 0; +static uint32 A, B, C, D; - /* Load magic initialization constants. */ - context->state[0] = 0x67452301; - context->state[1] = 0xefcdab89; - context->state[2] = 0x98badcfe; - context->state[3] = 0x10325476; +static uint32 F(uint32 X, uint32 Y, uint32 Z) +{ + return (X&Y) | ((~X)&Z); } -/* MD4 block update operation. Continues an MD4 message-digest - operation, processing another message block, and updating the - context. - */ -VOIDRET opiemd4update FUNCTION((context, input, inputLen), struct opiemdx_ctx *context AND unsigned char *input AND unsigned int inputLen) +static uint32 G(uint32 X, uint32 Y, uint32 Z) { - unsigned int i, index, partLen; + return (X&Y) | (X&Z) | (Y&Z); +} - /* Compute number of bytes mod 64 */ - index = (unsigned int) ((context->count[0] >> 3) & 0x3F); - /* Update number of bits */ - if ((context->count[0] += ((UINT4) inputLen << 3)) - < ((UINT4) inputLen << 3)) - context->count[1]++; - context->count[1] += ((UINT4) inputLen >> 29); - - partLen = 64 - index; - - /* Transform as many times as possible. */ - if (inputLen >= partLen) { - memcpy((POINTER) & context->buffer[index], (POINTER) input, partLen); - MD4Transform(context->state, context->buffer); - - for (i = partLen; i + 63 < inputLen; i += 64) - MD4Transform(context->state, &input[i]); - - index = 0; - } else - i = 0; +static uint32 H(uint32 X, uint32 Y, uint32 Z) +{ + return X^Y^Z; +} - /* Buffer remaining input */ - memcpy((POINTER) & context->buffer[index], (POINTER) & input[i], inputLen - i); +static uint32 lshift(uint32 x, int s) +{ + x &= 0xFFFFFFFF; + return ((x<<s)&0xFFFFFFFF) | (x>>(32-s)); } -/* MD4 finalization. Ends an MD4 message-digest operation, writing the - the message digest and zeroizing the context. - */ -VOIDRET opiemd4final FUNCTION((digest, context), unsigned char *digest AND struct opiemdx_ctx *context) +#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s) +#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s) +#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s) + +/* this applies md4 to 64 byte chunks */ +static void mdfour64(uint32 *M) { - unsigned char bits[8]; - unsigned int index, padLen; + int j; + uint32 AA, BB, CC, DD; + uint32 X[16]; - /* Save number of bits */ - Encode(bits, context->count, 8); + for (j=0;j<16;j++) + X[j] = M[j]; - /* Pad out to 56 mod 64. */ - index = (unsigned int) ((context->count[0] >> 3) & 0x3f); - padLen = (index < 56) ? (56 - index) : (120 - index); - opiemd4update(context, PADDING, padLen); - - /* Append length (before padding) */ - opiemd4update(context, bits, 8); - /* Store state in digest */ - Encode(digest, context->state, 16); + AA = A; BB = B; CC = C; DD = D; - /* Zeroize sensitive information. */ - memset((POINTER) context, 0, sizeof(*context)); -} + ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7); + ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19); + ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7); + ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19); + ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7); + ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19); + ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7); + ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19); -/* MD4 basic transformation. Transforms state based on block. - */ -static VOIDRET MD4Transform FUNCTION((state, block), UINT4 state[4] AND unsigned char block[64]) -{ - UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5); + ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13); + ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5); + ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13); + ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5); + ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13); + ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5); + ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13); - Decode(x, block, 64); + ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9); + ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15); + ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9); + ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15); + ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9); + ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15); + ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9); + ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15); - /* Round 1 */ - FF(a, b, c, d, x[0], S11); /* 1 */ - FF(d, a, b, c, x[1], S12); /* 2 */ - FF(c, d, a, b, x[2], S13); /* 3 */ - FF(b, c, d, a, x[3], S14); /* 4 */ - FF(a, b, c, d, x[4], S11); /* 5 */ - FF(d, a, b, c, x[5], S12); /* 6 */ - FF(c, d, a, b, x[6], S13); /* 7 */ - FF(b, c, d, a, x[7], S14); /* 8 */ - FF(a, b, c, d, x[8], S11); /* 9 */ - FF(d, a, b, c, x[9], S12); /* 10 */ - FF(c, d, a, b, x[10], S13); /* 11 */ - FF(b, c, d, a, x[11], S14); /* 12 */ - FF(a, b, c, d, x[12], S11); /* 13 */ - FF(d, a, b, c, x[13], S12); /* 14 */ - FF(c, d, a, b, x[14], S13); /* 15 */ - FF(b, c, d, a, x[15], S14); /* 16 */ - - /* Round 2 */ - GG(a, b, c, d, x[0], S21); /* 17 */ - GG(d, a, b, c, x[4], S22); /* 18 */ - GG(c, d, a, b, x[8], S23); /* 19 */ - GG(b, c, d, a, x[12], S24); /* 20 */ - GG(a, b, c, d, x[1], S21); /* 21 */ - GG(d, a, b, c, x[5], S22); /* 22 */ - GG(c, d, a, b, x[9], S23); /* 23 */ - GG(b, c, d, a, x[13], S24); /* 24 */ - GG(a, b, c, d, x[2], S21); /* 25 */ - GG(d, a, b, c, x[6], S22); /* 26 */ - GG(c, d, a, b, x[10], S23); /* 27 */ - GG(b, c, d, a, x[14], S24); /* 28 */ - GG(a, b, c, d, x[3], S21); /* 29 */ - GG(d, a, b, c, x[7], S22); /* 30 */ - GG(c, d, a, b, x[11], S23); /* 31 */ - GG(b, c, d, a, x[15], S24); /* 32 */ - - /* Round 3 */ - HH(a, b, c, d, x[0], S31); /* 33 */ - HH(d, a, b, c, x[8], S32); /* 34 */ - HH(c, d, a, b, x[4], S33); /* 35 */ - HH(b, c, d, a, x[12], S34); /* 36 */ - HH(a, b, c, d, x[2], S31); /* 37 */ - HH(d, a, b, c, x[10], S32); /* 38 */ - HH(c, d, a, b, x[6], S33); /* 39 */ - HH(b, c, d, a, x[14], S34); /* 40 */ - HH(a, b, c, d, x[1], S31); /* 41 */ - HH(d, a, b, c, x[9], S32); /* 42 */ - HH(c, d, a, b, x[5], S33); /* 43 */ - HH(b, c, d, a, x[13], S34); /* 44 */ - HH(a, b, c, d, x[3], S31); /* 45 */ - HH(d, a, b, c, x[11], S32); /* 46 */ - HH(c, d, a, b, x[7], S33); /* 47 */ - HH(b, c, d, a, x[15], S34); /* 48 */ - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; + A += AA; B += BB; C += CC; D += DD; + + A &= 0xFFFFFFFF; B &= 0xFFFFFFFF; + C &= 0xFFFFFFFF; D &= 0xFFFFFFFF; - /* Zeroize sensitive information. */ - memset((POINTER) x, 0, sizeof(x)); + for (j=0;j<16;j++) + X[j] = 0; } -/* Encodes input (UINT4) into output (unsigned char). Assumes len is - a multiple of 4. - */ -static VOIDRET Encode FUNCTION((output, input, len), unsigned char *output AND UINT4 *input AND unsigned int len) +static void copy64(uint32 *M, unsigned char *in) { - unsigned int i, j; + int i; + + for (i=0;i<16;i++) + M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) | + (in[i*4+1]<<8) | (in[i*4+0]<<0); +} - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (unsigned char) (input[i] & 0xff); - output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff); - output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff); - output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff); - } +static void copy4(unsigned char *out,uint32 x) +{ + out[0] = x&0xFF; + out[1] = (x>>8)&0xFF; + out[2] = (x>>16)&0xFF; + out[3] = (x>>24)&0xFF; } -/* Decodes input (unsigned char) into output (UINT4). Assumes len is - a multiple of 4. - */ -static VOIDRET Decode FUNCTION((output, input, len), UINT4 *output AND unsigned char *input AND unsigned int len) +/* produce a md4 message digest from data of length n bytes */ +void mdfour(unsigned char *out, unsigned char *in, int n) { - unsigned int i, j; + unsigned char buf[128]; + uint32 M[16]; + uint32 b = n * 8; + int i; + + A = 0x67452301; + B = 0xefcdab89; + C = 0x98badcfe; + D = 0x10325476; + + while (n > 64) { + copy64(M, in); + mdfour64(M); + in += 64; + n -= 64; + } - for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) | - (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24); + for (i=0;i<128;i++) + buf[i] = 0; + memcpy(buf, in, n); + buf[n] = 0x80; + + if (n <= 55) { + copy4(buf+56, b); + copy64(M, buf); + mdfour64(M); + } else { + copy4(buf+120, b); + copy64(M, buf); + mdfour64(M); + copy64(M, buf+64); + mdfour64(M); + } + + for (i=0;i<128;i++) + buf[i] = 0; + copy64(M, buf); + + copy4(out, A); + copy4(out+4, B); + copy4(out+8, C); + copy4(out+12, D); + + A = B = C = D = 0; } + + diff -Nur opie-2.32/libopie/md5c.c ../opie-2.32/libopie/md5c.c --- opie-2.32/libopie/md5c.c 1998-01-02 00:53:55.000000000 +0100 +++ ../opie-2.32/libopie/md5c.c 2006-07-16 01:28:44.000000000 +0200 @@ -1,304 +1,385 @@ -/* md5c.c: "RSA Data Security, Inc. MD5 Message-Digest Algorithm" - "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" - -%%% portions-copyright-cmetz-96 -Portions of this software are Copyright 1996-1998 by Craig Metz, All Rights -Reserved. The Inner Net License Version 2 applies to these portions of -the software. -You should have received a copy of the license with this software. If -you didn't get a copy, you may request one from <[EMAIL PROTECTED]>. - -Portions of this software are Copyright 1995 by Randall Atkinson and Dan -McDonald, All Rights Reserved. All Rights under this copyright are assigned -to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and -License Agreement applies to this software. - - History: - - Modified by cmetz for OPIE 2.3. Changed PTR to VOIDPTR. - Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. - Don't play macro games with memset/memcpy. Renamed exported - functions to avoid conflicts. Use unified context structure. - Modified at NRL for OPIE 2.1. Minor autoconf mods. - Modified at NRL for OPIE 2.0. - Originally from RSADSI reference code. -*/ -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All - rights reserved. - - License to copy and use this software is granted provided that it - is identified as the "RSA Data Security, Inc. MD5 Message-Digest - Algorithm" in all material mentioning or referencing this software - or this function. - - License is also granted to make and use derivative works provided - that such works are identified as "derived from the RSA Data - Security, Inc. MD5 Message-Digest Algorithm" in all material - mentioning or referencing the derived work. - - RSA Data Security, Inc. makes no representations concerning either - the merchantability of this software or the suitability of this - software for any particular purpose. It is provided "as is" - without express or implied warranty of any kind. +/* + Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. - These notices must be retained in any copies of any part of this - documentation and/or software. - */ + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. -#include "opie_cfg.h" -#include "opie.h" + L. Peter Deutsch + [EMAIL PROTECTED] -/* Constants for MD5Transform routine. */ -#define S11 7 -#define S12 12 -#define S13 17 -#define S14 22 -#define S21 5 -#define S22 9 -#define S23 14 -#define S24 20 -#define S31 4 -#define S32 11 -#define S33 16 -#define S34 23 -#define S41 6 -#define S42 10 -#define S43 15 -#define S44 21 - -static VOIDRET MD5Transform __P((UINT4[4], unsigned char[64])); - -static unsigned char 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 -}; - +/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ /* - * Encodes input (UINT4) into output (unsigned char). - * Assumes len is a multiple of 4. - */ -static VOIDRET EEncode FUNCTION((output, input, len), unsigned char *output AND UINT4 *input AND unsigned int len) -{ - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (unsigned char) (input[i] & 0xff); - output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff); - output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff); - output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff); - } -} + Independent implementation of MD5 (RFC 1321). -/* - * Decodes input (unsigned char) into output (UINT4). - * Assumes len is a multiple of 4. + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + + The original and principal author of md5.c is L. Peter Deutsch + <[EMAIL PROTECTED]>. Other authors are noted in the change history + that follows (in reverse chronological order): + + 2006-07-16 shg Patched to work with opie. + 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order + either statically or dynamically; added missing #include <string.h> + in library. + 2002-03-11 lpd Corrected argument list for main(), and added int return + type, in test program and T value program. + 2002-02-21 lpd Added missing #include <stdio.h> in test program. + 2000-07-03 lpd Patched to eliminate warnings about "constant is + unsigned in ANSI C, signed in traditional"; made test program + self-checking. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. */ -static VOIDRET EDecode FUNCTION((output, input, len), UINT4 *output AND unsigned char *input AND unsigned int len) -{ - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) | - (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24); -} -/* F, G, H and I are basic MD5 functions. */ -#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define I(x, y, z) ((y) ^ ((x) | (~z))) +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ -/* ROTATE_LEFT rotates x left n bits. */ -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) +#include "opie.h" +#include <string.h> -/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. - Rotation is separate from addition to prevent recomputation. */ +#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ +#ifdef ARCH_IS_BIG_ENDIAN +# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) +#else +# define BYTE_ORDER 0 +#endif + +#define T_MASK ((md5_word_t)~0) +#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) +#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) +#define T3 0x242070db +#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) +#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) +#define T6 0x4787c62a +#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) +#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) +#define T9 0x698098d8 +#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) +#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) +#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) +#define T13 0x6b901122 +#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) +#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) +#define T16 0x49b40821 +#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) +#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) +#define T19 0x265e5a51 +#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) +#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) +#define T22 0x02441453 +#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) +#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) +#define T25 0x21e1cde6 +#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) +#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) +#define T28 0x455a14ed +#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) +#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) +#define T31 0x676f02d9 +#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) +#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) +#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) +#define T35 0x6d9d6122 +#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) +#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) +#define T38 0x4bdecfa9 +#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) +#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) +#define T41 0x289b7ec6 +#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) +#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) +#define T44 0x04881d05 +#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) +#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) +#define T47 0x1fa27cf8 +#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) +#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) +#define T50 0x432aff97 +#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) +#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) +#define T53 0x655b59c3 +#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) +#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) +#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) +#define T57 0x6fa87e4f +#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) +#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) +#define T60 0x4e0811a1 +#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) +#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) +#define T63 0x2ad7d2bb +#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) -#define FF(a, b, c, d, x, s, ac) { \ - (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } - -#define GG(a, b, c, d, x, s, ac) { \ - (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } - -#define HH(a, b, c, d, x, s, ac) { \ - (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } - -#define II(a, b, c, d, x, s, ac) { \ - (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -/* MD5 initialization. Begins an MD5 operation, writing a new context. */ -VOIDRET opiemd5init FUNCTION((context), struct opiemdx_ctx *context) +static void +md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) { - context->count[0] = context->count[1] = 0; - /* Load magic initialization constants. */ - context->state[0] = 0x67452301; - context->state[1] = 0xefcdab89; - context->state[2] = 0x98badcfe; - context->state[3] = 0x10325476; + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; +#if BYTE_ORDER > 0 + /* Define storage only for big-endian CPUs. */ + md5_word_t X[16]; +#else + /* Define storage for little-endian or both types of CPUs. */ + md5_word_t xbuf[16]; + const md5_word_t *X; +#endif + + { +#if BYTE_ORDER == 0 + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static const int w = 1; + + if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ +#endif +#if BYTE_ORDER <= 0 /* little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if (!((data - (const md5_byte_t *)0) & 3)) { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } + } +#endif +#if BYTE_ORDER == 0 + else /* dynamic big-endian */ +#endif +#if BYTE_ORDER >= 0 /* big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const md5_byte_t *xp = data; + int i; + +# if BYTE_ORDER == 0 + X = xbuf; /* (dynamic only) */ +# else +# define xbuf X /* (static only) */ +# endif + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } +#endif + } + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; } -/* - * MD5 block update operation. Continues an MD5 message-digest - * operation, processing another message block, and updating the - * context. - */ -VOIDRET opiemd5update FUNCTION((context, input, inputLen), struct opiemdx_ctx *context AND unsigned char *input AND unsigned int inputLen) +void +md5_init(md5_state_t *pms) { - unsigned int i, index, partLen; - - /* Compute number of bytes mod 64 */ - index = (unsigned int) ((context->count[0] >> 3) & 0x3F); - - /* Update number of bits */ - if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3)) - context->count[1]++; - - context->count[1] += ((UINT4) inputLen >> 29); - partLen = 64 - index; - - /* Transform as many times as possible. */ - if (inputLen >= partLen) { - memcpy((VOIDPTR)&context->buffer[index], (VOIDPTR)input, partLen); - MD5Transform(context->state, context->buffer); - - for (i = partLen; i + 63 < inputLen; i += 64) - MD5Transform(context->state, &input[i]); - - index = 0; - } else - i = 0; - - /* Buffer remaining input */ - memcpy((VOIDPTR) & context->buffer[index], - (VOIDPTR) & input[i], - inputLen - i); + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; + pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; + pms->abcd[3] = 0x10325476; } -/* MD5 finalization. Ends an MD5 message-digest operation, writing the - the message digest and zeroizing the context. - */ -VOIDRET opiemd5final FUNCTION((digest, context), unsigned char *digest AND struct opiemdx_ctx *context) +void +md5_append(md5_state_t *pms, const md5_byte_t *data, unsigned nbytes) { - unsigned char bits[8]; - unsigned int index, padLen; - - /* Save number of bits */ - EEncode(bits, context->count, 8); - - /* Pad out to 56 mod 64. */ - index = (unsigned int) ((context->count[0] >> 3) & 0x3f); - padLen = (index < 56) ? (56 - index) : (120 - index); - opiemd5update(context, PADDING, padLen); - - /* Append length (before padding) */ - opiemd5update(context, bits, 8); - - /* Store state in digest */ - EEncode(digest, context->state, 16); - - /* Zeroize sensitive information. */ - memset((VOIDPTR) context, 0, sizeof(*context)); + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); } -/* MD5 basic transformation. Transforms state based on block. */ -static VOIDRET MD5Transform FUNCTION((state, block), UINT4 state[4] AND unsigned char block[64]) +void +md5_finish(md5_state_t *pms, md5_byte_t digest[16]) { - UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; - - EDecode(x, block, 64); - - /* Round 1 */ - FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ - FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ - FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ - FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ - FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ - FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ - FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ - FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ - FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ - FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ - FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ - FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ - FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ - FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ - FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ - FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ - - /* Round 2 */ - GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ - GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ - GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ - GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ - GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ - GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ - GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ - GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ - GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ - GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ - GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ - GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ - GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ - GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ - GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ - GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ - - /* Round 3 */ - HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ - HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ - HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ - HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ - HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ - HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ - HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ - HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ - HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ - HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ - HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ - HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ - HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ - HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ - HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ - HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ - - /* Round 4 */ - II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ - II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ - II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ - II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ - II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ - II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ - II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ - II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ - II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ - II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ - II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ - II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ - II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ - II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ - II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ - II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - - /* Zeroize sensitive information. */ - memset((VOIDPTR)x, 0, sizeof(x)); + static const md5_byte_t pad[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 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); } diff -Nur opie-2.32/opie.h ../opie-2.32/opie.h --- opie-2.32/opie.h 2006-07-16 01:29:28.000000000 +0200 +++ ../opie-2.32/opie.h 2006-07-16 01:28:55.000000000 +0200 @@ -159,14 +159,17 @@ #define OPIE_PRINCIPAL_MAX 32 #endif /* OPIE_PRINCIPAL_MAX */ -#include <stdint.h> -#define UINT4 uint32_t - -struct opiemdx_ctx { - UINT4 state[4]; - UINT4 count[2]; - unsigned char buffer[64]; -}; +#ifndef __alpha +#define UINT4 unsigned long +#else /* __alpha */ +#define UINT4 unsigned int +#endif /* __alpha */ + +typedef struct md5_state_s { + UINT4 count[2]; /* message length in bits, lsw first */ + UINT4 abcd[4]; /* digest buffer */ + unsigned char buf[64]; /* accumulate block */ +} md5_state_t; #ifndef SEEK_SET #define SEEK_SET 0 @@ -194,12 +197,10 @@ int opiekeycrunch __P((int, char *, char *, char *)); int opielock __P((char *)); int opielookup __P((struct opie *,char *)); -VOIDRET opiemd4init __P((struct opiemdx_ctx *)); -VOIDRET opiemd4update __P((struct opiemdx_ctx *,unsigned char *,unsigned int)); -VOIDRET opiemd4final __P((unsigned char *,struct opiemdx_ctx *)); -VOIDRET opiemd5init __P((struct opiemdx_ctx *)); -VOIDRET opiemd5update __P((struct opiemdx_ctx *,unsigned char *,unsigned int)); -VOIDRET opiemd5final __P((unsigned char *,struct opiemdx_ctx *)); +VOIDRET mdfour __P((unsigned char *out, unsigned char *in, int n)); +VOIDRET md5_init __P((md5_state_t *)); +VOIDRET md5_append __P((md5_state_t *,const unsigned char *,unsigned int)); +VOIDRET md5_finish __P((md5_state_t *,unsigned char *)); int opiepasscheck __P((char *)); VOIDRET opierandomchallenge __P((char *)); char * opieskipspace __P((register char *));