X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fsrp%2Fsrp_vfy.c;h=20e42584276b68ab46d2c6c9dd15d5dad6f82a0e;hp=df82ca3830d7a77ffe8aa6f4fabc26a1e5cbe277;hb=c7c7a8e60155d839671297d80680e6010bff2897;hpb=0f113f3ee4d629ef9a4a30911b22b224772085e5 diff --git a/crypto/srp/srp_vfy.c b/crypto/srp/srp_vfy.c index df82ca3830..20e4258427 100644 --- a/crypto/srp/srp_vfy.c +++ b/crypto/srp/srp_vfy.c @@ -1,65 +1,15 @@ -/* 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 "internal/cryptlib.h" +# include # include # include # include @@ -80,15 +30,21 @@ static char b64table[] = /* * Convert a base64 string into raw byte array representation. */ -static int t_fromb64(unsigned char *a, const char *src) +static int t_fromb64(unsigned char *a, size_t alen, const char *src) { char *loc; int i, j; int size; + if (alen == 0 || alen > INT_MAX) + return -1; + while (*src && (*src == ' ' || *src == '\t' || *src == '\n')) ++src; size = strlen(src); + if (size < 0 || size >= (int)alen) + return -1; + i = 0; while (i < size) { loc = strchr(b64table, src[i]); @@ -124,7 +80,7 @@ static int t_fromb64(unsigned char *a, const char *src) if (--i < 0) break; } - while (a[j] == 0 && j <= size) + while (j <= size && a[j] == 0) ++j; i = 0; while (j <= size) @@ -185,7 +141,7 @@ static char *t_tob64(char *dst, const unsigned char *src, int size) return olddst; } -static void SRP_user_pwd_free(SRP_user_pwd *user_pwd) +void SRP_user_pwd_free(SRP_user_pwd *user_pwd) { if (user_pwd == NULL) return; @@ -198,7 +154,7 @@ static void SRP_user_pwd_free(SRP_user_pwd *user_pwd) static SRP_user_pwd *SRP_user_pwd_new(void) { - SRP_user_pwd *ret = OPENSSL_malloc(sizeof(SRP_user_pwd)); + SRP_user_pwd *ret = OPENSSL_malloc(sizeof(*ret)); if (ret == NULL) return NULL; ret->N = NULL; @@ -220,9 +176,9 @@ static void SRP_user_pwd_set_gN(SRP_user_pwd *vinfo, const BIGNUM *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))) + if (id != NULL && NULL == (vinfo->id = OPENSSL_strdup(id))) return 0; - return (info == NULL || NULL != (vinfo->info = BUF_strdup(info))); + return (info == NULL || NULL != (vinfo->info = OPENSSL_strdup(info))); } static int SRP_user_pwd_set_sv(SRP_user_pwd *vinfo, const char *s, @@ -231,13 +187,25 @@ static int SRP_user_pwd_set_sv(SRP_user_pwd *vinfo, const char *s, unsigned char tmp[MAX_LEN]; int len; - if (strlen(s) > MAX_LEN || strlen(v) > MAX_LEN) + vinfo->v = NULL; + vinfo->s = NULL; + + len = t_fromb64(tmp, sizeof(tmp), v); + if (len < 0) 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); + 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) @@ -247,21 +215,39 @@ static int SRP_user_pwd_set_sv_BN(SRP_user_pwd *vinfo, BIGNUM *s, BIGNUM *v) 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)); + SRP_VBASE *vb = OPENSSL_malloc(sizeof(*vb)); if (vb == NULL) return NULL; - if (!(vb->users_pwd = sk_SRP_user_pwd_new_null()) || - !(vb->gN_cache = sk_SRP_gN_cache_new_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 = BUF_strdup(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); @@ -270,29 +256,32 @@ SRP_VBASE *SRP_VBASE_new(char *seed_key) return vb; } -int SRP_VBASE_free(SRP_VBASE *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); - return 0; } static SRP_gN_cache *SRP_gN_new_init(const char *ch) { 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->b64_bn = BUF_strdup(ch)) == NULL) + len = t_fromb64(tmp, sizeof(tmp), ch); + if (len < 0) + goto err; + + if ((newgN->b64_bn = OPENSSL_strdup(ch)) == NULL) goto err; - len = t_fromb64(tmp, ch); if ((newgN->bn = BN_bin2bn(tmp, len, NULL))) return newgN; @@ -391,13 +380,14 @@ int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file) * we add this couple in the internal Stack */ - if ((gN = (SRP_gN *) OPENSSL_malloc(sizeof(SRP_gN))) == NULL) + if ((gN = OPENSSL_malloc(sizeof(*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])) + 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; @@ -427,7 +417,7 @@ int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file) if (sk_SRP_user_pwd_insert(vb->users_pwd, user_pwd, 0) == 0) goto err; - user_pwd = NULL; /* abandon responsability */ + user_pwd = NULL; /* abandon responsibility */ } } } @@ -458,10 +448,8 @@ int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file) SRP_user_pwd_free(user_pwd); - if (tmpdb) - TXT_DB_free(tmpdb); - if (in) - BIO_free_all(in); + TXT_DB_free(tmpdb); + BIO_free_all(in); sk_SRP_gN_free(SRP_gN_tab); @@ -469,21 +457,53 @@ int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file) } -SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username) +static SRP_user_pwd *find_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; } + + return NULL; +} + +# if OPENSSL_API_COMPAT < 0x10100000L +/* + * 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 + +/* + * 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; + + if (vb == NULL) + return NULL; + + if ((user = find_user(vb, username)) != NULL) + return srp_user_pwd_dup(user); + if ((vb->seed_key == NULL) || (vb->default_g == NULL) || (vb->default_N == NULL)) return NULL; @@ -498,19 +518,25 @@ SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username) 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))) + 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; - err:SRP_user_pwd_free(user); + err: + EVP_MD_CTX_free(ctxt); + SRP_user_pwd_free(user); return NULL; } @@ -521,24 +547,27 @@ 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; + 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, N))) + if ((len = t_fromb64(tmp, sizeof(tmp), N)) <= 0) goto err; - N_bn = BN_bin2bn(tmp, len, NULL); - if (!(len = t_fromb64(tmp, g))) + 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 = BN_bin2bn(tmp, len, NULL); + 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); @@ -550,11 +579,12 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt, } if (*salt == NULL) { - RAND_pseudo_bytes(tmp2, SRP_RANDOM_SALT_LEN); + 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, *salt))) + if ((len = t_fromb64(tmp2, sizeof(tmp2), *salt)) <= 0) goto err; s = BN_bin2bn(tmp2, len, NULL); } @@ -563,34 +593,42 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt, goto err; BN_bn2bin(v, tmp); - if (((vf = OPENSSL_malloc(BN_num_bytes(v) * 2)) == NULL)) + vfsize = BN_num_bytes(v) * 2; + if (((vf = OPENSSL_malloc(vfsize)) == 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; } + *verifier = vf; + vf = NULL; result = defgNid; err: - if (N) { - BN_free(N_bn); - BN_free(g_bn); - } + 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) + * 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, @@ -600,6 +638,7 @@ int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, BIGNUM *x = NULL; BN_CTX *bn_ctx = BN_CTX_new(); unsigned char tmp2[MAX_LEN]; + BIGNUM *salttmp = NULL; if ((user == NULL) || (pass == NULL) || @@ -607,16 +646,16 @@ int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, (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); + if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0) + goto err; - *salt = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); + salttmp = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); + } else { + salttmp = *salt; } - x = SRP_Calc_x(*salt, user, pass); + x = SRP_Calc_x(salttmp, user, pass); *verifier = BN_new(); if (*verifier == NULL) @@ -627,12 +666,12 @@ int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, goto err; } - srp_bn_print(*verifier); - 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;