diff options
Diffstat (limited to 'appl')
| -rw-r--r-- | appl/lib/mkfile | 2 | ||||
| -rw-r--r-- | appl/lib/oldauth.b | 344 |
2 files changed, 346 insertions, 0 deletions
diff --git a/appl/lib/mkfile b/appl/lib/mkfile index e681967e..279ca1ac 100644 --- a/appl/lib/mkfile +++ b/appl/lib/mkfile @@ -77,6 +77,8 @@ TARG=\ nametree.dis\ names.dis\ newns.dis\ + ninep.dis\ + oldauth.dis\ palm.dis\ palmdb.dis\ palmfile.dis\ diff --git a/appl/lib/oldauth.b b/appl/lib/oldauth.b new file mode 100644 index 00000000..60bd9f54 --- /dev/null +++ b/appl/lib/oldauth.b @@ -0,0 +1,344 @@ +implement Oldauth; + +# +# TO DO +# - more error checking? +# - details of auth error handling +# + +include "sys.m"; + sys: Sys; + +include "ipints.m"; + ipints: IPints; + IPint: import ipints; + +include "crypt.m"; + crypt: Crypt; + PK, SK, PKsig: import crypt; + +include "msgio.m"; + msgio: Msgio; + +include "oldauth.m"; + +init() +{ + sys = load Sys Sys->PATH; + ipints = load IPints IPints->PATH; + crypt = load Crypt Crypt->PATH; + msgio = load Msgio Msgio->PATH; + msgio->init(); +} + +efmt() +{ + sys->werrstr("input or format error"); +} + +readauthinfo(filename: string): ref Authinfo +{ + fd := sys->open(filename, Sys->OREAD); + if(fd == nil) + return nil; + a := array[5] of string; + for(i := 0; i < len a; i++){ + (s, err) := getstr(fd); + if(err != nil){ + sys->werrstr(sys->sprint("%q: input or format error", filename)); + return nil; + } + a[i] = s; + } + info := ref Authinfo; + (info.spk, nil) = strtopk(a[0]); + info.cert = strtocert(a[1]); + (info.mysk, info.owner) = strtosk(a[2]); + if(info.spk == nil || info.cert == nil || info.mysk == nil){ + efmt(); + return nil; + } + info.mypk = crypt->sktopk(info.mysk); + info.alpha = IPint.strtoip(a[3], 64); + info.p = IPint.strtoip(a[4], 64); + if(info.alpha == nil || info.p == nil){ + efmt(); + return nil; + } + return info; +} + +writeauthinfo(filename: string, info: ref Authinfo): int +{ + if(info.alpha == nil || info.p == nil || + info.spk == nil || info.mysk == nil || info.cert == nil){ + sys->werrstr("invalid authinfo"); + return -1; + } + a := array[5] of string; + a[0] = pktostr(info.spk, info.cert.signer); # signer's public key + a[1] = certtostr(info.cert); # certificate for my public key + a[2] = sktostr(info.mysk, info.owner); # my secret/public key + a[3] = b64(info.alpha); # diffie hellman base + a[4] = b64(info.p); # diffie hellman modulus + fd := sys->open(filename, Sys->OWRITE|Sys->OTRUNC); + if(fd == nil){ + fd = sys->create(filename, Sys->OWRITE, 8r600); + if(fd == nil){ + fd = sys->open(filename, Sys->OWRITE); + if(fd == nil) + return -1; + } + } + for(i := 0; i < len a; i++) + if(sendstr(fd, a[i]) <= 0) + return -1; + return 0; +} + +sendstr(fd: ref Sys->FD, s: string): int +{ + a := array of byte s; + return msgio->sendmsg(fd, a, len a); +} + +getstr(fd: ref Sys->FD): (string, string) +{ + b := msgio->getmsg(fd); + if(b == nil) + return (nil, sys->sprint("%r")); + return (string b, nil); +} + +certtostr(c: ref Certificate): string +{ + s := sys->sprint("%s\n%s\n%s\n%ud\n", c.sa, c.ha, c.signer, c.exp); + pick r := c.sig { + RSA => + s += b64(r.n)+"\n"; + Elgamal => + s += b64(r.r)+"\n"+b64(r.s)+"\n"; + DSA => + s += b64(r.r)+"\n"+b64(r.s)+"\n"; + * => + raise "unknown key type"; + } + return s; +} + +pktostr(pk: ref PK, owner: string): string +{ + pick k := pk { + RSA => + s := sys->sprint("rsa\n%s\n", owner); + s += b64(k.n)+"\n"+b64(k.ek)+"\n"; + return s; + Elgamal => + s := sys->sprint("elgamal\n%s\n", owner); + s += b64(k.p)+"\n"+b64(k.alpha)+"\n"+b64(k.key)+"\n"; + return s; + DSA => + s := sys->sprint("dsa\n%s\n", owner); + s += b64(k.p)+"\n"+b64(k.q)+"\n"+b64(k.alpha)+"\n"+b64(k.key)+"\n"; + return s; + * => + raise "unknown key type"; + } +} + +sktostr(sk: ref SK, owner: string): string +{ + pick k := sk { + RSA => + s := sys->sprint("rsa\n%s\n", owner); + s += b64(k.pk.n)+"\n"+b64(k.pk.ek)+"\n"+b64(k.dk)+"\n"+ + b64(k.p)+"\n"+b64(k.q)+"\n"+ + b64(k.kp)+"\n"+b64(k.kq)+"\n"+ + k.c2.iptob64()+"\n"; + return s; + Elgamal => + pk := k.pk; + s := sys->sprint("elgamal\n%s\n", owner); + s += b64(pk.p)+"\n"+b64(pk.alpha)+"\n"+b64(pk.key)+"\n"+b64(k.secret)+"\n"; + return s; + DSA => + pk := k.pk; + s := sys->sprint("dsa\n%s\n", owner); + s += b64(pk.p)+"\n"+b64(pk.q)+"\n"+b64(pk.alpha)+"\n"+b64(k.secret)+"\n"; + return s; + * => + raise "unknown key type"; + } +} + +fields(s: string): array of string +{ + (nf, flds) := sys->tokenize(s, "\n^"); + a := array[nf] of string; + for(i := 0; i < len a; i++){ + a[i] = hd flds; + flds = tl flds; + } + return a; +} + +bigs(a: array of string): array of ref IPint +{ + b := array[len a] of ref IPint; + for(i := 0; i < len b; i++){ + b[i] = IPint.strtoip(a[i], 64); + if(b[i] == nil) + return nil; + } + return b; +} + +need[T](a: array of T, min: int): int +{ + if(len a < min){ + efmt(); + return 1; + } + return 0; +} + +strtocert(s: string): ref Certificate +{ + f := fields(s); + if(need(f, 4)) + return nil; + sa := f[0]; + ha := f[1]; + signer := f[2]; + exp := int big f[3]; # unsigned + b := bigs(f[4:]); + case f[0] { + "rsa" => + if(need(b, 1)) + return nil; + return ref Certificate(sa, ha, signer, exp, ref PKsig.RSA(b[0])); + "elgamal" => + if(need(b, 2)) + return nil; + return ref Certificate(sa, ha, signer, exp, ref PKsig.Elgamal(b[0], b[1])); + "dsa" => + if(need(b, 2)) + return nil; + return ref Certificate(sa, ha, signer, exp, ref PKsig.DSA(b[0], b[1])); + * => + sys->werrstr("unknown algorithm: "+f[0]); + return nil; + } +} + +strtopk(s: string): (ref PK, string) +{ + f := fields(s); + if(need(f, 3)) + return (nil, "format error"); + sa := f[0]; + owner := f[1]; + b := bigs(f[2:]); + case sa { + "rsa" => + if(need(b, 2)) + return (nil, "format error"); + return (ref PK.RSA(b[0], b[1]), owner); + "elgamal" => + if(need(b, 3)) + return (nil, "format error"); + return (ref PK.Elgamal(b[0], b[1], b[2]), owner); + "dsa" => + if(need(b, 4)) + return (nil, "format error"); + return (ref PK.DSA(b[0], b[1], b[2], b[3]), owner); + * => + return (nil, "unknown algorithm: "+f[0]); + } +} + +strtosk(s: string): (ref SK, string) +{ + f := fields(s); + if(need(f, 3)) + return (nil, "format error"); + sa := f[0]; + owner := f[1]; + b := bigs(f[2:]); + case sa { + "rsa" => + if(need(b, 8)) + return (nil, "format error"); + return (ref SK.RSA(ref PK.RSA(b[0], b[1]), b[2], b[3], b[4], b[5], b[6], b[7]), owner); + "elgamal" => + if(need(b, 4)) + return (nil, "format error"); + return (ref SK.Elgamal(ref PK.Elgamal(b[0], b[1], b[2]), b[3]), owner); + "dsa" => + if(need(b, 5)) + return (nil, "format error"); + return (ref SK.DSA(ref PK.DSA(b[0], b[1], b[2], b[3]), b[4]), owner); + * => + return (nil, "unknown algorithm: "+f[0]); + } +} + +skalg(sk: ref SK): string +{ + if(sk == nil) + return "nil"; + case tagof sk { + tagof SK.RSA => return "rsa"; + tagof SK.Elgamal => return "elgamal"; + tagof SK.DSA => return "dsa"; + * => return "gok"; + } +} + +sign(sk: ref SK, signer: string, exp: int, state: ref Crypt->DigestState, ha: string): ref Certificate +{ + # add signer name and expiration time to hash + if(state == nil) + return nil; + a := sys->aprint("%s %d", signer, exp); + digest := hash(ha, a, state); + if(digest == nil) + return nil; + b := IPint.bebytestoip(digest); + return ref Certificate(skalg(sk), ha, signer, exp, crypt->sign(sk, b)); +} + +verify(pk: ref PK, cert: ref Certificate, state: ref Crypt->DigestState): int +{ + if(state == nil) + return 0; + a := sys->aprint("%s %d", cert.signer, cert.exp); + digest := hash(cert.ha, a, state); + if(digest == nil) + return 0; + b := IPint.bebytestoip(digest); + return crypt->verify(pk, cert.sig, b); +} + +hash(ha: string, a: array of byte, state: ref Crypt->DigestState): array of byte +{ + digest: array of byte; + case ha { + "sha" or "sha1" => + digest = array[Crypt->SHA1dlen] of byte; + crypt->sha1(a, len a, digest, state); + "md5" => + digest = array[Crypt->MD5dlen] of byte; + crypt->md5(a, len a, digest, state); + * => + # don't bother with md4 + sys->werrstr("unimplemented algorithm: "+ha); + return nil; + } + return digest; +} + +b64(ip: ref IPint): string +{ + return ip.iptob64z(); +} |
