#include "../arcfour.h"
void
arcfour_key_init(ARCFour_key *key, uchar_t *keyval, int keyvallen)
{
uchar_t ext_keyval[256];
uchar_t tmp;
int i, j;
for (i = j = 0; i < 256; i++, j++) {
if (j == keyvallen)
j = 0;
ext_keyval[i] = keyval[j];
}
for (i = 0; i < 256; i++)
key->arr[i] = (uchar_t)i;
j = 0;
for (i = 0; i < 256; i++) {
j = (j + key->arr[i] + ext_keyval[i]) % 256;
tmp = key->arr[i];
key->arr[i] = key->arr[j];
key->arr[j] = tmp;
}
key->i = 0;
key->j = 0;
}
void
arcfour_crypt(ARCFour_key *key, uchar_t *in, uchar_t *out, size_t len)
{
size_t ii;
unsigned long long in0, merge = 0, merge0 = 0, merge1, mask = 0;
uchar_t i, j, *base, jj, *base1, tmp;
unsigned int tmp0, tmp1, i_accum, shift = 0, i1;
int index;
base = key->arr;
index = (((uintptr_t)in) & 0x7);
if (index > 0) {
i = key->i;
j = key->j;
for (index = 8 - index; (index-- > 0) && len > 0;
len--, in++, out++) {
i = i + 1;
j = j + key->arr[i];
tmp = key->arr[i];
key->arr[i] = key->arr[j];
key->arr[j] = tmp;
tmp = key->arr[i] + key->arr[j];
*out = *in ^ key->arr[tmp];
}
key->i = i;
key->j = j;
}
if (len == 0)
return;
#ifdef sun4v
if ((((uintptr_t)out) & 7) != 0) {
#endif
i = key->i;
j = key->j;
for (ii = 0; ii < len; ii++) {
i = i + 1;
tmp0 = base[i];
j = j + tmp0;
tmp1 = base[j];
base[i] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
out[ii] = in[ii] ^ base[tmp0];
}
key->i = i;
key->j = j;
#ifdef sun4v
} else {
i = key->i;
j = key->j;
if (((i+1) % 2) != 0) {
i = i + 1;
tmp0 = base[i];
j = j + tmp0;
tmp1 = base[j];
base[i] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
merge0 = (unsigned long long)(base[tmp0]) << 56;
shift = 8; mask = 0xff;
}
for (ii = 0, i1 = i; ii < ((len-1) & (~7));
ii += 8, i1 = i1&0xff) {
if (i1 < 248) {
i1 = (i1 + 1);
base1 = &base[i1];
tmp0 = base1[0];
j = j + tmp0;
tmp1 = base[j];
i_accum = tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
if (i1 == tmp0) {
merge =
(unsigned long long)(i_accum) << 56;
} else {
merge =
(unsigned long long)(base[tmp0]) <<
56;
}
tmp0 = base1[1];
j = j + tmp0;
if ((i1 ^ j) < 2) {
base1[0] = (uchar_t)i_accum;
tmp1 = base[j];
base1[1] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
merge |= (unsigned long long)
(base[tmp0]) << 48;
} else {
tmp1 = base[j];
i_accum = i_accum << 8;
i_accum |= tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
*((unsigned short *) &base[i1]) =
i_accum;
merge |=
(unsigned long long)(base[tmp0]) <<
48;
}
tmp0 = base1[2];
j = j + tmp0;
tmp1 = base[j];
base1[2] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp1 += tmp0;
tmp1 = tmp1 & 0xff;
merge |= (unsigned long long)(base[tmp1]) << 40;
tmp0 = base1[3];
j = j + tmp0;
tmp1 = base[j];
base1[3] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
merge |= (unsigned long long)(base[tmp0]) << 32;
tmp0 = base1[4];
j = j + tmp0;
tmp1 = base[j];
base1[4] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
merge |= (unsigned long long)(base[tmp0]) << 24;
tmp0 = base1[5];
j = j + tmp0;
tmp1 = base[j];
base1[5] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
merge |= (unsigned long long)(base[tmp0]) << 16;
i1 = (i1+6);
tmp0 = base1[6];
j = j + tmp0;
tmp1 = base[j];
i_accum = tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
if (i1 == tmp0) {
merge |=
(unsigned long long)(i_accum) << 8;
} else {
merge |=
(unsigned long long)(base[tmp0]) <<
8;
}
tmp0 = base1[7];
j = j + tmp0;
if ((i1 ^ j) < 2) {
base1[6] = (uchar_t)i_accum;
tmp1 = base[j];
base1[7] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
merge |=
(unsigned long long)(base[tmp0]);
} else {
tmp1 = base[j];
i_accum = i_accum << 8;
i_accum |= tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
*((unsigned short *) &base[i1]) =
i_accum;
merge |=
(unsigned long long)(base[tmp0]);
}
i1++;
} else {
i1 = (i1 + 1) & 0xff;
jj = (uchar_t)i1;
tmp0 = base[i1];
j = j + tmp0;
tmp1 = base[j];
i_accum = tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
if (i1 == tmp0) {
merge =
(unsigned long long)(i_accum) << 56;
} else {
merge =
(unsigned long long)(base[tmp0]) <<
56;
}
tmp0 = base[i1+1];
j = j + tmp0;
if ((jj ^ j) < 2) {
base[jj] = (uchar_t)i_accum;
tmp1 = base[j];
base[i1+1] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
merge |=
(unsigned long long)(base[tmp0]) <<
48;
} else {
tmp1 = base[j];
i_accum = i_accum << 8;
i_accum |= tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
*((unsigned short *) &base[jj]) =
i_accum;
merge |=
(unsigned long long)(base[tmp0]) <<
48;
}
i1 = (i1 + 2) & 0xff;
tmp0 = base[i1];
j = j + tmp0;
tmp1 = base[j];
base[i1] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
merge |= (unsigned long long)(base[tmp0]) << 40;
tmp0 = base[i1+1];
j = j + tmp0;
tmp1 = base[j];
base[i1+1] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
merge |= (unsigned long long)(base[tmp0]) << 32;
i1 = (i1 + 2) & 0xff;
tmp0 = base[i1];
j = j + tmp0;
tmp1 = base[j];
base[i1] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
merge |= (unsigned long long)(base[tmp0]) << 24;
tmp0 = base[i1+1];
j = j + tmp0;
tmp1 = base[j];
base[i1+1] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
merge |= (unsigned long long)(base[tmp0]) << 16;
i1 = (i1+2) &0xff;
jj = (uchar_t)i1;
tmp0 = base[i1];
j = j + tmp0;
tmp1 = base[j];
i_accum = tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
if (i1 == tmp0) {
merge |=
(unsigned long long)(i_accum) << 8;
} else {
merge |=
(unsigned long long)(base[tmp0]) <<
8;
}
i1++;
tmp0 = base[i1];
j = j + tmp0;
if ((jj ^ j) < 2) {
base[jj] = (uchar_t)i_accum;
tmp1 = base[j];
base[i1] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
merge |=
(unsigned long long)(base[tmp0]);
} else {
tmp1 = base[j];
i_accum = i_accum << 8;
i_accum |= tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
*((unsigned short *) &base[jj]) =
i_accum;
merge |=
(unsigned long long)(base[tmp0]);
}
}
in0 = *((unsigned long long *) (&in[ii]));
merge1 = merge0 | (merge >> shift);
merge0 = (merge & mask) << 56;
in0 = in0 ^ merge1;
*((unsigned long long *) (&out[ii])) = in0;
}
i = (uchar_t)i1;
if (shift) {
out[ii] = in[ii] ^ (merge0 >> 56);
ii++;
}
for (; ii < len; ii++) {
i = i + 1;
tmp0 = base[i];
j = j + tmp0;
tmp1 = base[j];
base[i] = (uchar_t)tmp1;
base[j] = (uchar_t)tmp0;
tmp0 += tmp1;
tmp0 = tmp0 & 0xff;
out[ii] = in[ii] ^ base[tmp0];
}
key->i = i;
key->j = j;
}
#endif
}