History

20110104-1044

forsyth committed 15 years ago

Commit a9460cd1 parent ce0a4515 files · +639 −-1Browse files

Unified · Split

5 files
  1. appl/lib/mkfile +2 −0
  2. appl/lib/oldauth.b +344 −0
  3. dis/lib/oldauth.dis +0 −0
  4. man/2/security-oldauth +246 −0
  5. module/oldauth.m +48 −0
appl/lib/mkfile+2−0
@@ -77,6 +77,8 @@ TARG=\ · 76 unmodified lines
7777 nametree.dis\
7878 names.dis\
7979 newns.dis\
80+ ninep.dis\
81+ oldauth.dis\
8082 palm.dis\
8183 palmdb.dis\
8284 palmfile.dis\
appl/lib/oldauth.b+344−0
@@ -0,0 +1,344 @@
1+implement Oldauth;
2+
3+#
4+# TO DO
5+# - more error checking?
6+# - details of auth error handling
7+#
8+
9+include "sys.m";
10+ sys: Sys;
11+
12+include "ipints.m";
13+ ipints: IPints;
14+ IPint: import ipints;
15+
16+include "crypt.m";
17+ crypt: Crypt;
18+ PK, SK, PKsig: import crypt;
19+
20+include "msgio.m";
21+ msgio: Msgio;
22+
23+include "oldauth.m";
24+
25+init()
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+
34+efmt()
35+{
36+ sys->werrstr("input or format error");
37+}
38+
39+readauthinfo(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+
71+writeauthinfo(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+
99+sendstr(fd: ref Sys->FD, s: string): int
100+{
101+ a := array of byte s;
102+ return msgio->sendmsg(fd, a, len a);
103+}
104+
105+getstr(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+
113+certtostr(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+
129+pktostr(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+
149+sktostr(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+
174+fields(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+
185+bigs(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+
196+need[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+
205+strtocert(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+
234+strtopk(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+
260+strtosk(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+
286+skalg(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+
298+sign(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+
311+verify(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+
323+hash(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+
341+b64(ip: ref IPint): string
342+{
343+ return ip.iptob64z();
344+}
dis/lib/oldauth.dis+0−0

Binary file not shown.

man/2/security-oldauth+246−0
@@ -0,0 +1,246 @@
1+.TH SECURITY-OLDAUTH 2
2+.SH NAME
3+oldauth: certtostr, pktostr, sktostr, strtocert, strtopk, strtosk, sign, verify, readauthinfo, writeauthinfo \- encoding for original Inferno authentication protocol
4+.SH SYNOPSIS
5+.EX
6+include "ipints.m";
7+include "crypt.m";
8+include "oldauth.m";
9+oldauth := load Oldauth Oldauth->PATH;
10+
11+Certificate: adt
12+{
13+ sa: string;
14+ ha: string;
15+ signer: string;
16+ exp: int;
17+ sig: ref Crypt->PKsig;
18+};
19+
20+Authinfo: adt
21+{
22+ mysk: ref Crypt->SK;
23+ mypk: ref Crypt->PK;
24+ owner: string;
25+ cert: ref Certificate;
26+ spk: ref Crypt->PK;
27+ alpha: ref IPints->IPint;
28+ p: ref IPints->IPint;
29+};
30+
31+sign: fn (sk: ref Crypt->SK, signer: string, exp: int,
32+ state: ref Crypt->DigestState, ha: string): ref Certificate;
33+verify: fn (pk: ref Crypt->PK, cert: ref Certificate,
34+ state: ref Crypt->DigestState): int;
35+
36+strtocert: fn(s: string): ref Certificate;
37+certtostr: fn(c: ref Certificate): string;
38+strtopk: fn(s: string): (ref Crypt->PK, string);
39+pktostr: fn(pk: ref Crypt->PK, owner: string): string;
40+strtosk: fn(s: string): (ref Crypt->SK, string);
41+sktostr: fn(sk: ref Crypt->SK, owner: string): string;
42+
43+readauthinfo: fn(filename: string): ref Authinfo;
44+writeauthinfo: fn(filename: string, info: ref Authinfo): int;
45+.EE
46+.SH DESCRIPTION
47+Certificates, public keys, and private keys are passed over networks and between applications using a Unicode representation.
48+This collection of functions provide a means to convert adts supplied by the system to and from their portable textual representation. These routines are used by
49+.IR login (2)
50+and
51+.IR factotum (4)
52+to implement the Inferno authentication protocol.
53+.PP
54+Public and private keys are represented by
55+.B Crypt->PK
56+and
57+.B Crypt->SK
58+(see
59+.IR keyring-intro (2)).
60+An authentication domain is represented by
61+the public key of the domain's
62+.IR signer ,
63+typically in control of a
64+.IR keyfs (4)
65+and running a
66+.IR logind (8).
67+Two adts associate a public/private key pair with a user name within a specific authentication domain:
68+.TP
69+.B Authinfo
70+The
71+.B Authinfo
72+adt contains an individual user's private and public key, a human-readable name for the key (eg, a user name),
73+the signer's certificate
74+and the signer's public key, and the Diffie-Hellman parameters.
75+The signer's certificate binds the user's public key to the given key name in the signer's domain.
76+.TP
77+.B Certificate
78+The
79+.B Certificate
80+adt contains a digital signature with the certification of the trusted authority (CA).
81+The signature covers not only the user's public key, but the key's name, the signer's name and
82+the expiration time of the certificate.
83+Both the key's name and the signer's name are local to the signer's domain.
84+.PP
85+.B Init
86+must be called before using any other operation in the module.
87+.PP
88+.B Sign
89+returns a Certificate containing the digital signature using secret key
90+.I sk
91+of a digest's
92+.IR state ,
93+which is the output of the hash algorithm named
94+.IR ha ,
95+combined with the hash of the signer's name, and the certificate's expiration time (in seconds from the Epoch).
96+Valid hash algorithms are
97+.B sha1
98+and
99+.BR md5 .
100+The expiry time should be zero if the certificate does not expire.
101+Typically the
102+.I state
103+is the result of hashing
104+.IP
105+.EX
106+array of byte pktostr(pk, username)
107+.EE
108+.PP
109+for a given public key
110+.I pk
111+that is associated with the given
112+.I username
113+by the signer.
114+.PP
115+.B Verify
116+checks that the given Certificate is the result of signing the given
117+.I state
118+using the secret (private) key corresponding to public key
119+.IR pk .
120+It returns true (non-zero) if the certificate is valid, including the signer's name, and the expiration time;
121+the caller must enforce the expiration time if desired.
122+It returns false (zero) if the certificate is invalid.
123+. #######
124+.PP
125+.B Sign
126+creates a digital signature of a digest from the concatenation of: a message, the name of the signer, and an expiration time.
127+.I State
128+is the digest state after running
129+.BR sha1 ,
130+.B md4
131+or
132+.B md5
133+over the message.
134+.I Ha
135+is a string specifying the hash algorithm to use:
136+.B
137+"sha"\fR,
138+.B
139+"sha1"\fR,
140+.B
141+"md4"\fR
142+or
143+.B
144+"md5"\fR.
145+.B Sign
146+extends the digest to cover the signer's name
147+(taken from the private key,
148+.IR sk )
149+and the expiration time.
150+It returns a certificate containing the digital signature of the digest, signer name, hash algorithm and signature algorithm.
151+If any parameter is invalid,
152+.B sign
153+returns nil.
154+The signature algorithm is implied by the type of the private key.
155+.PP
156+.B Verify
157+uses public key
158+.I pk
159+to verify a certificate.
160+It returns non-zero (true) if the certificate is valid; zero (false) otherwise.
161+.I State
162+is the digest state after running the chosen digest algorithm
163+over the message.
164+. #######
165+.PP
166+The remaining operations fetch and store those values and convert to and from text representations for use in protocols and for storage.
167+.PP
168+.B Strtocert
169+takes a string argument containing a varying number of newline-separated fields:
170+a signature algorithm, a hash algorithm, a signer's name, an expiration time, and values representing a digital signature.
171+It returns the corresponding
172+.BR Certificate .
173+If the string is of improper format, the result is
174+.IR nil .
175+.PP
176+.B Certtostr
177+performs the inverse operation: takes the
178+.B Certificate
179+.I c
180+and produces a text string suitable for communication over a network.
181+Note that the string will contain newline characters.
182+.PP
183+.B Strtopk
184+and
185+.B strtosk
186+take as their arguments a string
187+.I s
188+representing the public and private keys respectively.
189+.I S
190+contains an algorithm name, a user name and values representing the key.
191+Each returns a tuple
192+.BI ( k,\ s ),
193+where
194+.I k
195+is the resulting key value (ie,
196+.B Crypt->PK
197+or
198+.BR Crypt->SK )
199+and
200+.I s
201+is a string giving the name associated with the key, typically a user name.
202+If the format of
203+.I s
204+is invalid,
205+.I k
206+is
207+.IR nil ,
208+and
209+.I s
210+contains a diagnostic.
211+.PP
212+.B Pktostr
213+and
214+.B sktostr
215+perform the inverse operations:
216+they take a public key (secret key)
217+.I pk
218+or
219+.IR sk ,
220+the
221+.I owner
222+name to be associated with that key, and produce a printable representation as a string.
223+The
224+.I owner
225+names the user that owns the key; in the case of a public key,
226+the user is expected to possess the corresponding private key.
227+.PP
228+.B Readauthinfo
229+reads a representation of an
230+.B Authinfo
231+from a file.
232+It returns nil if there is a read error or a conversion error;
233+it returns a reference to the
234+.B Authinfo
235+otherwise.
236+.PP
237+.B Writeauthinfo
238+writes a representation of
239+.I info
240+to a file. It returns -1 if the write operation fails, 0 otherwise.
241+.SH SOURCE
242+.B /appl/lib/oldauth.b
243+.SH SEE ALSO
244+.IR crypt-intro (2),
245+.IR ipints (2),
246+.IR security-intro (2)
module/oldauth.m+48−0
@@ -0,0 +1,48 @@
1+Oldauth: module
2+{
3+ PATH: con "/dis/lib/oldauth.dis";
4+
5+ init: fn();
6+
7+ # Inferno certificate
8+ Certificate: adt
9+ {
10+ sa: string; # signature algorithm
11+ ha: string; # hash algorithm
12+ signer: string; # name of signer
13+ exp: int; # expiration date
14+ sig: ref Crypt->PKsig;
15+ };
16+
17+ # authentication info
18+ Authinfo: adt
19+ {
20+ mysk: ref Crypt->SK; # my private key
21+ mypk: ref Crypt->PK; # my public key
22+ owner: string; # owner of mypk for certificate
23+ cert: ref Certificate; # signature of my public key
24+ spk: ref Crypt->PK; # signers public key
25+ alpha: ref IPints->IPint; # diffie helman parameters
26+ p: ref IPints->IPint;
27+ };
28+
29+ # auth io
30+ readauthinfo: fn(filename: string): ref Authinfo;
31+ writeauthinfo: fn(filename: string, info: ref Authinfo): int;
32+
33+ # convert types to text in a canonical form
34+ certtostr: fn (c: ref Certificate): string;
35+ pktostr: fn (pk: ref Crypt->PK, owner: string): string;
36+ sktostr: fn (sk: ref Crypt->SK, owner: string): string;
37+
38+ # parse text into types
39+ strtocert: fn (s: string): ref Certificate;
40+ strtopk: fn (s: string): (ref Crypt->PK, string);
41+ strtosk: fn (s: string): (ref Crypt->SK, string);
42+
43+ # create and verify Certificates
44+ sign: fn (sk: ref Crypt->SK, signer: string, exp: int, state: ref Crypt->DigestState, ha: string):
45+ ref Certificate;
46+ verify: fn (pk: ref Crypt->PK, cert: ref Certificate, state: ref Crypt->DigestState):
47+ int;
48+};