X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fsrp%2Fsrp_vfy.c;h=eb4a38d4a7cef59942bd1c04192482da967c2562;hp=6889a6bded77ef32f0e42aff59dd479438423a87;hb=3d3f21aa976bd0b29fd1d92d96118b8e6a3209bb;hpb=71fa451343f97b3624374ed1359adc23fba5696e diff --git a/crypto/srp/srp_vfy.c b/crypto/srp/srp_vfy.c index 6889a6bded..eb4a38d4a7 100644 --- a/crypto/srp/srp_vfy.c +++ b/crypto/srp/srp_vfy.c @@ -1,658 +1,580 @@ -/* crypto/srp/srp_vfy.c */ -/* Written by Christophe Renou (christophe.renou@edelweb.fr) with - * the precious help of Peter Sylvester (peter.sylvester@edelweb.fr) - * for the EdelKey project and contributed to the OpenSSL project 2004. - */ -/* ==================================================================== - * Copyright (c) 2004 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). +/* + * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -#ifndef OPENSSL_NO_SRP -#include "cryptlib.h" -#include "srp_lcl.h" -#include -#include -#include -#include -#include - -#define SRP_RANDOM_SALT_LEN 20 -#define MAX_LEN 2500 -static char b64table[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; +#ifndef OPENSSL_NO_SRP +# include "internal/cryptlib.h" +# include +# include +# include +# include +# include +# include -/* the following two conversion routines have been inspired by code from Stanford */ +# define SRP_RANDOM_SALT_LEN 20 +# define MAX_LEN 2500 /* * Convert a base64 string into raw byte array representation. */ -static int t_fromb64(unsigned char *a, const char *src) - { - char *loc; - int i, j; - int size; - - while(*src && (*src == ' ' || *src == '\t' || *src == '\n')) - ++src; - size = strlen(src); - i = 0; - while(i < size) - { - loc = strchr(b64table, src[i]); - if(loc == (char *) 0) break; - else a[i] = loc - b64table; - ++i; - } - size = i; - i = size - 1; - j = size; - while(1) - { - a[j] = a[i]; - if(--i < 0) break; - a[j] |= (a[i] & 3) << 6; - --j; - a[j] = (unsigned char) ((a[i] & 0x3c) >> 2); - if(--i < 0) break; - a[j] |= (a[i] & 0xf) << 4; - --j; - a[j] = (unsigned char) ((a[i] & 0x30) >> 4); - if(--i < 0) break; - a[j] |= (a[i] << 2); - - a[--j] = 0; - if(--i < 0) break; - } - while(a[j] == 0 && j <= size) ++j; - i = 0; - while (j <= size) a[i++] = a[j++]; - return i; - } +static int t_fromb64(unsigned char *a, size_t alen, const char *src) +{ + size_t size = strlen(src); + /* Four bytes in src become three bytes output. */ + if (size > INT_MAX || (size / 4) * 3 > alen) + return -1; + + return EVP_DecodeBlock(a, (unsigned char *)src, (int)size); +} /* * Convert a raw byte string into a null-terminated base64 ASCII string. */ -static char *t_tob64(char *dst, const unsigned char *src, int size) - { - int c, pos = size % 3; - unsigned char b0 = 0, b1 = 0, b2 = 0, notleading = 0; - char *olddst = dst; - - switch(pos) - { - case 1: - b2 = src[0]; - break; - case 2: - b1 = src[0]; - b2 = src[1]; - break; - } - - while(1) - { - c = (b0 & 0xfc) >> 2; - if(notleading || c != 0) - { - *dst++ = b64table[c]; - notleading = 1; - } - c = ((b0 & 3) << 4) | ((b1 & 0xf0) >> 4); - if(notleading || c != 0) - { - *dst++ = b64table[c]; - notleading = 1; - } - c = ((b1 & 0xf) << 2) | ((b2 & 0xc0) >> 6); - if(notleading || c != 0) - { - *dst++ = b64table[c]; - notleading = 1; - } - c = b2 & 0x3f; - if(notleading || c != 0) - { - *dst++ = b64table[c]; - notleading = 1; - } - if(pos >= size) break; - else - { - b0 = src[pos++]; - b1 = src[pos++]; - b2 = src[pos++]; - } - } - - *dst++ = '\0'; - return olddst; - } - -static void SRP_user_pwd_free(SRP_user_pwd *user_pwd) - { - if (user_pwd == NULL) - return; - BN_free(user_pwd->s); - BN_clear_free(user_pwd->v); - OPENSSL_free(user_pwd->id); - OPENSSL_free(user_pwd->info); - OPENSSL_free(user_pwd); - } +static void t_tob64(char *dst, const unsigned char *src, int size) +{ + EVP_EncodeBlock((unsigned char *)dst, src, size); +} + +void SRP_user_pwd_free(SRP_user_pwd *user_pwd) +{ + if (user_pwd == NULL) + return; + BN_free(user_pwd->s); + BN_clear_free(user_pwd->v); + OPENSSL_free(user_pwd->id); + OPENSSL_free(user_pwd->info); + OPENSSL_free(user_pwd); +} static SRP_user_pwd *SRP_user_pwd_new(void) - { - SRP_user_pwd *ret = OPENSSL_malloc(sizeof(SRP_user_pwd)); - if (ret == NULL) - return NULL; - ret->N = NULL; - ret->g = NULL; - ret->s = NULL; - ret->v = NULL; - ret->id = NULL ; - ret->info = NULL; - return ret; - } +{ + SRP_user_pwd *ret = OPENSSL_malloc(sizeof(*ret)); + if (ret == NULL) + return NULL; + ret->N = NULL; + ret->g = NULL; + ret->s = NULL; + ret->v = NULL; + ret->id = NULL; + ret->info = NULL; + return ret; +} static void SRP_user_pwd_set_gN(SRP_user_pwd *vinfo, const BIGNUM *g, - const BIGNUM *N) - { - vinfo->N = N; - vinfo->g = g; - } + const BIGNUM *N) +{ + vinfo->N = N; + vinfo->g = g; +} static int SRP_user_pwd_set_ids(SRP_user_pwd *vinfo, const char *id, - const char *info) - { - if (id != NULL && NULL == (vinfo->id = BUF_strdup(id))) - return 0; - return (info == NULL || NULL != (vinfo->info = BUF_strdup(info))) ; - } + const char *info) +{ + if (id != NULL && NULL == (vinfo->id = OPENSSL_strdup(id))) + return 0; + return (info == NULL || NULL != (vinfo->info = OPENSSL_strdup(info))); +} static int SRP_user_pwd_set_sv(SRP_user_pwd *vinfo, const char *s, - const char *v) - { - unsigned char tmp[MAX_LEN]; - int len; - - if (strlen(s) > MAX_LEN || strlen(v) > MAX_LEN) - return 0; - len = t_fromb64(tmp, v); - if (NULL == (vinfo->v = BN_bin2bn(tmp, len, NULL)) ) - return 0; - len = t_fromb64(tmp, s); - return ((vinfo->s = BN_bin2bn(tmp, len, NULL)) != NULL) ; - } + const char *v) +{ + unsigned char tmp[MAX_LEN]; + int len; + + vinfo->v = NULL; + vinfo->s = NULL; + + len = t_fromb64(tmp, sizeof(tmp), v); + if (len < 0) + return 0; + if (NULL == (vinfo->v = BN_bin2bn(tmp, len, NULL))) + return 0; + len = t_fromb64(tmp, sizeof(tmp), s); + if (len < 0) + goto err; + vinfo->s = BN_bin2bn(tmp, len, NULL); + if (vinfo->s == NULL) + goto err; + return 1; + err: + BN_free(vinfo->v); + vinfo->v = NULL; + return 0; +} static int SRP_user_pwd_set_sv_BN(SRP_user_pwd *vinfo, BIGNUM *s, BIGNUM *v) - { - vinfo->v = v; - vinfo->s = s; - return (vinfo->s != NULL && vinfo->v != NULL) ; - } +{ + vinfo->v = v; + vinfo->s = s; + return (vinfo->s != NULL && vinfo->v != NULL); +} + +static SRP_user_pwd *srp_user_pwd_dup(SRP_user_pwd *src) +{ + SRP_user_pwd *ret; + + if (src == NULL) + return NULL; + if ((ret = SRP_user_pwd_new()) == NULL) + return NULL; + + SRP_user_pwd_set_gN(ret, src->g, src->N); + if (!SRP_user_pwd_set_ids(ret, src->id, src->info) + || !SRP_user_pwd_set_sv_BN(ret, BN_dup(src->s), BN_dup(src->v))) { + SRP_user_pwd_free(ret); + return NULL; + } + return ret; +} SRP_VBASE *SRP_VBASE_new(char *seed_key) - { - SRP_VBASE *vb = (SRP_VBASE *) OPENSSL_malloc(sizeof(SRP_VBASE)); - - if (vb == NULL) - return NULL; - if (!(vb->users_pwd = sk_SRP_user_pwd_new_null()) || - !(vb->gN_cache = sk_SRP_gN_cache_new_null())) - { - OPENSSL_free(vb); - return NULL; - } - vb->default_g = NULL; - vb->default_N = NULL; - vb->seed_key = NULL; - if ((seed_key != NULL) && - (vb->seed_key = BUF_strdup(seed_key)) == NULL) - { - sk_SRP_user_pwd_free(vb->users_pwd); - sk_SRP_gN_cache_free(vb->gN_cache); - OPENSSL_free(vb); - return NULL; - } - return vb; - } - - -int SRP_VBASE_free(SRP_VBASE *vb) - { - sk_SRP_user_pwd_pop_free(vb->users_pwd,SRP_user_pwd_free); - sk_SRP_gN_cache_free(vb->gN_cache); - OPENSSL_free(vb->seed_key); - OPENSSL_free(vb); - return 0; - } - +{ + SRP_VBASE *vb = OPENSSL_malloc(sizeof(*vb)); + + if (vb == NULL) + return NULL; + if ((vb->users_pwd = sk_SRP_user_pwd_new_null()) == NULL + || (vb->gN_cache = sk_SRP_gN_cache_new_null()) == NULL) { + OPENSSL_free(vb); + return NULL; + } + vb->default_g = NULL; + vb->default_N = NULL; + vb->seed_key = NULL; + if ((seed_key != NULL) && (vb->seed_key = OPENSSL_strdup(seed_key)) == NULL) { + sk_SRP_user_pwd_free(vb->users_pwd); + sk_SRP_gN_cache_free(vb->gN_cache); + OPENSSL_free(vb); + return NULL; + } + return vb; +} + +void SRP_VBASE_free(SRP_VBASE *vb) +{ + if (!vb) + return; + sk_SRP_user_pwd_pop_free(vb->users_pwd, SRP_user_pwd_free); + sk_SRP_gN_cache_free(vb->gN_cache); + OPENSSL_free(vb->seed_key); + OPENSSL_free(vb); +} static SRP_gN_cache *SRP_gN_new_init(const char *ch) - { - unsigned char tmp[MAX_LEN]; - int len; +{ + unsigned char tmp[MAX_LEN]; + int len; + SRP_gN_cache *newgN = OPENSSL_malloc(sizeof(*newgN)); - SRP_gN_cache *newgN = (SRP_gN_cache *)OPENSSL_malloc(sizeof(SRP_gN_cache)); - if (newgN == NULL) - return NULL; + if (newgN == NULL) + return NULL; - if ((newgN->b64_bn = BUF_strdup(ch)) == NULL) - goto err; + len = t_fromb64(tmp, sizeof(tmp), ch); + if (len < 0) + goto err; - len = t_fromb64(tmp, ch); - if ((newgN->bn = BN_bin2bn(tmp, len, NULL))) - return newgN; + if ((newgN->b64_bn = OPENSSL_strdup(ch)) == NULL) + goto err; - OPENSSL_free(newgN->b64_bn); -err: - OPENSSL_free(newgN); - return NULL; - } + if ((newgN->bn = BN_bin2bn(tmp, len, NULL))) + return newgN; + OPENSSL_free(newgN->b64_bn); + err: + OPENSSL_free(newgN); + return NULL; +} static void SRP_gN_free(SRP_gN_cache *gN_cache) - { - if (gN_cache == NULL) - return; - OPENSSL_free(gN_cache->b64_bn); - BN_free(gN_cache->bn); - OPENSSL_free(gN_cache); - } +{ + if (gN_cache == NULL) + return; + OPENSSL_free(gN_cache->b64_bn); + BN_free(gN_cache->bn); + OPENSSL_free(gN_cache); +} static SRP_gN *SRP_get_gN_by_id(const char *id, STACK_OF(SRP_gN) *gN_tab) - { - int i; - - SRP_gN *gN; - if (gN_tab != NULL) - for(i = 0; i < sk_SRP_gN_num(gN_tab); i++) - { - gN = sk_SRP_gN_value(gN_tab, i); - if (gN && (id == NULL || strcmp(gN->id,id)==0)) - return gN; - } - - return SRP_get_default_gN(id); - } +{ + int i; + + SRP_gN *gN; + if (gN_tab != NULL) + for (i = 0; i < sk_SRP_gN_num(gN_tab); i++) { + gN = sk_SRP_gN_value(gN_tab, i); + if (gN && (id == NULL || strcmp(gN->id, id) == 0)) + return gN; + } + + return SRP_get_default_gN(id); +} static BIGNUM *SRP_gN_place_bn(STACK_OF(SRP_gN_cache) *gN_cache, char *ch) - { - int i; - if (gN_cache == NULL) - return NULL; - - /* search if we have already one... */ - for(i = 0; i < sk_SRP_gN_cache_num(gN_cache); i++) - { - SRP_gN_cache *cache = sk_SRP_gN_cache_value(gN_cache, i); - if (strcmp(cache->b64_bn,ch)==0) - return cache->bn; - } - { /* it is the first time that we find it */ - SRP_gN_cache *newgN = SRP_gN_new_init(ch); - if (newgN) - { - if (sk_SRP_gN_cache_insert(gN_cache,newgN,0)>0) - return newgN->bn; - SRP_gN_free(newgN); - } - } - return NULL; - } - -/* this function parses verifier file. Format is: +{ + int i; + if (gN_cache == NULL) + return NULL; + + /* search if we have already one... */ + for (i = 0; i < sk_SRP_gN_cache_num(gN_cache); i++) { + SRP_gN_cache *cache = sk_SRP_gN_cache_value(gN_cache, i); + if (strcmp(cache->b64_bn, ch) == 0) + return cache->bn; + } + { /* it is the first time that we find it */ + SRP_gN_cache *newgN = SRP_gN_new_init(ch); + if (newgN) { + if (sk_SRP_gN_cache_insert(gN_cache, newgN, 0) > 0) + return newgN->bn; + SRP_gN_free(newgN); + } + } + return NULL; +} + +/* + * this function parses verifier file. Format is: * string(index):base64(N):base64(g):0 * string(username):base64(v):base64(salt):int(index) */ - int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file) - { - int error_code ; - STACK_OF(SRP_gN) *SRP_gN_tab = sk_SRP_gN_new_null(); - char *last_index = NULL; - int i; - char **pp; - - SRP_gN *gN = NULL; - SRP_user_pwd *user_pwd = NULL ; - - TXT_DB *tmpdb = NULL; - BIO *in = BIO_new(BIO_s_file()); - - error_code = SRP_ERR_OPEN_FILE; - - if (in == NULL || BIO_read_filename(in,verifier_file) <= 0) - goto err; - - error_code = SRP_ERR_VBASE_INCOMPLETE_FILE; - - if ((tmpdb =TXT_DB_read(in,DB_NUMBER)) == NULL) - goto err; - - error_code = SRP_ERR_MEMORY; - - - if (vb->seed_key) - { - last_index = SRP_get_default_gN(NULL)->id; - } - for (i = 0; i < sk_OPENSSL_PSTRING_num(tmpdb->data); i++) - { - pp = sk_OPENSSL_PSTRING_value(tmpdb->data,i); - if (pp[DB_srptype][0] == DB_SRP_INDEX) - { - /*we add this couple in the internal Stack */ - - if ((gN = (SRP_gN *)OPENSSL_malloc(sizeof(SRP_gN))) == NULL) - goto err; - - if (!(gN->id = BUF_strdup(pp[DB_srpid])) - || !(gN->N = SRP_gN_place_bn(vb->gN_cache,pp[DB_srpverifier])) - || !(gN->g = SRP_gN_place_bn(vb->gN_cache,pp[DB_srpsalt])) - || sk_SRP_gN_insert(SRP_gN_tab,gN,0) == 0) - goto err; - - gN = NULL; - - if (vb->seed_key != NULL) - { - last_index = pp[DB_srpid]; - } - } - else if (pp[DB_srptype][0] == DB_SRP_VALID) - { - /* it is a user .... */ - SRP_gN *lgN; - if ((lgN = SRP_get_gN_by_id(pp[DB_srpgN],SRP_gN_tab))!=NULL) - { - error_code = SRP_ERR_MEMORY; - if ((user_pwd = SRP_user_pwd_new()) == NULL) - goto err; - - SRP_user_pwd_set_gN(user_pwd,lgN->g,lgN->N); - if (!SRP_user_pwd_set_ids(user_pwd, pp[DB_srpid],pp[DB_srpinfo])) - goto err; - - error_code = SRP_ERR_VBASE_BN_LIB; - if (!SRP_user_pwd_set_sv(user_pwd, pp[DB_srpsalt],pp[DB_srpverifier])) - goto err; - - if (sk_SRP_user_pwd_insert(vb->users_pwd, user_pwd, 0) == 0) - goto err; - user_pwd = NULL; /* abandon responsability */ - } - } - } - - if (last_index != NULL) - { - /* this means that we want to simulate a default user */ - - if (((gN = SRP_get_gN_by_id(last_index,SRP_gN_tab))==NULL)) - { - error_code = SRP_ERR_VBASE_BN_LIB; - goto err; - } - vb->default_g = gN->g ; - vb->default_N = gN->N ; - gN = NULL ; - } - error_code = SRP_NO_ERROR; +{ + int error_code; + STACK_OF(SRP_gN) *SRP_gN_tab = sk_SRP_gN_new_null(); + char *last_index = NULL; + int i; + char **pp; + + SRP_gN *gN = NULL; + SRP_user_pwd *user_pwd = NULL; + + TXT_DB *tmpdb = NULL; + BIO *in = BIO_new(BIO_s_file()); + + error_code = SRP_ERR_OPEN_FILE; + + if (in == NULL || BIO_read_filename(in, verifier_file) <= 0) + goto err; + + error_code = SRP_ERR_VBASE_INCOMPLETE_FILE; + + if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL) + goto err; + + error_code = SRP_ERR_MEMORY; + + if (vb->seed_key) { + last_index = SRP_get_default_gN(NULL)->id; + } + for (i = 0; i < sk_OPENSSL_PSTRING_num(tmpdb->data); i++) { + pp = sk_OPENSSL_PSTRING_value(tmpdb->data, i); + if (pp[DB_srptype][0] == DB_SRP_INDEX) { + /* + * we add this couple in the internal Stack + */ + + if ((gN = OPENSSL_malloc(sizeof(*gN))) == NULL) + goto err; + + if ((gN->id = OPENSSL_strdup(pp[DB_srpid])) == NULL + || (gN->N = SRP_gN_place_bn(vb->gN_cache, pp[DB_srpverifier])) + == NULL + || (gN->g = SRP_gN_place_bn(vb->gN_cache, pp[DB_srpsalt])) + == NULL + || sk_SRP_gN_insert(SRP_gN_tab, gN, 0) == 0) + goto err; + + gN = NULL; + + if (vb->seed_key != NULL) { + last_index = pp[DB_srpid]; + } + } else if (pp[DB_srptype][0] == DB_SRP_VALID) { + /* it is a user .... */ + const SRP_gN *lgN; + + if ((lgN = SRP_get_gN_by_id(pp[DB_srpgN], SRP_gN_tab)) != NULL) { + error_code = SRP_ERR_MEMORY; + if ((user_pwd = SRP_user_pwd_new()) == NULL) + goto err; + + SRP_user_pwd_set_gN(user_pwd, lgN->g, lgN->N); + if (!SRP_user_pwd_set_ids + (user_pwd, pp[DB_srpid], pp[DB_srpinfo])) + goto err; + + error_code = SRP_ERR_VBASE_BN_LIB; + if (!SRP_user_pwd_set_sv + (user_pwd, pp[DB_srpsalt], pp[DB_srpverifier])) + goto err; + + if (sk_SRP_user_pwd_insert(vb->users_pwd, user_pwd, 0) == 0) + goto err; + user_pwd = NULL; /* abandon responsibility */ + } + } + } + + if (last_index != NULL) { + /* this means that we want to simulate a default user */ + + if (((gN = SRP_get_gN_by_id(last_index, SRP_gN_tab)) == NULL)) { + error_code = SRP_ERR_VBASE_BN_LIB; + goto err; + } + vb->default_g = gN->g; + vb->default_N = gN->N; + gN = NULL; + } + error_code = SRP_NO_ERROR; err: - /* there may be still some leaks to fix, if this fails, the application terminates most likely */ - - if (gN != NULL) - { - OPENSSL_free(gN->id); - OPENSSL_free(gN); - } + /* + * there may be still some leaks to fix, if this fails, the application + * terminates most likely + */ - SRP_user_pwd_free(user_pwd); + if (gN != NULL) { + OPENSSL_free(gN->id); + OPENSSL_free(gN); + } - if (tmpdb) TXT_DB_free(tmpdb); - if (in) BIO_free_all(in); + SRP_user_pwd_free(user_pwd); - sk_SRP_gN_free(SRP_gN_tab); + TXT_DB_free(tmpdb); + BIO_free_all(in); - return error_code; + sk_SRP_gN_free(SRP_gN_tab); - } + return error_code; +} -SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username) - { - int i; - SRP_user_pwd *user; - unsigned char digv[SHA_DIGEST_LENGTH]; - unsigned char digs[SHA_DIGEST_LENGTH]; - EVP_MD_CTX ctxt; - - if (vb == NULL) - return NULL; - for(i = 0; i < sk_SRP_user_pwd_num(vb->users_pwd); i++) - { - user = sk_SRP_user_pwd_value(vb->users_pwd, i); - if (strcmp(user->id,username)==0) - return user; - } - if ((vb->seed_key == NULL) || - (vb->default_g == NULL) || - (vb->default_N == NULL)) - return NULL; +static SRP_user_pwd *find_user(SRP_VBASE *vb, char *username) +{ + int i; + SRP_user_pwd *user; -/* if the user is unknown we set parameters as well if we have a seed_key */ + if (vb == NULL) + return NULL; - if ((user = SRP_user_pwd_new()) == NULL) - return NULL; - - SRP_user_pwd_set_gN(user,vb->default_g,vb->default_N); - - if (!SRP_user_pwd_set_ids(user,username,NULL)) - goto err; - - RAND_pseudo_bytes(digv, SHA_DIGEST_LENGTH); - EVP_MD_CTX_init(&ctxt); - EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL); - EVP_DigestUpdate(&ctxt, vb->seed_key, strlen(vb->seed_key)); - EVP_DigestUpdate(&ctxt, username, strlen(username)); - EVP_DigestFinal_ex(&ctxt, digs, NULL); - EVP_MD_CTX_cleanup(&ctxt); - if (SRP_user_pwd_set_sv_BN(user, BN_bin2bn(digs,SHA_DIGEST_LENGTH,NULL), BN_bin2bn(digv,SHA_DIGEST_LENGTH, NULL))) - return user; - -err: SRP_user_pwd_free(user); - return NULL; - } + for (i = 0; i < sk_SRP_user_pwd_num(vb->users_pwd); i++) { + user = sk_SRP_user_pwd_value(vb->users_pwd, i); + if (strcmp(user->id, username) == 0) + return user; + } + return NULL; +} +# if OPENSSL_API_COMPAT < 0x10100000L /* - create a verifier (*salt,*verifier,g and N are in base64) -*/ -char *SRP_create_verifier(const char *user, const char *pass, char **salt, - char **verifier, const char *N, const char *g) - { - int len; - char * result=NULL; - char *vf; - BIGNUM *N_bn = NULL, *g_bn = NULL, *s = NULL, *v = NULL; - unsigned char tmp[MAX_LEN]; - unsigned char tmp2[MAX_LEN]; - char * defgNid = NULL; - - if ((user == NULL)|| - (pass == NULL)|| - (salt == NULL)|| - (verifier == NULL)) - goto err; - - if (N) - { - if (!(len = t_fromb64(tmp, N))) goto err; - N_bn = BN_bin2bn(tmp, len, NULL); - if (!(len = t_fromb64(tmp, g))) goto err; - g_bn = BN_bin2bn(tmp, len, NULL); - defgNid = "*"; - } - else - { - SRP_gN * gN = SRP_get_gN_by_id(g, NULL) ; - if (gN == NULL) - goto err; - N_bn = gN->N; - g_bn = gN->g; - defgNid = gN->id; - } - - if (*salt == NULL) - { - RAND_pseudo_bytes(tmp2, SRP_RANDOM_SALT_LEN); - - s = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); - } - else - { - if (!(len = t_fromb64(tmp2, *salt))) - goto err; - s = BN_bin2bn(tmp2, len, NULL); - } - - - if(!SRP_create_verifier_BN(user, pass, &s, &v, N_bn, g_bn)) goto err; - - BN_bn2bin(v,tmp); - if (((vf = OPENSSL_malloc(BN_num_bytes(v)*2)) == NULL)) - goto err; - t_tob64(vf, tmp, BN_num_bytes(v)); - - *verifier = vf; - if (*salt == NULL) - { - char *tmp_salt; - - if ((tmp_salt = OPENSSL_malloc(SRP_RANDOM_SALT_LEN * 2)) == NULL) - { - OPENSSL_free(vf); - goto err; - } - t_tob64(tmp_salt, tmp2, SRP_RANDOM_SALT_LEN); - *salt = tmp_salt; - } - - result=defgNid; - -err: - if(N) - { - BN_free(N_bn); - BN_free(g_bn); - } - return result; - } + * DEPRECATED: use SRP_VBASE_get1_by_user instead. + * This method ignores the configured seed and fails for an unknown user. + * Ownership of the returned pointer is not released to the caller. + * In other words, caller must not free the result. + */ +SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username) +{ + return find_user(vb, username); +} +# endif /* - create a verifier (*salt,*verifier,g and N are BIGNUMs) -*/ -int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, BIGNUM **verifier, BIGNUM *N, BIGNUM *g) - { - int result=0; - BIGNUM *x = NULL; - BN_CTX *bn_ctx = BN_CTX_new(); - unsigned char tmp2[MAX_LEN]; - - if ((user == NULL)|| - (pass == NULL)|| - (salt == NULL)|| - (verifier == NULL)|| - (N == NULL)|| - (g == NULL)|| - (bn_ctx == NULL)) - goto err; - - srp_bn_print(N); - srp_bn_print(g); - - if (*salt == NULL) - { - RAND_pseudo_bytes(tmp2, SRP_RANDOM_SALT_LEN); + * Ownership of the returned pointer is released to the caller. + * In other words, caller must free the result once done. + */ +SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username) +{ + SRP_user_pwd *user; + unsigned char digv[SHA_DIGEST_LENGTH]; + unsigned char digs[SHA_DIGEST_LENGTH]; + EVP_MD_CTX *ctxt = NULL; - *salt = BN_bin2bn(tmp2,SRP_RANDOM_SALT_LEN,NULL); - } + if (vb == NULL) + return NULL; - x = SRP_Calc_x(*salt,user,pass); + if ((user = find_user(vb, username)) != NULL) + return srp_user_pwd_dup(user); - *verifier = BN_new(); - if(*verifier == NULL) goto err; + if ((vb->seed_key == NULL) || + (vb->default_g == NULL) || (vb->default_N == NULL)) + return NULL; - if (!BN_mod_exp(*verifier,g,x,N,bn_ctx)) - { - BN_clear_free(*verifier); - goto err; - } +/* if the user is unknown we set parameters as well if we have a seed_key */ - srp_bn_print(*verifier); + if ((user = SRP_user_pwd_new()) == NULL) + return NULL; + + SRP_user_pwd_set_gN(user, vb->default_g, vb->default_N); + + if (!SRP_user_pwd_set_ids(user, username, NULL)) + goto err; + + if (RAND_bytes(digv, SHA_DIGEST_LENGTH) <= 0) + goto err; + ctxt = EVP_MD_CTX_new(); + if (ctxt == NULL + || !EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL) + || !EVP_DigestUpdate(ctxt, vb->seed_key, strlen(vb->seed_key)) + || !EVP_DigestUpdate(ctxt, username, strlen(username)) + || !EVP_DigestFinal_ex(ctxt, digs, NULL)) + goto err; + EVP_MD_CTX_free(ctxt); + ctxt = NULL; + if (SRP_user_pwd_set_sv_BN(user, + BN_bin2bn(digs, SHA_DIGEST_LENGTH, NULL), + BN_bin2bn(digv, SHA_DIGEST_LENGTH, NULL))) + return user; - result=1; + err: + EVP_MD_CTX_free(ctxt); + SRP_user_pwd_free(user); + return NULL; +} -err: +/* + * create a verifier (*salt,*verifier,g and N are in base64) + */ +char *SRP_create_verifier(const char *user, const char *pass, char **salt, + char **verifier, const char *N, const char *g) +{ + int len; + char *result = NULL, *vf = NULL; + const BIGNUM *N_bn = NULL, *g_bn = NULL; + BIGNUM *N_bn_alloc = NULL, *g_bn_alloc = NULL, *s = NULL, *v = NULL; + unsigned char tmp[MAX_LEN]; + unsigned char tmp2[MAX_LEN]; + char *defgNid = NULL; + int vfsize = 0; + + if ((user == NULL) || + (pass == NULL) || (salt == NULL) || (verifier == NULL)) + goto err; + + if (N) { + if ((len = t_fromb64(tmp, sizeof(tmp), N)) <= 0) + goto err; + N_bn_alloc = BN_bin2bn(tmp, len, NULL); + N_bn = N_bn_alloc; + if ((len = t_fromb64(tmp, sizeof(tmp) ,g)) <= 0) + goto err; + g_bn_alloc = BN_bin2bn(tmp, len, NULL); + g_bn = g_bn_alloc; + defgNid = "*"; + } else { + SRP_gN *gN = SRP_get_gN_by_id(g, NULL); + if (gN == NULL) + goto err; + N_bn = gN->N; + g_bn = gN->g; + defgNid = gN->id; + } + + if (*salt == NULL) { + if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0) + goto err; + + s = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); + } else { + if ((len = t_fromb64(tmp2, sizeof(tmp2), *salt)) <= 0) + goto err; + s = BN_bin2bn(tmp2, len, NULL); + } + + if (!SRP_create_verifier_BN(user, pass, &s, &v, N_bn, g_bn)) + goto err; + + BN_bn2bin(v, tmp); + vfsize = BN_num_bytes(v) * 2; + if (((vf = OPENSSL_malloc(vfsize)) == NULL)) + goto err; + t_tob64(vf, tmp, BN_num_bytes(v)); + + if (*salt == NULL) { + char *tmp_salt; + + if ((tmp_salt = OPENSSL_malloc(SRP_RANDOM_SALT_LEN * 2)) == NULL) { + goto err; + } + t_tob64(tmp_salt, tmp2, SRP_RANDOM_SALT_LEN); + *salt = tmp_salt; + } + + *verifier = vf; + vf = NULL; + result = defgNid; - BN_clear_free(x); - BN_CTX_free(bn_ctx); - return result; - } + err: + BN_free(N_bn_alloc); + BN_free(g_bn_alloc); + OPENSSL_clear_free(vf, vfsize); + BN_clear_free(s); + BN_clear_free(v); + return result; +} +/* + * create a verifier (*salt,*verifier,g and N are BIGNUMs). If *salt != NULL + * then the provided salt will be used. On successful exit *verifier will point + * to a newly allocated BIGNUM containing the verifier and (if a salt was not + * provided) *salt will be populated with a newly allocated BIGNUM containing a + * random salt. + * The caller is responsible for freeing the allocated *salt and *verifier + * BIGNUMS. + */ +int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, + BIGNUM **verifier, const BIGNUM *N, + const BIGNUM *g) +{ + int result = 0; + BIGNUM *x = NULL; + BN_CTX *bn_ctx = BN_CTX_new(); + unsigned char tmp2[MAX_LEN]; + BIGNUM *salttmp = NULL; + + if ((user == NULL) || + (pass == NULL) || + (salt == NULL) || + (verifier == NULL) || (N == NULL) || (g == NULL) || (bn_ctx == NULL)) + goto err; + + if (*salt == NULL) { + if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0) + goto err; + + salttmp = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); + } else { + salttmp = *salt; + } + + x = SRP_Calc_x(salttmp, user, pass); + + *verifier = BN_new(); + if (*verifier == NULL) + goto err; + + if (!BN_mod_exp(*verifier, g, x, N, bn_ctx)) { + BN_clear_free(*verifier); + goto err; + } + + result = 1; + *salt = salttmp; + err: + if (salt != NULL && *salt != salttmp) + BN_clear_free(salttmp); + BN_clear_free(x); + BN_CTX_free(bn_ctx); + return result; +} #endif