added elliptic curve stuff and RIPEMD-160

This commit is contained in:
aiju 2012-06-04 11:50:37 +02:00
parent c065e02a99
commit 005248b4c5
4 changed files with 903 additions and 1 deletions

View file

@ -403,4 +403,37 @@ PEMChain*readcertchain(char *filename);
/* aes_xts.c */
int aes_xts_encrypt(ulong tweak[], ulong ecb[], vlong sectorNumber, uchar *input, uchar *output, ulong len) ;
int aes_xts_decrypt(ulong tweak[], ulong ecb[], vlong sectorNumber, uchar *input, uchar *output, ulong len);
int aes_xts_decrypt(ulong tweak[], ulong ecb[], vlong sectorNumber, uchar *input, uchar *output, ulong len);
typedef struct ECpoint{
int inf;
mpint *x;
mpint *y;
} ECpoint;
typedef ECpoint ECpub;
typedef struct ECpriv{
ECpoint;
mpint *d;
} ECpriv;
typedef struct ECdomain{
mpint *p;
mpint *a;
mpint *b;
ECpoint *G;
mpint *n;
mpint *h;
} ECdomain;
void ecassign(ECdomain *, ECpoint *old, ECpoint *new);
void ecadd(ECdomain *, ECpoint *a, ECpoint *b, ECpoint *s);
void ecmul(ECdomain *, ECpoint *a, mpint *k, ECpoint *s);
ECpoint* strtoec(ECdomain *, char *, char **, ECpoint *);
ECpriv* ecgen(ECdomain *, ECpriv*);
int ecverify(ECdomain *, ECpoint *);
int ecpubverify(ECdomain *, ECpub *);
void ecdsasign(ECdomain *, ECpriv *, uchar *, int, mpint *, mpint *);
int ecdsaverify(ECdomain *, ECpub *, uchar *, int, mpint *, mpint *);
DigestState* ripemd160(uchar *, ulong, uchar *, DigestState *);

484
sys/src/libsec/port/ecc.c Normal file
View file

@ -0,0 +1,484 @@
#include "os.h"
#include <mp.h>
#include <libsec.h>
#include <ctype.h>
void
ecassign(ECdomain *, ECpoint *a, ECpoint *b)
{
b->inf = a->inf;
mpassign(a->x, b->x);
mpassign(a->y, b->y);
}
void
ecadd(ECdomain *dom, ECpoint *a, ECpoint *b, ECpoint *s)
{
mpint *l, *k, *sx, *sy;
if(a->inf && b->inf){
s->inf = 1;
return;
}
if(a->inf){
ecassign(dom, b, s);
return;
}
if(b->inf){
ecassign(dom, a, s);
return;
}
if(mpcmp(a->x, b->x) == 0 && (mpcmp(a->y, mpzero) == 0 || mpcmp(a->y, b->y) != 0)){
s->inf = 1;
return;
}
l = mpnew(0);
k = mpnew(0);
sx = mpnew(0);
sy = mpnew(0);
if(mpcmp(a->x, b->x) == 0 && mpcmp(a->y, b->y) == 0){
mpadd(mpone, mptwo, k);
mpmul(a->x, a->x, l);
mpmul(l, k, l);
mpadd(l, dom->a, l);
mpleft(a->y, 1, k);
mpmod(k, dom->p, k);
mpinvert(k, dom->p, k);
mpmul(k, l, l);
mpmod(l, dom->p, l);
mpleft(a->x, 1, k);
mpmul(l, l, sx);
mpsub(sx, k, sx);
mpmod(sx, dom->p, sx);
mpsub(a->x, sx, sy);
mpmul(l, sy, sy);
mpsub(sy, a->y, sy);
mpmod(sy, dom->p, sy);
mpassign(sx, s->x);
mpassign(sy, s->y);
mpfree(sx);
mpfree(sy);
mpfree(l);
mpfree(k);
return;
}
mpsub(b->y, a->y, l);
mpmod(l, dom->p, l);
mpsub(b->x, a->x, k);
mpmod(k, dom->p, k);
mpinvert(k, dom->p, k);
mpmul(k, l, l);
mpmod(l, dom->p, l);
mpmul(l, l, sx);
mpsub(sx, a->x, sx);
mpsub(sx, b->x, sx);
mpmod(sx, dom->p, sx);
mpsub(a->x, sx, sy);
mpmul(sy, l, sy);
mpsub(sy, a->y, sy);
mpmod(sy, dom->p, sy);
mpassign(sx, s->x);
mpassign(sy, s->y);
mpfree(sx);
mpfree(sy);
mpfree(l);
mpfree(k);
}
void
ecmul(ECdomain *dom, ECpoint *a, mpint *k, ECpoint *s)
{
ECpoint ns, na;
mpint *l;
if(a->inf || mpcmp(k, mpzero) == 0){
s->inf = 1;
return;
}
ns.inf = 1;
ns.x = mpnew(0);
ns.y = mpnew(0);
na.x = mpnew(0);
na.y = mpnew(0);
ecassign(dom, a, &na);
l = mpcopy(k);
l->sign = 1;
while(mpcmp(l, mpzero) != 0){
if(l->p[0] & 1)
ecadd(dom, &na, &ns, &ns);
ecadd(dom, &na, &na, &na);
mpright(l, 1, l);
}
if(k->sign < 0){
ns.y->sign = -1;
mpmod(ns.y, dom->p, ns.y);
}
ecassign(dom, &ns, s);
mpfree(ns.x);
mpfree(ns.y);
mpfree(na.x);
mpfree(na.y);
}
int
ecverify(ECdomain *dom, ECpoint *a)
{
mpint *p, *q;
int r;
if(a->inf)
return 1;
p = mpnew(0);
q = mpnew(0);
mpmul(a->y, a->y, p);
mpmod(p, dom->p, p);
mpmul(a->x, a->x, q);
mpadd(q, dom->a, q);
mpmul(a->x, q, q);
mpadd(q, dom->b, q);
mpmod(q, dom->p, q);
r = mpcmp(p, q);
mpfree(p);
mpfree(q);
return r == 0;
}
int
ecpubverify(ECdomain *dom, ECpub *a)
{
ECpoint p;
int r;
if(a->inf)
return 0;
if(!ecverify(dom, a))
return 0;
p.x = mpnew(0);
p.y = mpnew(0);
ecmul(dom, a, dom->n, &p);
r = p.inf;
mpfree(p.x);
mpfree(p.y);
return r;
}
static void
fixnibble(uchar *a)
{
if(*a >= 'a')
*a -= 'a'-10;
else if(*a >= 'A')
*a -= 'A'-10;
else
*a -= '0';
}
static int
octet(char **s)
{
uchar c, d;
c = *(*s)++;
if(!isxdigit(c))
return -1;
d = *(*s)++;
if(!isxdigit(d))
return -1;
fixnibble(&c);
fixnibble(&d);
return (c << 4) | d;
}
static mpint*
halfpt(ECdomain *dom, char *s, char **rptr, mpint *out)
{
char *buf, *r;
int n;
mpint *ret;
n = ((mpsignif(dom->p)+7)/8)*2;
if(strlen(s) < n)
return 0;
buf = malloc(n+1);
buf[n] = 0;
memcpy(buf, s, n);
ret = strtomp(buf, &r, 16, out);
*rptr = s + (r - buf);
free(buf);
return ret;
}
static int
mpleg(mpint *a, mpint *b)
{
int r, k;
mpint *m, *n, *t;
r = 1;
m = mpcopy(a);
n = mpcopy(b);
for(;;){
if(mpcmp(m, n) > 0)
mpmod(m, n, m);
if(mpcmp(m, mpzero) == 0){
r = 0;
break;
}
if(mpcmp(m, mpone) == 0)
break;
k = mplowbits0(m);
if(k > 0){
if(k & 1)
switch(n->p[0] & 15){
case 3: case 5: case 11: case 13:
r = -r;
}
mpright(m, k, m);
}
if((n->p[0] & 3) == 3 && (m->p[0] & 3) == 3)
r = -r;
t = m;
m = n;
n = t;
}
mpfree(m);
mpfree(n);
return r;
}
static int
mpsqrt(mpint *n, mpint *p, mpint *r)
{
mpint *a, *t, *s, *xp, *xq, *yp, *yq, *zp, *zq, *N;
if(mpleg(n, p) == -1)
return 0;
a = mpnew(0);
t = mpnew(0);
s = mpnew(0);
N = mpnew(0);
xp = mpnew(0);
xq = mpnew(0);
yp = mpnew(0);
yq = mpnew(0);
zp = mpnew(0);
zq = mpnew(0);
for(;;){
for(;;){
mprand(mpsignif(p), genrandom, a);
if(mpcmp(a, mpzero) > 0 && mpcmp(a, p) < 0)
break;
}
mpmul(a, a, t);
mpsub(t, n, t);
mpmod(t, p, t);
if(mpleg(t, p) == -1)
break;
}
mpadd(p, mpone, N);
mpright(N, 1, N);
mpmul(a, a, t);
mpsub(t, n, t);
mpassign(a, xp);
uitomp(1, xq);
uitomp(1, yp);
uitomp(0, yq);
while(mpcmp(N, mpzero) != 0){
if(N->p[0] & 1){
mpmul(xp, yp, zp);
mpmul(xq, yq, zq);
mpmul(zq, t, zq);
mpadd(zp, zq, zp);
mpmod(zp, p, zp);
mpmul(xp, yq, zq);
mpmul(xq, yp, s);
mpadd(zq, s, zq);
mpmod(zq, p, yq);
mpassign(zp, yp);
}
mpmul(xp, xp, zp);
mpmul(xq, xq, zq);
mpmul(zq, t, zq);
mpadd(zp, zq, zp);
mpmod(zp, p, zp);
mpmul(xp, xq, zq);
mpadd(zq, zq, zq);
mpmod(zq, p, xq);
mpassign(zp, xp);
mpright(N, 1, N);
}
if(mpcmp(yq, mpzero) != 0)
abort();
mpassign(yp, r);
mpfree(a);
mpfree(t);
mpfree(s);
mpfree(N);
mpfree(xp);
mpfree(xq);
mpfree(yp);
mpfree(yq);
mpfree(zp);
mpfree(zq);
return 1;
}
ECpoint*
strtoec(ECdomain *dom, char *s, char **rptr, ECpoint *ret)
{
int allocd, o;
mpint *r;
allocd = 0;
if(ret == nil){
allocd = 1;
ret = mallocz(sizeof(*ret), 1);
if(ret == nil)
return nil;
ret->x = mpnew(0);
ret->y = mpnew(0);
}
o = 0;
switch(octet(&s)){
case 0:
ret->inf = 1;
return ret;
case 3:
o = 1;
case 2:
if(halfpt(dom, s, &s, ret->x) == nil)
goto err;
r = mpnew(0);
mpmul(ret->x, ret->x, r);
mpadd(r, dom->a, r);
mpmul(r, ret->x, r);
mpadd(r, dom->b, r);
if(!mpsqrt(r, dom->p, r)){
mpfree(r);
goto err;
}
if((r->p[0] & 1) != o)
mpsub(dom->p, r, r);
mpassign(r, ret->y);
mpfree(r);
if(!ecverify(dom, ret))
goto err;
return ret;
case 4:
if(halfpt(dom, s, &s, ret->x) == nil)
goto err;
if(halfpt(dom, s, &s, ret->y) == nil)
goto err;
if(!ecverify(dom, ret))
goto err;
return ret;
}
err:
if(rptr)
*rptr = s;
if(allocd){
free(ret->x);
free(ret->y);
free(ret);
}
return nil;
}
ECpriv*
ecgen(ECdomain *dom, ECpriv *p)
{
if(p == nil){
p = mallocz(sizeof(*p), 1);
if(p == nil)
return nil;
}
p->x = mpnew(0);
p->y = mpnew(0);
p->d = mpnew(0);
for(;;){
mprand(mpsignif(dom->n), genrandom, p->d);
if(mpcmp(p->d, mpzero) > 0 && mpcmp(p->d, dom->n) < 0)
break;
}
ecmul(dom, dom->G, p->d, p);
return p;
}
void
ecdsasign(ECdomain *dom, ECpriv *priv, uchar *dig, int len, mpint *r, mpint *s)
{
ECpriv tmp;
mpint *E, *t;
tmp.x = mpnew(0);
tmp.y = mpnew(0);
E = betomp(dig, len, nil);
t = mpnew(0);
if(mpsignif(dom->n) < 8*len)
mpright(E, 8*len - mpsignif(dom->n), E);
for(;;){
ecgen(dom, &tmp);
mpmod(tmp.x, dom->n, r);
if(mpcmp(r, mpzero) == 0)
continue;
mpmul(r, priv->d, s);
mpadd(E, s, s);
mpinvert(tmp.d, dom->n, t);
mpmul(s, t, s);
mpmod(s, dom->n, s);
if(mpcmp(s, mpzero) != 0)
break;
}
mpfree(t);
mpfree(E);
mpfree(tmp.x);
mpfree(tmp.y);
}
int
ecdsaverify(ECdomain *dom, ECpub *pub, uchar *dig, int len, mpint *r, mpint *s)
{
mpint *E, *t, *u1, *u2;
ECpoint R, S;
int ret;
if(mpcmp(r, mpone) < 0 || mpcmp(s, mpone) < 0 || mpcmp(r, dom->n) >= 0 || mpcmp(r, dom->n) >= 0)
return 0;
E = betomp(dig, len, nil);
if(mpsignif(dom->n) < 8*len)
mpright(E, 8*len - mpsignif(dom->n), E);
t = mpnew(0);
u1 = mpnew(0);
u2 = mpnew(0);
R.x = mpnew(0);
R.y = mpnew(0);
S.x = mpnew(0);
S.y = mpnew(0);
mpinvert(s, dom->n, t);
mpmul(E, t, u1);
mpmod(u1, dom->n, u1);
mpmul(r, t, u2);
mpmod(u2, dom->n, u2);
ecmul(dom, dom->G, u1, &R);
ecmul(dom, pub, u2, &S);
ecadd(dom, &R, &S, &R);
ret = 0;
if(!R.inf){
mpmod(R.x, dom->n, t);
ret = mpcmp(r, t) == 0;
}
mpfree(t);
mpfree(u1);
mpfree(u2);
mpfree(R.x);
mpfree(R.y);
mpfree(S.x);
mpfree(S.y);
return ret;
}

View file

@ -18,6 +18,8 @@ CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\
dsagen.c dsaalloc.c dsaprivtopub.c dsasign.c dsaverify.c \
tlshand.c thumb.c readcert.c \
aes_xts.c \
ecc.c\
ripemd.c\
ALLOFILES=${CFILES:%.c=%.$O}

View file

@ -0,0 +1,383 @@
#include "os.h"
#include <libsec.h>
#define BYTES_TO_DWORD(strptr) \
(((u32int) *((strptr)+3) << 24) | \
((u32int) *((strptr)+2) << 16) | \
((u32int) *((strptr)+1) << 8) | \
((u32int) *(strptr)))
#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* the five basic functions F(), G() and H() */
#define F(x, y, z) ((x) ^ (y) ^ (z))
#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define H(x, y, z) (((x) | ~(y)) ^ (z))
#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define J(x, y, z) ((x) ^ ((y) | ~(z)))
/* the ten basic operations FF() through III() */
#define FF(a, b, c, d, e, x, s) {\
(a) += F((b), (c), (d)) + (x);\
(a) = ROL((a), (s)) + (e);\
(c) = ROL((c), 10);\
}
#define GG(a, b, c, d, e, x, s) {\
(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
(a) = ROL((a), (s)) + (e);\
(c) = ROL((c), 10);\
}
#define HH(a, b, c, d, e, x, s) {\
(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
(a) = ROL((a), (s)) + (e);\
(c) = ROL((c), 10);\
}
#define II(a, b, c, d, e, x, s) {\
(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
(a) = ROL((a), (s)) + (e);\
(c) = ROL((c), 10);\
}
#define JJ(a, b, c, d, e, x, s) {\
(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\
(a) = ROL((a), (s)) + (e);\
(c) = ROL((c), 10);\
}
#define FFF(a, b, c, d, e, x, s) {\
(a) += F((b), (c), (d)) + (x);\
(a) = ROL((a), (s)) + (e);\
(c) = ROL((c), 10);\
}
#define GGG(a, b, c, d, e, x, s) {\
(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\
(a) = ROL((a), (s)) + (e);\
(c) = ROL((c), 10);\
}
#define HHH(a, b, c, d, e, x, s) {\
(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\
(a) = ROL((a), (s)) + (e);\
(c) = ROL((c), 10);\
}
#define III(a, b, c, d, e, x, s) {\
(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\
(a) = ROL((a), (s)) + (e);\
(c) = ROL((c), 10);\
}
#define JJJ(a, b, c, d, e, x, s) {\
(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\
(a) = ROL((a), (s)) + (e);\
(c) = ROL((c), 10);\
}
static void MDinit(u32int *MDbuf)
{
MDbuf[0] = 0x67452301UL;
MDbuf[1] = 0xefcdab89UL;
MDbuf[2] = 0x98badcfeUL;
MDbuf[3] = 0x10325476UL;
MDbuf[4] = 0xc3d2e1f0UL;
return;
}
static void compress(u32int *MDbuf, u32int *X)
{
u32int aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2],
dd = MDbuf[3], ee = MDbuf[4];
u32int aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2],
ddd = MDbuf[3], eee = MDbuf[4];
/* round 1 */
FF(aa, bb, cc, dd, ee, X[ 0], 11);
FF(ee, aa, bb, cc, dd, X[ 1], 14);
FF(dd, ee, aa, bb, cc, X[ 2], 15);
FF(cc, dd, ee, aa, bb, X[ 3], 12);
FF(bb, cc, dd, ee, aa, X[ 4], 5);
FF(aa, bb, cc, dd, ee, X[ 5], 8);
FF(ee, aa, bb, cc, dd, X[ 6], 7);
FF(dd, ee, aa, bb, cc, X[ 7], 9);
FF(cc, dd, ee, aa, bb, X[ 8], 11);
FF(bb, cc, dd, ee, aa, X[ 9], 13);
FF(aa, bb, cc, dd, ee, X[10], 14);
FF(ee, aa, bb, cc, dd, X[11], 15);
FF(dd, ee, aa, bb, cc, X[12], 6);
FF(cc, dd, ee, aa, bb, X[13], 7);
FF(bb, cc, dd, ee, aa, X[14], 9);
FF(aa, bb, cc, dd, ee, X[15], 8);
/* round 2 */
GG(ee, aa, bb, cc, dd, X[ 7], 7);
GG(dd, ee, aa, bb, cc, X[ 4], 6);
GG(cc, dd, ee, aa, bb, X[13], 8);
GG(bb, cc, dd, ee, aa, X[ 1], 13);
GG(aa, bb, cc, dd, ee, X[10], 11);
GG(ee, aa, bb, cc, dd, X[ 6], 9);
GG(dd, ee, aa, bb, cc, X[15], 7);
GG(cc, dd, ee, aa, bb, X[ 3], 15);
GG(bb, cc, dd, ee, aa, X[12], 7);
GG(aa, bb, cc, dd, ee, X[ 0], 12);
GG(ee, aa, bb, cc, dd, X[ 9], 15);
GG(dd, ee, aa, bb, cc, X[ 5], 9);
GG(cc, dd, ee, aa, bb, X[ 2], 11);
GG(bb, cc, dd, ee, aa, X[14], 7);
GG(aa, bb, cc, dd, ee, X[11], 13);
GG(ee, aa, bb, cc, dd, X[ 8], 12);
/* round 3 */
HH(dd, ee, aa, bb, cc, X[ 3], 11);
HH(cc, dd, ee, aa, bb, X[10], 13);
HH(bb, cc, dd, ee, aa, X[14], 6);
HH(aa, bb, cc, dd, ee, X[ 4], 7);
HH(ee, aa, bb, cc, dd, X[ 9], 14);
HH(dd, ee, aa, bb, cc, X[15], 9);
HH(cc, dd, ee, aa, bb, X[ 8], 13);
HH(bb, cc, dd, ee, aa, X[ 1], 15);
HH(aa, bb, cc, dd, ee, X[ 2], 14);
HH(ee, aa, bb, cc, dd, X[ 7], 8);
HH(dd, ee, aa, bb, cc, X[ 0], 13);
HH(cc, dd, ee, aa, bb, X[ 6], 6);
HH(bb, cc, dd, ee, aa, X[13], 5);
HH(aa, bb, cc, dd, ee, X[11], 12);
HH(ee, aa, bb, cc, dd, X[ 5], 7);
HH(dd, ee, aa, bb, cc, X[12], 5);
/* round 4 */
II(cc, dd, ee, aa, bb, X[ 1], 11);
II(bb, cc, dd, ee, aa, X[ 9], 12);
II(aa, bb, cc, dd, ee, X[11], 14);
II(ee, aa, bb, cc, dd, X[10], 15);
II(dd, ee, aa, bb, cc, X[ 0], 14);
II(cc, dd, ee, aa, bb, X[ 8], 15);
II(bb, cc, dd, ee, aa, X[12], 9);
II(aa, bb, cc, dd, ee, X[ 4], 8);
II(ee, aa, bb, cc, dd, X[13], 9);
II(dd, ee, aa, bb, cc, X[ 3], 14);
II(cc, dd, ee, aa, bb, X[ 7], 5);
II(bb, cc, dd, ee, aa, X[15], 6);
II(aa, bb, cc, dd, ee, X[14], 8);
II(ee, aa, bb, cc, dd, X[ 5], 6);
II(dd, ee, aa, bb, cc, X[ 6], 5);
II(cc, dd, ee, aa, bb, X[ 2], 12);
/* round 5 */
JJ(bb, cc, dd, ee, aa, X[ 4], 9);
JJ(aa, bb, cc, dd, ee, X[ 0], 15);
JJ(ee, aa, bb, cc, dd, X[ 5], 5);
JJ(dd, ee, aa, bb, cc, X[ 9], 11);
JJ(cc, dd, ee, aa, bb, X[ 7], 6);
JJ(bb, cc, dd, ee, aa, X[12], 8);
JJ(aa, bb, cc, dd, ee, X[ 2], 13);
JJ(ee, aa, bb, cc, dd, X[10], 12);
JJ(dd, ee, aa, bb, cc, X[14], 5);
JJ(cc, dd, ee, aa, bb, X[ 1], 12);
JJ(bb, cc, dd, ee, aa, X[ 3], 13);
JJ(aa, bb, cc, dd, ee, X[ 8], 14);
JJ(ee, aa, bb, cc, dd, X[11], 11);
JJ(dd, ee, aa, bb, cc, X[ 6], 8);
JJ(cc, dd, ee, aa, bb, X[15], 5);
JJ(bb, cc, dd, ee, aa, X[13], 6);
/* parallel round 1 */
JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8);
JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9);
JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9);
JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11);
JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13);
JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15);
JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15);
JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5);
JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7);
JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7);
JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8);
JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11);
JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14);
JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14);
JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12);
JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6);
/* parallel round 2 */
III(eee, aaa, bbb, ccc, ddd, X[ 6], 9);
III(ddd, eee, aaa, bbb, ccc, X[11], 13);
III(ccc, ddd, eee, aaa, bbb, X[ 3], 15);
III(bbb, ccc, ddd, eee, aaa, X[ 7], 7);
III(aaa, bbb, ccc, ddd, eee, X[ 0], 12);
III(eee, aaa, bbb, ccc, ddd, X[13], 8);
III(ddd, eee, aaa, bbb, ccc, X[ 5], 9);
III(ccc, ddd, eee, aaa, bbb, X[10], 11);
III(bbb, ccc, ddd, eee, aaa, X[14], 7);
III(aaa, bbb, ccc, ddd, eee, X[15], 7);
III(eee, aaa, bbb, ccc, ddd, X[ 8], 12);
III(ddd, eee, aaa, bbb, ccc, X[12], 7);
III(ccc, ddd, eee, aaa, bbb, X[ 4], 6);
III(bbb, ccc, ddd, eee, aaa, X[ 9], 15);
III(aaa, bbb, ccc, ddd, eee, X[ 1], 13);
III(eee, aaa, bbb, ccc, ddd, X[ 2], 11);
/* parallel round 3 */
HHH(ddd, eee, aaa, bbb, ccc, X[15], 9);
HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7);
HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15);
HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11);
HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8);
HHH(ddd, eee, aaa, bbb, ccc, X[14], 6);
HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6);
HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14);
HHH(aaa, bbb, ccc, ddd, eee, X[11], 12);
HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13);
HHH(ddd, eee, aaa, bbb, ccc, X[12], 5);
HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14);
HHH(bbb, ccc, ddd, eee, aaa, X[10], 13);
HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13);
HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7);
HHH(ddd, eee, aaa, bbb, ccc, X[13], 5);
/* parallel round 4 */
GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15);
GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5);
GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8);
GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11);
GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14);
GGG(ccc, ddd, eee, aaa, bbb, X[11], 14);
GGG(bbb, ccc, ddd, eee, aaa, X[15], 6);
GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14);
GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6);
GGG(ddd, eee, aaa, bbb, ccc, X[12], 9);
GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12);
GGG(bbb, ccc, ddd, eee, aaa, X[13], 9);
GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12);
GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5);
GGG(ddd, eee, aaa, bbb, ccc, X[10], 15);
GGG(ccc, ddd, eee, aaa, bbb, X[14], 8);
/* parallel round 5 */
FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8);
FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5);
FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12);
FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9);
FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12);
FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5);
FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14);
FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6);
FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8);
FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13);
FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6);
FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5);
FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15);
FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13);
FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11);
FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11);
/* combine results */
ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */
MDbuf[1] = MDbuf[2] + dd + eee;
MDbuf[2] = MDbuf[3] + ee + aaa;
MDbuf[3] = MDbuf[4] + aa + bbb;
MDbuf[4] = MDbuf[0] + bb + ccc;
MDbuf[0] = ddd;
return;
}
static void MDfinish(u32int *MDbuf, uchar *strptr, u32int lswlen, u32int mswlen)
{
unsigned int i; /* counter */
u32int X[16]; /* message words */
memset(X, 0, 16*sizeof(u32int));
/* put bytes from strptr into X */
for (i=0; i<(lswlen&63); i++) {
/* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */
X[i>>2] ^= (u32int) *strptr++ << (8 * (i&3));
}
/* append the bit m_n == 1 */
X[(lswlen>>2)&15] ^= (u32int)1 << (8*(lswlen&3) + 7);
if ((lswlen & 63) > 55) {
/* length goes to next block */
compress(MDbuf, X);
memset(X, 0, 16*sizeof(u32int));
}
/* append length in bits*/
X[14] = lswlen << 3;
X[15] = (lswlen >> 29) | (mswlen << 3);
compress(MDbuf, X);
return;
}
DigestState*
ripemd160(uchar *p, ulong len, uchar *digest, DigestState *s)
{
u32int x[16];
int i, j, k;
if(s == nil){
s = malloc(sizeof(*s));
if(s == nil)
return nil;
memset(s, 0, sizeof(*s));
s->malloced = 1;
}
if(s->seeded == 0){
MDinit(s->state);
s->seeded = 1;
}
/* fill out the partial 64 byte block from previous calls */
if(s->blen){
i = 64 - s->blen;
if(len < i)
i = len;
memmove(s->buf + s->blen, p, i);
len -= i;
s->blen += i;
p += i;
if(s->blen == 64){
for(i = 0; i < 16; i++)
x[i] = BYTES_TO_DWORD(s->buf + i * 4);
compress(s->state, x);
s->len += s->blen;
s->blen = 0;
}
}
/* do 64 byte blocks */
i = len & ~0x3f;
if(i){
for(j = 0; j < i; j += 64){
for(k = 0; k < 16; k++)
x[k] = BYTES_TO_DWORD(p + j + k * 4);
compress(s->state, x);
}
s->len += i;
len -= i;
p += i;
}
/* save the left overs if not last call */
if(digest == 0){
if(len){
memmove(s->buf, p, len);
s->blen += len;
}
return s;
}
MDfinish(s->state, p, s->len + len, 0);
for(i = 0; i < 5; i++){
digest[4 * i] = s->state[i];
digest[4 * i + 1] = s->state[i] >> 8;
digest[4 * i + 2] = s->state[i] >> 16;
digest[4 * i + 3] = s->state[i] >> 24;
}
if(s->malloced == 1)
free(s);
return nil;
}