]>
Commit | Line | Data |
---|---|---|
edc032b5 | 1 | /* crypto/srp/srp_vfy.c */ |
0f113f3e MC |
2 | /* |
3 | * Written by Christophe Renou (christophe.renou@edelweb.fr) with the | |
4 | * precious help of Peter Sylvester (peter.sylvester@edelweb.fr) for the | |
5 | * EdelKey project and contributed to the OpenSSL project 2004. | |
edc032b5 BL |
6 | */ |
7 | /* ==================================================================== | |
8 | * Copyright (c) 2004 The OpenSSL Project. All rights reserved. | |
9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | |
13 | * | |
14 | * 1. Redistributions of source code must retain the above copyright | |
0f113f3e | 15 | * notice, this list of conditions and the following disclaimer. |
edc032b5 BL |
16 | * |
17 | * 2. Redistributions in binary form must reproduce the above copyright | |
18 | * notice, this list of conditions and the following disclaimer in | |
19 | * the documentation and/or other materials provided with the | |
20 | * distribution. | |
21 | * | |
22 | * 3. All advertising materials mentioning features or use of this | |
23 | * software must display the following acknowledgment: | |
24 | * "This product includes software developed by the OpenSSL Project | |
25 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
26 | * | |
27 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
28 | * endorse or promote products derived from this software without | |
29 | * prior written permission. For written permission, please contact | |
30 | * licensing@OpenSSL.org. | |
31 | * | |
32 | * 5. Products derived from this software may not be called "OpenSSL" | |
33 | * nor may "OpenSSL" appear in their names without prior written | |
34 | * permission of the OpenSSL Project. | |
35 | * | |
36 | * 6. Redistributions of any form whatsoever must retain the following | |
37 | * acknowledgment: | |
38 | * "This product includes software developed by the OpenSSL Project | |
39 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
40 | * | |
41 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
42 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
43 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
44 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
45 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
46 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
47 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
48 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
49 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
50 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
51 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
52 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
53 | * ==================================================================== | |
54 | * | |
55 | * This product includes cryptographic software written by Eric Young | |
56 | * (eay@cryptsoft.com). This product includes software written by Tim | |
57 | * Hudson (tjh@cryptsoft.com). | |
58 | * | |
59 | */ | |
60 | #ifndef OPENSSL_NO_SRP | |
b39fc560 | 61 | # include "internal/cryptlib.h" |
dfb56425 | 62 | # include <openssl/sha.h> |
0f113f3e MC |
63 | # include <openssl/srp.h> |
64 | # include <openssl/evp.h> | |
65 | # include <openssl/buffer.h> | |
66 | # include <openssl/rand.h> | |
67 | # include <openssl/txt_db.h> | |
edc032b5 | 68 | |
0f113f3e MC |
69 | # define SRP_RANDOM_SALT_LEN 20 |
70 | # define MAX_LEN 2500 | |
edc032b5 BL |
71 | |
72 | static char b64table[] = | |
0f113f3e | 73 | "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; |
edc032b5 | 74 | |
0f113f3e MC |
75 | /* |
76 | * the following two conversion routines have been inspired by code from | |
77 | * Stanford | |
78 | */ | |
edc032b5 BL |
79 | |
80 | /* | |
81 | * Convert a base64 string into raw byte array representation. | |
82 | */ | |
83 | static int t_fromb64(unsigned char *a, const char *src) | |
0f113f3e MC |
84 | { |
85 | char *loc; | |
86 | int i, j; | |
87 | int size; | |
88 | ||
89 | while (*src && (*src == ' ' || *src == '\t' || *src == '\n')) | |
90 | ++src; | |
91 | size = strlen(src); | |
92 | i = 0; | |
93 | while (i < size) { | |
94 | loc = strchr(b64table, src[i]); | |
95 | if (loc == (char *)0) | |
96 | break; | |
97 | else | |
98 | a[i] = loc - b64table; | |
99 | ++i; | |
100 | } | |
101 | /* if nothing valid to process we have a zero length response */ | |
102 | if (i == 0) | |
103 | return 0; | |
104 | size = i; | |
105 | i = size - 1; | |
106 | j = size; | |
107 | while (1) { | |
108 | a[j] = a[i]; | |
109 | if (--i < 0) | |
110 | break; | |
111 | a[j] |= (a[i] & 3) << 6; | |
112 | --j; | |
113 | a[j] = (unsigned char)((a[i] & 0x3c) >> 2); | |
114 | if (--i < 0) | |
115 | break; | |
116 | a[j] |= (a[i] & 0xf) << 4; | |
117 | --j; | |
118 | a[j] = (unsigned char)((a[i] & 0x30) >> 4); | |
119 | if (--i < 0) | |
120 | break; | |
121 | a[j] |= (a[i] << 2); | |
122 | ||
123 | a[--j] = 0; | |
124 | if (--i < 0) | |
125 | break; | |
126 | } | |
127 | while (a[j] == 0 && j <= size) | |
128 | ++j; | |
129 | i = 0; | |
130 | while (j <= size) | |
131 | a[i++] = a[j++]; | |
132 | return i; | |
133 | } | |
edc032b5 BL |
134 | |
135 | /* | |
136 | * Convert a raw byte string into a null-terminated base64 ASCII string. | |
137 | */ | |
138 | static char *t_tob64(char *dst, const unsigned char *src, int size) | |
0f113f3e MC |
139 | { |
140 | int c, pos = size % 3; | |
141 | unsigned char b0 = 0, b1 = 0, b2 = 0, notleading = 0; | |
142 | char *olddst = dst; | |
143 | ||
144 | switch (pos) { | |
145 | case 1: | |
146 | b2 = src[0]; | |
147 | break; | |
148 | case 2: | |
149 | b1 = src[0]; | |
150 | b2 = src[1]; | |
151 | break; | |
152 | } | |
153 | ||
154 | while (1) { | |
155 | c = (b0 & 0xfc) >> 2; | |
156 | if (notleading || c != 0) { | |
157 | *dst++ = b64table[c]; | |
158 | notleading = 1; | |
159 | } | |
160 | c = ((b0 & 3) << 4) | ((b1 & 0xf0) >> 4); | |
161 | if (notleading || c != 0) { | |
162 | *dst++ = b64table[c]; | |
163 | notleading = 1; | |
164 | } | |
165 | c = ((b1 & 0xf) << 2) | ((b2 & 0xc0) >> 6); | |
166 | if (notleading || c != 0) { | |
167 | *dst++ = b64table[c]; | |
168 | notleading = 1; | |
169 | } | |
170 | c = b2 & 0x3f; | |
171 | if (notleading || c != 0) { | |
172 | *dst++ = b64table[c]; | |
173 | notleading = 1; | |
174 | } | |
175 | if (pos >= size) | |
176 | break; | |
177 | else { | |
178 | b0 = src[pos++]; | |
179 | b1 = src[pos++]; | |
180 | b2 = src[pos++]; | |
181 | } | |
182 | } | |
183 | ||
184 | *dst++ = '\0'; | |
185 | return olddst; | |
186 | } | |
edc032b5 BL |
187 | |
188 | static void SRP_user_pwd_free(SRP_user_pwd *user_pwd) | |
0f113f3e MC |
189 | { |
190 | if (user_pwd == NULL) | |
191 | return; | |
192 | BN_free(user_pwd->s); | |
193 | BN_clear_free(user_pwd->v); | |
194 | OPENSSL_free(user_pwd->id); | |
195 | OPENSSL_free(user_pwd->info); | |
196 | OPENSSL_free(user_pwd); | |
197 | } | |
edc032b5 | 198 | |
71fa4513 | 199 | static SRP_user_pwd *SRP_user_pwd_new(void) |
0f113f3e | 200 | { |
b4faea50 | 201 | SRP_user_pwd *ret = OPENSSL_malloc(sizeof(*ret)); |
0f113f3e MC |
202 | if (ret == NULL) |
203 | return NULL; | |
204 | ret->N = NULL; | |
205 | ret->g = NULL; | |
206 | ret->s = NULL; | |
207 | ret->v = NULL; | |
208 | ret->id = NULL; | |
209 | ret->info = NULL; | |
210 | return ret; | |
211 | } | |
edc032b5 BL |
212 | |
213 | static void SRP_user_pwd_set_gN(SRP_user_pwd *vinfo, const BIGNUM *g, | |
0f113f3e MC |
214 | const BIGNUM *N) |
215 | { | |
216 | vinfo->N = N; | |
217 | vinfo->g = g; | |
218 | } | |
edc032b5 BL |
219 | |
220 | static int SRP_user_pwd_set_ids(SRP_user_pwd *vinfo, const char *id, | |
0f113f3e MC |
221 | const char *info) |
222 | { | |
223 | if (id != NULL && NULL == (vinfo->id = BUF_strdup(id))) | |
224 | return 0; | |
225 | return (info == NULL || NULL != (vinfo->info = BUF_strdup(info))); | |
226 | } | |
edc032b5 BL |
227 | |
228 | static int SRP_user_pwd_set_sv(SRP_user_pwd *vinfo, const char *s, | |
0f113f3e MC |
229 | const char *v) |
230 | { | |
231 | unsigned char tmp[MAX_LEN]; | |
232 | int len; | |
233 | ||
234 | if (strlen(s) > MAX_LEN || strlen(v) > MAX_LEN) | |
235 | return 0; | |
236 | len = t_fromb64(tmp, v); | |
237 | if (NULL == (vinfo->v = BN_bin2bn(tmp, len, NULL))) | |
238 | return 0; | |
239 | len = t_fromb64(tmp, s); | |
240 | return ((vinfo->s = BN_bin2bn(tmp, len, NULL)) != NULL); | |
241 | } | |
edc032b5 | 242 | |
71fa4513 | 243 | static int SRP_user_pwd_set_sv_BN(SRP_user_pwd *vinfo, BIGNUM *s, BIGNUM *v) |
0f113f3e MC |
244 | { |
245 | vinfo->v = v; | |
246 | vinfo->s = s; | |
247 | return (vinfo->s != NULL && vinfo->v != NULL); | |
248 | } | |
edc032b5 BL |
249 | |
250 | SRP_VBASE *SRP_VBASE_new(char *seed_key) | |
0f113f3e | 251 | { |
b4faea50 | 252 | SRP_VBASE *vb = OPENSSL_malloc(sizeof(*vb)); |
0f113f3e MC |
253 | |
254 | if (vb == NULL) | |
255 | return NULL; | |
75ebbd9a RS |
256 | if ((vb->users_pwd = sk_SRP_user_pwd_new_null()) == NULL |
257 | || (vb->gN_cache = sk_SRP_gN_cache_new_null()) == NULL) { | |
0f113f3e MC |
258 | OPENSSL_free(vb); |
259 | return NULL; | |
260 | } | |
261 | vb->default_g = NULL; | |
262 | vb->default_N = NULL; | |
263 | vb->seed_key = NULL; | |
264 | if ((seed_key != NULL) && (vb->seed_key = BUF_strdup(seed_key)) == NULL) { | |
265 | sk_SRP_user_pwd_free(vb->users_pwd); | |
266 | sk_SRP_gN_cache_free(vb->gN_cache); | |
267 | OPENSSL_free(vb); | |
268 | return NULL; | |
269 | } | |
270 | return vb; | |
271 | } | |
edc032b5 | 272 | |
895cba19 | 273 | void SRP_VBASE_free(SRP_VBASE *vb) |
0f113f3e | 274 | { |
895cba19 RS |
275 | if (!vb) |
276 | return; | |
0f113f3e MC |
277 | sk_SRP_user_pwd_pop_free(vb->users_pwd, SRP_user_pwd_free); |
278 | sk_SRP_gN_cache_free(vb->gN_cache); | |
279 | OPENSSL_free(vb->seed_key); | |
280 | OPENSSL_free(vb); | |
0f113f3e | 281 | } |
edc032b5 BL |
282 | |
283 | static SRP_gN_cache *SRP_gN_new_init(const char *ch) | |
0f113f3e MC |
284 | { |
285 | unsigned char tmp[MAX_LEN]; | |
286 | int len; | |
b4faea50 | 287 | SRP_gN_cache *newgN = OPENSSL_malloc(sizeof(*newgN)); |
edc032b5 | 288 | |
0f113f3e MC |
289 | if (newgN == NULL) |
290 | return NULL; | |
edc032b5 | 291 | |
0f113f3e MC |
292 | if ((newgN->b64_bn = BUF_strdup(ch)) == NULL) |
293 | goto err; | |
edc032b5 | 294 | |
0f113f3e MC |
295 | len = t_fromb64(tmp, ch); |
296 | if ((newgN->bn = BN_bin2bn(tmp, len, NULL))) | |
297 | return newgN; | |
edc032b5 | 298 | |
0f113f3e MC |
299 | OPENSSL_free(newgN->b64_bn); |
300 | err: | |
301 | OPENSSL_free(newgN); | |
302 | return NULL; | |
303 | } | |
edc032b5 BL |
304 | |
305 | static void SRP_gN_free(SRP_gN_cache *gN_cache) | |
0f113f3e MC |
306 | { |
307 | if (gN_cache == NULL) | |
308 | return; | |
309 | OPENSSL_free(gN_cache->b64_bn); | |
310 | BN_free(gN_cache->bn); | |
311 | OPENSSL_free(gN_cache); | |
312 | } | |
edc032b5 BL |
313 | |
314 | static SRP_gN *SRP_get_gN_by_id(const char *id, STACK_OF(SRP_gN) *gN_tab) | |
0f113f3e MC |
315 | { |
316 | int i; | |
317 | ||
318 | SRP_gN *gN; | |
319 | if (gN_tab != NULL) | |
320 | for (i = 0; i < sk_SRP_gN_num(gN_tab); i++) { | |
321 | gN = sk_SRP_gN_value(gN_tab, i); | |
322 | if (gN && (id == NULL || strcmp(gN->id, id) == 0)) | |
323 | return gN; | |
324 | } | |
325 | ||
326 | return SRP_get_default_gN(id); | |
327 | } | |
edc032b5 BL |
328 | |
329 | static BIGNUM *SRP_gN_place_bn(STACK_OF(SRP_gN_cache) *gN_cache, char *ch) | |
0f113f3e MC |
330 | { |
331 | int i; | |
332 | if (gN_cache == NULL) | |
333 | return NULL; | |
334 | ||
335 | /* search if we have already one... */ | |
336 | for (i = 0; i < sk_SRP_gN_cache_num(gN_cache); i++) { | |
337 | SRP_gN_cache *cache = sk_SRP_gN_cache_value(gN_cache, i); | |
338 | if (strcmp(cache->b64_bn, ch) == 0) | |
339 | return cache->bn; | |
340 | } | |
341 | { /* it is the first time that we find it */ | |
342 | SRP_gN_cache *newgN = SRP_gN_new_init(ch); | |
343 | if (newgN) { | |
344 | if (sk_SRP_gN_cache_insert(gN_cache, newgN, 0) > 0) | |
345 | return newgN->bn; | |
346 | SRP_gN_free(newgN); | |
347 | } | |
348 | } | |
349 | return NULL; | |
350 | } | |
351 | ||
352 | /* | |
353 | * this function parses verifier file. Format is: | |
edc032b5 BL |
354 | * string(index):base64(N):base64(g):0 |
355 | * string(username):base64(v):base64(salt):int(index) | |
356 | */ | |
357 | ||
edc032b5 | 358 | int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file) |
0f113f3e MC |
359 | { |
360 | int error_code; | |
361 | STACK_OF(SRP_gN) *SRP_gN_tab = sk_SRP_gN_new_null(); | |
362 | char *last_index = NULL; | |
363 | int i; | |
364 | char **pp; | |
365 | ||
366 | SRP_gN *gN = NULL; | |
367 | SRP_user_pwd *user_pwd = NULL; | |
368 | ||
369 | TXT_DB *tmpdb = NULL; | |
370 | BIO *in = BIO_new(BIO_s_file()); | |
371 | ||
372 | error_code = SRP_ERR_OPEN_FILE; | |
373 | ||
374 | if (in == NULL || BIO_read_filename(in, verifier_file) <= 0) | |
375 | goto err; | |
376 | ||
377 | error_code = SRP_ERR_VBASE_INCOMPLETE_FILE; | |
378 | ||
379 | if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL) | |
380 | goto err; | |
381 | ||
382 | error_code = SRP_ERR_MEMORY; | |
383 | ||
384 | if (vb->seed_key) { | |
385 | last_index = SRP_get_default_gN(NULL)->id; | |
386 | } | |
387 | for (i = 0; i < sk_OPENSSL_PSTRING_num(tmpdb->data); i++) { | |
388 | pp = sk_OPENSSL_PSTRING_value(tmpdb->data, i); | |
389 | if (pp[DB_srptype][0] == DB_SRP_INDEX) { | |
390 | /* | |
391 | * we add this couple in the internal Stack | |
392 | */ | |
393 | ||
b4faea50 | 394 | if ((gN = OPENSSL_malloc(sizeof(*gN))) == NULL) |
0f113f3e MC |
395 | goto err; |
396 | ||
75ebbd9a RS |
397 | if ((gN->id = BUF_strdup(pp[DB_srpid])) == NULL |
398 | || (gN->N = SRP_gN_place_bn(vb->gN_cache, pp[DB_srpverifier])) | |
399 | == NULL | |
400 | || (gN->g = SRP_gN_place_bn(vb->gN_cache, pp[DB_srpsalt])) | |
401 | == NULL | |
0f113f3e MC |
402 | || sk_SRP_gN_insert(SRP_gN_tab, gN, 0) == 0) |
403 | goto err; | |
404 | ||
405 | gN = NULL; | |
406 | ||
407 | if (vb->seed_key != NULL) { | |
408 | last_index = pp[DB_srpid]; | |
409 | } | |
410 | } else if (pp[DB_srptype][0] == DB_SRP_VALID) { | |
411 | /* it is a user .... */ | |
412 | const SRP_gN *lgN; | |
413 | ||
414 | if ((lgN = SRP_get_gN_by_id(pp[DB_srpgN], SRP_gN_tab)) != NULL) { | |
415 | error_code = SRP_ERR_MEMORY; | |
416 | if ((user_pwd = SRP_user_pwd_new()) == NULL) | |
417 | goto err; | |
418 | ||
419 | SRP_user_pwd_set_gN(user_pwd, lgN->g, lgN->N); | |
420 | if (!SRP_user_pwd_set_ids | |
421 | (user_pwd, pp[DB_srpid], pp[DB_srpinfo])) | |
422 | goto err; | |
423 | ||
424 | error_code = SRP_ERR_VBASE_BN_LIB; | |
425 | if (!SRP_user_pwd_set_sv | |
426 | (user_pwd, pp[DB_srpsalt], pp[DB_srpverifier])) | |
427 | goto err; | |
428 | ||
429 | if (sk_SRP_user_pwd_insert(vb->users_pwd, user_pwd, 0) == 0) | |
430 | goto err; | |
431 | user_pwd = NULL; /* abandon responsability */ | |
432 | } | |
433 | } | |
434 | } | |
435 | ||
436 | if (last_index != NULL) { | |
437 | /* this means that we want to simulate a default user */ | |
438 | ||
439 | if (((gN = SRP_get_gN_by_id(last_index, SRP_gN_tab)) == NULL)) { | |
440 | error_code = SRP_ERR_VBASE_BN_LIB; | |
441 | goto err; | |
442 | } | |
443 | vb->default_g = gN->g; | |
444 | vb->default_N = gN->N; | |
445 | gN = NULL; | |
446 | } | |
447 | error_code = SRP_NO_ERROR; | |
edc032b5 BL |
448 | |
449 | err: | |
0f113f3e MC |
450 | /* |
451 | * there may be still some leaks to fix, if this fails, the application | |
452 | * terminates most likely | |
453 | */ | |
edc032b5 | 454 | |
0f113f3e MC |
455 | if (gN != NULL) { |
456 | OPENSSL_free(gN->id); | |
457 | OPENSSL_free(gN); | |
458 | } | |
edc032b5 | 459 | |
0f113f3e | 460 | SRP_user_pwd_free(user_pwd); |
edc032b5 | 461 | |
895cba19 | 462 | TXT_DB_free(tmpdb); |
ca3a82c3 | 463 | BIO_free_all(in); |
edc032b5 | 464 | |
0f113f3e | 465 | sk_SRP_gN_free(SRP_gN_tab); |
edc032b5 | 466 | |
0f113f3e | 467 | return error_code; |
edc032b5 | 468 | |
0f113f3e | 469 | } |
edc032b5 BL |
470 | |
471 | SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username) | |
0f113f3e MC |
472 | { |
473 | int i; | |
474 | SRP_user_pwd *user; | |
475 | unsigned char digv[SHA_DIGEST_LENGTH]; | |
476 | unsigned char digs[SHA_DIGEST_LENGTH]; | |
477 | EVP_MD_CTX ctxt; | |
478 | ||
479 | if (vb == NULL) | |
480 | return NULL; | |
481 | for (i = 0; i < sk_SRP_user_pwd_num(vb->users_pwd); i++) { | |
482 | user = sk_SRP_user_pwd_value(vb->users_pwd, i); | |
483 | if (strcmp(user->id, username) == 0) | |
484 | return user; | |
485 | } | |
486 | if ((vb->seed_key == NULL) || | |
487 | (vb->default_g == NULL) || (vb->default_N == NULL)) | |
488 | return NULL; | |
edc032b5 BL |
489 | |
490 | /* if the user is unknown we set parameters as well if we have a seed_key */ | |
491 | ||
0f113f3e MC |
492 | if ((user = SRP_user_pwd_new()) == NULL) |
493 | return NULL; | |
494 | ||
495 | SRP_user_pwd_set_gN(user, vb->default_g, vb->default_N); | |
edc032b5 | 496 | |
0f113f3e MC |
497 | if (!SRP_user_pwd_set_ids(user, username, NULL)) |
498 | goto err; | |
499 | ||
266483d2 MC |
500 | if (RAND_bytes(digv, SHA_DIGEST_LENGTH) <= 0) |
501 | goto err; | |
0f113f3e MC |
502 | EVP_MD_CTX_init(&ctxt); |
503 | EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL); | |
504 | EVP_DigestUpdate(&ctxt, vb->seed_key, strlen(vb->seed_key)); | |
505 | EVP_DigestUpdate(&ctxt, username, strlen(username)); | |
506 | EVP_DigestFinal_ex(&ctxt, digs, NULL); | |
507 | EVP_MD_CTX_cleanup(&ctxt); | |
508 | if (SRP_user_pwd_set_sv_BN | |
509 | (user, BN_bin2bn(digs, SHA_DIGEST_LENGTH, NULL), | |
510 | BN_bin2bn(digv, SHA_DIGEST_LENGTH, NULL))) | |
511 | return user; | |
512 | ||
895cba19 RS |
513 | err: |
514 | SRP_user_pwd_free(user); | |
0f113f3e MC |
515 | return NULL; |
516 | } | |
edc032b5 BL |
517 | |
518 | /* | |
0f113f3e MC |
519 | * create a verifier (*salt,*verifier,g and N are in base64) |
520 | */ | |
edc032b5 | 521 | char *SRP_create_verifier(const char *user, const char *pass, char **salt, |
0f113f3e MC |
522 | char **verifier, const char *N, const char *g) |
523 | { | |
524 | int len; | |
525 | char *result = NULL; | |
526 | char *vf; | |
527 | BIGNUM *N_bn = NULL, *g_bn = NULL, *s = NULL, *v = NULL; | |
528 | unsigned char tmp[MAX_LEN]; | |
529 | unsigned char tmp2[MAX_LEN]; | |
530 | char *defgNid = NULL; | |
531 | ||
532 | if ((user == NULL) || | |
533 | (pass == NULL) || (salt == NULL) || (verifier == NULL)) | |
534 | goto err; | |
535 | ||
536 | if (N) { | |
75ebbd9a | 537 | if ((len = t_fromb64(tmp, N)) == 0) |
0f113f3e MC |
538 | goto err; |
539 | N_bn = BN_bin2bn(tmp, len, NULL); | |
75ebbd9a | 540 | if ((len = t_fromb64(tmp, g)) == 0) |
0f113f3e MC |
541 | goto err; |
542 | g_bn = BN_bin2bn(tmp, len, NULL); | |
543 | defgNid = "*"; | |
544 | } else { | |
545 | SRP_gN *gN = SRP_get_gN_by_id(g, NULL); | |
546 | if (gN == NULL) | |
547 | goto err; | |
548 | N_bn = gN->N; | |
549 | g_bn = gN->g; | |
550 | defgNid = gN->id; | |
551 | } | |
552 | ||
553 | if (*salt == NULL) { | |
266483d2 MC |
554 | if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0) |
555 | goto err; | |
0f113f3e MC |
556 | |
557 | s = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); | |
558 | } else { | |
75ebbd9a | 559 | if ((len = t_fromb64(tmp2, *salt)) == 0) |
0f113f3e MC |
560 | goto err; |
561 | s = BN_bin2bn(tmp2, len, NULL); | |
562 | } | |
563 | ||
564 | if (!SRP_create_verifier_BN(user, pass, &s, &v, N_bn, g_bn)) | |
565 | goto err; | |
566 | ||
567 | BN_bn2bin(v, tmp); | |
568 | if (((vf = OPENSSL_malloc(BN_num_bytes(v) * 2)) == NULL)) | |
569 | goto err; | |
570 | t_tob64(vf, tmp, BN_num_bytes(v)); | |
571 | ||
572 | *verifier = vf; | |
573 | if (*salt == NULL) { | |
574 | char *tmp_salt; | |
575 | ||
576 | if ((tmp_salt = OPENSSL_malloc(SRP_RANDOM_SALT_LEN * 2)) == NULL) { | |
577 | OPENSSL_free(vf); | |
578 | goto err; | |
579 | } | |
580 | t_tob64(tmp_salt, tmp2, SRP_RANDOM_SALT_LEN); | |
581 | *salt = tmp_salt; | |
582 | } | |
583 | ||
584 | result = defgNid; | |
585 | ||
586 | err: | |
587 | if (N) { | |
588 | BN_free(N_bn); | |
589 | BN_free(g_bn); | |
590 | } | |
591 | return result; | |
592 | } | |
edc032b5 BL |
593 | |
594 | /* | |
0f113f3e MC |
595 | * create a verifier (*salt,*verifier,g and N are BIGNUMs) |
596 | */ | |
8892ce77 | 597 | int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, |
0f113f3e MC |
598 | BIGNUM **verifier, const BIGNUM *N, |
599 | const BIGNUM *g) | |
600 | { | |
601 | int result = 0; | |
602 | BIGNUM *x = NULL; | |
603 | BN_CTX *bn_ctx = BN_CTX_new(); | |
604 | unsigned char tmp2[MAX_LEN]; | |
edc032b5 | 605 | |
0f113f3e MC |
606 | if ((user == NULL) || |
607 | (pass == NULL) || | |
608 | (salt == NULL) || | |
609 | (verifier == NULL) || (N == NULL) || (g == NULL) || (bn_ctx == NULL)) | |
610 | goto err; | |
edc032b5 | 611 | |
0f113f3e | 612 | if (*salt == NULL) { |
266483d2 MC |
613 | if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0) |
614 | goto err; | |
edc032b5 | 615 | |
0f113f3e MC |
616 | *salt = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); |
617 | } | |
edc032b5 | 618 | |
0f113f3e | 619 | x = SRP_Calc_x(*salt, user, pass); |
edc032b5 | 620 | |
0f113f3e MC |
621 | *verifier = BN_new(); |
622 | if (*verifier == NULL) | |
623 | goto err; | |
edc032b5 | 624 | |
0f113f3e MC |
625 | if (!BN_mod_exp(*verifier, g, x, N, bn_ctx)) { |
626 | BN_clear_free(*verifier); | |
627 | goto err; | |
628 | } | |
edc032b5 | 629 | |
0f113f3e | 630 | result = 1; |
edc032b5 | 631 | |
0f113f3e | 632 | err: |
edc032b5 | 633 | |
0f113f3e MC |
634 | BN_clear_free(x); |
635 | BN_CTX_free(bn_ctx); | |
636 | return result; | |
637 | } | |
edc032b5 BL |
638 | |
639 | #endif |