/* md5 block update operation. continues an md5 message-digest
operation, processing another message block, and updating the
context.
*/
void cmd5::md5update (md5_ctx *context, unsigned char *input, unsigned int inputlen)
{
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) {
md5_memcpy
((pointer)&context->buffer[index], (pointer)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 */
md5_memcpy
((pointer)&context->buffer[index], (pointer)&input[i],
inputlen-i);
}
/* md5 finalization. ends an md5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
void cmd5::md5final (unsigned char digest[16], md5_ctx *context)
{
unsigned char bits[8];
unsigned int index, padlen;
/* save number of bits */
encode (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);
md5update (context, padding, padlen);
/* append length (before padding) */
md5update (context, bits, 8);
/* store state in digest */
encode (digest, context->state, 16);
/* zeroize sensitive information.
*/
md5_memset ((pointer)context, 0, sizeof (*context));
}
/* md5 basic transformation. transforms state based on block.
*/
static void encode (unsigned char *output, uint4 *input, 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);
}
}
/* decodes input (unsigned char) into output (uint4). assumes len is
a multiple of 4.
*/
static void decode (uint4 *output, unsigned char *input, 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);
}
/* note: replace "for loop" with standard memcpy if possible.
*/
static void md5_memcpy (pointer output, pointer input, unsigned int len)
{
unsigned int i;
for (i = 0; i < len; i++)
output[i] = input[i];
}
/* note: replace "for loop" with standard memset if possible.
*/
static void md5_memset (pointer output, int value, unsigned int len)
{
unsigned int i;
for (i = 0; i < len; i++)
((char *)output)[i] = (char)value;
}
void cmd5::md5transform (uint4 state[4], unsigned char block[64])
{
uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
decode (x, block, 64);