blob: 7227c85566a54cece660b3900a723ec8ab3a92cc [file] [log] [blame]
rsc2277c5d2004-03-21 04:33:13 +00001/*
2 * SSH RSA authentication.
3 *
4 * Client protocol:
5 * read public key
6 * if you don't like it, read another, repeat
7 * write challenge
8 * read response
9 * all numbers are hexadecimal biginits parsable with strtomp.
10 */
11
12#include "dat.h"
13
14enum {
15 CHavePub,
16 CHaveResp,
17
18 Maxphase,
19};
20
21static char *phasenames[] = {
22[CHavePub] "CHavePub",
23[CHaveResp] "CHaveResp",
24};
25
26struct State
27{
28 RSApriv *priv;
29 mpint *resp;
30 int off;
31 Key *key;
32};
33
34static RSApriv*
35readrsapriv(Key *k)
36{
37 char *a;
38 RSApriv *priv;
39
40 priv = rsaprivalloc();
41
42 if((a=strfindattr(k->attr, "ek"))==nil || (priv->pub.ek=strtomp(a, nil, 16, nil))==nil)
43 goto Error;
44 if((a=strfindattr(k->attr, "n"))==nil || (priv->pub.n=strtomp(a, nil, 16, nil))==nil)
45 goto Error;
46 if((a=strfindattr(k->privattr, "!p"))==nil || (priv->p=strtomp(a, nil, 16, nil))==nil)
47 goto Error;
48 if((a=strfindattr(k->privattr, "!q"))==nil || (priv->q=strtomp(a, nil, 16, nil))==nil)
49 goto Error;
50 if((a=strfindattr(k->privattr, "!kp"))==nil || (priv->kp=strtomp(a, nil, 16, nil))==nil)
51 goto Error;
52 if((a=strfindattr(k->privattr, "!kq"))==nil || (priv->kq=strtomp(a, nil, 16, nil))==nil)
53 goto Error;
54 if((a=strfindattr(k->privattr, "!c2"))==nil || (priv->c2=strtomp(a, nil, 16, nil))==nil)
55 goto Error;
56 if((a=strfindattr(k->privattr, "!dk"))==nil || (priv->dk=strtomp(a, nil, 16, nil))==nil)
57 goto Error;
58 return priv;
59
60Error:
61 rsaprivfree(priv);
62 return nil;
63}
64
65static int
66sshrsainit(Proto*, Fsstate *fss)
67{
68 int iscli;
69 State *s;
70
71 if((iscli = isclient(strfindattr(fss->attr, "role"))) < 0)
72 return failure(fss, nil);
73 if(iscli==0)
74 return failure(fss, "sshrsa server unimplemented");
75
76 s = emalloc(sizeof *s);
77 fss->phasename = phasenames;
78 fss->maxphase = Maxphase;
79 fss->phase = CHavePub;
80 fss->ps = s;
81 return RpcOk;
82}
83
84static int
85sshrsaread(Fsstate *fss, void *va, uint *n)
86{
87 RSApriv *priv;
88 State *s;
89
90 s = fss->ps;
91 switch(fss->phase){
92 default:
93 return phaseerror(fss, "read");
94 case CHavePub:
95 if(s->key){
96 closekey(s->key);
97 s->key = nil;
98 }
99 if((s->key = findkey(fss, Kuser, nil, s->off, fss->attr, nil)) == nil)
100 return failure(fss, nil);
101 s->off++;
102 priv = s->key->priv;
103 *n = snprint(va, *n, "%B", priv->pub.n);
104 return RpcOk;
105 case CHaveResp:
106 *n = snprint(va, *n, "%B", s->resp);
107 fss->phase = Established;
108 return RpcOk;
109 }
110}
111
112static int
113sshrsawrite(Fsstate *fss, void *va, uint)
114{
115 mpint *m;
116 State *s;
117
118 s = fss->ps;
119 switch(fss->phase){
120 default:
121 return phaseerror(fss, "write");
122 case CHavePub:
123 if(s->key == nil)
124 return failure(fss, "no current key");
125 m = strtomp(va, nil, 16, nil);
126 m = rsadecrypt(s->key->priv, m, m);
127 s->resp = m;
128 fss->phase = CHaveResp;
129 return RpcOk;
130 }
131}
132
133static void
134sshrsaclose(Fsstate *fss)
135{
136 State *s;
137
138 s = fss->ps;
139 if(s->key)
140 closekey(s->key);
141 if(s->resp)
142 mpfree(s->resp);
143 free(s);
144}
145
146static int
147sshrsaaddkey(Key *k)
148{
149 fmtinstall('B', mpconv);
150
151 if((k->priv = readrsapriv(k)) == nil){
152 werrstr("malformed key data");
153 return -1;
154 }
155 return replacekey(k);
156}
157
158static void
159sshrsaclosekey(Key *k)
160{
161 rsaprivfree(k->priv);
162}
163
164Proto sshrsa = {
165.name= "sshrsa",
166.init= sshrsainit,
167.write= sshrsawrite,
168.read= sshrsaread,
169.close= sshrsaclose,
170.addkey= sshrsaaddkey,
171.closekey= sshrsaclosekey,
172};