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