1implement Oldauth; 2 3# 4# TO DO 5# - more error checking? 6# - details of auth error handling 7# 8 9include "sys.m"; 10 sys: Sys; 11 12include "ipints.m"; 13 ipints: IPints; 14 IPint: import ipints; 15 16include "crypt.m"; 17 crypt: Crypt; 18 PK, SK, PKsig: import crypt; 19 20include "msgio.m"; 21 msgio: Msgio; 22 23include "oldauth.m"; 24 25init() 26{ 27 sys = load Sys Sys->PATH; 28 ipints = load IPints IPints->PATH; 29 crypt = load Crypt Crypt->PATH; 30 msgio = load Msgio Msgio->PATH; 31 msgio->init(); 32} 33 34efmt() 35{ 36 sys->werrstr("input or format error"); 37} 38 39readauthinfo(filename: string): ref Authinfo 40{ 41 fd := sys->open(filename, Sys->OREAD); 42 if(fd == nil) 43 return nil; 44 a := array[5] of string; 45 for(i := 0; i < len a; i++){ 46 (s, err) := getstr(fd); 47 if(err != nil){ 48 sys->werrstr(sys->sprint("%q: input or format error", filename)); 49 return nil; 50 } 51 a[i] = s; 52 } 53 info := ref Authinfo; 54 (info.spk, nil) = strtopk(a[0]); 55 info.cert = strtocert(a[1]); 56 (info.mysk, info.owner) = strtosk(a[2]); 57 if(info.spk == nil || info.cert == nil || info.mysk == nil){ 58 efmt(); 59 return nil; 60 } 61 info.mypk = crypt->sktopk(info.mysk); 62 info.alpha = IPint.strtoip(a[3], 64); 63 info.p = IPint.strtoip(a[4], 64); 64 if(info.alpha == nil || info.p == nil){ 65 efmt(); 66 return nil; 67 } 68 return info; 69} 70 71writeauthinfo(filename: string, info: ref Authinfo): int 72{ 73 if(info.alpha == nil || info.p == nil || 74 info.spk == nil || info.mysk == nil || info.cert == nil){ 75 sys->werrstr("invalid authinfo"); 76 return -1; 77 } 78 a := array[5] of string; 79 a[0] = pktostr(info.spk, info.cert.signer); # signer's public key 80 a[1] = certtostr(info.cert); # certificate for my public key 81 a[2] = sktostr(info.mysk, info.owner); # my secret/public key 82 a[3] = b64(info.alpha); # diffie hellman base 83 a[4] = b64(info.p); # diffie hellman modulus 84 fd := sys->open(filename, Sys->OWRITE|Sys->OTRUNC); 85 if(fd == nil){ 86 fd = sys->create(filename, Sys->OWRITE, 8r600); 87 if(fd == nil){ 88 fd = sys->open(filename, Sys->OWRITE); 89 if(fd == nil) 90 return -1; 91 } 92 } 93 for(i := 0; i < len a; i++) 94 if(sendstr(fd, a[i]) <= 0) 95 return -1; 96 return 0; 97} 98 99sendstr(fd: ref Sys->FD, s: string): int 100{ 101 a := array of byte s; 102 return msgio->sendmsg(fd, a, len a); 103} 104 105getstr(fd: ref Sys->FD): (string, string) 106{ 107 b := msgio->getmsg(fd); 108 if(b == nil) 109 return (nil, sys->sprint("%r")); 110 return (string b, nil); 111} 112 113certtostr(c: ref Certificate): string 114{ 115 s := sys->sprint("%s\n%s\n%s\n%ud\n", c.sa, c.ha, c.signer, c.exp); 116 pick r := c.sig { 117 RSA => 118 s += b64(r.n)+"\n"; 119 Elgamal => 120 s += b64(r.r)+"\n"+b64(r.s)+"\n"; 121 DSA => 122 s += b64(r.r)+"\n"+b64(r.s)+"\n"; 123 * => 124 raise "unknown key type"; 125 } 126 return s; 127} 128 129pktostr(pk: ref PK, owner: string): string 130{ 131 pick k := pk { 132 RSA => 133 s := sys->sprint("rsa\n%s\n", owner); 134 s += b64(k.n)+"\n"+b64(k.ek)+"\n"; 135 return s; 136 Elgamal => 137 s := sys->sprint("elgamal\n%s\n", owner); 138 s += b64(k.p)+"\n"+b64(k.alpha)+"\n"+b64(k.key)+"\n"; 139 return s; 140 DSA => 141 s := sys->sprint("dsa\n%s\n", owner); 142 s += b64(k.p)+"\n"+b64(k.q)+"\n"+b64(k.alpha)+"\n"+b64(k.key)+"\n"; 143 return s; 144 * => 145 raise "unknown key type"; 146 } 147} 148 149sktostr(sk: ref SK, owner: string): string 150{ 151 pick k := sk { 152 RSA => 153 s := sys->sprint("rsa\n%s\n", owner); 154 s += b64(k.pk.n)+"\n"+b64(k.pk.ek)+"\n"+b64(k.dk)+"\n"+ 155 b64(k.p)+"\n"+b64(k.q)+"\n"+ 156 b64(k.kp)+"\n"+b64(k.kq)+"\n"+ 157 k.c2.iptob64()+"\n"; 158 return s; 159 Elgamal => 160 pk := k.pk; 161 s := sys->sprint("elgamal\n%s\n", owner); 162 s += b64(pk.p)+"\n"+b64(pk.alpha)+"\n"+b64(pk.key)+"\n"+b64(k.secret)+"\n"; 163 return s; 164 DSA => 165 pk := k.pk; 166 s := sys->sprint("dsa\n%s\n", owner); 167 s += b64(pk.p)+"\n"+b64(pk.q)+"\n"+b64(pk.alpha)+"\n"+b64(k.secret)+"\n"; 168 return s; 169 * => 170 raise "unknown key type"; 171 } 172} 173 174fields(s: string): array of string 175{ 176 (nf, flds) := sys->tokenize(s, "\n^"); 177 a := array[nf] of string; 178 for(i := 0; i < len a; i++){ 179 a[i] = hd flds; 180 flds = tl flds; 181 } 182 return a; 183} 184 185bigs(a: array of string): array of ref IPint 186{ 187 b := array[len a] of ref IPint; 188 for(i := 0; i < len b; i++){ 189 b[i] = IPint.strtoip(a[i], 64); 190 if(b[i] == nil) 191 return nil; 192 } 193 return b; 194} 195 196need[T](a: array of T, min: int): int 197{ 198 if(len a < min){ 199 efmt(); 200 return 1; 201 } 202 return 0; 203} 204 205strtocert(s: string): ref Certificate 206{ 207 f := fields(s); 208 if(need(f, 4)) 209 return nil; 210 sa := f[0]; 211 ha := f[1]; 212 signer := f[2]; 213 exp := int big f[3]; # unsigned 214 b := bigs(f[4:]); 215 case f[0] { 216 "rsa" => 217 if(need(b, 1)) 218 return nil; 219 return ref Certificate(sa, ha, signer, exp, ref PKsig.RSA(b[0])); 220 "elgamal" => 221 if(need(b, 2)) 222 return nil; 223 return ref Certificate(sa, ha, signer, exp, ref PKsig.Elgamal(b[0], b[1])); 224 "dsa" => 225 if(need(b, 2)) 226 return nil; 227 return ref Certificate(sa, ha, signer, exp, ref PKsig.DSA(b[0], b[1])); 228 * => 229 sys->werrstr("unknown algorithm: "+f[0]); 230 return nil; 231 } 232} 233 234strtopk(s: string): (ref PK, string) 235{ 236 f := fields(s); 237 if(need(f, 3)) 238 return (nil, "format error"); 239 sa := f[0]; 240 owner := f[1]; 241 b := bigs(f[2:]); 242 case sa { 243 "rsa" => 244 if(need(b, 2)) 245 return (nil, "format error"); 246 return (ref PK.RSA(b[0], b[1]), owner); 247 "elgamal" => 248 if(need(b, 3)) 249 return (nil, "format error"); 250 return (ref PK.Elgamal(b[0], b[1], b[2]), owner); 251 "dsa" => 252 if(need(b, 4)) 253 return (nil, "format error"); 254 return (ref PK.DSA(b[0], b[1], b[2], b[3]), owner); 255 * => 256 return (nil, "unknown algorithm: "+f[0]); 257 } 258} 259 260strtosk(s: string): (ref SK, string) 261{ 262 f := fields(s); 263 if(need(f, 3)) 264 return (nil, "format error"); 265 sa := f[0]; 266 owner := f[1]; 267 b := bigs(f[2:]); 268 case sa { 269 "rsa" => 270 if(need(b, 8)) 271 return (nil, "format error"); 272 return (ref SK.RSA(ref PK.RSA(b[0], b[1]), b[2], b[3], b[4], b[5], b[6], b[7]), owner); 273 "elgamal" => 274 if(need(b, 4)) 275 return (nil, "format error"); 276 return (ref SK.Elgamal(ref PK.Elgamal(b[0], b[1], b[2]), b[3]), owner); 277 "dsa" => 278 if(need(b, 5)) 279 return (nil, "format error"); 280 return (ref SK.DSA(ref PK.DSA(b[0], b[1], b[2], b[3]), b[4]), owner); 281 * => 282 return (nil, "unknown algorithm: "+f[0]); 283 } 284} 285 286skalg(sk: ref SK): string 287{ 288 if(sk == nil) 289 return "nil"; 290 case tagof sk { 291 tagof SK.RSA => return "rsa"; 292 tagof SK.Elgamal => return "elgamal"; 293 tagof SK.DSA => return "dsa"; 294 * => return "gok"; 295 } 296} 297 298sign(sk: ref SK, signer: string, exp: int, state: ref Crypt->DigestState, ha: string): ref Certificate 299{ 300 # add signer name and expiration time to hash 301 if(state == nil) 302 return nil; 303 a := sys->aprint("%s %d", signer, exp); 304 digest := hash(ha, a, state); 305 if(digest == nil) 306 return nil; 307 b := IPint.bebytestoip(digest); 308 return ref Certificate(skalg(sk), ha, signer, exp, crypt->sign(sk, b)); 309} 310 311verify(pk: ref PK, cert: ref Certificate, state: ref Crypt->DigestState): int 312{ 313 if(state == nil) 314 return 0; 315 a := sys->aprint("%s %d", cert.signer, cert.exp); 316 digest := hash(cert.ha, a, state); 317 if(digest == nil) 318 return 0; 319 b := IPint.bebytestoip(digest); 320 return crypt->verify(pk, cert.sig, b); 321} 322 323hash(ha: string, a: array of byte, state: ref Crypt->DigestState): array of byte 324{ 325 digest: array of byte; 326 case ha { 327 "sha" or "sha1" => 328 digest = array[Crypt->SHA1dlen] of byte; 329 crypt->sha1(a, len a, digest, state); 330 "md5" => 331 digest = array[Crypt->MD5dlen] of byte; 332 crypt->md5(a, len a, digest, state); 333 * => 334 # don't bother with md4 335 sys->werrstr("unimplemented algorithm: "+ha); 336 return nil; 337 } 338 return digest; 339} 340 341b64(ip: ref IPint): string 342{ 343 return ip.iptob64z(); 344} 345