srp_vfy.c revision 306195
1/* crypto/srp/srp_vfy.c */ 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. 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 15 * notice, this list of conditions and the following disclaimer. 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 61# include "cryptlib.h" 62# include "srp_lcl.h" 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> 68 69# define SRP_RANDOM_SALT_LEN 20 70# define MAX_LEN 2500 71 72static char b64table[] = 73 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; 74 75/* 76 * the following two conversion routines have been inspired by code from 77 * Stanford 78 */ 79 80/* 81 * Convert a base64 string into raw byte array representation. 82 */ 83static int t_fromb64(unsigned char *a, size_t alen, const char *src) 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 if (alen > INT_MAX || size > (int)alen) 93 return -1; 94 95 i = 0; 96 while (i < size) { 97 loc = strchr(b64table, src[i]); 98 if (loc == (char *)0) 99 break; 100 else 101 a[i] = loc - b64table; 102 ++i; 103 } 104 /* if nothing valid to process we have a zero length response */ 105 if (i == 0) 106 return 0; 107 size = i; 108 i = size - 1; 109 j = size; 110 while (1) { 111 a[j] = a[i]; 112 if (--i < 0) 113 break; 114 a[j] |= (a[i] & 3) << 6; 115 --j; 116 a[j] = (unsigned char)((a[i] & 0x3c) >> 2); 117 if (--i < 0) 118 break; 119 a[j] |= (a[i] & 0xf) << 4; 120 --j; 121 a[j] = (unsigned char)((a[i] & 0x30) >> 4); 122 if (--i < 0) 123 break; 124 a[j] |= (a[i] << 2); 125 126 a[--j] = 0; 127 if (--i < 0) 128 break; 129 } 130 while (a[j] == 0 && j <= size) 131 ++j; 132 i = 0; 133 while (j <= size) 134 a[i++] = a[j++]; 135 return i; 136} 137 138/* 139 * Convert a raw byte string into a null-terminated base64 ASCII string. 140 */ 141static char *t_tob64(char *dst, const unsigned char *src, int size) 142{ 143 int c, pos = size % 3; 144 unsigned char b0 = 0, b1 = 0, b2 = 0, notleading = 0; 145 char *olddst = dst; 146 147 switch (pos) { 148 case 1: 149 b2 = src[0]; 150 break; 151 case 2: 152 b1 = src[0]; 153 b2 = src[1]; 154 break; 155 } 156 157 while (1) { 158 c = (b0 & 0xfc) >> 2; 159 if (notleading || c != 0) { 160 *dst++ = b64table[c]; 161 notleading = 1; 162 } 163 c = ((b0 & 3) << 4) | ((b1 & 0xf0) >> 4); 164 if (notleading || c != 0) { 165 *dst++ = b64table[c]; 166 notleading = 1; 167 } 168 c = ((b1 & 0xf) << 2) | ((b2 & 0xc0) >> 6); 169 if (notleading || c != 0) { 170 *dst++ = b64table[c]; 171 notleading = 1; 172 } 173 c = b2 & 0x3f; 174 if (notleading || c != 0) { 175 *dst++ = b64table[c]; 176 notleading = 1; 177 } 178 if (pos >= size) 179 break; 180 else { 181 b0 = src[pos++]; 182 b1 = src[pos++]; 183 b2 = src[pos++]; 184 } 185 } 186 187 *dst++ = '\0'; 188 return olddst; 189} 190 191void SRP_user_pwd_free(SRP_user_pwd *user_pwd) 192{ 193 if (user_pwd == NULL) 194 return; 195 BN_free(user_pwd->s); 196 BN_clear_free(user_pwd->v); 197 OPENSSL_free(user_pwd->id); 198 OPENSSL_free(user_pwd->info); 199 OPENSSL_free(user_pwd); 200} 201 202static SRP_user_pwd *SRP_user_pwd_new() 203{ 204 SRP_user_pwd *ret = OPENSSL_malloc(sizeof(SRP_user_pwd)); 205 if (ret == NULL) 206 return NULL; 207 ret->N = NULL; 208 ret->g = NULL; 209 ret->s = NULL; 210 ret->v = NULL; 211 ret->id = NULL; 212 ret->info = NULL; 213 return ret; 214} 215 216static void SRP_user_pwd_set_gN(SRP_user_pwd *vinfo, const BIGNUM *g, 217 const BIGNUM *N) 218{ 219 vinfo->N = N; 220 vinfo->g = g; 221} 222 223static int SRP_user_pwd_set_ids(SRP_user_pwd *vinfo, const char *id, 224 const char *info) 225{ 226 if (id != NULL && NULL == (vinfo->id = BUF_strdup(id))) 227 return 0; 228 return (info == NULL || NULL != (vinfo->info = BUF_strdup(info))); 229} 230 231static int SRP_user_pwd_set_sv(SRP_user_pwd *vinfo, const char *s, 232 const char *v) 233{ 234 unsigned char tmp[MAX_LEN]; 235 int len; 236 237 vinfo->v = NULL; 238 vinfo->s = NULL; 239 240 len = t_fromb64(tmp, sizeof(tmp), v); 241 if (len < 0) 242 return 0; 243 if (NULL == (vinfo->v = BN_bin2bn(tmp, len, NULL))) 244 return 0; 245 len = t_fromb64(tmp, sizeof(tmp), s); 246 if (len < 0) 247 goto err; 248 vinfo->s = BN_bin2bn(tmp, len, NULL); 249 if (vinfo->s == NULL) 250 goto err; 251 return 1; 252 err: 253 BN_free(vinfo->v); 254 vinfo->v = NULL; 255 return 0; 256} 257 258static int SRP_user_pwd_set_sv_BN(SRP_user_pwd *vinfo, BIGNUM *s, BIGNUM *v) 259{ 260 vinfo->v = v; 261 vinfo->s = s; 262 return (vinfo->s != NULL && vinfo->v != NULL); 263} 264 265static SRP_user_pwd *srp_user_pwd_dup(SRP_user_pwd *src) 266{ 267 SRP_user_pwd *ret; 268 269 if (src == NULL) 270 return NULL; 271 if ((ret = SRP_user_pwd_new()) == NULL) 272 return NULL; 273 274 SRP_user_pwd_set_gN(ret, src->g, src->N); 275 if (!SRP_user_pwd_set_ids(ret, src->id, src->info) 276 || !SRP_user_pwd_set_sv_BN(ret, BN_dup(src->s), BN_dup(src->v))) { 277 SRP_user_pwd_free(ret); 278 return NULL; 279 } 280 return ret; 281} 282 283SRP_VBASE *SRP_VBASE_new(char *seed_key) 284{ 285 SRP_VBASE *vb = (SRP_VBASE *)OPENSSL_malloc(sizeof(SRP_VBASE)); 286 287 if (vb == NULL) 288 return NULL; 289 if (!(vb->users_pwd = sk_SRP_user_pwd_new_null()) || 290 !(vb->gN_cache = sk_SRP_gN_cache_new_null())) { 291 OPENSSL_free(vb); 292 return NULL; 293 } 294 vb->default_g = NULL; 295 vb->default_N = NULL; 296 vb->seed_key = NULL; 297 if ((seed_key != NULL) && (vb->seed_key = BUF_strdup(seed_key)) == NULL) { 298 sk_SRP_user_pwd_free(vb->users_pwd); 299 sk_SRP_gN_cache_free(vb->gN_cache); 300 OPENSSL_free(vb); 301 return NULL; 302 } 303 return vb; 304} 305 306int SRP_VBASE_free(SRP_VBASE *vb) 307{ 308 sk_SRP_user_pwd_pop_free(vb->users_pwd, SRP_user_pwd_free); 309 sk_SRP_gN_cache_free(vb->gN_cache); 310 OPENSSL_free(vb->seed_key); 311 OPENSSL_free(vb); 312 return 0; 313} 314 315static SRP_gN_cache *SRP_gN_new_init(const char *ch) 316{ 317 unsigned char tmp[MAX_LEN]; 318 int len; 319 320 SRP_gN_cache *newgN = 321 (SRP_gN_cache *)OPENSSL_malloc(sizeof(SRP_gN_cache)); 322 if (newgN == NULL) 323 return NULL; 324 325 len = t_fromb64(tmp, sizeof(tmp), ch); 326 if (len < 0) 327 goto err; 328 329 if ((newgN->b64_bn = BUF_strdup(ch)) == NULL) 330 goto err; 331 332 if ((newgN->bn = BN_bin2bn(tmp, len, NULL))) 333 return newgN; 334 335 OPENSSL_free(newgN->b64_bn); 336 err: 337 OPENSSL_free(newgN); 338 return NULL; 339} 340 341static void SRP_gN_free(SRP_gN_cache *gN_cache) 342{ 343 if (gN_cache == NULL) 344 return; 345 OPENSSL_free(gN_cache->b64_bn); 346 BN_free(gN_cache->bn); 347 OPENSSL_free(gN_cache); 348} 349 350static SRP_gN *SRP_get_gN_by_id(const char *id, STACK_OF(SRP_gN) *gN_tab) 351{ 352 int i; 353 354 SRP_gN *gN; 355 if (gN_tab != NULL) 356 for (i = 0; i < sk_SRP_gN_num(gN_tab); i++) { 357 gN = sk_SRP_gN_value(gN_tab, i); 358 if (gN && (id == NULL || strcmp(gN->id, id) == 0)) 359 return gN; 360 } 361 362 return SRP_get_default_gN(id); 363} 364 365static BIGNUM *SRP_gN_place_bn(STACK_OF(SRP_gN_cache) *gN_cache, char *ch) 366{ 367 int i; 368 if (gN_cache == NULL) 369 return NULL; 370 371 /* search if we have already one... */ 372 for (i = 0; i < sk_SRP_gN_cache_num(gN_cache); i++) { 373 SRP_gN_cache *cache = sk_SRP_gN_cache_value(gN_cache, i); 374 if (strcmp(cache->b64_bn, ch) == 0) 375 return cache->bn; 376 } 377 { /* it is the first time that we find it */ 378 SRP_gN_cache *newgN = SRP_gN_new_init(ch); 379 if (newgN) { 380 if (sk_SRP_gN_cache_insert(gN_cache, newgN, 0) > 0) 381 return newgN->bn; 382 SRP_gN_free(newgN); 383 } 384 } 385 return NULL; 386} 387 388/* 389 * this function parses verifier file. Format is: 390 * string(index):base64(N):base64(g):0 391 * string(username):base64(v):base64(salt):int(index) 392 */ 393 394int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file) 395{ 396 int error_code; 397 STACK_OF(SRP_gN) *SRP_gN_tab = sk_SRP_gN_new_null(); 398 char *last_index = NULL; 399 int i; 400 char **pp; 401 402 SRP_gN *gN = NULL; 403 SRP_user_pwd *user_pwd = NULL; 404 405 TXT_DB *tmpdb = NULL; 406 BIO *in = BIO_new(BIO_s_file()); 407 408 error_code = SRP_ERR_OPEN_FILE; 409 410 if (in == NULL || BIO_read_filename(in, verifier_file) <= 0) 411 goto err; 412 413 error_code = SRP_ERR_VBASE_INCOMPLETE_FILE; 414 415 if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL) 416 goto err; 417 418 error_code = SRP_ERR_MEMORY; 419 420 if (vb->seed_key) { 421 last_index = SRP_get_default_gN(NULL)->id; 422 } 423 for (i = 0; i < sk_OPENSSL_PSTRING_num(tmpdb->data); i++) { 424 pp = sk_OPENSSL_PSTRING_value(tmpdb->data, i); 425 if (pp[DB_srptype][0] == DB_SRP_INDEX) { 426 /* 427 * we add this couple in the internal Stack 428 */ 429 430 if ((gN = (SRP_gN *) OPENSSL_malloc(sizeof(SRP_gN))) == NULL) 431 goto err; 432 433 if (!(gN->id = BUF_strdup(pp[DB_srpid])) 434 || !(gN->N = 435 SRP_gN_place_bn(vb->gN_cache, pp[DB_srpverifier])) 436 || !(gN->g = SRP_gN_place_bn(vb->gN_cache, pp[DB_srpsalt])) 437 || sk_SRP_gN_insert(SRP_gN_tab, gN, 0) == 0) 438 goto err; 439 440 gN = NULL; 441 442 if (vb->seed_key != NULL) { 443 last_index = pp[DB_srpid]; 444 } 445 } else if (pp[DB_srptype][0] == DB_SRP_VALID) { 446 /* it is a user .... */ 447 SRP_gN *lgN; 448 if ((lgN = SRP_get_gN_by_id(pp[DB_srpgN], SRP_gN_tab)) != NULL) { 449 error_code = SRP_ERR_MEMORY; 450 if ((user_pwd = SRP_user_pwd_new()) == NULL) 451 goto err; 452 453 SRP_user_pwd_set_gN(user_pwd, lgN->g, lgN->N); 454 if (!SRP_user_pwd_set_ids 455 (user_pwd, pp[DB_srpid], pp[DB_srpinfo])) 456 goto err; 457 458 error_code = SRP_ERR_VBASE_BN_LIB; 459 if (!SRP_user_pwd_set_sv 460 (user_pwd, pp[DB_srpsalt], pp[DB_srpverifier])) 461 goto err; 462 463 if (sk_SRP_user_pwd_insert(vb->users_pwd, user_pwd, 0) == 0) 464 goto err; 465 user_pwd = NULL; /* abandon responsability */ 466 } 467 } 468 } 469 470 if (last_index != NULL) { 471 /* this means that we want to simulate a default user */ 472 473 if (((gN = SRP_get_gN_by_id(last_index, SRP_gN_tab)) == NULL)) { 474 error_code = SRP_ERR_VBASE_BN_LIB; 475 goto err; 476 } 477 vb->default_g = gN->g; 478 vb->default_N = gN->N; 479 gN = NULL; 480 } 481 error_code = SRP_NO_ERROR; 482 483 err: 484 /* 485 * there may be still some leaks to fix, if this fails, the application 486 * terminates most likely 487 */ 488 489 if (gN != NULL) { 490 OPENSSL_free(gN->id); 491 OPENSSL_free(gN); 492 } 493 494 SRP_user_pwd_free(user_pwd); 495 496 if (tmpdb) 497 TXT_DB_free(tmpdb); 498 if (in) 499 BIO_free_all(in); 500 501 sk_SRP_gN_free(SRP_gN_tab); 502 503 return error_code; 504 505} 506 507static SRP_user_pwd *find_user(SRP_VBASE *vb, char *username) 508{ 509 int i; 510 SRP_user_pwd *user; 511 512 if (vb == NULL) 513 return NULL; 514 515 for (i = 0; i < sk_SRP_user_pwd_num(vb->users_pwd); i++) { 516 user = sk_SRP_user_pwd_value(vb->users_pwd, i); 517 if (strcmp(user->id, username) == 0) 518 return user; 519 } 520 521 return NULL; 522} 523 524/* 525 * This method ignores the configured seed and fails for an unknown user. 526 * Ownership of the returned pointer is not released to the caller. 527 * In other words, caller must not free the result. 528 */ 529SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username) 530{ 531 return find_user(vb, username); 532} 533 534/* 535 * Ownership of the returned pointer is released to the caller. 536 * In other words, caller must free the result once done. 537 */ 538SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username) 539{ 540 SRP_user_pwd *user; 541 unsigned char digv[SHA_DIGEST_LENGTH]; 542 unsigned char digs[SHA_DIGEST_LENGTH]; 543 EVP_MD_CTX ctxt; 544 545 if (vb == NULL) 546 return NULL; 547 548 if ((user = find_user(vb, username)) != NULL) 549 return srp_user_pwd_dup(user); 550 551 if ((vb->seed_key == NULL) || 552 (vb->default_g == NULL) || (vb->default_N == NULL)) 553 return NULL; 554 555/* if the user is unknown we set parameters as well if we have a seed_key */ 556 557 if ((user = SRP_user_pwd_new()) == NULL) 558 return NULL; 559 560 SRP_user_pwd_set_gN(user, vb->default_g, vb->default_N); 561 562 if (!SRP_user_pwd_set_ids(user, username, NULL)) 563 goto err; 564 565 if (RAND_bytes(digv, SHA_DIGEST_LENGTH) <= 0) 566 goto err; 567 EVP_MD_CTX_init(&ctxt); 568 EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL); 569 EVP_DigestUpdate(&ctxt, vb->seed_key, strlen(vb->seed_key)); 570 EVP_DigestUpdate(&ctxt, username, strlen(username)); 571 EVP_DigestFinal_ex(&ctxt, digs, NULL); 572 EVP_MD_CTX_cleanup(&ctxt); 573 if (SRP_user_pwd_set_sv_BN 574 (user, BN_bin2bn(digs, SHA_DIGEST_LENGTH, NULL), 575 BN_bin2bn(digv, SHA_DIGEST_LENGTH, NULL))) 576 return user; 577 578 err:SRP_user_pwd_free(user); 579 return NULL; 580} 581 582/* 583 * create a verifier (*salt,*verifier,g and N are in base64) 584 */ 585char *SRP_create_verifier(const char *user, const char *pass, char **salt, 586 char **verifier, const char *N, const char *g) 587{ 588 int len; 589 char *result = NULL, *vf = NULL; 590 BIGNUM *N_bn = NULL, *g_bn = NULL, *s = NULL, *v = NULL; 591 unsigned char tmp[MAX_LEN]; 592 unsigned char tmp2[MAX_LEN]; 593 char *defgNid = NULL; 594 int vfsize = 0; 595 596 if ((user == NULL) || 597 (pass == NULL) || (salt == NULL) || (verifier == NULL)) 598 goto err; 599 600 if (N) { 601 if (!(len = t_fromb64(tmp, sizeof(tmp), N))) 602 goto err; 603 N_bn = BN_bin2bn(tmp, len, NULL); 604 if (!(len = t_fromb64(tmp, sizeof(tmp), g))) 605 goto err; 606 g_bn = BN_bin2bn(tmp, len, NULL); 607 defgNid = "*"; 608 } else { 609 SRP_gN *gN = SRP_get_gN_by_id(g, NULL); 610 if (gN == NULL) 611 goto err; 612 N_bn = gN->N; 613 g_bn = gN->g; 614 defgNid = gN->id; 615 } 616 617 if (*salt == NULL) { 618 if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0) 619 goto err; 620 621 s = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); 622 } else { 623 if (!(len = t_fromb64(tmp2, sizeof(tmp2), *salt))) 624 goto err; 625 s = BN_bin2bn(tmp2, len, NULL); 626 } 627 628 if (!SRP_create_verifier_BN(user, pass, &s, &v, N_bn, g_bn)) 629 goto err; 630 631 BN_bn2bin(v, tmp); 632 vfsize = BN_num_bytes(v) * 2; 633 if (((vf = OPENSSL_malloc(vfsize)) == NULL)) 634 goto err; 635 t_tob64(vf, tmp, BN_num_bytes(v)); 636 637 if (*salt == NULL) { 638 char *tmp_salt; 639 640 if ((tmp_salt = OPENSSL_malloc(SRP_RANDOM_SALT_LEN * 2)) == NULL) { 641 goto err; 642 } 643 t_tob64(tmp_salt, tmp2, SRP_RANDOM_SALT_LEN); 644 *salt = tmp_salt; 645 } 646 647 *verifier = vf; 648 vf = NULL; 649 result = defgNid; 650 651 err: 652 if (N) { 653 BN_free(N_bn); 654 BN_free(g_bn); 655 } 656 if (vf != NULL) 657 OPENSSL_cleanse(vf, vfsize); 658 OPENSSL_free(vf); 659 BN_clear_free(s); 660 BN_clear_free(v); 661 return result; 662} 663 664/* 665 * create a verifier (*salt,*verifier,g and N are BIGNUMs). If *salt != NULL 666 * then the provided salt will be used. On successful exit *verifier will point 667 * to a newly allocated BIGNUM containing the verifier and (if a salt was not 668 * provided) *salt will be populated with a newly allocated BIGNUM containing a 669 * random salt. 670 * The caller is responsible for freeing the allocated *salt and *verifier 671 * BIGNUMS. 672 */ 673int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, 674 BIGNUM **verifier, BIGNUM *N, BIGNUM *g) 675{ 676 int result = 0; 677 BIGNUM *x = NULL; 678 BN_CTX *bn_ctx = BN_CTX_new(); 679 unsigned char tmp2[MAX_LEN]; 680 BIGNUM *salttmp = NULL; 681 682 if ((user == NULL) || 683 (pass == NULL) || 684 (salt == NULL) || 685 (verifier == NULL) || (N == NULL) || (g == NULL) || (bn_ctx == NULL)) 686 goto err; 687 688 srp_bn_print(N); 689 srp_bn_print(g); 690 691 if (*salt == NULL) { 692 if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0) 693 goto err; 694 695 salttmp = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); 696 } else { 697 salttmp = *salt; 698 } 699 700 x = SRP_Calc_x(salttmp, user, pass); 701 702 *verifier = BN_new(); 703 if (*verifier == NULL) 704 goto err; 705 706 if (!BN_mod_exp(*verifier, g, x, N, bn_ctx)) { 707 BN_clear_free(*verifier); 708 goto err; 709 } 710 711 srp_bn_print(*verifier); 712 713 result = 1; 714 *salt = salttmp; 715 716 err: 717 if (*salt != salttmp) 718 BN_clear_free(salttmp); 719 BN_clear_free(x); 720 BN_CTX_free(bn_ctx); 721 return result; 722} 723 724#endif 725