1implement Createsignerkey; 2 3include "sys.m"; 4 sys: Sys; 5 6include "draw.m"; 7 8include "daytime.m"; 9 10include "ipints.m"; 11include "crypt.m"; 12 crypt: Crypt; 13 14include "oldauth.m"; 15 oldauth: Oldauth; 16 17include "arg.m"; 18 19# signer key never expires 20SKexpire: con 0; 21 22# size in bits of modulus for public keys 23PKmodlen: con 1024; 24 25# size in bits of modulus for diffie hellman 26DHmodlen: con 1024; 27 28algs := array[] of {"rsa", "elgamal"}; # first entry is default 29 30Createsignerkey: module 31{ 32 init: fn(nil: ref Draw->Context, nil: list of string); 33}; 34 35init(nil: ref Draw->Context, args: list of string) 36{ 37 err: string; 38 39 sys = load Sys Sys->PATH; 40 crypt = load Crypt Crypt->PATH; 41 oldauth = load Oldauth Oldauth->PATH; 42 oldauth->init(); 43 arg := load Arg Arg->PATH; 44 45 arg->init(args); 46 arg->setusage("createsignerkey [-a algorithm] [-f keyfile] [-e ddmmyyyy] [-b size-in-bits] name-of-owner"); 47 alg := algs[0]; 48 filename := "/keydb/signerkey"; 49 expire := SKexpire; 50 bits := PKmodlen; 51 while((c := arg->opt()) != 0){ 52 case c { 53 'a' => 54 alg = arg->arg(); 55 if(alg == nil) 56 arg->usage(); 57 for(i:=0;; i++){ 58 if(i >= len algs) 59 error(sys->sprint("unknown algorithm: %s", alg)); 60 else if(alg == algs[i]) 61 break; 62 } 63 'f' or 'k' => 64 filename = arg->earg(); 65 'e' => 66 s := arg->earg(); 67 (err, expire) = checkdate(s); 68 if(err != nil) 69 error(err); 70 'b' => 71 s := arg->earg(); 72 bits = int s; 73 if(bits < 32 || bits > 4096) 74 error("modulus must be in the range of 32 to 4096 bits"); 75 * => 76 arg->usage(); 77 } 78 } 79 args = arg->argv(); 80 if(args == nil) 81 arg->usage(); 82 arg = nil; 83 84 owner := hd args; 85 86 # generate a local key, self-signed 87 info := ref Oldauth->Authinfo; 88 info.mysk = crypt->genSK(alg, bits); 89 if(info.mysk == nil) 90 error(sys->sprint("algorithm %s not configured in system", alg)); 91 info.owner = owner; 92 info.mypk = crypt->sktopk(info.mysk); 93 info.spk = crypt->sktopk(info.mysk); 94 myPKbuf := array of byte oldauth->pktostr(info.mypk, owner); 95 state := crypt->sha1(myPKbuf, len myPKbuf, nil, nil); 96 info.cert = oldauth->sign(info.mysk, owner, expire, state, "sha1"); 97 (info.alpha, info.p) = crypt->dhparams(DHmodlen); 98 99 if(oldauth->writeauthinfo(filename, info) < 0) 100 error(sys->sprint("can't write signerkey file %s: %r", filename)); 101} 102 103error(s: string) 104{ 105 sys->fprint(sys->fildes(2), "createsignerkey: %s\n", s); 106 raise "fail:error"; 107} 108 109checkdate(word: string): (string, int) 110{ 111 if(len word != 8) 112 return ("!date must be in form ddmmyyyy", 0); 113 114 daytime := load Daytime Daytime->PATH; 115 116 now := daytime->now(); 117 118 tm := daytime->local(now); 119 tm.sec = 59; 120 tm.min = 59; 121 tm.hour = 24; 122 123 tm.mday = int word[0:2]; 124 if(tm.mday > 31 || tm.mday < 1) 125 return ("!bad day of month", 0); 126 127 tm.mon = int word[2:4] - 1; 128 if(tm.mon > 11 || tm.mday < 0) 129 return ("!bad month", 0); 130 131 tm.year = int word[4:8] - 1900; 132 if(tm.year < 70) 133 return ("!bad year", 0); 134 135 newdate := daytime->tm2epoch(tm); 136 if(newdate < now) 137 return ("!expiration date must be in the future", 0); 138 139 return (nil, newdate); 140} 141