1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
implement Authproto;
# SSH RSA authentication.
#
# Client protocol:
# read public key
# if you don't like it, read another, repeat
# write challenge
# read response
# all numbers are hexadecimal biginits parsable with strtomp.
#
include "sys.m";
sys: Sys;
Rread, Rwrite: import Sys;
include "draw.m";
include "keyring.m";
kr: Keyring;
IPint, RSAsk, RSApk: import kr;
include "../authio.m";
authio: Authio;
Aattr, Aval, Aquery: import Authio;
Attr, IO, Key, Authinfo: import authio;
eqbytes, memrandom: import authio;
lookattrval: import authio;
init(f: Authio): string
{
authio = f;
sys = load Sys Sys->PATH;
kr = load Keyring Keyring->PATH;
# base16 = load Encoding Encoding->BASE16PATH;
return nil;
}
interaction(attrs: list of ref Attr, io: ref IO): string
{
role := lookattrval(attrs, "role");
if(role == nil)
return "role not specified";
if(role != "client")
return "only client role supported";
sk: ref RSAsk;
keys: list of ref Key;
err: string;
for(;;){
waitread(io);
(keys, err) = io.findkeys(attrs, "");
if(keys != nil)
break;
io.error(err);
}
for(; keys != nil; keys = tl keys){
(sk, err) = keytorsa(hd keys);
if(sk != nil){
r := array of byte sk.pk.n.iptostr(16);
while(!io.reply2read(r, len r))
waitread(io);
data := io.rdwr();
if(data != nil){
chal := IPint.strtoip(string data, 16);
if(chal == nil){
io.error("invalid challenge value");
continue;
}
m := sk.decrypt(chal);
b := array of byte m.iptostr(16);
io.write(b, len b);
io.done(nil);
return nil;
}
}
}
for(;;){
io.error("no key matches "+authio->attrtext(attrs));
waitread(io);
}
}
waitread(io: ref IO)
{
while(io.rdwr() != nil)
io.error("no current key");
}
Badkey: exception(string);
ipint(attrs: list of ref Attr, name: string): ref IPint raises Badkey
{
s := lookattrval(attrs, name);
if(s == nil)
raise Badkey("missing attribute "+name);
m := IPint.strtoip(s, 16);
if(m == nil)
raise Badkey("invalid value for "+name);
return m;
}
keytorsa(k: ref Key): (ref RSAsk, string)
{
sk := ref RSAsk;
sk.pk = ref RSApk;
{
sk.pk.ek = ipint(k.attrs, "ek");
sk.pk.n = ipint(k.attrs, "n");
sk.dk = ipint(k.secrets, "!dk");
sk.p = ipint(k.secrets, "!p");
sk.q = ipint(k.secrets, "!q");
sk.kp = ipint(k.secrets, "!kp");
sk.kq = ipint(k.secrets, "!kq");
sk.c2 = ipint(k.secrets, "!c2");
}exception e{
Badkey =>
return (nil, "rsa key "+e);
}
return (sk, nil);
}
keycheck(k: ref Authio->Key): string
{
return keytorsa(k).t1;
}
|