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