summaryrefslogtreecommitdiffstats
path: root/3rd_party/libsrp6a-sha512/srp6a_sha512_client.c
diff options
context:
space:
mode:
Diffstat (limited to '3rd_party/libsrp6a-sha512/srp6a_sha512_client.c')
-rw-r--r--3rd_party/libsrp6a-sha512/srp6a_sha512_client.c363
1 files changed, 363 insertions, 0 deletions
diff --git a/3rd_party/libsrp6a-sha512/srp6a_sha512_client.c b/3rd_party/libsrp6a-sha512/srp6a_sha512_client.c
new file mode 100644
index 0000000..db59fe8
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/srp6a_sha512_client.c
@@ -0,0 +1,363 @@
1/*
2 * Copyright (c) 1997-2007 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 * Redistributions in source or binary form must retain an intact copy
27 * of this copyright notice.
28 */
29#include "t_defines.h"
30#include "srp.h"
31#include "t_sha.h"
32
33/*
34 * SRP-6/6a has two minor refinements relative to SRP-3/RFC2945:
35 * 1. The "g^x" value is multipled by three in the client's
36 * calculation of its session key.
37 * SRP-6a: The "g^x" value is multiplied by the hash of
38 * N and g in the client's session key calculation.
39 * 2. The value of u is taken as the hash of A and B,
40 * instead of the top 32 bits of the hash of B.
41 * This eliminates the old restriction where the
42 * server had to receive A before it could send B.
43 */
44
45/****************************/
46#define SHA512_DIGESTSIZE 64
47#define SRP6_SHA512_KEY_LEN 64
48
49/*
50 * The client keeps track of the running hash
51 * state via SHA512_CTX structures pointed to by the
52 * meth_data pointer. The "hash" member is the hash value that
53 * will be sent to the other side; the "ckhash" member is the
54 * hash value expected from the other side.
55 */
56struct sha512_client_meth_st {
57 SHA512_CTX hash;
58 SHA512_CTX ckhash;
59 unsigned char k[SRP6_SHA512_KEY_LEN];
60};
61
62#define SHA512_CLIENT_CTXP(srp) ((struct sha512_client_meth_st *)(srp)->meth_data)
63
64static SRP_RESULT
65srp6a_sha512_client_init(SRP * srp)
66{
67 srp->magic = SRP_MAGIC_CLIENT;
68 srp->flags = SRP_FLAG_MOD_ACCEL | SRP_FLAG_LEFT_PAD;
69 srp->meth_data = malloc(sizeof(struct sha512_client_meth_st));
70 SHA512Init(&SHA512_CLIENT_CTXP(srp)->hash);
71 SHA512Init(&SHA512_CLIENT_CTXP(srp)->ckhash);
72 return SRP_SUCCESS;
73}
74
75static SRP_RESULT
76srp6_sha512_client_finish(SRP * srp)
77{
78 if(srp->meth_data) {
79 memset(srp->meth_data, 0, sizeof(struct sha512_client_meth_st));
80 free(srp->meth_data);
81 }
82 return SRP_SUCCESS;
83}
84
85static SRP_RESULT
86srp6_sha512_client_params(SRP * srp, const unsigned char * modulus, int modlen,
87 const unsigned char * generator, int genlen,
88 const unsigned char * salt, int saltlen)
89{
90 int i;
91 unsigned char buf1[SHA512_DIGESTSIZE], buf2[SHA512_DIGESTSIZE];
92 SHA512_CTX ctxt;
93
94 /* Fields set by SRP_set_params */
95
96 /* Update hash state */
97 SHA512Init(&ctxt);
98 SHA512Update(&ctxt, modulus, modlen);
99 SHA512Final(buf1, &ctxt); /* buf1 = H(modulus) */
100
101 SHA512Init(&ctxt);
102 SHA512Update(&ctxt, generator, genlen);
103 SHA512Final(buf2, &ctxt); /* buf2 = H(generator) */
104
105 for(i = 0; i < sizeof(buf1); ++i)
106 buf1[i] ^= buf2[i]; /* buf1 = H(modulus) xor H(generator) */
107
108 /* hash: H(N) xor H(g) */
109 SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, buf1, sizeof(buf1));
110
111 SHA512Init(&ctxt);
112 SHA512Update(&ctxt, srp->username->data, srp->username->length);
113 SHA512Final(buf1, &ctxt); /* buf1 = H(user) */
114
115 /* hash: (H(N) xor H(g)) | H(U) */
116 SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, buf1, sizeof(buf1));
117
118 /* hash: (H(N) xor H(g)) | H(U) | s */
119 SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, salt, saltlen);
120
121 return SRP_SUCCESS;
122}
123
124static SRP_RESULT
125srp6_sha512_client_auth(SRP * srp, const unsigned char * a, int alen)
126{
127 /* On the client, the authenticator is the raw password-derived hash */
128 srp->password = BigIntegerFromBytes(a, alen);
129
130 /* verifier = g^x mod N */
131 srp->verifier = BigIntegerFromInt(0);
132 BigIntegerModExp(srp->verifier, srp->generator, srp->password, srp->modulus, srp->bctx, srp->accel);
133
134 return SRP_SUCCESS;
135}
136
137static SRP_RESULT
138srp6_sha512_client_passwd(SRP * srp, const unsigned char * p, int plen)
139{
140 SHA512_CTX ctxt;
141 unsigned char dig[SHA512_DIGESTSIZE];
142 int r;
143
144 SHA512Init(&ctxt);
145 SHA512Update(&ctxt, srp->username->data, srp->username->length);
146 SHA512Update(&ctxt, ":", 1);
147 SHA512Update(&ctxt, p, plen);
148 SHA512Final(dig, &ctxt); /* dig = H(U | ":" | P) */
149
150 SHA512Init(&ctxt);
151 SHA512Update(&ctxt, srp->salt->data, srp->salt->length);
152 SHA512Update(&ctxt, dig, sizeof(dig));
153 SHA512Final(dig, &ctxt); /* dig = H(s | H(U | ":" | P)) */
154 memset(&ctxt, 0, sizeof(ctxt));
155
156 r = SRP_set_authenticator(srp, dig, sizeof(dig));
157 memset(dig, 0, sizeof(dig));
158
159 return r;
160}
161
162static SRP_RESULT
163srp6_sha512_client_genpub(SRP * srp, cstr ** result)
164{
165 cstr * astr;
166 int slen = (SRP_get_secret_bits(BigIntegerBitLen(srp->modulus)) + 7) / 8;
167
168 if(result == NULL)
169 astr = cstr_new();
170 else {
171 if(*result == NULL)
172 *result = cstr_new();
173 astr = *result;
174 }
175
176 cstr_set_length(astr, BigIntegerByteLen(srp->modulus));
177 t_random((unsigned char*)astr->data, slen);
178 srp->secret = BigIntegerFromBytes((const unsigned char*)astr->data, slen);
179 /* Force g^a mod n to "wrap around" by adding log[2](n) to "a". */
180 BigIntegerAddInt(srp->secret, srp->secret, BigIntegerBitLen(srp->modulus));
181 /* A = g^a mod n */
182 srp->pubkey = BigIntegerFromInt(0);
183 BigIntegerModExp(srp->pubkey, srp->generator, srp->secret, srp->modulus, srp->bctx, srp->accel);
184 BigIntegerToCstr(srp->pubkey, astr);
185
186 /* hash: (H(N) xor H(g)) | H(U) | s | A */
187 SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, astr->data, astr->length);
188 /* ckhash: A */
189 SHA512Update(&SHA512_CLIENT_CTXP(srp)->ckhash, astr->data, astr->length);
190
191 if(result == NULL) /* astr was a temporary */
192 cstr_clear_free(astr);
193
194 return SRP_SUCCESS;
195}
196
197static SRP_RESULT
198srp6_sha512_client_key_ex(SRP * srp, cstr ** result,
199 const unsigned char * pubkey, int pubkeylen, BigInteger k)
200{
201 SHA512_CTX ctxt;
202 unsigned char dig[SHA512_DIGESTSIZE];
203 BigInteger gb, e;
204 cstr * s;
205 int modlen;
206
207 modlen = BigIntegerByteLen(srp->modulus);
208 if(pubkeylen > modlen)
209 return SRP_ERROR;
210
211 /* Compute u from client's and server's values */
212 SHA512Init(&ctxt);
213 /* Use s as a temporary to store client's value */
214 s = cstr_new();
215 if(srp->flags & SRP_FLAG_LEFT_PAD) {
216 BigIntegerToCstrEx(srp->pubkey, s, modlen);
217 SHA512Update(&ctxt, s->data, s->length);
218 if(pubkeylen < modlen) {
219 memcpy(s->data + (modlen - pubkeylen), pubkey, pubkeylen);
220 memset(s->data, 0, modlen - pubkeylen);
221 SHA512Update(&ctxt, s->data, modlen);
222 }
223 else
224 SHA512Update(&ctxt, pubkey, pubkeylen);
225 }
226 else {
227 BigIntegerToCstr(srp->pubkey, s);
228 SHA512Update(&ctxt, s->data, s->length);
229 SHA512Update(&ctxt, pubkey, pubkeylen);
230 }
231 SHA512Final(dig, &ctxt);
232 srp->u = BigIntegerFromBytes(dig, SHA512_DIGESTSIZE);
233
234 /* hash: (H(N) xor H(g)) | H(U) | s | A | B */
235 SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, pubkey, pubkeylen);
236
237 gb = BigIntegerFromBytes(pubkey, pubkeylen);
238 /* reject B == 0, B >= modulus */
239 if(BigIntegerCmp(gb, srp->modulus) >= 0 || BigIntegerCmpInt(gb, 0) == 0) {
240 BigIntegerFree(gb);
241 cstr_clear_free(s);
242 return SRP_ERROR;
243 }
244 e = BigIntegerFromInt(0);
245 srp->key = BigIntegerFromInt(0);
246 /* unblind g^b (mod N) */
247 BigIntegerSub(srp->key, srp->modulus, srp->verifier);
248 /* use e as temporary, e == -k*v (mod N) */
249 BigIntegerMul(e, k, srp->key, srp->bctx);
250 BigIntegerAdd(e, e, gb);
251 BigIntegerMod(gb, e, srp->modulus, srp->bctx);
252
253 /* compute gb^(a + ux) (mod N) */
254 BigIntegerMul(e, srp->password, srp->u, srp->bctx);
255 BigIntegerAdd(e, e, srp->secret); /* e = a + ux */
256
257 BigIntegerModExp(srp->key, gb, e, srp->modulus, srp->bctx, srp->accel);
258 BigIntegerClearFree(e);
259 BigIntegerClearFree(gb);
260
261 /* convert srp->key into a session key, update hash states */
262 BigIntegerToCstr(srp->key, s);
263 SHA512Init(&ctxt);
264 SHA512Update(&ctxt, s->data, s->length);
265 SHA512Final((unsigned char*)&SHA512_CLIENT_CTXP(srp)->k, &ctxt);
266 cstr_clear_free(s);
267
268 /* hash: (H(N) xor H(g)) | H(U) | s | A | B | K */
269 SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, SHA512_CLIENT_CTXP(srp)->k, SRP6_SHA512_KEY_LEN);
270 /* hash: (H(N) xor H(g)) | H(U) | s | A | B | K | ex_data */
271 if(srp->ex_data->length > 0)
272 SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash,
273 srp->ex_data->data, srp->ex_data->length);
274 if(result) {
275 if(*result == NULL)
276 *result = cstr_new();
277 cstr_setn(*result, (const char*)SHA512_CLIENT_CTXP(srp)->k, SRP6_SHA512_KEY_LEN);
278 }
279
280 return SRP_SUCCESS;
281}
282
283static SRP_RESULT
284srp6a_sha512_client_key(SRP * srp, cstr ** result,
285 const unsigned char * pubkey, int pubkeylen)
286{
287 SRP_RESULT ret;
288 BigInteger k;
289 cstr * s;
290 SHA512_CTX ctxt;
291 unsigned char dig[SHA512_DIGESTSIZE];
292
293 SHA512Init(&ctxt);
294 s = cstr_new();
295 BigIntegerToCstr(srp->modulus, s);
296 SHA512Update(&ctxt, s->data, s->length);
297 if(srp->flags & SRP_FLAG_LEFT_PAD)
298 BigIntegerToCstrEx(srp->generator, s, s->length);
299 else
300 BigIntegerToCstr(srp->generator, s);
301 SHA512Update(&ctxt, s->data, s->length);
302 SHA512Final(dig, &ctxt);
303 cstr_free(s);
304
305 k = BigIntegerFromBytes(dig, SHA512_DIGESTSIZE);
306 if(BigIntegerCmpInt(k, 0) == 0)
307 ret = SRP_ERROR;
308 else
309 ret = srp6_sha512_client_key_ex(srp, result, pubkey, pubkeylen, k);
310 BigIntegerClearFree(k);
311 return ret;
312}
313
314static SRP_RESULT
315srp6_sha512_client_verify(SRP * srp, const unsigned char * proof, int prooflen)
316{
317 unsigned char expected[SHA512_DIGESTSIZE];
318
319 SHA512Final(expected, &SHA512_CLIENT_CTXP(srp)->ckhash);
320 if(prooflen == SHA512_DIGESTSIZE && memcmp(expected, proof, prooflen) == 0)
321 return SRP_SUCCESS;
322 else
323 return SRP_ERROR;
324}
325
326static SRP_RESULT
327srp6_sha512_client_respond(SRP * srp, cstr ** proof)
328{
329 if(proof == NULL)
330 return SRP_ERROR;
331
332 if(*proof == NULL)
333 *proof = cstr_new();
334
335 /* proof contains client's response */
336 cstr_set_length(*proof, SHA512_DIGESTSIZE);
337 SHA512Final((unsigned char*)(*proof)->data, &SHA512_CLIENT_CTXP(srp)->hash);
338
339 /* ckhash: A | M | K */
340 SHA512Update(&SHA512_CLIENT_CTXP(srp)->ckhash, (*proof)->data, (*proof)->length);
341 SHA512Update(&SHA512_CLIENT_CTXP(srp)->ckhash, SHA512_CLIENT_CTXP(srp)->k, SRP6_SHA512_KEY_LEN);
342 return SRP_SUCCESS;
343}
344
345static SRP_METHOD srp6a_sha512_client_meth = {
346 "SRP-6a sha512 client (tjw)",
347 srp6a_sha512_client_init,
348 srp6_sha512_client_finish,
349 srp6_sha512_client_params,
350 srp6_sha512_client_auth,
351 srp6_sha512_client_passwd,
352 srp6_sha512_client_genpub,
353 srp6a_sha512_client_key,
354 srp6_sha512_client_verify,
355 srp6_sha512_client_respond,
356 NULL
357};
358
359_TYPE( SRP_METHOD * )
360SRP6a_sha512_client_method()
361{
362 return &srp6a_sha512_client_meth;
363}