Cross Reference: md4.c
xref
: /
osnet-11
/
usr
/
src
/
grub
/
grub2
/
grub-core
/
lib
/
libgcrypt
/
cipher
/
md4.c
Home
History
Annotate
Line#
Navigate
Download
Search
only in
./
2
N/A
/*
md4.c
- MD4 Message-Digest Algorithm
2
N/A
* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
2
N/A
*
2
N/A
* This file is part of Libgcrypt.
2
N/A
*
2
N/A
* Libgcrypt is free software; you can redistribute it
and
/
or
modify
2
N/A
* it under the terms of the GNU Lesser General Public License as
2
N/A
* published by the Free Software Foundation; either version 2.1 of
2
N/A
* the License, or (at your option) any later version.
2
N/A
*
2
N/A
* Libgcrypt is distributed in the hope that it will be useful,
2
N/A
* but WITHOUT ANY WARRANTY; without even the implied warranty of
2
N/A
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2
N/A
* GNU Lesser General Public License for more details.
2
N/A
*
2
N/A
* You should have received a copy of the GNU Lesser General Public
2
N/A
* License along with this program; if not, write to the Free Software
2
N/A
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
2
N/A
*
2
N/A
* Based on
md5.c
in libgcrypt, but rewritten to compute md4 checksums
2
N/A
* using a public domain md4 implementation with the following comments:
2
N/A
*
2
N/A
* Modified by Wei Dai from Andrew M. Kuchling's
md4.c
2
N/A
* The original code and all modifications are in the public domain.
2
N/A
*
2
N/A
* This is the original introductory comment:
2
N/A
*
2
N/A
*
md4.c
: MD4 hash algorithm.
2
N/A
*
2
N/A
* Part of the Python Cryptography Toolkit, version 1.1
2
N/A
*
2
N/A
* Distribute and use freely; there are no restrictions on further
2
N/A
* dissemination and usage except those imposed by the laws of your
2
N/A
* country of residence.
2
N/A
*
2
N/A
*/
2
N/A
2
N/A
/* MD4 test suite:
2
N/A
* MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0
2
N/A
* MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24
2
N/A
* MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d
2
N/A
* MD4 ("message digest") = d9130a8164549fe818874806e1c7014b
2
N/A
* MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9
2
N/A
* MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
2
N/A
* 043f8582f241db351ce627e153e7f0e4
2
N/A
* MD4 ("123456789012345678901234567890123456789012345678901234567890123456
2
N/A
* 78901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536
2
N/A
*/
2
N/A
2
N/A
#
include
<
config.h
>
2
N/A
#
include
<
stdio.h
>
2
N/A
#
include
<
stdlib.h
>
2
N/A
#
include
<
string.h
>
2
N/A
2
N/A
#
include
"
g10lib.h
"
2
N/A
#
include
"
memory.h
"
2
N/A
#
include
"
cipher.h
"
2
N/A
2
N/A
#
include
"
bithelp.h
"
2
N/A
2
N/A
2
N/A
typedef
struct
{
2
N/A
u32
A,B,C,D;
/* chaining variables */
2
N/A
u32
nblocks
;
2
N/A
byte
buf
[
64
];
2
N/A
int
count
;
2
N/A
}
MD4_CONTEXT
;
2
N/A
2
N/A
2
N/A
static
void
2
N/A
md4_init
(
void
*
context
)
2
N/A
{
2
N/A
MD4_CONTEXT
*
ctx
=
context
;
2
N/A
2
N/A
ctx
->A =
0x67452301
;
2
N/A
ctx
->B =
0xefcdab89
;
2
N/A
ctx
->C =
0x98badcfe
;
2
N/A
ctx
->D =
0x10325476
;
2
N/A
2
N/A
ctx
->
nblocks
= 0;
2
N/A
ctx
->
count
= 0;
2
N/A
}
2
N/A
2
N/A
#
define
F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
2
N/A
#
define
G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
2
N/A
#
define
H(x, y, z) ((x) ^ (y) ^ (z))
2
N/A
2
N/A
2
N/A
/****************
2
N/A
* transform 64 bytes
2
N/A
*/
2
N/A
static
void
2
N/A
transform
(
MD4_CONTEXT
*
ctx
,
const
unsigned
char
*
data
)
2
N/A
{
2
N/A
u32
in
[
16
];
2
N/A
register
u32
A =
ctx
->A;
2
N/A
register
u32
B =
ctx
->B;
2
N/A
register
u32
C =
ctx
->C;
2
N/A
register
u32
D =
ctx
->D;
2
N/A
2
N/A
#
ifdef
WORDS_BIGENDIAN
2
N/A
{
2
N/A
int
i;
2
N/A
byte
*
p2
;
2
N/A
const
byte
*
p1
;
2
N/A
for
(i=0,
p1
=
data
,
p2
=(
byte
*)
in
; i <
16
; i++,
p2
+=
4
)
2
N/A
{
2
N/A
p2
[
3
] = *
p1
++;
2
N/A
p2
[
2
] = *
p1
++;
2
N/A
p2
[
1
] = *
p1
++;
2
N/A
p2
[0] = *
p1
++;
2
N/A
}
2
N/A
}
2
N/A
#
else
2
N/A
memcpy
(
in
,
data
,
64
);
2
N/A
#
endif
2
N/A
2
N/A
/* Round 1. */
2
N/A
#
define
function
(a,b,c,d,k,s) a=
rol
(a+F(b,c,d)+
in
[k],s);
2
N/A
function
(A,B,C,D, 0,
3
);
2
N/A
function
(D,A,B,C,
1
,
7
);
2
N/A
function
(C,D,A,B,
2
,
11
);
2
N/A
function
(B,C,D,A,
3
,
19
);
2
N/A
function
(A,B,C,D,
4
,
3
);
2
N/A
function
(D,A,B,C,
5
,
7
);
2
N/A
function
(C,D,A,B,
6
,
11
);
2
N/A
function
(B,C,D,A,
7
,
19
);
2
N/A
function
(A,B,C,D,
8
,
3
);
2
N/A
function
(D,A,B,C,
9
,
7
);
2
N/A
function
(C,D,A,B,
10
,
11
);
2
N/A
function
(B,C,D,A,
11
,
19
);
2
N/A
function
(A,B,C,D,
12
,
3
);
2
N/A
function
(D,A,B,C,
13
,
7
);
2
N/A
function
(C,D,A,B,
14
,
11
);
2
N/A
function
(B,C,D,A,
15
,
19
);
2
N/A
2
N/A
#
undef
function
2
N/A
2
N/A
/* Round 2. */
2
N/A
#
define
function
(a,b,c,d,k,s) a=
rol
(a+G(b,c,d)+
in
[k]+
0x5a827999
,s);
2
N/A
2
N/A
function
(A,B,C,D, 0,
3
);
2
N/A
function
(D,A,B,C,
4
,
5
);
2
N/A
function
(C,D,A,B,
8
,
9
);
2
N/A
function
(B,C,D,A,
12
,
13
);
2
N/A
function
(A,B,C,D,
1
,
3
);
2
N/A
function
(D,A,B,C,
5
,
5
);
2
N/A
function
(C,D,A,B,
9
,
9
);
2
N/A
function
(B,C,D,A,
13
,
13
);
2
N/A
function
(A,B,C,D,
2
,
3
);
2
N/A
function
(D,A,B,C,
6
,
5
);
2
N/A
function
(C,D,A,B,
10
,
9
);
2
N/A
function
(B,C,D,A,
14
,
13
);
2
N/A
function
(A,B,C,D,
3
,
3
);
2
N/A
function
(D,A,B,C,
7
,
5
);
2
N/A
function
(C,D,A,B,
11
,
9
);
2
N/A
function
(B,C,D,A,
15
,
13
);
2
N/A
2
N/A
#
undef
function
2
N/A
2
N/A
/* Round 3. */
2
N/A
#
define
function
(a,b,c,d,k,s) a=
rol
(a+H(b,c,d)+
in
[k]+
0x6ed9eba1
,s);
2
N/A
2
N/A
function
(A,B,C,D, 0,
3
);
2
N/A
function
(D,A,B,C,
8
,
9
);
2
N/A
function
(C,D,A,B,
4
,
11
);
2
N/A
function
(B,C,D,A,
12
,
15
);
2
N/A
function
(A,B,C,D,
2
,
3
);
2
N/A
function
(D,A,B,C,
10
,
9
);
2
N/A
function
(C,D,A,B,
6
,
11
);
2
N/A
function
(B,C,D,A,
14
,
15
);
2
N/A
function
(A,B,C,D,
1
,
3
);
2
N/A
function
(D,A,B,C,
9
,
9
);
2
N/A
function
(C,D,A,B,
5
,
11
);
2
N/A
function
(B,C,D,A,
13
,
15
);
2
N/A
function
(A,B,C,D,
3
,
3
);
2
N/A
function
(D,A,B,C,
11
,
9
);
2
N/A
function
(C,D,A,B,
7
,
11
);
2
N/A
function
(B,C,D,A,
15
,
15
);
2
N/A
2
N/A
2
N/A
/* Put checksum in context given as argument. */
2
N/A
ctx
->A += A;
2
N/A
ctx
->B += B;
2
N/A
ctx
->C += C;
2
N/A
ctx
->D += D;
2
N/A
}
2
N/A
2
N/A
2
N/A
2
N/A
/* The routine updates the message-digest context to
2
N/A
* account for the presence of each of the characters inBuf[0..inLen-1]
2
N/A
* in the message whose digest is being computed.
2
N/A
*/
2
N/A
static
void
2
N/A
md4_write
(
void
*
context
,
const
void
*
inbuf_arg
,
size_t
inlen
)
2
N/A
{
2
N/A
const
unsigned
char
*
inbuf
=
inbuf_arg
;
2
N/A
MD4_CONTEXT
*
hd
=
context
;
2
N/A
2
N/A
if
(
hd
->
count
==
64
)
/* flush the buffer */
2
N/A
{
2
N/A
transform
(
hd
,
hd
->
buf
);
2
N/A
_gcry_burn_stack
(
80
+
6
*
sizeof
(
void
*));
2
N/A
hd
->
count
= 0;
2
N/A
hd
->
nblocks
++;
2
N/A
}
2
N/A
if
( !
inbuf
)
2
N/A
return
;
2
N/A
2
N/A
if
(
hd
->
count
)
2
N/A
{
2
N/A
for
( ;
inlen
&&
hd
->
count
<
64
;
inlen
-- )
2
N/A
hd
->
buf
[
hd
->
count
++] = *
inbuf
++;
2
N/A
md4_write
(
hd
,
NULL
, 0 );
2
N/A
if
( !
inlen
)
2
N/A
return
;
2
N/A
}
2
N/A
_gcry_burn_stack
(
80
+
6
*
sizeof
(
void
*));
2
N/A
2
N/A
while
(
inlen
>=
64
)
2
N/A
{
2
N/A
transform
(
hd
,
inbuf
);
2
N/A
hd
->
count
= 0;
2
N/A
hd
->
nblocks
++;
2
N/A
inlen
-=
64
;
2
N/A
inbuf
+=
64
;
2
N/A
}
2
N/A
for
( ;
inlen
&&
hd
->
count
<
64
;
inlen
-- )
2
N/A
hd
->
buf
[
hd
->
count
++] = *
inbuf
++;
2
N/A
}
2
N/A
2
N/A
2
N/A
2
N/A
/* The routine final terminates the message-digest computation and
2
N/A
* ends with the desired message digest in mdContext->digest[0...15].
2
N/A
* The handle is prepared for a new MD4 cycle.
2
N/A
* Returns 16 bytes representing the digest.
2
N/A
*/
2
N/A
2
N/A
static
void
2
N/A
md4_final
(
void
*
context
)
2
N/A
{
2
N/A
MD4_CONTEXT
*
hd
=
context
;
2
N/A
u32
t,
msb
,
lsb
;
2
N/A
byte
*p;
2
N/A
2
N/A
md4_write
(
hd
,
NULL
, 0);
/* flush */
;
2
N/A
2
N/A
t =
hd
->
nblocks
;
2
N/A
/* multiply by 64 to make a byte count */
2
N/A
lsb
= t <<
6
;
2
N/A
msb
= t >>
26
;
2
N/A
/* add the count */
2
N/A
t =
lsb
;
2
N/A
if
( (
lsb
+=
hd
->
count
) < t )
2
N/A
msb
++;
2
N/A
/* multiply by 8 to make a bit count */
2
N/A
t =
lsb
;
2
N/A
lsb
<<=
3
;
2
N/A
msb
<<=
3
;
2
N/A
msb
|= t >>
29
;
2
N/A
2
N/A
if
(
hd
->
count
<
56
)
/* enough room */
2
N/A
{
2
N/A
hd
->
buf
[
hd
->
count
++] =
0x80
;
/* pad */
2
N/A
while
(
hd
->
count
<
56
)
2
N/A
hd
->
buf
[
hd
->
count
++] = 0;
/* pad */
2
N/A
}
2
N/A
else
/* need one extra block */
2
N/A
{
2
N/A
hd
->
buf
[
hd
->
count
++] =
0x80
;
/* pad character */
2
N/A
while
(
hd
->
count
<
64
)
2
N/A
hd
->
buf
[
hd
->
count
++] = 0;
2
N/A
md4_write
(
hd
,
NULL
, 0);
/* flush */
;
2
N/A
memset
(
hd
->
buf
, 0,
56
);
/* fill next block with zeroes */
2
N/A
}
2
N/A
/* append the 64 bit count */
2
N/A
hd
->
buf
[
56
] =
lsb
;
2
N/A
hd
->
buf
[
57
] =
lsb
>>
8
;
2
N/A
hd
->
buf
[
58
] =
lsb
>>
16
;
2
N/A
hd
->
buf
[
59
] =
lsb
>>
24
;
2
N/A
hd
->
buf
[
60
] =
msb
;
2
N/A
hd
->
buf
[
61
] =
msb
>>
8
;
2
N/A
hd
->
buf
[
62
] =
msb
>>
16
;
2
N/A
hd
->
buf
[
63
] =
msb
>>
24
;
2
N/A
transform
(
hd
,
hd
->
buf
);
2
N/A
_gcry_burn_stack
(
80
+
6
*
sizeof
(
void
*));
2
N/A
2
N/A
p =
hd
->
buf
;
2
N/A
#
ifdef
WORDS_BIGENDIAN
2
N/A
#
define
X(a)
do
{ *p++ =
hd
->a ; *p++ =
hd
->a >>
8
; \
2
N/A
*p++ =
hd
->a >>
16
; *p++ =
hd
->a >>
24
; }
while
(0)
2
N/A
#
else
/* little endian */
2
N/A
#
define
X(a)
do
{ *(
u32
*)p = (*
hd
).a ; p +=
4
; }
while
(0)
2
N/A
#
endif
2
N/A
X(A);
2
N/A
X(B);
2
N/A
X(C);
2
N/A
X(D);
2
N/A
#
undef
X
2
N/A
2
N/A
}
2
N/A
2
N/A
static
byte
*
2
N/A
md4_read
(
void
*
context
)
2
N/A
{
2
N/A
MD4_CONTEXT
*
hd
=
context
;
2
N/A
return
hd
->
buf
;
2
N/A
}
2
N/A
2
N/A
static
byte
asn
[
18
] =
/* Object ID is 1.2.840.113549.2.4 */
2
N/A
{
0x30
,
0x20
,
0x30
,
0x0c
,
0x06
,
0x08
,
0x2a
,
0x86
,
0x48
,
2
N/A
0x86
,
0xf7
,
0x0d
,
0x02
,
0x04
,
0x05
,
0x00
,
0x04
,
0x10
};
2
N/A
2
N/A
static
gcry_md_oid_spec_t
oid_spec_md4
[] =
2
N/A
{
2
N/A
/* iso.member-body.us.rsadsi.digestAlgorithm.md4 */
2
N/A
{
"1.2.840.113549.2.4"
},
2
N/A
{
NULL
},
2
N/A
};
2
N/A
2
N/A
gcry_md_spec_t
_gcry_digest_spec_md4
=
2
N/A
{
2
N/A
"MD4"
,
asn
,
DIM
(
asn
),
oid_spec_md4
,
16
,
2
N/A
md4_init
,
md4_write
,
md4_final
,
md4_read
,
2
N/A
sizeof
(
MD4_CONTEXT
)
2
N/A
};
2
N/A