diff options
author | aiju <aiju@phicode.de> | 2012-06-04 11:50:37 +0200 |
---|---|---|
committer | aiju <aiju@phicode.de> | 2012-06-04 11:50:37 +0200 |
commit | 005248b4c5277e149c6e673949c874ce76774fde (patch) | |
tree | 3a1d09156d6b6e237ea3e00c45a884700c9c2351 | |
parent | c065e02a99635971809a8a1b34dd0874c30ec800 (diff) |
added elliptic curve stuff and RIPEMD-160
-rw-r--r-- | sys/include/libsec.h | 35 | ||||
-rw-r--r-- | sys/src/libsec/port/ecc.c | 484 | ||||
-rw-r--r-- | sys/src/libsec/port/mkfile | 2 | ||||
-rw-r--r-- | sys/src/libsec/port/ripemd.c | 383 |
4 files changed, 903 insertions, 1 deletions
diff --git a/sys/include/libsec.h b/sys/include/libsec.h index 3bde79323..bc20ab847 100644 --- a/sys/include/libsec.h +++ b/sys/include/libsec.h @@ -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);
\ No newline at end of file +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 *);
\ No newline at end of file diff --git a/sys/src/libsec/port/ecc.c b/sys/src/libsec/port/ecc.c new file mode 100644 index 000000000..eb5c593af --- /dev/null +++ b/sys/src/libsec/port/ecc.c @@ -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; +} diff --git a/sys/src/libsec/port/mkfile b/sys/src/libsec/port/mkfile index b14df90a4..59d2f17ac 100644 --- a/sys/src/libsec/port/mkfile +++ b/sys/src/libsec/port/mkfile @@ -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} diff --git a/sys/src/libsec/port/ripemd.c b/sys/src/libsec/port/ripemd.c new file mode 100644 index 000000000..72138081f --- /dev/null +++ b/sys/src/libsec/port/ripemd.c @@ -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; + +} |