Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34215415
md4.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
7 KB
Subscribers
None
md4.c
View Options
/* md4.c - MD4 Message-Digest Algorithm
* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
* Libgcrypt 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.
*
* Libgcrypt 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* Based on md5.c in libgcrypt, but rewritten to compute md4 checksums
* using a public domain md4 implementation with the following comments:
*
* Modified by Wei Dai from Andrew M. Kuchling's md4.c
* The original code and all modifications are in the public domain.
*
* This is the original introductory comment:
*
* md4.c : MD4 hash algorithm.
*
* Part of the Python Cryptography Toolkit, version 1.1
*
* Distribute and use freely; there are no restrictions on further
* dissemination and usage except those imposed by the laws of your
* country of residence.
*
*/
/* MD4 test suite:
* MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0
* MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24
* MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d
* MD4 ("message digest") = d9130a8164549fe818874806e1c7014b
* MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9
* MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
* 043f8582f241db351ce627e153e7f0e4
* MD4 ("123456789012345678901234567890123456789012345678901234567890123456
* 78901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536
*/
#include
<config.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
"g10lib.h"
#include
"cipher.h"
#include
"bithelp.h"
typedef
struct
{
u32
A
,
B
,
C
,
D
;
/* chaining variables */
u32
nblocks
;
byte
buf
[
64
];
int
count
;
}
MD4_CONTEXT
;
static
void
md4_init
(
void
*
context
)
{
MD4_CONTEXT
*
ctx
=
context
;
ctx
->
A
=
0x67452301
;
ctx
->
B
=
0xefcdab89
;
ctx
->
C
=
0x98badcfe
;
ctx
->
D
=
0x10325476
;
ctx
->
nblocks
=
0
;
ctx
->
count
=
0
;
}
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
/****************
* transform 64 bytes
*/
static
void
transform
(
MD4_CONTEXT
*
ctx
,
const
unsigned
char
*
data
)
{
u32
in
[
16
];
register
u32
A
=
ctx
->
A
;
register
u32
B
=
ctx
->
B
;
register
u32
C
=
ctx
->
C
;
register
u32
D
=
ctx
->
D
;
#ifdef WORDS_BIGENDIAN
{
int
i
;
byte
*
p2
,
*
p1
;
for
(
i
=
0
,
p1
=
data
,
p2
=
(
byte
*
)
in
;
i
<
16
;
i
++
,
p2
+=
4
)
{
p2
[
3
]
=
*
p1
++
;
p2
[
2
]
=
*
p1
++
;
p2
[
1
]
=
*
p1
++
;
p2
[
0
]
=
*
p1
++
;
}
}
#else
memcpy
(
in
,
data
,
64
);
#endif
/* Round 1. */
#define function(a,b,c,d,k,s) a=rol(a+F(b,c,d)+in[k],s);
function
(
A
,
B
,
C
,
D
,
0
,
3
);
function
(
D
,
A
,
B
,
C
,
1
,
7
);
function
(
C
,
D
,
A
,
B
,
2
,
11
);
function
(
B
,
C
,
D
,
A
,
3
,
19
);
function
(
A
,
B
,
C
,
D
,
4
,
3
);
function
(
D
,
A
,
B
,
C
,
5
,
7
);
function
(
C
,
D
,
A
,
B
,
6
,
11
);
function
(
B
,
C
,
D
,
A
,
7
,
19
);
function
(
A
,
B
,
C
,
D
,
8
,
3
);
function
(
D
,
A
,
B
,
C
,
9
,
7
);
function
(
C
,
D
,
A
,
B
,
10
,
11
);
function
(
B
,
C
,
D
,
A
,
11
,
19
);
function
(
A
,
B
,
C
,
D
,
12
,
3
);
function
(
D
,
A
,
B
,
C
,
13
,
7
);
function
(
C
,
D
,
A
,
B
,
14
,
11
);
function
(
B
,
C
,
D
,
A
,
15
,
19
);
#undef function
/* Round 2. */
#define function(a,b,c,d,k,s) a=rol(a+G(b,c,d)+in[k]+0x5a827999,s);
function
(
A
,
B
,
C
,
D
,
0
,
3
);
function
(
D
,
A
,
B
,
C
,
4
,
5
);
function
(
C
,
D
,
A
,
B
,
8
,
9
);
function
(
B
,
C
,
D
,
A
,
12
,
13
);
function
(
A
,
B
,
C
,
D
,
1
,
3
);
function
(
D
,
A
,
B
,
C
,
5
,
5
);
function
(
C
,
D
,
A
,
B
,
9
,
9
);
function
(
B
,
C
,
D
,
A
,
13
,
13
);
function
(
A
,
B
,
C
,
D
,
2
,
3
);
function
(
D
,
A
,
B
,
C
,
6
,
5
);
function
(
C
,
D
,
A
,
B
,
10
,
9
);
function
(
B
,
C
,
D
,
A
,
14
,
13
);
function
(
A
,
B
,
C
,
D
,
3
,
3
);
function
(
D
,
A
,
B
,
C
,
7
,
5
);
function
(
C
,
D
,
A
,
B
,
11
,
9
);
function
(
B
,
C
,
D
,
A
,
15
,
13
);
#undef function
/* Round 3. */
#define function(a,b,c,d,k,s) a=rol(a+H(b,c,d)+in[k]+0x6ed9eba1,s);
function
(
A
,
B
,
C
,
D
,
0
,
3
);
function
(
D
,
A
,
B
,
C
,
8
,
9
);
function
(
C
,
D
,
A
,
B
,
4
,
11
);
function
(
B
,
C
,
D
,
A
,
12
,
15
);
function
(
A
,
B
,
C
,
D
,
2
,
3
);
function
(
D
,
A
,
B
,
C
,
10
,
9
);
function
(
C
,
D
,
A
,
B
,
6
,
11
);
function
(
B
,
C
,
D
,
A
,
14
,
15
);
function
(
A
,
B
,
C
,
D
,
1
,
3
);
function
(
D
,
A
,
B
,
C
,
9
,
9
);
function
(
C
,
D
,
A
,
B
,
5
,
11
);
function
(
B
,
C
,
D
,
A
,
13
,
15
);
function
(
A
,
B
,
C
,
D
,
3
,
3
);
function
(
D
,
A
,
B
,
C
,
11
,
9
);
function
(
C
,
D
,
A
,
B
,
7
,
11
);
function
(
B
,
C
,
D
,
A
,
15
,
15
);
/* Put checksum in context given as argument. */
ctx
->
A
+=
A
;
ctx
->
B
+=
B
;
ctx
->
C
+=
C
;
ctx
->
D
+=
D
;
}
/* The routine updates the message-digest context to
* account for the presence of each of the characters inBuf[0..inLen-1]
* in the message whose digest is being computed.
*/
static
void
md4_write
(
void
*
context
,
const
void
*
inbuf_arg
,
size_t
inlen
)
{
const
unsigned
char
*
inbuf
=
inbuf_arg
;
MD4_CONTEXT
*
hd
=
context
;
if
(
hd
->
count
==
64
)
/* flush the buffer */
{
transform
(
hd
,
hd
->
buf
);
_gcry_burn_stack
(
80
+
6
*
sizeof
(
void
*
));
hd
->
count
=
0
;
hd
->
nblocks
++
;
}
if
(
!
inbuf
)
return
;
if
(
hd
->
count
)
{
for
(
;
inlen
&&
hd
->
count
<
64
;
inlen
--
)
hd
->
buf
[
hd
->
count
++
]
=
*
inbuf
++
;
md4_write
(
hd
,
NULL
,
0
);
if
(
!
inlen
)
return
;
}
_gcry_burn_stack
(
80
+
6
*
sizeof
(
void
*
));
while
(
inlen
>=
64
)
{
transform
(
hd
,
inbuf
);
hd
->
count
=
0
;
hd
->
nblocks
++
;
inlen
-=
64
;
inbuf
+=
64
;
}
for
(
;
inlen
&&
hd
->
count
<
64
;
inlen
--
)
hd
->
buf
[
hd
->
count
++
]
=
*
inbuf
++
;
}
/* The routine final terminates the message-digest computation and
* ends with the desired message digest in mdContext->digest[0...15].
* The handle is prepared for a new MD4 cycle.
* Returns 16 bytes representing the digest.
*/
static
void
md4_final
(
void
*
context
)
{
MD4_CONTEXT
*
hd
=
context
;
u32
t
,
msb
,
lsb
;
byte
*
p
;
md4_write
(
hd
,
NULL
,
0
);
/* flush */
;
t
=
hd
->
nblocks
;
/* multiply by 64 to make a byte count */
lsb
=
t
<<
6
;
msb
=
t
>>
26
;
/* add the count */
t
=
lsb
;
if
(
(
lsb
+=
hd
->
count
)
<
t
)
msb
++
;
/* multiply by 8 to make a bit count */
t
=
lsb
;
lsb
<<=
3
;
msb
<<=
3
;
msb
|=
t
>>
29
;
if
(
hd
->
count
<
56
)
/* enough room */
{
hd
->
buf
[
hd
->
count
++
]
=
0x80
;
/* pad */
while
(
hd
->
count
<
56
)
hd
->
buf
[
hd
->
count
++
]
=
0
;
/* pad */
}
else
/* need one extra block */
{
hd
->
buf
[
hd
->
count
++
]
=
0x80
;
/* pad character */
while
(
hd
->
count
<
64
)
hd
->
buf
[
hd
->
count
++
]
=
0
;
md4_write
(
hd
,
NULL
,
0
);
/* flush */
;
memset
(
hd
->
buf
,
0
,
56
);
/* fill next block with zeroes */
}
/* append the 64 bit count */
hd
->
buf
[
56
]
=
lsb
;
hd
->
buf
[
57
]
=
lsb
>>
8
;
hd
->
buf
[
58
]
=
lsb
>>
16
;
hd
->
buf
[
59
]
=
lsb
>>
24
;
hd
->
buf
[
60
]
=
msb
;
hd
->
buf
[
61
]
=
msb
>>
8
;
hd
->
buf
[
62
]
=
msb
>>
16
;
hd
->
buf
[
63
]
=
msb
>>
24
;
transform
(
hd
,
hd
->
buf
);
_gcry_burn_stack
(
80
+
6
*
sizeof
(
void
*
));
p
=
hd
->
buf
;
#ifdef WORDS_BIGENDIAN
#define X(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \
*p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0)
#else
/* little endian */
#define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0)
#endif
X
(
A
);
X
(
B
);
X
(
C
);
X
(
D
);
#undef X
}
static
byte
*
md4_read
(
void
*
context
)
{
MD4_CONTEXT
*
hd
=
context
;
return
hd
->
buf
;
}
static
byte
asn
[
18
]
=
/* Object ID is 1.2.840.113549.2.4 */
{
0x30
,
0x20
,
0x30
,
0x0c
,
0x06
,
0x08
,
0x2a
,
0x86
,
0x48
,
0x86
,
0xf7
,
0x0d
,
0x02
,
0x04
,
0x05
,
0x00
,
0x04
,
0x10
};
static
gcry_md_oid_spec_t
oid_spec_md4
[]
=
{
/* iso.member-body.us.rsadsi.digestAlgorithm.md4 */
{
"1.2.840.113549.2.4"
},
{
NULL
},
};
gcry_md_spec_t
_gcry_digest_spec_md4
=
{
"MD4"
,
asn
,
DIM
(
asn
),
oid_spec_md4
,
16
,
md4_init
,
md4_write
,
md4_final
,
md4_read
,
sizeof
(
MD4_CONTEXT
)
};
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Fri, Dec 19, 2:24 PM (1 d, 20 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
8c/62/7b2e4a2c9338db6797fe745e4878
Attached To
rC libgcrypt
Event Timeline
Log In to Comment