Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Robert Dubner
OpenLDAP
Commits
03f4554e
Commit
03f4554e
authored
Oct 13, 2021
by
Robert Dubner
Browse files
Sanitize radiusclient/md5
parent
f549bbc8
Changes
4
Hide whitespace changes
Inline
Side-by-side
contrib/slapd-modules/radiusov/demonstration/radiusclient/hmacmd5.c
View file @
03f4554e
...
...
@@ -10,7 +10,10 @@
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
*
* As noted below, portions of this code were derived from public-domain sources
*
*/
#include
<string.h>
#include
"hmacmd5.h"
...
...
@@ -110,6 +113,6 @@ hmac_md5_final( HMAC_MD5_CTX *context,
md5_init
(
&
context
->
context
);
// init context for second pass
md5_update
(
&
context
->
context
,
k_opad
,
64
);
// start with outer pad
md5_update
(
&
context
->
context
,
digest
,
16
);
// then results of first hash
md5_final
(
digest
,
&
context
->
context
);
// finish up second pass
md5_final
(
digest
,
&
context
->
context
);
// finish up second pass
}
contrib/slapd-modules/radiusov/demonstration/radiusclient/hmacmd5.h
View file @
03f4554e
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2021 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*
* As noted below, portions of this code were derived from public-domain sources
*
*/
#ifndef _h_HMACMD5_H
#define _h_HMACMD5_H
#include
<stdint.h>
#include
"md5.h"
typedef
struct
HMAC_MD5_CTX_
...
...
contrib/slapd-modules/radiusov/demonstration/radiusclient/md5.c
View file @
03f4554e
/**
* @note license is LGPL, but largely derived from a public domain source.
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2021 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*
* As noted below, portions of this code were derived from public-domain sources
*
* @file md5.c
* @brief md5 digest functions.
*/
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* (This is a heavily cut-down "BSD license".)
*
* This differs from Colin Plumb's older public domain implementation in that
* no exactly 32-bit integer data type is required (any 32-bit or wider
* unsigned integer data type will do), there's no compile-time endianness
* configuration, and the function prototypes match OpenSSL's. No code from
* Colin Plumb's implementation has been reused; this comment merely compares
* the properties of the two independent implementations.
*
* The primary goals of this implementation are portability and ease of use.
* It is meant to be fast, but not as fast as possible. Some known
* optimizations are not included to reduce source code size and avoid
* compile-time configuration.
*/
#include
<string.h>
#include
"md5.h"
/** Calculate the MD5 hash of the contents of a buffer
/*
* The basic MD5 functions.
*
*
@param[out] out Whe
re to
write the MD5 digest. Must be a minimum of MD5_DIGEST_LENGTH.
*
@param[in] in Data to hash.
*
@param[in] inlen Length of the data
.
*
F and G are optimized compa
re
d
to
their RFC 1321 definitions for
*
architectures that lack an AND-NOT instruction, just like in Colin Plumb's
*
implementation
.
*/
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
#define H(x, y, z) (((x) ^ (y)) ^ (z))
#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
void
md5_calc
(
uint8_t
*
out
,
uint8_t
const
*
in
,
size_t
inlen
)
{
MD5_CTX
ctx
;
md5_init
(
&
ctx
);
md5_update
(
&
ctx
,
in
,
inlen
);
md5_final
(
out
,
&
ctx
);
}
/*
* The MD5 transformation for all four rounds.
*/
#define STEP(f, a, b, c, d, x, t, s) \
(a) += f((b), (c), (d)) + (x) + (t); \
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
(a) += (b);
#ifndef HAVE_OPENSSL_MD5_H
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
* SET reads 4 input bytes in little-endian byte order and stores them in a
* properly aligned word in host byte order.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
* The check for little-endian architectures that tolerate unaligned memory
* accesses is just an optimization. Nothing will break if it fails to detect
* a suitable architecture.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to md5_init, call md5_update as
* needed on buffers full of bytes, and then call md5_final, which
* will fill a supplied 16-byte array with the digest.
* Unfortunately, this optimization may be a C strict aliasing rules violation
* if the caller's data buffer has effective type that cannot be aliased by
* MD5_u32plus. In practice, this problem may occur if these MD5 routines are
* inlined into a calling function, or with future and dangerously advanced
* link-time optimizations. For the time being, keeping these MD5 routines in
* their own translation unit avoids the problem.
*/
#define PUT_64BIT_LE(cp, value) do {\
(cp)[7] = (value)[1] >> 24;\
(cp)[6] = (value)[1] >> 16;\
(cp)[5] = (value)[1] >> 8;\
(cp)[4] = (value)[1];\
(cp)[3] = (value)[0] >> 24;\
(cp)[2] = (value)[0] >> 16;\
(cp)[1] = (value)[0] >> 8;\
(cp)[0] = (value)[0];\
} while (0)
#define PUT_32BIT_LE(cp, value) do {\
(cp)[3] = (value) >> 24;\
(cp)[2] = (value) >> 16;\
(cp)[1] = (value) >> 8;\
(cp)[0] = (value);\
} while (0)
static
const
uint8_t
PADDING
[
MD5_BLOCK_LENGTH
]
=
{
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
};
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
#define SET(n) \
(*(MD5_u32plus *)&ptr[(n) * 4])
#define GET(n) \
SET(n)
#else
#define SET(n) \
(ctx->block[(n)] = \
(MD5_u32plus)ptr[(n) * 4] | \
((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
#define GET(n) \
(ctx->block[(n)])
#endif
/** Initialise a new MD5 context
*
* Set bit count to 0 and buffer to mysterious initialization constants.
*
* @param[out] ctx to initialise.
/*
* This processes one or more 64-byte data blocks, but does NOT update the bit
* counters. There are no alignment requirements.
*/
static
const
void
*
body
(
MD5_CTX
*
ctx
,
const
void
*
data
,
unsigned
long
size
)
{
const
unsigned
char
*
ptr
;
MD5_u32plus
a
,
b
,
c
,
d
;
MD5_u32plus
saved_a
,
saved_b
,
saved_c
,
saved_d
;
ptr
=
(
const
unsigned
char
*
)
data
;
a
=
ctx
->
a
;
b
=
ctx
->
b
;
c
=
ctx
->
c
;
d
=
ctx
->
d
;
do
{
saved_a
=
a
;
saved_b
=
b
;
saved_c
=
c
;
saved_d
=
d
;
/* Round 1 */
STEP
(
F
,
a
,
b
,
c
,
d
,
SET
(
0
),
0xd76aa478
,
7
)
STEP
(
F
,
d
,
a
,
b
,
c
,
SET
(
1
),
0xe8c7b756
,
12
)
STEP
(
F
,
c
,
d
,
a
,
b
,
SET
(
2
),
0x242070db
,
17
)
STEP
(
F
,
b
,
c
,
d
,
a
,
SET
(
3
),
0xc1bdceee
,
22
)
STEP
(
F
,
a
,
b
,
c
,
d
,
SET
(
4
),
0xf57c0faf
,
7
)
STEP
(
F
,
d
,
a
,
b
,
c
,
SET
(
5
),
0x4787c62a
,
12
)
STEP
(
F
,
c
,
d
,
a
,
b
,
SET
(
6
),
0xa8304613
,
17
)
STEP
(
F
,
b
,
c
,
d
,
a
,
SET
(
7
),
0xfd469501
,
22
)
STEP
(
F
,
a
,
b
,
c
,
d
,
SET
(
8
),
0x698098d8
,
7
)
STEP
(
F
,
d
,
a
,
b
,
c
,
SET
(
9
),
0x8b44f7af
,
12
)
STEP
(
F
,
c
,
d
,
a
,
b
,
SET
(
10
),
0xffff5bb1
,
17
)
STEP
(
F
,
b
,
c
,
d
,
a
,
SET
(
11
),
0x895cd7be
,
22
)
STEP
(
F
,
a
,
b
,
c
,
d
,
SET
(
12
),
0x6b901122
,
7
)
STEP
(
F
,
d
,
a
,
b
,
c
,
SET
(
13
),
0xfd987193
,
12
)
STEP
(
F
,
c
,
d
,
a
,
b
,
SET
(
14
),
0xa679438e
,
17
)
STEP
(
F
,
b
,
c
,
d
,
a
,
SET
(
15
),
0x49b40821
,
22
)
/* Round 2 */
STEP
(
G
,
a
,
b
,
c
,
d
,
GET
(
1
),
0xf61e2562
,
5
)
STEP
(
G
,
d
,
a
,
b
,
c
,
GET
(
6
),
0xc040b340
,
9
)
STEP
(
G
,
c
,
d
,
a
,
b
,
GET
(
11
),
0x265e5a51
,
14
)
STEP
(
G
,
b
,
c
,
d
,
a
,
GET
(
0
),
0xe9b6c7aa
,
20
)
STEP
(
G
,
a
,
b
,
c
,
d
,
GET
(
5
),
0xd62f105d
,
5
)
STEP
(
G
,
d
,
a
,
b
,
c
,
GET
(
10
),
0x02441453
,
9
)
STEP
(
G
,
c
,
d
,
a
,
b
,
GET
(
15
),
0xd8a1e681
,
14
)
STEP
(
G
,
b
,
c
,
d
,
a
,
GET
(
4
),
0xe7d3fbc8
,
20
)
STEP
(
G
,
a
,
b
,
c
,
d
,
GET
(
9
),
0x21e1cde6
,
5
)
STEP
(
G
,
d
,
a
,
b
,
c
,
GET
(
14
),
0xc33707d6
,
9
)
STEP
(
G
,
c
,
d
,
a
,
b
,
GET
(
3
),
0xf4d50d87
,
14
)
STEP
(
G
,
b
,
c
,
d
,
a
,
GET
(
8
),
0x455a14ed
,
20
)
STEP
(
G
,
a
,
b
,
c
,
d
,
GET
(
13
),
0xa9e3e905
,
5
)
STEP
(
G
,
d
,
a
,
b
,
c
,
GET
(
2
),
0xfcefa3f8
,
9
)
STEP
(
G
,
c
,
d
,
a
,
b
,
GET
(
7
),
0x676f02d9
,
14
)
STEP
(
G
,
b
,
c
,
d
,
a
,
GET
(
12
),
0x8d2a4c8a
,
20
)
/* Round 3 */
STEP
(
H
,
a
,
b
,
c
,
d
,
GET
(
5
),
0xfffa3942
,
4
)
STEP
(
H2
,
d
,
a
,
b
,
c
,
GET
(
8
),
0x8771f681
,
11
)
STEP
(
H
,
c
,
d
,
a
,
b
,
GET
(
11
),
0x6d9d6122
,
16
)
STEP
(
H2
,
b
,
c
,
d
,
a
,
GET
(
14
),
0xfde5380c
,
23
)
STEP
(
H
,
a
,
b
,
c
,
d
,
GET
(
1
),
0xa4beea44
,
4
)
STEP
(
H2
,
d
,
a
,
b
,
c
,
GET
(
4
),
0x4bdecfa9
,
11
)
STEP
(
H
,
c
,
d
,
a
,
b
,
GET
(
7
),
0xf6bb4b60
,
16
)
STEP
(
H2
,
b
,
c
,
d
,
a
,
GET
(
10
),
0xbebfbc70
,
23
)
STEP
(
H
,
a
,
b
,
c
,
d
,
GET
(
13
),
0x289b7ec6
,
4
)
STEP
(
H2
,
d
,
a
,
b
,
c
,
GET
(
0
),
0xeaa127fa
,
11
)
STEP
(
H
,
c
,
d
,
a
,
b
,
GET
(
3
),
0xd4ef3085
,
16
)
STEP
(
H2
,
b
,
c
,
d
,
a
,
GET
(
6
),
0x04881d05
,
23
)
STEP
(
H
,
a
,
b
,
c
,
d
,
GET
(
9
),
0xd9d4d039
,
4
)
STEP
(
H2
,
d
,
a
,
b
,
c
,
GET
(
12
),
0xe6db99e5
,
11
)
STEP
(
H
,
c
,
d
,
a
,
b
,
GET
(
15
),
0x1fa27cf8
,
16
)
STEP
(
H2
,
b
,
c
,
d
,
a
,
GET
(
2
),
0xc4ac5665
,
23
)
/* Round 4 */
STEP
(
I
,
a
,
b
,
c
,
d
,
GET
(
0
),
0xf4292244
,
6
)
STEP
(
I
,
d
,
a
,
b
,
c
,
GET
(
7
),
0x432aff97
,
10
)
STEP
(
I
,
c
,
d
,
a
,
b
,
GET
(
14
),
0xab9423a7
,
15
)
STEP
(
I
,
b
,
c
,
d
,
a
,
GET
(
5
),
0xfc93a039
,
21
)
STEP
(
I
,
a
,
b
,
c
,
d
,
GET
(
12
),
0x655b59c3
,
6
)
STEP
(
I
,
d
,
a
,
b
,
c
,
GET
(
3
),
0x8f0ccc92
,
10
)
STEP
(
I
,
c
,
d
,
a
,
b
,
GET
(
10
),
0xffeff47d
,
15
)
STEP
(
I
,
b
,
c
,
d
,
a
,
GET
(
1
),
0x85845dd1
,
21
)
STEP
(
I
,
a
,
b
,
c
,
d
,
GET
(
8
),
0x6fa87e4f
,
6
)
STEP
(
I
,
d
,
a
,
b
,
c
,
GET
(
15
),
0xfe2ce6e0
,
10
)
STEP
(
I
,
c
,
d
,
a
,
b
,
GET
(
6
),
0xa3014314
,
15
)
STEP
(
I
,
b
,
c
,
d
,
a
,
GET
(
13
),
0x4e0811a1
,
21
)
STEP
(
I
,
a
,
b
,
c
,
d
,
GET
(
4
),
0xf7537e82
,
6
)
STEP
(
I
,
d
,
a
,
b
,
c
,
GET
(
11
),
0xbd3af235
,
10
)
STEP
(
I
,
c
,
d
,
a
,
b
,
GET
(
2
),
0x2ad7d2bb
,
15
)
STEP
(
I
,
b
,
c
,
d
,
a
,
GET
(
9
),
0xeb86d391
,
21
)
a
+=
saved_a
;
b
+=
saved_b
;
c
+=
saved_c
;
d
+=
saved_d
;
ptr
+=
64
;
}
while
(
size
-=
64
);
ctx
->
a
=
a
;
ctx
->
b
=
b
;
ctx
->
c
=
c
;
ctx
->
d
=
d
;
return
ptr
;
}
void
md5_init
(
MD5_CTX
*
ctx
)
{
ctx
->
count
[
0
]
=
0
;
ctx
->
count
[
1
]
=
0
;
ctx
->
state
[
0
]
=
0x67452301
;
ctx
->
state
[
1
]
=
0xefcdab89
;
ctx
->
state
[
2
]
=
0x98badcfe
;
ctx
->
state
[
3
]
=
0x10325476
;
ctx
->
a
=
0x67452301
;
ctx
->
b
=
0xefcdab89
;
ctx
->
c
=
0x98badcfe
;
ctx
->
d
=
0x10325476
;
ctx
->
lo
=
0
;
ctx
->
hi
=
0
;
}
/** Feed additional data into the MD5 hashing function
*
* @param[in,out] ctx to update.
* @param[in] in Data to hash.
* @param[in] inlen Length of the data.
*/
void
md5_update
(
MD5_CTX
*
ctx
,
uint8_t
const
*
in
,
size_t
inlen
)
md5_update
(
MD5_CTX
*
ctx
,
const
void
*
data
,
unsigned
long
size
)
{
size_t
have
,
need
;
MD5_u32plus
saved_lo
;
unsigned
long
used
,
available
;
/* Check how many bytes we already have and how many more we need. */
have
=
(
size_t
)((
ctx
->
count
[
0
]
>>
3
)
&
(
MD5_BLOCK_LENGTH
-
1
));
need
=
MD5_BLOCK_LENGTH
-
have
;
saved_lo
=
ctx
->
lo
;
if
((
ctx
->
lo
=
(
saved_lo
+
size
)
&
0x1fffffff
)
<
saved_lo
)
ctx
->
hi
++
;
ctx
->
hi
+=
size
>>
29
;
/* Update bitcount */
/* ctx->count += (uint64_t)inlen << 3;*/
if
((
ctx
->
count
[
0
]
+=
((
uint32_t
)
inlen
<<
3
))
<
(
uint32_t
)
inlen
)
{
/* Overflowed ctx->count[0] */
ctx
->
count
[
1
]
++
;
}
ctx
->
count
[
1
]
+=
((
uint32_t
)
inlen
>>
29
);
used
=
saved_lo
&
0x3f
;
if
(
inlen
>=
ne
ed
)
if
(
us
ed
)
{
if
(
have
!=
0
)
{
memcpy
(
ctx
->
buffer
+
have
,
in
,
need
);
md5_transform
(
ctx
->
state
,
ctx
->
buffer
);
in
+=
need
;
inlen
-=
need
;
have
=
0
;
}
available
=
64
-
used
;
/* Process data in MD5_BLOCK_LENGTH-byte chunks. */
while
(
inlen
>=
MD5_BLOCK_LENGTH
)
if
(
size
<
available
)
{
md5_transform
(
ctx
->
state
,
in
);
in
+=
MD5_BLOCK_LENGTH
;
inlen
-=
MD5_BLOCK_LENGTH
;
memcpy
(
&
ctx
->
buffer
[
used
],
data
,
size
);
return
;
}
}
/* Handle any remaining bytes of data. */
if
(
inlen
!=
0
)
memcpy
(
ctx
->
buffer
+
have
,
in
,
inlen
);
}
memcpy
(
&
ctx
->
buffer
[
used
],
data
,
available
);
data
=
(
const
unsigned
char
*
)
data
+
available
;
size
-=
available
;
body
(
ctx
,
ctx
->
buffer
,
64
);
}
/** Finalise the MD5 context and write out the hash
*
* Final wrapup - pad to 64-byte boundary with the bit pattern 1 0*
* (64-bit count of bits processed, MSB-first).
*
* @param[out] out Where to write the MD5 digest. Minimum length of MD5_DIGEST_LENGTH.
* @param[in,out] ctx to finalise.
*/
void
md5_final
(
uint8_t
out
[
MD5_DIGEST_LENGTH
],
MD5_CTX
*
ctx
)
{
uint8_t
count
[
8
];
size_t
padlen
;
int
i
;
/* Convert count to 8 bytes in little endian order. */
PUT_64BIT_LE
(
count
,
ctx
->
count
);
/* Pad out to 56 mod 64. */
padlen
=
MD5_BLOCK_LENGTH
-
((
ctx
->
count
[
0
]
>>
3
)
&
(
MD5_BLOCK_LENGTH
-
1
));
if
(
padlen
<
1
+
8
)
padlen
+=
MD5_BLOCK_LENGTH
;
md5_update
(
ctx
,
PADDING
,
padlen
-
8
);
/* padlen - 8 <= 64 */
md5_update
(
ctx
,
count
,
8
);
if
(
out
!=
NULL
)
if
(
size
>=
64
)
{
for
(
i
=
0
;
i
<
4
;
i
++
)
PUT_32BIT_LE
(
out
+
i
*
4
,
ctx
->
state
[
i
])
;
data
=
body
(
ctx
,
data
,
size
&
~
(
unsigned
long
)
0x3f
);
size
&=
0x3f
;
}
memset
(
ctx
,
0
,
sizeof
(
*
ctx
));
/* in case it's sensitive */
}
/* The four core functions - F1 is optimized somewhat */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
memcpy
(
ctx
->
buffer
,
data
,
size
);
}
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
#define OUT(dst, src) \
(dst)[0] = (unsigned char)(src); \
(dst)[1] = (unsigned char)((src) >> 8); \
(dst)[2] = (unsigned char)((src) >> 16); \
(dst)[3] = (unsigned char)((src) >> 24);
/** The core of the MD5 algorithm
*
* This alters an existing MD5 hash to reflect the addition of 16
* longwords of new data. md5_update blocks the data and converts bytes
* into longwords for this routine.
*
* @param[in] state 16 bytes of data to feed into the hashing function.
* @param[in,out] block MD5 digest block to update.
*/
void
md5_
transform
(
uint32_t
state
[
4
],
uint8_t
const
block
[
MD5_BLOCK_LENGTH
]
)
md5_
final
(
unsigned
char
*
result
,
MD5_CTX
*
ctx
)
{
uint32_t
a
,
b
,
c
,
d
,
in
[
MD5_BLOCK_LENGTH
/
4
];
unsigned
long
used
,
available
;
used
=
ctx
->
lo
&
0x3f
;
for
(
a
=
0
;
a
<
MD5_BLOCK_LENGTH
/
4
;
a
++
)
ctx
->
buffer
[
used
++
]
=
0x80
;
available
=
64
-
used
;
if
(
available
<
8
)
{
in
[
a
]
=
(
uint32_t
)(
(
uint32_t
)(
block
[
a
*
4
+
0
])
|
(
uint32_t
)(
block
[
a
*
4
+
1
])
<<
8
|
(
uint32_t
)(
block
[
a
*
4
+
2
])
<<
16
|
(
uint32_t
)(
block
[
a
*
4
+
3
])
<<
24
);
memset
(
&
ctx
->
buffer
[
used
],
0
,
available
);
body
(
ctx
,
ctx
->
buffer
,
64
);
used
=
0
;
available
=
64
;
}
a
=
state
[
0
];
b
=
state
[
1
];
c
=
state
[
2
];
d
=
state
[
3
];
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
0
]
+
0xd76aa478
,
7
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
1
]
+
0xe8c7b756
,
12
);
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
2
]
+
0x242070db
,
17
);
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
3
]
+
0xc1bdceee
,
22
);
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
4
]
+
0xf57c0faf
,
7
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
5
]
+
0x4787c62a
,
12
);
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
6
]
+
0xa8304613
,
17
);
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
7
]
+
0xfd469501
,
22
);
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
8
]
+
0x698098d8
,
7
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
9
]
+
0x8b44f7af
,
12
);
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
10
]
+
0xffff5bb1
,
17
);
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
11
]
+
0x895cd7be
,
22
);
MD5STEP
(
F1
,
a
,
b
,
c
,
d
,
in
[
12
]
+
0x6b901122
,
7
);
MD5STEP
(
F1
,
d
,
a
,
b
,
c
,
in
[
13
]
+
0xfd987193
,
12
);
MD5STEP
(
F1
,
c
,
d
,
a
,
b
,
in
[
14
]
+
0xa679438e
,
17
);
MD5STEP
(
F1
,
b
,
c
,
d
,
a
,
in
[
15
]
+
0x49b40821
,
22
);
MD5STEP
(
F2
,
a
,
b
,
c
,
d
,
in
[
1
]
+
0xf61e2562
,
5
);
MD5STEP
(
F2
,
d
,
a
,
b
,
c
,
in
[
6
]
+
0xc040b340
,
9
);
MD5STEP
(
F2
,
c
,
d
,
a
,
b
,
in
[
11
]
+
0x265e5a51
,
14
);
MD5STEP
(
F2
,
b
,
c
,
d
,
a
,
in
[
0
]
+
0xe9b6c7aa
,
20
);
MD5STEP
(
F2
,
a
,
b
,
c
,
d
,
in
[
5
]
+
0xd62f105d
,
5
);
MD5STEP
(
F2
,
d
,
a
,
b
,
c
,
in
[
10
]
+
0x02441453
,
9
);
MD5STEP
(
F2
,
c
,
d
,
a
,
b
,
in
[
15
]
+
0xd8a1e681
,
14
);
MD5STEP
(
F2
,
b
,
c
,
d
,
a
,
in
[
4
]
+
0xe7d3fbc8
,
20
);
MD5STEP
(
F2
,
a
,
b
,
c
,
d
,
in
[
9
]
+
0x21e1cde6
,
5
);
MD5STEP
(
F2
,
d
,
a
,
b
,
c
,
in
[
14
]
+
0xc33707d6
,
9
);
MD5STEP
(
F2
,
c
,
d
,
a
,
b
,
in
[
3
]
+
0xf4d50d87
,
14
);
MD5STEP
(
F2
,
b
,
c
,
d
,
a
,
in
[
8
]
+
0x455a14ed
,
20
);
MD5STEP
(
F2
,
a
,
b
,
c
,
d
,
in
[
13
]
+
0xa9e3e905
,
5
);
MD5STEP
(
F2
,
d
,
a
,
b
,
c
,
in
[
2
]
+
0xfcefa3f8
,
9
);
MD5STEP
(
F2
,
c
,
d
,
a
,
b
,
in
[
7
]
+
0x676f02d9
,
14
);
MD5STEP
(
F2
,
b
,
c
,
d
,
a
,
in
[
12
]
+
0x8d2a4c8a
,
20
);
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
5
]
+
0xfffa3942
,
4
);
MD5STEP
(
F3
,
d
,
a
,
b
,
c
,
in
[
8
]
+
0x8771f681
,
11
);
MD5STEP
(
F3
,
c
,
d
,
a
,
b
,
in
[
11
]
+
0x6d9d6122
,
16
);
MD5STEP
(
F3
,
b
,
c
,
d
,
a
,
in
[
14
]
+
0xfde5380c
,
23
);
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
1
]
+
0xa4beea44
,
4
);
MD5STEP
(
F3
,
d
,
a
,
b
,
c
,
in
[
4
]
+
0x4bdecfa9
,
11
);
MD5STEP
(
F3
,
c
,
d
,
a
,
b
,
in
[
7
]
+
0xf6bb4b60
,
16
);
MD5STEP
(
F3
,
b
,
c
,
d
,
a
,
in
[
10
]
+
0xbebfbc70
,
23
);
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
13
]
+
0x289b7ec6
,
4
);
MD5STEP
(
F3
,
d
,
a
,
b
,
c
,
in
[
0
]
+
0xeaa127fa
,
11
);
MD5STEP
(
F3
,
c
,
d
,
a
,
b
,
in
[
3
]
+
0xd4ef3085
,
16
);
MD5STEP
(
F3
,
b
,
c
,
d
,
a
,
in
[
6
]
+
0x04881d05
,
23
);
MD5STEP
(
F3
,
a
,
b
,
c
,
d
,
in
[
9
]
+
0xd9d4d039
,
4
);
MD5STEP
(
F3
,
d
,
a
,
b
,
c
,
in
[
12
]
+
0xe6db99e5
,
11
);
MD5STEP
(
F3
,
c
,
d
,
a
,
b
,
in
[
15
]
+
0x1fa27cf8
,
16
);
MD5STEP
(
F3
,
b
,
c
,
d
,
a
,
in
[
2
]
+
0xc4ac5665
,
23
);
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
0
]
+
0xf4292244
,
6
);
MD5STEP
(
F4
,
d
,
a
,
b
,
c
,
in
[
7
]
+
0x432aff97
,
10
);
MD5STEP
(
F4
,
c
,
d
,
a
,
b
,
in
[
14
]
+
0xab9423a7
,
15
);
MD5STEP
(
F4
,
b
,
c
,
d
,
a
,
in
[
5
]
+
0xfc93a039
,
21
);
MD5STEP
(
F4
,
a
,
b
,
c
,
d
,
in
[
12
]
+
0x655b59c3
,
6
);