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