added ecdsa to factotum
This commit is contained in:
parent
46efa642ad
commit
d2357e6961
6 changed files with 265 additions and 1 deletions
|
@ -435,5 +435,7 @@ int ecverify(ECdomain *, ECpoint *);
|
||||||
int ecpubverify(ECdomain *, ECpub *);
|
int ecpubverify(ECdomain *, ECpub *);
|
||||||
void ecdsasign(ECdomain *, ECpriv *, uchar *, int, mpint *, mpint *);
|
void ecdsasign(ECdomain *, ECpriv *, uchar *, int, mpint *, mpint *);
|
||||||
int ecdsaverify(ECdomain *, ECpub *, uchar *, int, mpint *, mpint *);
|
int ecdsaverify(ECdomain *, ECpub *, uchar *, int, mpint *, mpint *);
|
||||||
|
void base58enc(uchar *, char *, int);
|
||||||
|
int base58dec(char *, uchar *, int);
|
||||||
|
|
||||||
DigestState* ripemd160(uchar *, ulong, uchar *, DigestState *);
|
DigestState* ripemd160(uchar *, ulong, uchar *, DigestState *);
|
||||||
|
|
|
@ -237,3 +237,4 @@ extern Proto rsa; /* rsa.c */
|
||||||
extern Proto wep; /* wep.c */
|
extern Proto wep; /* wep.c */
|
||||||
/* extern Proto srs; /* srs.c */
|
/* extern Proto srs; /* srs.c */
|
||||||
extern Proto httpdigest; /* httpdigest.c */
|
extern Proto httpdigest; /* httpdigest.c */
|
||||||
|
extern Proto ecdsa;
|
||||||
|
|
204
sys/src/cmd/auth/factotum/ecdsa.c
Normal file
204
sys/src/cmd/auth/factotum/ecdsa.c
Normal file
|
@ -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?",
|
||||||
|
};
|
|
@ -40,6 +40,7 @@ prototab[] =
|
||||||
&rsa,
|
&rsa,
|
||||||
&vnc,
|
&vnc,
|
||||||
&wep,
|
&wep,
|
||||||
|
&ecdsa,
|
||||||
nil,
|
nil,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ PROTO=\
|
||||||
pass.$O\
|
pass.$O\
|
||||||
rsa.$O\
|
rsa.$O\
|
||||||
wep.$O\
|
wep.$O\
|
||||||
|
ecdsa.$O\
|
||||||
|
|
||||||
FOFILES=\
|
FOFILES=\
|
||||||
$PROTO\
|
$PROTO\
|
||||||
|
|
|
@ -482,3 +482,58 @@ ecdsaverify(ECdomain *dom, ECpub *pub, uchar *dig, int len, mpint *r, mpint *s)
|
||||||
mpfree(S.y);
|
mpfree(S.y);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *code = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||||
|
|
||||||
|
void
|
||||||
|
base58enc(uchar *src, char *dst, int len)
|
||||||
|
{
|
||||||
|
mpint *n, *r, *b;
|
||||||
|
char *sdst, t;
|
||||||
|
|
||||||
|
sdst = dst;
|
||||||
|
n = betomp(src, len, nil);
|
||||||
|
b = uitomp(58, nil);
|
||||||
|
r = mpnew(0);
|
||||||
|
while(mpcmp(n, mpzero) != 0){
|
||||||
|
mpdiv(n, b, n, r);
|
||||||
|
*dst++ = code[mptoui(r)];
|
||||||
|
}
|
||||||
|
for(; *src == 0; src++)
|
||||||
|
*dst++ = code[0];
|
||||||
|
dst--;
|
||||||
|
while(dst > sdst){
|
||||||
|
t = *sdst;
|
||||||
|
*sdst++ = *dst;
|
||||||
|
*dst-- = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
base58dec(char *src, uchar *dst, int len)
|
||||||
|
{
|
||||||
|
mpint *n, *b, *r;
|
||||||
|
char *t;
|
||||||
|
|
||||||
|
n = mpnew(0);
|
||||||
|
r = mpnew(0);
|
||||||
|
b = uitomp(58, nil);
|
||||||
|
for(; *src; src++){
|
||||||
|
t = strchr(code, *src);
|
||||||
|
if(t == nil){
|
||||||
|
mpfree(n);
|
||||||
|
mpfree(r);
|
||||||
|
mpfree(b);
|
||||||
|
werrstr("invalid base58 char");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uitomp(t - code, r);
|
||||||
|
mpmul(n, b, n);
|
||||||
|
mpadd(n, r, n);
|
||||||
|
}
|
||||||
|
mptobe(n, dst, len, nil);
|
||||||
|
mpfree(n);
|
||||||
|
mpfree(r);
|
||||||
|
mpfree(b);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue