#ifndef _KERNEL
#include <stdint.h>
#endif
#include <sys/types.h>
#include <sys/md5.h>
#include <sys/md5_consts.h>
#include "md5_byteswap.h"
#if !defined(_KERNEL) || defined(_BOOT)
#include <strings.h>
#endif
#ifdef _KERNEL
#include <sys/systm.h>
#endif
static void Encode(uint8_t *, const uint32_t *, size_t);
#if !defined(__amd64)
static void MD5Transform(uint32_t, uint32_t, uint32_t, uint32_t, MD5_CTX *,
const uint8_t [64]);
#else
void md5_block_asm_host_order(MD5_CTX *ctx, const void *inpp,
unsigned int input_length_in_blocks);
#endif
static uint8_t PADDING[64] = { 0x80, };
#define F(b, c, d) (((b) & (c)) | ((~b) & (d)))
#define G(b, c, d) (((b) & (d)) | ((c) & (~d)))
#define H(b, c, d) ((b) ^ (c) ^ (d))
#define I(b, c, d) ((c) ^ ((b) | (~d)))
#define ROTATE_LEFT(x, n) \
(((x) << (n)) | ((x) >> ((sizeof (x) << 3) - (n))))
#define FF(a, b, c, d, x, s, ac) { \
(a) += F((b), (c), (d)) + (x) + ((unsigned long long)(ac)); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G((b), (c), (d)) + (x) + ((unsigned long long)(ac)); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H((b), (c), (d)) + (x) + ((unsigned long long)(ac)); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I((b), (c), (d)) + (x) + ((unsigned long long)(ac)); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#if defined(__i386) || defined(__amd64)
#define MD5_CONST(x) (MD5_CONST_ ## x)
#define MD5_CONST_e(x) MD5_CONST(x)
#define MD5_CONST_o(x) MD5_CONST(x)
#else
#ifdef sun4v
#pragma align 64 (md5_consts)
#define _MD5_CHECK_ALIGNMENT
#endif
static const uint32_t md5_consts[] = {
MD5_CONST_0, MD5_CONST_1, MD5_CONST_2, MD5_CONST_3,
MD5_CONST_4, MD5_CONST_5, MD5_CONST_6, MD5_CONST_7,
MD5_CONST_8, MD5_CONST_9, MD5_CONST_10, MD5_CONST_11,
MD5_CONST_12, MD5_CONST_13, MD5_CONST_14, MD5_CONST_15,
MD5_CONST_16, MD5_CONST_17, MD5_CONST_18, MD5_CONST_19,
MD5_CONST_20, MD5_CONST_21, MD5_CONST_22, MD5_CONST_23,
MD5_CONST_24, MD5_CONST_25, MD5_CONST_26, MD5_CONST_27,
MD5_CONST_28, MD5_CONST_29, MD5_CONST_30, MD5_CONST_31,
MD5_CONST_32, MD5_CONST_33, MD5_CONST_34, MD5_CONST_35,
MD5_CONST_36, MD5_CONST_37, MD5_CONST_38, MD5_CONST_39,
MD5_CONST_40, MD5_CONST_41, MD5_CONST_42, MD5_CONST_43,
MD5_CONST_44, MD5_CONST_45, MD5_CONST_46, MD5_CONST_47,
MD5_CONST_48, MD5_CONST_49, MD5_CONST_50, MD5_CONST_51,
MD5_CONST_52, MD5_CONST_53, MD5_CONST_54, MD5_CONST_55,
MD5_CONST_56, MD5_CONST_57, MD5_CONST_58, MD5_CONST_59,
MD5_CONST_60, MD5_CONST_61, MD5_CONST_62, MD5_CONST_63
};
#ifdef sun4v
#define MD5_CONST_e(x) (md5_consts64[x/2] >> 32)
#define MD5_CONST_o(x) (md5_consts64[x/2])
#else
#define MD5_CONST_e(x) (md5_consts[x])
#define MD5_CONST_o(x) (md5_consts[x])
#endif
#endif
void
MD5Init(MD5_CTX *ctx)
{
ctx->count[0] = ctx->count[1] = 0;
ctx->state[0] = MD5_INIT_CONST_1;
ctx->state[1] = MD5_INIT_CONST_2;
ctx->state[2] = MD5_INIT_CONST_3;
ctx->state[3] = MD5_INIT_CONST_4;
}
void
MD5Update(MD5_CTX *ctx, const void *inpp, unsigned int input_len)
{
uint32_t i, buf_index, buf_len;
#ifdef sun4v
uint32_t old_asi;
#endif
#if defined(__amd64)
uint32_t block_count;
#endif
const unsigned char *input = (const unsigned char *)inpp;
buf_index = (ctx->count[0] >> 3) & 0x3F;
if ((ctx->count[0] += (input_len << 3)) < (input_len << 3))
ctx->count[1]++;
ctx->count[1] += (input_len >> 29);
buf_len = 64 - buf_index;
i = 0;
if (input_len >= buf_len) {
#ifdef sun4v
old_asi = get_little();
set_little(0x88);
#endif
if (buf_index) {
bcopy(input, &ctx->buf_un.buf8[buf_index], buf_len);
#if !defined(__amd64)
MD5Transform(ctx->state[0], ctx->state[1],
ctx->state[2], ctx->state[3], ctx,
ctx->buf_un.buf8);
#else
md5_block_asm_host_order(ctx, ctx->buf_un.buf8, 1);
#endif
i = buf_len;
}
#if !defined(__amd64)
for (; i + 63 < input_len; i += 64)
MD5Transform(ctx->state[0], ctx->state[1],
ctx->state[2], ctx->state[3], ctx, &input[i]);
#else
block_count = (input_len - i) >> 6;
if (block_count > 0) {
md5_block_asm_host_order(ctx, &input[i], block_count);
i += block_count << 6;
}
#endif
#ifdef sun4v
set_little(old_asi);
#endif
if (input_len == i)
return;
buf_index = 0;
}
bcopy(&input[i], &ctx->buf_un.buf8[buf_index], input_len - i);
}
void
MD5Final(void *digest, MD5_CTX *ctx)
{
uint8_t bitcount_le[sizeof (ctx->count)];
uint32_t index = (ctx->count[0] >> 3) & 0x3f;
Encode(bitcount_le, ctx->count, sizeof (bitcount_le));
MD5Update(ctx, PADDING, ((index < 56) ? 56 : 120) - index);
MD5Update(ctx, bitcount_le, sizeof (bitcount_le));
Encode(digest, ctx->state, sizeof (ctx->state));
bzero(ctx, sizeof (*ctx));
}
#ifndef _KERNEL
void
md5_calc(unsigned char *output, unsigned char *input, unsigned int inlen)
{
MD5_CTX context;
MD5Init(&context);
MD5Update(&context, input, inlen);
MD5Final(output, &context);
}
#endif
#if !defined(__amd64)
static void
MD5Transform(uint32_t a, uint32_t b, uint32_t c, uint32_t d,
MD5_CTX *ctx, const uint8_t block[64])
{
register uint32_t x_0, x_1, x_2, x_3, x_4, x_5, x_6, x_7;
register uint32_t x_8, x_9, x_10, x_11, x_12, x_13, x_14, x_15;
#ifdef sun4v
unsigned long long *md5_consts64;
md5_consts64 = (unsigned long long *) md5_consts;
#endif
#ifdef _MD5_CHECK_ALIGNMENT
if ((uintptr_t)block & 0x3) {
bcopy(block, ctx->buf_un.buf32, sizeof (ctx->buf_un.buf32));
#ifdef sun4v
x_15 = LOAD_LITTLE_32_f(ctx->buf_un.buf32);
x_14 = LOAD_LITTLE_32_e(ctx->buf_un.buf32);
x_13 = LOAD_LITTLE_32_d(ctx->buf_un.buf32);
x_12 = LOAD_LITTLE_32_c(ctx->buf_un.buf32);
x_11 = LOAD_LITTLE_32_b(ctx->buf_un.buf32);
x_10 = LOAD_LITTLE_32_a(ctx->buf_un.buf32);
x_9 = LOAD_LITTLE_32_9(ctx->buf_un.buf32);
x_8 = LOAD_LITTLE_32_8(ctx->buf_un.buf32);
x_7 = LOAD_LITTLE_32_7(ctx->buf_un.buf32);
x_6 = LOAD_LITTLE_32_6(ctx->buf_un.buf32);
x_5 = LOAD_LITTLE_32_5(ctx->buf_un.buf32);
x_4 = LOAD_LITTLE_32_4(ctx->buf_un.buf32);
x_3 = LOAD_LITTLE_32_3(ctx->buf_un.buf32);
x_2 = LOAD_LITTLE_32_2(ctx->buf_un.buf32);
x_1 = LOAD_LITTLE_32_1(ctx->buf_un.buf32);
x_0 = LOAD_LITTLE_32_0(ctx->buf_un.buf32);
#else
x_15 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 15);
x_14 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 14);
x_13 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 13);
x_12 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 12);
x_11 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 11);
x_10 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 10);
x_9 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 9);
x_8 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 8);
x_7 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 7);
x_6 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 6);
x_5 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 5);
x_4 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 4);
x_3 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 3);
x_2 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 2);
x_1 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 1);
x_0 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 0);
#endif
} else
#endif
{
#ifdef sun4v
x_15 = LOAD_LITTLE_32_f(block);
x_14 = LOAD_LITTLE_32_e(block);
x_13 = LOAD_LITTLE_32_d(block);
x_12 = LOAD_LITTLE_32_c(block);
x_11 = LOAD_LITTLE_32_b(block);
x_10 = LOAD_LITTLE_32_a(block);
x_9 = LOAD_LITTLE_32_9(block);
x_8 = LOAD_LITTLE_32_8(block);
x_7 = LOAD_LITTLE_32_7(block);
x_6 = LOAD_LITTLE_32_6(block);
x_5 = LOAD_LITTLE_32_5(block);
x_4 = LOAD_LITTLE_32_4(block);
x_3 = LOAD_LITTLE_32_3(block);
x_2 = LOAD_LITTLE_32_2(block);
x_1 = LOAD_LITTLE_32_1(block);
x_0 = LOAD_LITTLE_32_0(block);
#else
x_15 = LOAD_LITTLE_32(block + 60);
x_14 = LOAD_LITTLE_32(block + 56);
x_13 = LOAD_LITTLE_32(block + 52);
x_12 = LOAD_LITTLE_32(block + 48);
x_11 = LOAD_LITTLE_32(block + 44);
x_10 = LOAD_LITTLE_32(block + 40);
x_9 = LOAD_LITTLE_32(block + 36);
x_8 = LOAD_LITTLE_32(block + 32);
x_7 = LOAD_LITTLE_32(block + 28);
x_6 = LOAD_LITTLE_32(block + 24);
x_5 = LOAD_LITTLE_32(block + 20);
x_4 = LOAD_LITTLE_32(block + 16);
x_3 = LOAD_LITTLE_32(block + 12);
x_2 = LOAD_LITTLE_32(block + 8);
x_1 = LOAD_LITTLE_32(block + 4);
x_0 = LOAD_LITTLE_32(block + 0);
#endif
}
FF(a, b, c, d, x_0, MD5_SHIFT_11, MD5_CONST_e(0));
FF(d, a, b, c, x_1, MD5_SHIFT_12, MD5_CONST_o(1));
FF(c, d, a, b, x_2, MD5_SHIFT_13, MD5_CONST_e(2));
FF(b, c, d, a, x_3, MD5_SHIFT_14, MD5_CONST_o(3));
FF(a, b, c, d, x_4, MD5_SHIFT_11, MD5_CONST_e(4));
FF(d, a, b, c, x_5, MD5_SHIFT_12, MD5_CONST_o(5));
FF(c, d, a, b, x_6, MD5_SHIFT_13, MD5_CONST_e(6));
FF(b, c, d, a, x_7, MD5_SHIFT_14, MD5_CONST_o(7));
FF(a, b, c, d, x_8, MD5_SHIFT_11, MD5_CONST_e(8));
FF(d, a, b, c, x_9, MD5_SHIFT_12, MD5_CONST_o(9));
FF(c, d, a, b, x_10, MD5_SHIFT_13, MD5_CONST_e(10));
FF(b, c, d, a, x_11, MD5_SHIFT_14, MD5_CONST_o(11));
FF(a, b, c, d, x_12, MD5_SHIFT_11, MD5_CONST_e(12));
FF(d, a, b, c, x_13, MD5_SHIFT_12, MD5_CONST_o(13));
FF(c, d, a, b, x_14, MD5_SHIFT_13, MD5_CONST_e(14));
FF(b, c, d, a, x_15, MD5_SHIFT_14, MD5_CONST_o(15));
GG(a, b, c, d, x_1, MD5_SHIFT_21, MD5_CONST_e(16));
GG(d, a, b, c, x_6, MD5_SHIFT_22, MD5_CONST_o(17));
GG(c, d, a, b, x_11, MD5_SHIFT_23, MD5_CONST_e(18));
GG(b, c, d, a, x_0, MD5_SHIFT_24, MD5_CONST_o(19));
GG(a, b, c, d, x_5, MD5_SHIFT_21, MD5_CONST_e(20));
GG(d, a, b, c, x_10, MD5_SHIFT_22, MD5_CONST_o(21));
GG(c, d, a, b, x_15, MD5_SHIFT_23, MD5_CONST_e(22));
GG(b, c, d, a, x_4, MD5_SHIFT_24, MD5_CONST_o(23));
GG(a, b, c, d, x_9, MD5_SHIFT_21, MD5_CONST_e(24));
GG(d, a, b, c, x_14, MD5_SHIFT_22, MD5_CONST_o(25));
GG(c, d, a, b, x_3, MD5_SHIFT_23, MD5_CONST_e(26));
GG(b, c, d, a, x_8, MD5_SHIFT_24, MD5_CONST_o(27));
GG(a, b, c, d, x_13, MD5_SHIFT_21, MD5_CONST_e(28));
GG(d, a, b, c, x_2, MD5_SHIFT_22, MD5_CONST_o(29));
GG(c, d, a, b, x_7, MD5_SHIFT_23, MD5_CONST_e(30));
GG(b, c, d, a, x_12, MD5_SHIFT_24, MD5_CONST_o(31));
HH(a, b, c, d, x_5, MD5_SHIFT_31, MD5_CONST_e(32));
HH(d, a, b, c, x_8, MD5_SHIFT_32, MD5_CONST_o(33));
HH(c, d, a, b, x_11, MD5_SHIFT_33, MD5_CONST_e(34));
HH(b, c, d, a, x_14, MD5_SHIFT_34, MD5_CONST_o(35));
HH(a, b, c, d, x_1, MD5_SHIFT_31, MD5_CONST_e(36));
HH(d, a, b, c, x_4, MD5_SHIFT_32, MD5_CONST_o(37));
HH(c, d, a, b, x_7, MD5_SHIFT_33, MD5_CONST_e(38));
HH(b, c, d, a, x_10, MD5_SHIFT_34, MD5_CONST_o(39));
HH(a, b, c, d, x_13, MD5_SHIFT_31, MD5_CONST_e(40));
HH(d, a, b, c, x_0, MD5_SHIFT_32, MD5_CONST_o(41));
HH(c, d, a, b, x_3, MD5_SHIFT_33, MD5_CONST_e(42));
HH(b, c, d, a, x_6, MD5_SHIFT_34, MD5_CONST_o(43));
HH(a, b, c, d, x_9, MD5_SHIFT_31, MD5_CONST_e(44));
HH(d, a, b, c, x_12, MD5_SHIFT_32, MD5_CONST_o(45));
HH(c, d, a, b, x_15, MD5_SHIFT_33, MD5_CONST_e(46));
HH(b, c, d, a, x_2, MD5_SHIFT_34, MD5_CONST_o(47));
II(a, b, c, d, x_0, MD5_SHIFT_41, MD5_CONST_e(48));
II(d, a, b, c, x_7, MD5_SHIFT_42, MD5_CONST_o(49));
II(c, d, a, b, x_14, MD5_SHIFT_43, MD5_CONST_e(50));
II(b, c, d, a, x_5, MD5_SHIFT_44, MD5_CONST_o(51));
II(a, b, c, d, x_12, MD5_SHIFT_41, MD5_CONST_e(52));
II(d, a, b, c, x_3, MD5_SHIFT_42, MD5_CONST_o(53));
II(c, d, a, b, x_10, MD5_SHIFT_43, MD5_CONST_e(54));
II(b, c, d, a, x_1, MD5_SHIFT_44, MD5_CONST_o(55));
II(a, b, c, d, x_8, MD5_SHIFT_41, MD5_CONST_e(56));
II(d, a, b, c, x_15, MD5_SHIFT_42, MD5_CONST_o(57));
II(c, d, a, b, x_6, MD5_SHIFT_43, MD5_CONST_e(58));
II(b, c, d, a, x_13, MD5_SHIFT_44, MD5_CONST_o(59));
II(a, b, c, d, x_4, MD5_SHIFT_41, MD5_CONST_e(60));
II(d, a, b, c, x_11, MD5_SHIFT_42, MD5_CONST_o(61));
II(c, d, a, b, x_2, MD5_SHIFT_43, MD5_CONST_e(62));
II(b, c, d, a, x_9, MD5_SHIFT_44, MD5_CONST_o(63));
ctx->state[0] += a;
ctx->state[1] += b;
ctx->state[2] += c;
ctx->state[3] += d;
x_0 = x_1 = x_2 = x_3 = x_4 = x_5 = x_6 = x_7 = x_8 = 0;
x_9 = x_10 = x_11 = x_12 = x_13 = x_14 = x_15 = 0;
}
#endif
static void
Encode(uint8_t *_RESTRICT_KYWD output, const uint32_t *_RESTRICT_KYWD input,
size_t input_len)
{
size_t i, j;
for (i = 0, j = 0; j < input_len; i++, j += sizeof (uint32_t)) {
#ifdef _LITTLE_ENDIAN
#ifdef _MD5_CHECK_ALIGNMENT
if ((uintptr_t)output & 0x3)
bcopy(input + i, output + j, 4);
else *(uint32_t *)(output + j) = input[i];
#else
*(uint32_t *)(output + j) = input[i];
#endif
#else
output[j] = input[i] & 0xff;
output[j + 1] = (input[i] >> 8) & 0xff;
output[j + 2] = (input[i] >> 16) & 0xff;
output[j + 3] = (input[i] >> 24) & 0xff;
#endif
}
}