ead: clean up
[openwrt.git] / package / network / services / ead / src / tinysrp / t_client.c
1 /*
2  * Copyright (c) 1997-1999  The Stanford SRP Authentication Project
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
18  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
21  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
22  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
23  * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
24  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25  *
26  * In addition, the following conditions apply:
27  *
28  * 1. Any software that incorporates the SRP authentication technology
29  *    must display the following acknowlegment:
30  *    "This product uses the 'Secure Remote Password' cryptographic
31  *     authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
32  *
33  * 2. Any software that incorporates all or part of the SRP distribution
34  *    itself must also display the following acknowledgment:
35  *    "This product includes software developed by Tom Wu and Eugene
36  *     Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
37  *
38  * 3. Redistributions in source or binary form must retain an intact copy
39  *    of this copyright notice and list of conditions.
40  */
41
42 #include <stdio.h>
43 #include "t_defines.h"
44 #include "t_pwd.h"
45 #include "t_client.h"
46 #include "t_sha.h"
47
48 _TYPE( struct t_client * )
49 t_clientopen(u, n, g, s)
50      const char * u;
51      struct t_num * n;
52      struct t_num * g;
53      struct t_num * s;
54 {
55   struct t_client * tc;
56   unsigned char buf1[SHA_DIGESTSIZE], buf2[SHA_DIGESTSIZE];
57   SHA1_CTX ctxt;
58   int i, validated;
59   struct t_preconf * tpc;
60
61   validated = 0;
62   if(n->len < MIN_MOD_BYTES)
63     return 0;
64   for(i = 0; i < t_getprecount(); ++i) {
65     tpc = t_getpreparam(i);
66     if(tpc->modulus.len == n->len && tpc->generator.len == g->len &&
67        memcmp(tpc->modulus.data, n->data, n->len) == 0 &&
68        memcmp(tpc->generator.data, g->data, g->len) == 0) {
69       validated = 1;    /* Match found, done */
70       break;
71     }
72   }
73
74   if(validated == 0)
75     return 0;
76
77   if((tc = malloc(sizeof(struct t_client))) == 0)
78     return 0;
79
80   strncpy(tc->username, u, MAXUSERLEN);
81
82   SHA1Init(&tc->hash);
83
84   tc->n.len = n->len;
85   tc->n.data = tc->nbuf;
86   memcpy(tc->n.data, n->data, tc->n.len);
87
88   SHA1Init(&ctxt);
89   SHA1Update(&ctxt, tc->n.data, tc->n.len);
90   SHA1Final(buf1, &ctxt);
91
92   tc->g.len = g->len;
93   tc->g.data = tc->gbuf;
94   memcpy(tc->g.data, g->data, tc->g.len);
95
96   SHA1Init(&ctxt);
97   SHA1Update(&ctxt, tc->g.data, tc->g.len);
98   SHA1Final(buf2, &ctxt);
99
100   for(i = 0; i < sizeof(buf1); ++i)
101     buf1[i] ^= buf2[i];
102
103   SHA1Update(&tc->hash, buf1, sizeof(buf1));
104
105   SHA1Init(&ctxt);
106   SHA1Update(&ctxt, tc->username, strlen(tc->username));
107   SHA1Final(buf1, &ctxt);
108
109   SHA1Update(&tc->hash, buf1, sizeof(buf1));
110
111   tc->s.len = s->len;
112   tc->s.data = tc->sbuf;
113   memcpy(tc->s.data, s->data, tc->s.len);
114
115   SHA1Update(&tc->hash, tc->s.data, tc->s.len);
116
117   tc->a.data = tc->abuf;
118   tc->A.data = tc->Abuf;
119   tc->p.data = tc->pbuf;
120   tc->v.data = tc->vbuf;
121
122   SHA1Init(&tc->ckhash);
123
124   return tc;
125 }
126
127 _TYPE( struct t_num * )
128 t_clientgenexp(tc)
129      struct t_client * tc;
130 {
131   BigInteger a, A, n, g;
132
133   if(tc->n.len < ALEN)
134     tc->a.len = tc->n.len;
135   else
136     tc->a.len = ALEN;
137
138   t_random(tc->a.data, tc->a.len);
139   a = BigIntegerFromBytes(tc->a.data, tc->a.len);
140   n = BigIntegerFromBytes(tc->n.data, tc->n.len);
141   g = BigIntegerFromBytes(tc->g.data, tc->g.len);
142   A = BigIntegerFromInt(0);
143   BigIntegerModExp(A, g, a, n);
144   tc->A.len = BigIntegerToBytes(A, tc->A.data);
145
146   BigIntegerFree(A);
147   BigIntegerFree(a);
148   BigIntegerFree(g);
149   BigIntegerFree(n);
150
151   SHA1Update(&tc->hash, tc->A.data, tc->A.len);
152   SHA1Update(&tc->ckhash, tc->A.data, tc->A.len);
153
154   return &tc->A;
155 }
156
157 _TYPE( void )
158 t_clientpasswd(tc, password)
159      struct t_client * tc;
160      char * password;
161 {
162   BigInteger n, g, p, v;
163   SHA1_CTX ctxt;
164   unsigned char dig[SHA_DIGESTSIZE];
165
166   n = BigIntegerFromBytes(tc->n.data, tc->n.len);
167   g = BigIntegerFromBytes(tc->g.data, tc->g.len);
168
169   SHA1Init(&ctxt);
170   SHA1Update(&ctxt, tc->username, strlen(tc->username));
171   SHA1Update(&ctxt, ":", 1);
172   SHA1Update(&ctxt, password, strlen(password));
173   SHA1Final(dig, &ctxt);
174
175   SHA1Init(&ctxt);
176   SHA1Update(&ctxt, tc->s.data, tc->s.len);
177   SHA1Update(&ctxt, dig, sizeof(dig));
178   SHA1Final(dig, &ctxt);
179
180   p = BigIntegerFromBytes(dig, sizeof(dig));
181
182   v = BigIntegerFromInt(0);
183   BigIntegerModExp(v, g, p, n);
184
185   tc->p.len = BigIntegerToBytes(p, tc->p.data);
186   BigIntegerFree(p);
187
188   tc->v.len = BigIntegerToBytes(v, tc->v.data);
189   BigIntegerFree(v);
190 }
191
192 _TYPE( unsigned char * )
193 t_clientgetkey(tc, serverval)
194      struct t_client * tc;
195      struct t_num * serverval;
196 {
197   BigInteger n, B, v, p, a, sum, S;
198   unsigned char sbuf[MAXPARAMLEN];
199   unsigned char dig[SHA_DIGESTSIZE];
200   unsigned slen;
201   unsigned int u;
202   SHA1_CTX ctxt;
203
204   SHA1Init(&ctxt);
205   SHA1Update(&ctxt, serverval->data, serverval->len);
206   SHA1Final(dig, &ctxt);
207   u = (dig[0] << 24) | (dig[1] << 16) | (dig[2] << 8) | dig[3];
208   if(u == 0)
209     return NULL;
210
211   SHA1Update(&tc->hash, serverval->data, serverval->len);
212
213   B = BigIntegerFromBytes(serverval->data, serverval->len);
214   n = BigIntegerFromBytes(tc->n.data, tc->n.len);
215
216   if(BigIntegerCmp(B, n) >= 0 || BigIntegerCmpInt(B, 0) == 0) {
217     BigIntegerFree(B);
218     BigIntegerFree(n);
219     return NULL;
220   }
221   v = BigIntegerFromBytes(tc->v.data, tc->v.len);
222   if(BigIntegerCmp(B, v) < 0)
223     BigIntegerAdd(B, B, n);
224   BigIntegerSub(B, B, v);
225   BigIntegerFree(v);
226
227   a = BigIntegerFromBytes(tc->a.data, tc->a.len);
228   p = BigIntegerFromBytes(tc->p.data, tc->p.len);
229
230   sum = BigIntegerFromInt(0);
231   BigIntegerMulInt(sum, p, u);
232   BigIntegerAdd(sum, sum, a);
233
234   BigIntegerFree(p);
235   BigIntegerFree(a);
236
237   S = BigIntegerFromInt(0);
238   BigIntegerModExp(S, B, sum, n);
239   slen = BigIntegerToBytes(S, sbuf);
240
241   BigIntegerFree(S);
242   BigIntegerFree(sum);
243   BigIntegerFree(B);
244   BigIntegerFree(n);
245
246   t_sessionkey(tc->session_key, sbuf, slen);
247   memset(sbuf, 0, slen);
248
249   SHA1Update(&tc->hash, tc->session_key, sizeof(tc->session_key));
250
251   SHA1Final(tc->session_response, &tc->hash);
252   SHA1Update(&tc->ckhash, tc->session_response, sizeof(tc->session_response));
253   SHA1Update(&tc->ckhash, tc->session_key, sizeof(tc->session_key));
254
255   return tc->session_key;
256 }
257
258 _TYPE( int )
259 t_clientverify(tc, resp)
260     struct t_client * tc;
261     unsigned char * resp;
262 {
263   unsigned char expected[SHA_DIGESTSIZE];
264
265   SHA1Final(expected, &tc->ckhash);
266   return memcmp(expected, resp, sizeof(expected));
267 }
268
269 _TYPE( unsigned char * )
270 t_clientresponse(tc)
271     struct t_client * tc;
272 {
273   return tc->session_response;
274 }
275
276 _TYPE( void )
277 t_clientclose(tc)
278      struct t_client * tc;
279 {
280   memset(tc->abuf, 0, sizeof(tc->abuf));
281   memset(tc->pbuf, 0, sizeof(tc->pbuf));
282   memset(tc->vbuf, 0, sizeof(tc->vbuf));
283   memset(tc->session_key, 0, sizeof(tc->session_key));
284   free(tc);
285 }