xref: /freebsd/crypto/openssl/ssl/tls_srp.c (revision a93cbc2be851ef88019a97cf7a22ba24e3a88fe1)
11f13597dSJung-uk Kim /* ssl/tls_srp.c */
21f13597dSJung-uk Kim /* Written by Christophe Renou (christophe.renou@edelweb.fr) with
31f13597dSJung-uk Kim  * the precious help of Peter Sylvester (peter.sylvester@edelweb.fr)
41f13597dSJung-uk Kim  * for the EdelKey project and contributed to the OpenSSL project 2004.
51f13597dSJung-uk Kim  */
61f13597dSJung-uk Kim /* ====================================================================
71f13597dSJung-uk Kim  * Copyright (c) 2004-2011 The OpenSSL Project.  All rights reserved.
81f13597dSJung-uk Kim  *
91f13597dSJung-uk Kim  * Redistribution and use in source and binary forms, with or without
101f13597dSJung-uk Kim  * modification, are permitted provided that the following conditions
111f13597dSJung-uk Kim  * are met:
121f13597dSJung-uk Kim  *
131f13597dSJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
141f13597dSJung-uk Kim  *    notice, this list of conditions and the following disclaimer.
151f13597dSJung-uk Kim  *
161f13597dSJung-uk Kim  * 2. Redistributions in binary form must reproduce the above copyright
171f13597dSJung-uk Kim  *    notice, this list of conditions and the following disclaimer in
181f13597dSJung-uk Kim  *    the documentation and/or other materials provided with the
191f13597dSJung-uk Kim  *    distribution.
201f13597dSJung-uk Kim  *
211f13597dSJung-uk Kim  * 3. All advertising materials mentioning features or use of this
221f13597dSJung-uk Kim  *    software must display the following acknowledgment:
231f13597dSJung-uk Kim  *    "This product includes software developed by the OpenSSL Project
241f13597dSJung-uk Kim  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
251f13597dSJung-uk Kim  *
261f13597dSJung-uk Kim  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
271f13597dSJung-uk Kim  *    endorse or promote products derived from this software without
281f13597dSJung-uk Kim  *    prior written permission. For written permission, please contact
291f13597dSJung-uk Kim  *    licensing@OpenSSL.org.
301f13597dSJung-uk Kim  *
311f13597dSJung-uk Kim  * 5. Products derived from this software may not be called "OpenSSL"
321f13597dSJung-uk Kim  *    nor may "OpenSSL" appear in their names without prior written
331f13597dSJung-uk Kim  *    permission of the OpenSSL Project.
341f13597dSJung-uk Kim  *
351f13597dSJung-uk Kim  * 6. Redistributions of any form whatsoever must retain the following
361f13597dSJung-uk Kim  *    acknowledgment:
371f13597dSJung-uk Kim  *    "This product includes software developed by the OpenSSL Project
381f13597dSJung-uk Kim  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
391f13597dSJung-uk Kim  *
401f13597dSJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
411f13597dSJung-uk Kim  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
421f13597dSJung-uk Kim  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
431f13597dSJung-uk Kim  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
441f13597dSJung-uk Kim  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
451f13597dSJung-uk Kim  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
461f13597dSJung-uk Kim  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
471f13597dSJung-uk Kim  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
481f13597dSJung-uk Kim  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
491f13597dSJung-uk Kim  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
501f13597dSJung-uk Kim  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
511f13597dSJung-uk Kim  * OF THE POSSIBILITY OF SUCH DAMAGE.
521f13597dSJung-uk Kim  * ====================================================================
531f13597dSJung-uk Kim  *
541f13597dSJung-uk Kim  * This product includes cryptographic software written by Eric Young
551f13597dSJung-uk Kim  * (eay@cryptsoft.com).  This product includes software written by Tim
561f13597dSJung-uk Kim  * Hudson (tjh@cryptsoft.com).
571f13597dSJung-uk Kim  *
581f13597dSJung-uk Kim  */
591f13597dSJung-uk Kim #include "ssl_locl.h"
601f13597dSJung-uk Kim #ifndef OPENSSL_NO_SRP
611f13597dSJung-uk Kim 
621f13597dSJung-uk Kim #include <openssl/rand.h>
631f13597dSJung-uk Kim #include <openssl/srp.h>
641f13597dSJung-uk Kim #include <openssl/err.h>
651f13597dSJung-uk Kim 
661f13597dSJung-uk Kim int SSL_CTX_SRP_CTX_free(struct ssl_ctx_st *ctx)
671f13597dSJung-uk Kim 	{
681f13597dSJung-uk Kim 	if (ctx == NULL)
691f13597dSJung-uk Kim 		return 0;
701f13597dSJung-uk Kim 	OPENSSL_free(ctx->srp_ctx.login);
711f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.N);
721f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.g);
731f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.s);
741f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.B);
751f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.A);
761f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.a);
771f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.b);
781f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.v);
791f13597dSJung-uk Kim 	ctx->srp_ctx.TLS_ext_srp_username_callback = NULL;
801f13597dSJung-uk Kim 	ctx->srp_ctx.SRP_cb_arg = NULL;
811f13597dSJung-uk Kim 	ctx->srp_ctx.SRP_verify_param_callback = NULL;
821f13597dSJung-uk Kim 	ctx->srp_ctx.SRP_give_srp_client_pwd_callback = NULL;
831f13597dSJung-uk Kim 	ctx->srp_ctx.N = NULL;
841f13597dSJung-uk Kim 	ctx->srp_ctx.g = NULL;
851f13597dSJung-uk Kim 	ctx->srp_ctx.s = NULL;
861f13597dSJung-uk Kim 	ctx->srp_ctx.B = NULL;
871f13597dSJung-uk Kim 	ctx->srp_ctx.A = NULL;
881f13597dSJung-uk Kim 	ctx->srp_ctx.a = NULL;
891f13597dSJung-uk Kim 	ctx->srp_ctx.b = NULL;
901f13597dSJung-uk Kim 	ctx->srp_ctx.v = NULL;
911f13597dSJung-uk Kim 	ctx->srp_ctx.login = NULL;
921f13597dSJung-uk Kim 	ctx->srp_ctx.info = NULL;
931f13597dSJung-uk Kim 	ctx->srp_ctx.strength = SRP_MINIMAL_N;
941f13597dSJung-uk Kim 	ctx->srp_ctx.srp_Mask = 0;
951f13597dSJung-uk Kim 	return (1);
961f13597dSJung-uk Kim 	}
971f13597dSJung-uk Kim 
981f13597dSJung-uk Kim int SSL_SRP_CTX_free(struct ssl_st *s)
991f13597dSJung-uk Kim 	{
1001f13597dSJung-uk Kim 	if (s == NULL)
1011f13597dSJung-uk Kim 		return 0;
1021f13597dSJung-uk Kim 	OPENSSL_free(s->srp_ctx.login);
1031f13597dSJung-uk Kim 	BN_free(s->srp_ctx.N);
1041f13597dSJung-uk Kim 	BN_free(s->srp_ctx.g);
1051f13597dSJung-uk Kim 	BN_free(s->srp_ctx.s);
1061f13597dSJung-uk Kim 	BN_free(s->srp_ctx.B);
1071f13597dSJung-uk Kim 	BN_free(s->srp_ctx.A);
1081f13597dSJung-uk Kim 	BN_free(s->srp_ctx.a);
1091f13597dSJung-uk Kim 	BN_free(s->srp_ctx.b);
1101f13597dSJung-uk Kim 	BN_free(s->srp_ctx.v);
1111f13597dSJung-uk Kim 	s->srp_ctx.TLS_ext_srp_username_callback = NULL;
1121f13597dSJung-uk Kim 	s->srp_ctx.SRP_cb_arg = NULL;
1131f13597dSJung-uk Kim 	s->srp_ctx.SRP_verify_param_callback = NULL;
1141f13597dSJung-uk Kim 	s->srp_ctx.SRP_give_srp_client_pwd_callback = NULL;
1151f13597dSJung-uk Kim 	s->srp_ctx.N = NULL;
1161f13597dSJung-uk Kim 	s->srp_ctx.g = NULL;
1171f13597dSJung-uk Kim 	s->srp_ctx.s = NULL;
1181f13597dSJung-uk Kim 	s->srp_ctx.B = NULL;
1191f13597dSJung-uk Kim 	s->srp_ctx.A = NULL;
1201f13597dSJung-uk Kim 	s->srp_ctx.a = NULL;
1211f13597dSJung-uk Kim 	s->srp_ctx.b = NULL;
1221f13597dSJung-uk Kim 	s->srp_ctx.v = NULL;
1231f13597dSJung-uk Kim 	s->srp_ctx.login = NULL;
1241f13597dSJung-uk Kim 	s->srp_ctx.info = NULL;
1251f13597dSJung-uk Kim 	s->srp_ctx.strength = SRP_MINIMAL_N;
1261f13597dSJung-uk Kim 	s->srp_ctx.srp_Mask = 0;
1271f13597dSJung-uk Kim 	return (1);
1281f13597dSJung-uk Kim 	}
1291f13597dSJung-uk Kim 
1301f13597dSJung-uk Kim int SSL_SRP_CTX_init(struct ssl_st *s)
1311f13597dSJung-uk Kim 	{
1321f13597dSJung-uk Kim 	SSL_CTX *ctx;
1331f13597dSJung-uk Kim 
1341f13597dSJung-uk Kim 	if ((s == NULL) || ((ctx = s->ctx) == NULL))
1351f13597dSJung-uk Kim 		return 0;
1361f13597dSJung-uk Kim 	s->srp_ctx.SRP_cb_arg = ctx->srp_ctx.SRP_cb_arg;
1371f13597dSJung-uk Kim 	/* set client Hello login callback */
1381f13597dSJung-uk Kim 	s->srp_ctx.TLS_ext_srp_username_callback = ctx->srp_ctx.TLS_ext_srp_username_callback;
1391f13597dSJung-uk Kim 	/* set SRP N/g param callback for verification */
1401f13597dSJung-uk Kim 	s->srp_ctx.SRP_verify_param_callback = ctx->srp_ctx.SRP_verify_param_callback;
1411f13597dSJung-uk Kim 	/* set SRP client passwd callback */
1421f13597dSJung-uk Kim 	s->srp_ctx.SRP_give_srp_client_pwd_callback = ctx->srp_ctx.SRP_give_srp_client_pwd_callback;
1431f13597dSJung-uk Kim 
1441f13597dSJung-uk Kim 	s->srp_ctx.N = NULL;
1451f13597dSJung-uk Kim 	s->srp_ctx.g = NULL;
1461f13597dSJung-uk Kim 	s->srp_ctx.s = NULL;
1471f13597dSJung-uk Kim 	s->srp_ctx.B = NULL;
1481f13597dSJung-uk Kim 	s->srp_ctx.A = NULL;
1491f13597dSJung-uk Kim 	s->srp_ctx.a = NULL;
1501f13597dSJung-uk Kim 	s->srp_ctx.b = NULL;
1511f13597dSJung-uk Kim 	s->srp_ctx.v = NULL;
1521f13597dSJung-uk Kim 	s->srp_ctx.login = NULL;
1531f13597dSJung-uk Kim 	s->srp_ctx.info = ctx->srp_ctx.info;
1541f13597dSJung-uk Kim 	s->srp_ctx.strength = ctx->srp_ctx.strength;
1551f13597dSJung-uk Kim 
1561f13597dSJung-uk Kim 	if (((ctx->srp_ctx.N != NULL) &&
1571f13597dSJung-uk Kim 		 ((s->srp_ctx.N = BN_dup(ctx->srp_ctx.N)) == NULL)) ||
1581f13597dSJung-uk Kim 		((ctx->srp_ctx.g != NULL) &&
1591f13597dSJung-uk Kim 		 ((s->srp_ctx.g = BN_dup(ctx->srp_ctx.g)) == NULL)) ||
1601f13597dSJung-uk Kim 		((ctx->srp_ctx.s != NULL) &&
1611f13597dSJung-uk Kim 		 ((s->srp_ctx.s = BN_dup(ctx->srp_ctx.s)) == NULL)) ||
1621f13597dSJung-uk Kim 		((ctx->srp_ctx.B != NULL) &&
1631f13597dSJung-uk Kim 		 ((s->srp_ctx.B = BN_dup(ctx->srp_ctx.B)) == NULL)) ||
1641f13597dSJung-uk Kim 		((ctx->srp_ctx.A != NULL) &&
1651f13597dSJung-uk Kim 		 ((s->srp_ctx.A = BN_dup(ctx->srp_ctx.A)) == NULL)) ||
1661f13597dSJung-uk Kim 		((ctx->srp_ctx.a != NULL) &&
1671f13597dSJung-uk Kim 		 ((s->srp_ctx.a = BN_dup(ctx->srp_ctx.a)) == NULL)) ||
1681f13597dSJung-uk Kim 		((ctx->srp_ctx.v != NULL) &&
1691f13597dSJung-uk Kim 		 ((s->srp_ctx.v = BN_dup(ctx->srp_ctx.v)) == NULL)) ||
1701f13597dSJung-uk Kim 		((ctx->srp_ctx.b != NULL) &&
1711f13597dSJung-uk Kim 		 ((s->srp_ctx.b = BN_dup(ctx->srp_ctx.b)) == NULL)))
1721f13597dSJung-uk Kim 		{
1731f13597dSJung-uk Kim 		SSLerr(SSL_F_SSL_SRP_CTX_INIT,ERR_R_BN_LIB);
1741f13597dSJung-uk Kim 		goto err;
1751f13597dSJung-uk Kim 		}
1761f13597dSJung-uk Kim 	if ((ctx->srp_ctx.login != NULL) &&
1771f13597dSJung-uk Kim 		((s->srp_ctx.login = BUF_strdup(ctx->srp_ctx.login)) == NULL))
1781f13597dSJung-uk Kim 		{
1791f13597dSJung-uk Kim 		SSLerr(SSL_F_SSL_SRP_CTX_INIT,ERR_R_INTERNAL_ERROR);
1801f13597dSJung-uk Kim 		goto err;
1811f13597dSJung-uk Kim 		}
1821f13597dSJung-uk Kim 	s->srp_ctx.srp_Mask = ctx->srp_ctx.srp_Mask;
1831f13597dSJung-uk Kim 
1841f13597dSJung-uk Kim 	return (1);
1851f13597dSJung-uk Kim err:
1861f13597dSJung-uk Kim 	OPENSSL_free(s->srp_ctx.login);
1871f13597dSJung-uk Kim 	BN_free(s->srp_ctx.N);
1881f13597dSJung-uk Kim 	BN_free(s->srp_ctx.g);
1891f13597dSJung-uk Kim 	BN_free(s->srp_ctx.s);
1901f13597dSJung-uk Kim 	BN_free(s->srp_ctx.B);
1911f13597dSJung-uk Kim 	BN_free(s->srp_ctx.A);
1921f13597dSJung-uk Kim 	BN_free(s->srp_ctx.a);
1931f13597dSJung-uk Kim 	BN_free(s->srp_ctx.b);
1941f13597dSJung-uk Kim 	BN_free(s->srp_ctx.v);
1951f13597dSJung-uk Kim 	return (0);
1961f13597dSJung-uk Kim 	}
1971f13597dSJung-uk Kim 
1981f13597dSJung-uk Kim int SSL_CTX_SRP_CTX_init(struct ssl_ctx_st *ctx)
1991f13597dSJung-uk Kim 	{
2001f13597dSJung-uk Kim 	if (ctx == NULL)
2011f13597dSJung-uk Kim 		return 0;
2021f13597dSJung-uk Kim 
2031f13597dSJung-uk Kim 	ctx->srp_ctx.SRP_cb_arg = NULL;
2041f13597dSJung-uk Kim 	/* set client Hello login callback */
2051f13597dSJung-uk Kim 	ctx->srp_ctx.TLS_ext_srp_username_callback = NULL;
2061f13597dSJung-uk Kim 	/* set SRP N/g param callback for verification */
2071f13597dSJung-uk Kim 	ctx->srp_ctx.SRP_verify_param_callback = NULL;
2081f13597dSJung-uk Kim 	/* set SRP client passwd callback */
2091f13597dSJung-uk Kim 	ctx->srp_ctx.SRP_give_srp_client_pwd_callback = NULL;
2101f13597dSJung-uk Kim 
2111f13597dSJung-uk Kim 	ctx->srp_ctx.N = NULL;
2121f13597dSJung-uk Kim 	ctx->srp_ctx.g = NULL;
2131f13597dSJung-uk Kim 	ctx->srp_ctx.s = NULL;
2141f13597dSJung-uk Kim 	ctx->srp_ctx.B = NULL;
2151f13597dSJung-uk Kim 	ctx->srp_ctx.A = NULL;
2161f13597dSJung-uk Kim 	ctx->srp_ctx.a = NULL;
2171f13597dSJung-uk Kim 	ctx->srp_ctx.b = NULL;
2181f13597dSJung-uk Kim 	ctx->srp_ctx.v = NULL;
2191f13597dSJung-uk Kim 	ctx->srp_ctx.login = NULL;
2201f13597dSJung-uk Kim 	ctx->srp_ctx.srp_Mask = 0;
2211f13597dSJung-uk Kim 	ctx->srp_ctx.info = NULL;
2221f13597dSJung-uk Kim 	ctx->srp_ctx.strength = SRP_MINIMAL_N;
2231f13597dSJung-uk Kim 
2241f13597dSJung-uk Kim 	return (1);
2251f13597dSJung-uk Kim 	}
2261f13597dSJung-uk Kim 
2271f13597dSJung-uk Kim /* server side */
2281f13597dSJung-uk Kim int SSL_srp_server_param_with_username(SSL *s, int *ad)
2291f13597dSJung-uk Kim 	{
2301f13597dSJung-uk Kim 	unsigned char b[SSL_MAX_MASTER_KEY_LENGTH];
2311f13597dSJung-uk Kim 	int al;
2321f13597dSJung-uk Kim 
2331f13597dSJung-uk Kim 	*ad = SSL_AD_UNKNOWN_PSK_IDENTITY;
2341f13597dSJung-uk Kim 	if ((s->srp_ctx.TLS_ext_srp_username_callback !=NULL) &&
2351f13597dSJung-uk Kim 		((al = s->srp_ctx.TLS_ext_srp_username_callback(s, ad, s->srp_ctx.SRP_cb_arg))!=SSL_ERROR_NONE))
2361f13597dSJung-uk Kim 			return al;
2371f13597dSJung-uk Kim 
2381f13597dSJung-uk Kim 	*ad = SSL_AD_INTERNAL_ERROR;
2391f13597dSJung-uk Kim 	if ((s->srp_ctx.N == NULL) ||
2401f13597dSJung-uk Kim 		(s->srp_ctx.g == NULL) ||
2411f13597dSJung-uk Kim 		(s->srp_ctx.s == NULL) ||
2421f13597dSJung-uk Kim 		(s->srp_ctx.v == NULL))
2431f13597dSJung-uk Kim 		return SSL3_AL_FATAL;
2441f13597dSJung-uk Kim 
24509286989SJung-uk Kim 	if (RAND_bytes(b, sizeof(b)) <= 0)
24609286989SJung-uk Kim 		return SSL3_AL_FATAL;
2471f13597dSJung-uk Kim 	s->srp_ctx.b = BN_bin2bn(b,sizeof(b),NULL);
2481f13597dSJung-uk Kim 	OPENSSL_cleanse(b,sizeof(b));
2491f13597dSJung-uk Kim 
2501f13597dSJung-uk Kim 	/* Calculate:  B = (kv + g^b) % N  */
2511f13597dSJung-uk Kim 
2521f13597dSJung-uk Kim 	return ((s->srp_ctx.B = SRP_Calc_B(s->srp_ctx.b, s->srp_ctx.N, s->srp_ctx.g, s->srp_ctx.v)) != NULL)?
2531f13597dSJung-uk Kim 			SSL_ERROR_NONE:SSL3_AL_FATAL;
2541f13597dSJung-uk Kim 	}
2551f13597dSJung-uk Kim 
2561f13597dSJung-uk Kim /* If the server just has the raw password, make up a verifier entry on the fly */
2571f13597dSJung-uk Kim int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass, const char *grp)
2581f13597dSJung-uk Kim 	{
2591f13597dSJung-uk Kim 	SRP_gN *GN = SRP_get_default_gN(grp);
2601f13597dSJung-uk Kim 	if(GN == NULL) return -1;
2611f13597dSJung-uk Kim 	s->srp_ctx.N = BN_dup(GN->N);
2621f13597dSJung-uk Kim 	s->srp_ctx.g = BN_dup(GN->g);
2631f13597dSJung-uk Kim 	if(s->srp_ctx.v != NULL)
2641f13597dSJung-uk Kim 		{
2651f13597dSJung-uk Kim 		BN_clear_free(s->srp_ctx.v);
2661f13597dSJung-uk Kim 		s->srp_ctx.v = NULL;
2671f13597dSJung-uk Kim 		}
2681f13597dSJung-uk Kim 	if(s->srp_ctx.s != NULL)
2691f13597dSJung-uk Kim 		{
2701f13597dSJung-uk Kim 		BN_clear_free(s->srp_ctx.s);
2711f13597dSJung-uk Kim 		s->srp_ctx.s = NULL;
2721f13597dSJung-uk Kim 		}
2731f13597dSJung-uk Kim 	if(!SRP_create_verifier_BN(user, pass, &s->srp_ctx.s, &s->srp_ctx.v, GN->N, GN->g)) return -1;
2741f13597dSJung-uk Kim 
2751f13597dSJung-uk Kim 	return 1;
2761f13597dSJung-uk Kim 	}
2771f13597dSJung-uk Kim 
2781f13597dSJung-uk Kim int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
2791f13597dSJung-uk Kim 			     BIGNUM *sa, BIGNUM *v, char *info)
2801f13597dSJung-uk Kim 	{
2811f13597dSJung-uk Kim 	if (N!= NULL)
2821f13597dSJung-uk Kim 		{
2831f13597dSJung-uk Kim 		if (s->srp_ctx.N != NULL)
2841f13597dSJung-uk Kim 			{
2851f13597dSJung-uk Kim 			if (!BN_copy(s->srp_ctx.N,N))
2861f13597dSJung-uk Kim 				{
2871f13597dSJung-uk Kim 				BN_free(s->srp_ctx.N);
2881f13597dSJung-uk Kim 				s->srp_ctx.N = NULL;
2891f13597dSJung-uk Kim 				}
2901f13597dSJung-uk Kim 			}
2911f13597dSJung-uk Kim 		else
2921f13597dSJung-uk Kim 			s->srp_ctx.N = BN_dup(N);
2931f13597dSJung-uk Kim 		}
2941f13597dSJung-uk Kim 	if (g!= NULL)
2951f13597dSJung-uk Kim 		{
2961f13597dSJung-uk Kim 		if (s->srp_ctx.g != NULL)
2971f13597dSJung-uk Kim 			{
2981f13597dSJung-uk Kim 			if (!BN_copy(s->srp_ctx.g,g))
2991f13597dSJung-uk Kim 				{
3001f13597dSJung-uk Kim 				BN_free(s->srp_ctx.g);
3011f13597dSJung-uk Kim 				s->srp_ctx.g = NULL;
3021f13597dSJung-uk Kim 				}
3031f13597dSJung-uk Kim 			}
3041f13597dSJung-uk Kim 		else
3051f13597dSJung-uk Kim 			s->srp_ctx.g = BN_dup(g);
3061f13597dSJung-uk Kim 		}
3071f13597dSJung-uk Kim 	if (sa!= NULL)
3081f13597dSJung-uk Kim 		{
3091f13597dSJung-uk Kim 		if (s->srp_ctx.s != NULL)
3101f13597dSJung-uk Kim 			{
3111f13597dSJung-uk Kim 			if (!BN_copy(s->srp_ctx.s,sa))
3121f13597dSJung-uk Kim 				{
3131f13597dSJung-uk Kim 				BN_free(s->srp_ctx.s);
3141f13597dSJung-uk Kim 				s->srp_ctx.s = NULL;
3151f13597dSJung-uk Kim 				}
3161f13597dSJung-uk Kim 			}
3171f13597dSJung-uk Kim 		else
3181f13597dSJung-uk Kim 			s->srp_ctx.s = BN_dup(sa);
3191f13597dSJung-uk Kim 		}
3201f13597dSJung-uk Kim 	if (v!= NULL)
3211f13597dSJung-uk Kim 		{
3221f13597dSJung-uk Kim 		if (s->srp_ctx.v != NULL)
3231f13597dSJung-uk Kim 			{
3241f13597dSJung-uk Kim 			if (!BN_copy(s->srp_ctx.v,v))
3251f13597dSJung-uk Kim 				{
3261f13597dSJung-uk Kim 				BN_free(s->srp_ctx.v);
3271f13597dSJung-uk Kim 				s->srp_ctx.v = NULL;
3281f13597dSJung-uk Kim 				}
3291f13597dSJung-uk Kim 			}
3301f13597dSJung-uk Kim 		else
3311f13597dSJung-uk Kim 			s->srp_ctx.v = BN_dup(v);
3321f13597dSJung-uk Kim 		}
3331f13597dSJung-uk Kim 	s->srp_ctx.info = info;
3341f13597dSJung-uk Kim 
3351f13597dSJung-uk Kim 	if (!(s->srp_ctx.N) ||
3361f13597dSJung-uk Kim 		!(s->srp_ctx.g) ||
3371f13597dSJung-uk Kim 		!(s->srp_ctx.s) ||
3381f13597dSJung-uk Kim 		!(s->srp_ctx.v))
3391f13597dSJung-uk Kim 		return -1;
3401f13597dSJung-uk Kim 
3411f13597dSJung-uk Kim 	return 1;
3421f13597dSJung-uk Kim 	}
3431f13597dSJung-uk Kim 
3441f13597dSJung-uk Kim int SRP_generate_server_master_secret(SSL *s,unsigned char *master_key)
3451f13597dSJung-uk Kim 	{
3461f13597dSJung-uk Kim 	BIGNUM *K = NULL, *u = NULL;
3471f13597dSJung-uk Kim 	int ret = -1, tmp_len;
3481f13597dSJung-uk Kim 	unsigned char *tmp = NULL;
3491f13597dSJung-uk Kim 
3501f13597dSJung-uk Kim 	if (!SRP_Verify_A_mod_N(s->srp_ctx.A,s->srp_ctx.N))
3511f13597dSJung-uk Kim 		goto err;
3521f13597dSJung-uk Kim 	if (!(u = SRP_Calc_u(s->srp_ctx.A,s->srp_ctx.B,s->srp_ctx.N)))
3531f13597dSJung-uk Kim 		goto err;
3541f13597dSJung-uk Kim 	if (!(K = SRP_Calc_server_key(s->srp_ctx.A, s->srp_ctx.v, u, s->srp_ctx.b, s->srp_ctx.N)))
3551f13597dSJung-uk Kim 		goto err;
3561f13597dSJung-uk Kim 
3571f13597dSJung-uk Kim 	tmp_len = BN_num_bytes(K);
3581f13597dSJung-uk Kim 	if ((tmp = OPENSSL_malloc(tmp_len)) == NULL)
3591f13597dSJung-uk Kim 		goto err;
3601f13597dSJung-uk Kim 	BN_bn2bin(K, tmp);
3611f13597dSJung-uk Kim 	ret = s->method->ssl3_enc->generate_master_secret(s,master_key,tmp,tmp_len);
3621f13597dSJung-uk Kim err:
3631f13597dSJung-uk Kim 	if (tmp)
3641f13597dSJung-uk Kim 		{
3651f13597dSJung-uk Kim 		OPENSSL_cleanse(tmp,tmp_len) ;
3661f13597dSJung-uk Kim 		OPENSSL_free(tmp);
3671f13597dSJung-uk Kim 		}
3681f13597dSJung-uk Kim 	BN_clear_free(K);
3691f13597dSJung-uk Kim 	BN_clear_free(u);
3701f13597dSJung-uk Kim 	return ret;
3711f13597dSJung-uk Kim 	}
3721f13597dSJung-uk Kim 
3731f13597dSJung-uk Kim /* client side */
3741f13597dSJung-uk Kim int SRP_generate_client_master_secret(SSL *s,unsigned char *master_key)
3751f13597dSJung-uk Kim 	{
3761f13597dSJung-uk Kim 	BIGNUM *x = NULL, *u = NULL, *K = NULL;
3771f13597dSJung-uk Kim 	int ret = -1, tmp_len;
3781f13597dSJung-uk Kim 	char *passwd = NULL;
3791f13597dSJung-uk Kim 	unsigned char *tmp = NULL;
3801f13597dSJung-uk Kim 
3811f13597dSJung-uk Kim 	/* Checks if b % n == 0
3821f13597dSJung-uk Kim 	 */
3831f13597dSJung-uk Kim 	if (SRP_Verify_B_mod_N(s->srp_ctx.B,s->srp_ctx.N)==0) goto err;
3841f13597dSJung-uk Kim 	if (!(u = SRP_Calc_u(s->srp_ctx.A,s->srp_ctx.B,s->srp_ctx.N))) goto err;
3851f13597dSJung-uk Kim 	if (s->srp_ctx.SRP_give_srp_client_pwd_callback == NULL) goto err;
3861f13597dSJung-uk Kim 	if (!(passwd = s->srp_ctx.SRP_give_srp_client_pwd_callback(s, s->srp_ctx.SRP_cb_arg))) goto err;
3871f13597dSJung-uk Kim 	if (!(x = SRP_Calc_x(s->srp_ctx.s,s->srp_ctx.login,passwd))) goto err;
3881f13597dSJung-uk Kim 	if (!(K = SRP_Calc_client_key(s->srp_ctx.N, s->srp_ctx.B, s->srp_ctx.g, x, s->srp_ctx.a, u))) goto err;
3891f13597dSJung-uk Kim 
3901f13597dSJung-uk Kim 	tmp_len = BN_num_bytes(K);
3911f13597dSJung-uk Kim 	if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) goto err;
3921f13597dSJung-uk Kim 	BN_bn2bin(K, tmp);
3931f13597dSJung-uk Kim 	ret = s->method->ssl3_enc->generate_master_secret(s,master_key,tmp,tmp_len);
3941f13597dSJung-uk Kim err:
3951f13597dSJung-uk Kim 	if (tmp)
3961f13597dSJung-uk Kim 		{
3971f13597dSJung-uk Kim 		OPENSSL_cleanse(tmp,tmp_len) ;
3981f13597dSJung-uk Kim 		OPENSSL_free(tmp);
3991f13597dSJung-uk Kim 		}
4001f13597dSJung-uk Kim 	BN_clear_free(K);
4011f13597dSJung-uk Kim 	BN_clear_free(x);
4021f13597dSJung-uk Kim 	if (passwd)
4031f13597dSJung-uk Kim 		{
4041f13597dSJung-uk Kim 		OPENSSL_cleanse(passwd,strlen(passwd)) ;
4051f13597dSJung-uk Kim 		OPENSSL_free(passwd);
4061f13597dSJung-uk Kim 		}
4071f13597dSJung-uk Kim 	BN_clear_free(u);
4081f13597dSJung-uk Kim 	return ret;
4091f13597dSJung-uk Kim 	}
4101f13597dSJung-uk Kim 
411*a93cbc2bSJung-uk Kim int srp_verify_server_param(SSL *s, int *al)
412*a93cbc2bSJung-uk Kim 	{
413*a93cbc2bSJung-uk Kim 	SRP_CTX *srp = &s->srp_ctx;
414*a93cbc2bSJung-uk Kim 	/* Sanity check parameters: we can quickly check B % N == 0
415*a93cbc2bSJung-uk Kim 	 * by checking B != 0 since B < N
416*a93cbc2bSJung-uk Kim 	 */
417*a93cbc2bSJung-uk Kim 	if (BN_ucmp(srp->g, srp->N) >=0 || BN_ucmp(srp->B, srp->N) >= 0
418*a93cbc2bSJung-uk Kim 		|| BN_is_zero(srp->B))
419*a93cbc2bSJung-uk Kim 		{
420*a93cbc2bSJung-uk Kim 		*al = SSL3_AD_ILLEGAL_PARAMETER;
421*a93cbc2bSJung-uk Kim 		return 0;
422*a93cbc2bSJung-uk Kim 		}
423*a93cbc2bSJung-uk Kim 
424*a93cbc2bSJung-uk Kim 	if (BN_num_bits(srp->N) < srp->strength)
425*a93cbc2bSJung-uk Kim 		{
426*a93cbc2bSJung-uk Kim 		*al = TLS1_AD_INSUFFICIENT_SECURITY;
427*a93cbc2bSJung-uk Kim 		return 0;
428*a93cbc2bSJung-uk Kim 		}
429*a93cbc2bSJung-uk Kim 
430*a93cbc2bSJung-uk Kim 	if (srp->SRP_verify_param_callback)
431*a93cbc2bSJung-uk Kim 		{
432*a93cbc2bSJung-uk Kim 		if (srp->SRP_verify_param_callback(s, srp->SRP_cb_arg) <= 0)
433*a93cbc2bSJung-uk Kim 			{
434*a93cbc2bSJung-uk Kim 			*al = TLS1_AD_INSUFFICIENT_SECURITY;
435*a93cbc2bSJung-uk Kim 			return 0;
436*a93cbc2bSJung-uk Kim 			}
437*a93cbc2bSJung-uk Kim 		}
438*a93cbc2bSJung-uk Kim 	else if(!SRP_check_known_gN_param(srp->g, srp->N))
439*a93cbc2bSJung-uk Kim 		{
440*a93cbc2bSJung-uk Kim 		*al = TLS1_AD_INSUFFICIENT_SECURITY;
441*a93cbc2bSJung-uk Kim 		return 0;
442*a93cbc2bSJung-uk Kim 		}
443*a93cbc2bSJung-uk Kim 
444*a93cbc2bSJung-uk Kim 	return 1;
445*a93cbc2bSJung-uk Kim 	}
446*a93cbc2bSJung-uk Kim 
447*a93cbc2bSJung-uk Kim 
4481f13597dSJung-uk Kim int SRP_Calc_A_param(SSL *s)
4491f13597dSJung-uk Kim 	{
4501f13597dSJung-uk Kim 	unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH];
4511f13597dSJung-uk Kim 
4521f13597dSJung-uk Kim 	RAND_bytes(rnd, sizeof(rnd));
4531f13597dSJung-uk Kim 	s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a);
4541f13597dSJung-uk Kim 	OPENSSL_cleanse(rnd, sizeof(rnd));
4551f13597dSJung-uk Kim 
4561f13597dSJung-uk Kim 	if (!(s->srp_ctx.A = SRP_Calc_A(s->srp_ctx.a,s->srp_ctx.N,s->srp_ctx.g)))
4571f13597dSJung-uk Kim 		return -1;
4581f13597dSJung-uk Kim 
4591f13597dSJung-uk Kim 	return 1;
4601f13597dSJung-uk Kim 	}
4611f13597dSJung-uk Kim 
4621f13597dSJung-uk Kim BIGNUM *SSL_get_srp_g(SSL *s)
4631f13597dSJung-uk Kim 	{
4641f13597dSJung-uk Kim 	if (s->srp_ctx.g != NULL)
4651f13597dSJung-uk Kim 		return s->srp_ctx.g;
4661f13597dSJung-uk Kim 	return s->ctx->srp_ctx.g;
4671f13597dSJung-uk Kim 	}
4681f13597dSJung-uk Kim 
4691f13597dSJung-uk Kim BIGNUM *SSL_get_srp_N(SSL *s)
4701f13597dSJung-uk Kim 	{
4711f13597dSJung-uk Kim 	if (s->srp_ctx.N != NULL)
4721f13597dSJung-uk Kim 		return s->srp_ctx.N;
4731f13597dSJung-uk Kim 	return s->ctx->srp_ctx.N;
4741f13597dSJung-uk Kim 	}
4751f13597dSJung-uk Kim 
4761f13597dSJung-uk Kim char *SSL_get_srp_username(SSL *s)
4771f13597dSJung-uk Kim 	{
4781f13597dSJung-uk Kim 	if (s->srp_ctx.login != NULL)
4791f13597dSJung-uk Kim 		return s->srp_ctx.login;
4801f13597dSJung-uk Kim 	return s->ctx->srp_ctx.login;
4811f13597dSJung-uk Kim 	}
4821f13597dSJung-uk Kim 
4831f13597dSJung-uk Kim char *SSL_get_srp_userinfo(SSL *s)
4841f13597dSJung-uk Kim 	{
4851f13597dSJung-uk Kim 	if (s->srp_ctx.info != NULL)
4861f13597dSJung-uk Kim 		return s->srp_ctx.info;
4871f13597dSJung-uk Kim 	return s->ctx->srp_ctx.info;
4881f13597dSJung-uk Kim 	}
4891f13597dSJung-uk Kim 
4901f13597dSJung-uk Kim #define tls1_ctx_ctrl ssl3_ctx_ctrl
4911f13597dSJung-uk Kim #define tls1_ctx_callback_ctrl ssl3_ctx_callback_ctrl
4921f13597dSJung-uk Kim 
4931f13597dSJung-uk Kim int SSL_CTX_set_srp_username(SSL_CTX *ctx,char *name)
4941f13597dSJung-uk Kim 	{
4951f13597dSJung-uk Kim 	return tls1_ctx_ctrl(ctx,SSL_CTRL_SET_TLS_EXT_SRP_USERNAME,0,name);
4961f13597dSJung-uk Kim 	}
4971f13597dSJung-uk Kim 
4981f13597dSJung-uk Kim int SSL_CTX_set_srp_password(SSL_CTX *ctx,char *password)
4991f13597dSJung-uk Kim 	{
5001f13597dSJung-uk Kim 	return tls1_ctx_ctrl(ctx,SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD,0,password);
5011f13597dSJung-uk Kim 	}
5021f13597dSJung-uk Kim 
5031f13597dSJung-uk Kim int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength)
5041f13597dSJung-uk Kim 	{
5051f13597dSJung-uk Kim 	return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH, strength,
5061f13597dSJung-uk Kim 			     NULL);
5071f13597dSJung-uk Kim 	}
5081f13597dSJung-uk Kim 
5091f13597dSJung-uk Kim int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx, int (*cb)(SSL *,void *))
5101f13597dSJung-uk Kim 	{
5111f13597dSJung-uk Kim 	return tls1_ctx_callback_ctrl(ctx,SSL_CTRL_SET_SRP_VERIFY_PARAM_CB,
5121f13597dSJung-uk Kim 				      (void (*)(void))cb);
5131f13597dSJung-uk Kim 	}
5141f13597dSJung-uk Kim 
5151f13597dSJung-uk Kim int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg)
5161f13597dSJung-uk Kim 	{
5171f13597dSJung-uk Kim 	return tls1_ctx_ctrl(ctx,SSL_CTRL_SET_SRP_ARG,0,arg);
5181f13597dSJung-uk Kim 	}
5191f13597dSJung-uk Kim 
5201f13597dSJung-uk Kim int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
5211f13597dSJung-uk Kim 				      int (*cb)(SSL *,int *,void *))
5221f13597dSJung-uk Kim 	{
5231f13597dSJung-uk Kim 	return tls1_ctx_callback_ctrl(ctx,SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB,
5241f13597dSJung-uk Kim 				      (void (*)(void))cb);
5251f13597dSJung-uk Kim 	}
5261f13597dSJung-uk Kim 
5271f13597dSJung-uk Kim int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx, char *(*cb)(SSL *,void *))
5281f13597dSJung-uk Kim 	{
5291f13597dSJung-uk Kim 	return tls1_ctx_callback_ctrl(ctx,SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB,
5301f13597dSJung-uk Kim 				      (void (*)(void))cb);
5311f13597dSJung-uk Kim 	}
5321f13597dSJung-uk Kim 
5331f13597dSJung-uk Kim #endif
534