diff options
author | aiju <aiju@phicode.de> | 2012-06-06 16:43:15 +0200 |
---|---|---|
committer | aiju <aiju@phicode.de> | 2012-06-06 16:43:15 +0200 |
commit | d2357e6961b3b3a80c51f03e0e01e7c80c5c0415 (patch) | |
tree | 18ef8ba9afbb3f1b2585465c0501c3f7454ab58b /sys/src/cmd/auth | |
parent | 46efa642ad05b65dfb62cf1fa86edfe3ce75ee86 (diff) |
added ecdsa to factotum
Diffstat (limited to 'sys/src/cmd/auth')
-rw-r--r-- | sys/src/cmd/auth/factotum/dat.h | 1 | ||||
-rw-r--r-- | sys/src/cmd/auth/factotum/ecdsa.c | 204 | ||||
-rw-r--r-- | sys/src/cmd/auth/factotum/fs.c | 1 | ||||
-rw-r--r-- | sys/src/cmd/auth/factotum/mkfile | 1 |
4 files changed, 207 insertions, 0 deletions
diff --git a/sys/src/cmd/auth/factotum/dat.h b/sys/src/cmd/auth/factotum/dat.h index c8203cafa..b36f869e5 100644 --- a/sys/src/cmd/auth/factotum/dat.h +++ b/sys/src/cmd/auth/factotum/dat.h @@ -237,3 +237,4 @@ extern Proto rsa; /* rsa.c */ extern Proto wep; /* wep.c */ /* extern Proto srs; /* srs.c */ extern Proto httpdigest; /* httpdigest.c */ +extern Proto ecdsa; diff --git a/sys/src/cmd/auth/factotum/ecdsa.c b/sys/src/cmd/auth/factotum/ecdsa.c new file mode 100644 index 000000000..d21c97299 --- /dev/null +++ b/sys/src/cmd/auth/factotum/ecdsa.c @@ -0,0 +1,204 @@ +#include "dat.h" + +enum { + CHaveKey, + CHaveText, + Maxphase +}; + +static ECdomain dom; + +static char *phasenames[] = { + "CHaveKey", + "CHaveText", +}; + +struct State { + ECpriv p; + char *sign; +}; + +static int +decryptkey(Fsstate *fss, char *key, char *password) +{ + uchar keyenc[53], hash[32], ivec[AESbsize]; + AESstate s; + State *st; + char buf[100]; + + if(base58dec(key, keyenc, 53) < 0) + return failure(fss, "invalid base58"); + sha2_256((uchar *)password, strlen(password), hash, nil); + sha2_256(hash, 32, hash, nil); + genrandom(ivec, sizeof ivec); + setupAESstate(&s, hash, 32, keyenc+37); + aesCBCdecrypt(keyenc, 37, &s); + memset(buf, 0, sizeof buf); + base58enc(keyenc, buf, 37); + if(keyenc[0] != 0x80) + return failure(fss, "invalid key '%s'", buf); + sha2_256(keyenc, 33, hash, nil); + sha2_256(hash, 32, hash, nil); + if(memcmp(keyenc + 33, hash, 4) != 0) + return failure(fss, "checksum error"); + st = fss->ps; + st->p.d = betomp(keyenc + 1, 32, nil); + st->p.x = mpnew(0); + st->p.y = mpnew(0); + ecmul(&dom, dom.G, st->p.d, &st->p); + return RpcOk; +} + +static int +ecdsainit(Proto *, Fsstate *fss) +{ + int iscli; + Key *k; + Keyinfo ki; + int ret; + char *key, *password; + Attr *attr; + + if(dom.p == nil){ + dom.p = strtomp("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", nil, 16, nil); + dom.a = uitomp(0, nil); + dom.b = uitomp(7, nil); + dom.n = strtomp("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", nil, 16, nil); + dom.h = uitomp(1, nil); + dom.G = strtoec(&dom, "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", nil, nil); + } + if((iscli = isclient(_strfindattr(fss->attr, "role"))) < 0) + return failure(fss, nil); + if(iscli==0) + return failure(fss, "ecdsa server unimplemented"); + mkkeyinfo(&ki, fss, nil); + ret = findkey(&k, &ki, "key? !password?"); + if(ret == RpcOk){ + key = _strfindattr(k->attr, "key"); + password = _strfindattr(k->privattr, "!password"); + + }else{ + if(!_strfindattr(fss->attr, "dom")) + return ret; + attr = _copyattr(fss->attr); + _delattr(attr, "key"); + mkkeyinfo(&ki, fss, attr); + ret = findkey(&k, &ki, "dom? !password?"); + if(ret != RpcOk) + return ret; + key = _strfindattr(fss->attr, "key"); + password = _strfindattr(k->privattr, "!password"); + } + if(key == nil || password == nil) + return RpcNeedkey; + fss->ps = malloc(sizeof(State)); + ret = decryptkey(fss, key, password); + if(ret != RpcOk) + return ret; + + setattrs(fss->attr, k->attr); + fss->phasename = phasenames; + fss->maxphase = Maxphase; + fss->phase = CHaveKey; + return RpcOk; +} + +static char * +derencode(mpint *r, mpint *s) +{ + uchar buf[100], rk[33], sk[33]; + char *str; + int rl, sl, i; + + mptobe(r, rk, 32, nil); + mptobe(s, sk, 32, nil); + rl = (mpsignif(r) + 7)/8; + sl = (mpsignif(s) + 7)/8; + if(rk[0] & 0x80){ + memmove(rk + 1, rk, 32); + rk[0] = 0; + rl++; + } + if(sk[0] & 0x80){ + memmove(sk + 1, sk, 32); + sk[0] = 0; + sl++; + } + buf[0] = 0x30; + buf[1] = 4 + rl + sl; + buf[2] = 0x02; + buf[3] = rl; + memmove(buf + 4, rk, rl); + buf[4 + rl] = 0x02; + buf[5 + rl] = sl; + memmove(buf + 6 + rl, sk, sl); + str = malloc(1024); + for(i = 0; i < 6 + rl + sl; i++) + sprint(str + 2 * i, "%.2x", buf[i]); + return str; +} + +static int +ecdsawrite(Fsstate *fss, void *va, uint n) +{ + State *st; + uchar hash[32]; + mpint *r, *s; + + st = fss->ps; + switch(fss->phase){ + default: + return phaseerror(fss, "write"); + case CHaveKey: + sha2_256(va, n, hash, nil); + sha2_256(hash, 32, hash, nil); + r = mpnew(0); + s = mpnew(0); + ecdsasign(&dom, &st->p, hash, 32, r, s); + st->sign = derencode(r, s); + mpfree(r); + mpfree(s); + fss->phase = CHaveText; + return RpcOk; + } +} + +static int +ecdsaread(Fsstate *fss, void *va, uint *n) +{ + switch(fss->phase){ + default: + return phaseerror(fss, "read"); + case CHaveText: + *n = snprint(va, *n, ((State *)fss->ps)->sign); + fss->phase = Established; + return RpcOk; + } +} + +static void +ecdsaclose(Fsstate *fss) +{ + State *st; + + st = fss->ps; + if(st->p.x != nil){ + mpfree(st->p.x); + mpfree(st->p.y); + mpfree(st->p.d); + } + if(st->sign != nil) + free(st->sign); + free(st); + fss->ps = nil; +} + +Proto ecdsa = { + .name = "ecdsa", + .init = ecdsainit, + .read = ecdsaread, + .write = ecdsawrite, + .close = ecdsaclose, + .addkey = replacekey, + .keyprompt= "key? !password?", +}; diff --git a/sys/src/cmd/auth/factotum/fs.c b/sys/src/cmd/auth/factotum/fs.c index 7d204aa09..78176f781 100644 --- a/sys/src/cmd/auth/factotum/fs.c +++ b/sys/src/cmd/auth/factotum/fs.c @@ -40,6 +40,7 @@ prototab[] = &rsa, &vnc, &wep, + &ecdsa, nil, }; diff --git a/sys/src/cmd/auth/factotum/mkfile b/sys/src/cmd/auth/factotum/mkfile index 1bdf31a62..fe1bb1526 100644 --- a/sys/src/cmd/auth/factotum/mkfile +++ b/sys/src/cmd/auth/factotum/mkfile @@ -13,6 +13,7 @@ PROTO=\ pass.$O\ rsa.$O\ wep.$O\ + ecdsa.$O\ FOFILES=\ $PROTO\ |