xref: /inferno-os/appl/cmd/auth/createsignerkey.b (revision 5e15e9a076ca680fcee5c9775b9ef0f52984c61a)
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