xref: /freebsd/crypto/openssl/ssl/tls_srp.c (revision 1f13597d10e771d5546d31839150812bde8e4a56)
1*1f13597dSJung-uk Kim /* ssl/tls_srp.c */
2*1f13597dSJung-uk Kim /* Written by Christophe Renou (christophe.renou@edelweb.fr) with
3*1f13597dSJung-uk Kim  * the precious help of Peter Sylvester (peter.sylvester@edelweb.fr)
4*1f13597dSJung-uk Kim  * for the EdelKey project and contributed to the OpenSSL project 2004.
5*1f13597dSJung-uk Kim  */
6*1f13597dSJung-uk Kim /* ====================================================================
7*1f13597dSJung-uk Kim  * Copyright (c) 2004-2011 The OpenSSL Project.  All rights reserved.
8*1f13597dSJung-uk Kim  *
9*1f13597dSJung-uk Kim  * Redistribution and use in source and binary forms, with or without
10*1f13597dSJung-uk Kim  * modification, are permitted provided that the following conditions
11*1f13597dSJung-uk Kim  * are met:
12*1f13597dSJung-uk Kim  *
13*1f13597dSJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
14*1f13597dSJung-uk Kim  *    notice, this list of conditions and the following disclaimer.
15*1f13597dSJung-uk Kim  *
16*1f13597dSJung-uk Kim  * 2. Redistributions in binary form must reproduce the above copyright
17*1f13597dSJung-uk Kim  *    notice, this list of conditions and the following disclaimer in
18*1f13597dSJung-uk Kim  *    the documentation and/or other materials provided with the
19*1f13597dSJung-uk Kim  *    distribution.
20*1f13597dSJung-uk Kim  *
21*1f13597dSJung-uk Kim  * 3. All advertising materials mentioning features or use of this
22*1f13597dSJung-uk Kim  *    software must display the following acknowledgment:
23*1f13597dSJung-uk Kim  *    "This product includes software developed by the OpenSSL Project
24*1f13597dSJung-uk Kim  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25*1f13597dSJung-uk Kim  *
26*1f13597dSJung-uk Kim  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27*1f13597dSJung-uk Kim  *    endorse or promote products derived from this software without
28*1f13597dSJung-uk Kim  *    prior written permission. For written permission, please contact
29*1f13597dSJung-uk Kim  *    licensing@OpenSSL.org.
30*1f13597dSJung-uk Kim  *
31*1f13597dSJung-uk Kim  * 5. Products derived from this software may not be called "OpenSSL"
32*1f13597dSJung-uk Kim  *    nor may "OpenSSL" appear in their names without prior written
33*1f13597dSJung-uk Kim  *    permission of the OpenSSL Project.
34*1f13597dSJung-uk Kim  *
35*1f13597dSJung-uk Kim  * 6. Redistributions of any form whatsoever must retain the following
36*1f13597dSJung-uk Kim  *    acknowledgment:
37*1f13597dSJung-uk Kim  *    "This product includes software developed by the OpenSSL Project
38*1f13597dSJung-uk Kim  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39*1f13597dSJung-uk Kim  *
40*1f13597dSJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41*1f13597dSJung-uk Kim  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42*1f13597dSJung-uk Kim  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43*1f13597dSJung-uk Kim  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44*1f13597dSJung-uk Kim  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45*1f13597dSJung-uk Kim  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46*1f13597dSJung-uk Kim  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47*1f13597dSJung-uk Kim  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48*1f13597dSJung-uk Kim  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49*1f13597dSJung-uk Kim  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50*1f13597dSJung-uk Kim  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51*1f13597dSJung-uk Kim  * OF THE POSSIBILITY OF SUCH DAMAGE.
52*1f13597dSJung-uk Kim  * ====================================================================
53*1f13597dSJung-uk Kim  *
54*1f13597dSJung-uk Kim  * This product includes cryptographic software written by Eric Young
55*1f13597dSJung-uk Kim  * (eay@cryptsoft.com).  This product includes software written by Tim
56*1f13597dSJung-uk Kim  * Hudson (tjh@cryptsoft.com).
57*1f13597dSJung-uk Kim  *
58*1f13597dSJung-uk Kim  */
59*1f13597dSJung-uk Kim #include "ssl_locl.h"
60*1f13597dSJung-uk Kim #ifndef OPENSSL_NO_SRP
61*1f13597dSJung-uk Kim 
62*1f13597dSJung-uk Kim #include <openssl/rand.h>
63*1f13597dSJung-uk Kim #include <openssl/srp.h>
64*1f13597dSJung-uk Kim #include <openssl/err.h>
65*1f13597dSJung-uk Kim 
66*1f13597dSJung-uk Kim int SSL_CTX_SRP_CTX_free(struct ssl_ctx_st *ctx)
67*1f13597dSJung-uk Kim 	{
68*1f13597dSJung-uk Kim 	if (ctx == NULL)
69*1f13597dSJung-uk Kim 		return 0;
70*1f13597dSJung-uk Kim 	OPENSSL_free(ctx->srp_ctx.login);
71*1f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.N);
72*1f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.g);
73*1f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.s);
74*1f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.B);
75*1f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.A);
76*1f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.a);
77*1f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.b);
78*1f13597dSJung-uk Kim 	BN_free(ctx->srp_ctx.v);
79*1f13597dSJung-uk Kim 	ctx->srp_ctx.TLS_ext_srp_username_callback = NULL;
80*1f13597dSJung-uk Kim 	ctx->srp_ctx.SRP_cb_arg = NULL;
81*1f13597dSJung-uk Kim 	ctx->srp_ctx.SRP_verify_param_callback = NULL;
82*1f13597dSJung-uk Kim 	ctx->srp_ctx.SRP_give_srp_client_pwd_callback = NULL;
83*1f13597dSJung-uk Kim 	ctx->srp_ctx.N = NULL;
84*1f13597dSJung-uk Kim 	ctx->srp_ctx.g = NULL;
85*1f13597dSJung-uk Kim 	ctx->srp_ctx.s = NULL;
86*1f13597dSJung-uk Kim 	ctx->srp_ctx.B = NULL;
87*1f13597dSJung-uk Kim 	ctx->srp_ctx.A = NULL;
88*1f13597dSJung-uk Kim 	ctx->srp_ctx.a = NULL;
89*1f13597dSJung-uk Kim 	ctx->srp_ctx.b = NULL;
90*1f13597dSJung-uk Kim 	ctx->srp_ctx.v = NULL;
91*1f13597dSJung-uk Kim 	ctx->srp_ctx.login = NULL;
92*1f13597dSJung-uk Kim 	ctx->srp_ctx.info = NULL;
93*1f13597dSJung-uk Kim 	ctx->srp_ctx.strength = SRP_MINIMAL_N;
94*1f13597dSJung-uk Kim 	ctx->srp_ctx.srp_Mask = 0;
95*1f13597dSJung-uk Kim 	return (1);
96*1f13597dSJung-uk Kim 	}
97*1f13597dSJung-uk Kim 
98*1f13597dSJung-uk Kim int SSL_SRP_CTX_free(struct ssl_st *s)
99*1f13597dSJung-uk Kim 	{
100*1f13597dSJung-uk Kim 	if (s == NULL)
101*1f13597dSJung-uk Kim 		return 0;
102*1f13597dSJung-uk Kim 	OPENSSL_free(s->srp_ctx.login);
103*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.N);
104*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.g);
105*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.s);
106*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.B);
107*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.A);
108*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.a);
109*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.b);
110*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.v);
111*1f13597dSJung-uk Kim 	s->srp_ctx.TLS_ext_srp_username_callback = NULL;
112*1f13597dSJung-uk Kim 	s->srp_ctx.SRP_cb_arg = NULL;
113*1f13597dSJung-uk Kim 	s->srp_ctx.SRP_verify_param_callback = NULL;
114*1f13597dSJung-uk Kim 	s->srp_ctx.SRP_give_srp_client_pwd_callback = NULL;
115*1f13597dSJung-uk Kim 	s->srp_ctx.N = NULL;
116*1f13597dSJung-uk Kim 	s->srp_ctx.g = NULL;
117*1f13597dSJung-uk Kim 	s->srp_ctx.s = NULL;
118*1f13597dSJung-uk Kim 	s->srp_ctx.B = NULL;
119*1f13597dSJung-uk Kim 	s->srp_ctx.A = NULL;
120*1f13597dSJung-uk Kim 	s->srp_ctx.a = NULL;
121*1f13597dSJung-uk Kim 	s->srp_ctx.b = NULL;
122*1f13597dSJung-uk Kim 	s->srp_ctx.v = NULL;
123*1f13597dSJung-uk Kim 	s->srp_ctx.login = NULL;
124*1f13597dSJung-uk Kim 	s->srp_ctx.info = NULL;
125*1f13597dSJung-uk Kim 	s->srp_ctx.strength = SRP_MINIMAL_N;
126*1f13597dSJung-uk Kim 	s->srp_ctx.srp_Mask = 0;
127*1f13597dSJung-uk Kim 	return (1);
128*1f13597dSJung-uk Kim 	}
129*1f13597dSJung-uk Kim 
130*1f13597dSJung-uk Kim int SSL_SRP_CTX_init(struct ssl_st *s)
131*1f13597dSJung-uk Kim 	{
132*1f13597dSJung-uk Kim 	SSL_CTX *ctx;
133*1f13597dSJung-uk Kim 
134*1f13597dSJung-uk Kim 	if ((s == NULL) || ((ctx = s->ctx) == NULL))
135*1f13597dSJung-uk Kim 		return 0;
136*1f13597dSJung-uk Kim 	s->srp_ctx.SRP_cb_arg = ctx->srp_ctx.SRP_cb_arg;
137*1f13597dSJung-uk Kim 	/* set client Hello login callback */
138*1f13597dSJung-uk Kim 	s->srp_ctx.TLS_ext_srp_username_callback = ctx->srp_ctx.TLS_ext_srp_username_callback;
139*1f13597dSJung-uk Kim 	/* set SRP N/g param callback for verification */
140*1f13597dSJung-uk Kim 	s->srp_ctx.SRP_verify_param_callback = ctx->srp_ctx.SRP_verify_param_callback;
141*1f13597dSJung-uk Kim 	/* set SRP client passwd callback */
142*1f13597dSJung-uk Kim 	s->srp_ctx.SRP_give_srp_client_pwd_callback = ctx->srp_ctx.SRP_give_srp_client_pwd_callback;
143*1f13597dSJung-uk Kim 
144*1f13597dSJung-uk Kim 	s->srp_ctx.N = NULL;
145*1f13597dSJung-uk Kim 	s->srp_ctx.g = NULL;
146*1f13597dSJung-uk Kim 	s->srp_ctx.s = NULL;
147*1f13597dSJung-uk Kim 	s->srp_ctx.B = NULL;
148*1f13597dSJung-uk Kim 	s->srp_ctx.A = NULL;
149*1f13597dSJung-uk Kim 	s->srp_ctx.a = NULL;
150*1f13597dSJung-uk Kim 	s->srp_ctx.b = NULL;
151*1f13597dSJung-uk Kim 	s->srp_ctx.v = NULL;
152*1f13597dSJung-uk Kim 	s->srp_ctx.login = NULL;
153*1f13597dSJung-uk Kim 	s->srp_ctx.info = ctx->srp_ctx.info;
154*1f13597dSJung-uk Kim 	s->srp_ctx.strength = ctx->srp_ctx.strength;
155*1f13597dSJung-uk Kim 
156*1f13597dSJung-uk Kim 	if (((ctx->srp_ctx.N != NULL) &&
157*1f13597dSJung-uk Kim 		 ((s->srp_ctx.N = BN_dup(ctx->srp_ctx.N)) == NULL)) ||
158*1f13597dSJung-uk Kim 		((ctx->srp_ctx.g != NULL) &&
159*1f13597dSJung-uk Kim 		 ((s->srp_ctx.g = BN_dup(ctx->srp_ctx.g)) == NULL)) ||
160*1f13597dSJung-uk Kim 		((ctx->srp_ctx.s != NULL) &&
161*1f13597dSJung-uk Kim 		 ((s->srp_ctx.s = BN_dup(ctx->srp_ctx.s)) == NULL)) ||
162*1f13597dSJung-uk Kim 		((ctx->srp_ctx.B != NULL) &&
163*1f13597dSJung-uk Kim 		 ((s->srp_ctx.B = BN_dup(ctx->srp_ctx.B)) == NULL)) ||
164*1f13597dSJung-uk Kim 		((ctx->srp_ctx.A != NULL) &&
165*1f13597dSJung-uk Kim 		 ((s->srp_ctx.A = BN_dup(ctx->srp_ctx.A)) == NULL)) ||
166*1f13597dSJung-uk Kim 		((ctx->srp_ctx.a != NULL) &&
167*1f13597dSJung-uk Kim 		 ((s->srp_ctx.a = BN_dup(ctx->srp_ctx.a)) == NULL)) ||
168*1f13597dSJung-uk Kim 		((ctx->srp_ctx.v != NULL) &&
169*1f13597dSJung-uk Kim 		 ((s->srp_ctx.v = BN_dup(ctx->srp_ctx.v)) == NULL)) ||
170*1f13597dSJung-uk Kim 		((ctx->srp_ctx.b != NULL) &&
171*1f13597dSJung-uk Kim 		 ((s->srp_ctx.b = BN_dup(ctx->srp_ctx.b)) == NULL)))
172*1f13597dSJung-uk Kim 		{
173*1f13597dSJung-uk Kim 		SSLerr(SSL_F_SSL_SRP_CTX_INIT,ERR_R_BN_LIB);
174*1f13597dSJung-uk Kim 		goto err;
175*1f13597dSJung-uk Kim 		}
176*1f13597dSJung-uk Kim 	if ((ctx->srp_ctx.login != NULL) &&
177*1f13597dSJung-uk Kim 		((s->srp_ctx.login = BUF_strdup(ctx->srp_ctx.login)) == NULL))
178*1f13597dSJung-uk Kim 		{
179*1f13597dSJung-uk Kim 		SSLerr(SSL_F_SSL_SRP_CTX_INIT,ERR_R_INTERNAL_ERROR);
180*1f13597dSJung-uk Kim 		goto err;
181*1f13597dSJung-uk Kim 		}
182*1f13597dSJung-uk Kim 	s->srp_ctx.srp_Mask = ctx->srp_ctx.srp_Mask;
183*1f13597dSJung-uk Kim 
184*1f13597dSJung-uk Kim 	return (1);
185*1f13597dSJung-uk Kim err:
186*1f13597dSJung-uk Kim 	OPENSSL_free(s->srp_ctx.login);
187*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.N);
188*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.g);
189*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.s);
190*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.B);
191*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.A);
192*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.a);
193*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.b);
194*1f13597dSJung-uk Kim 	BN_free(s->srp_ctx.v);
195*1f13597dSJung-uk Kim 	return (0);
196*1f13597dSJung-uk Kim 	}
197*1f13597dSJung-uk Kim 
198*1f13597dSJung-uk Kim int SSL_CTX_SRP_CTX_init(struct ssl_ctx_st *ctx)
199*1f13597dSJung-uk Kim 	{
200*1f13597dSJung-uk Kim 	if (ctx == NULL)
201*1f13597dSJung-uk Kim 		return 0;
202*1f13597dSJung-uk Kim 
203*1f13597dSJung-uk Kim 	ctx->srp_ctx.SRP_cb_arg = NULL;
204*1f13597dSJung-uk Kim 	/* set client Hello login callback */
205*1f13597dSJung-uk Kim 	ctx->srp_ctx.TLS_ext_srp_username_callback = NULL;
206*1f13597dSJung-uk Kim 	/* set SRP N/g param callback for verification */
207*1f13597dSJung-uk Kim 	ctx->srp_ctx.SRP_verify_param_callback = NULL;
208*1f13597dSJung-uk Kim 	/* set SRP client passwd callback */
209*1f13597dSJung-uk Kim 	ctx->srp_ctx.SRP_give_srp_client_pwd_callback = NULL;
210*1f13597dSJung-uk Kim 
211*1f13597dSJung-uk Kim 	ctx->srp_ctx.N = NULL;
212*1f13597dSJung-uk Kim 	ctx->srp_ctx.g = NULL;
213*1f13597dSJung-uk Kim 	ctx->srp_ctx.s = NULL;
214*1f13597dSJung-uk Kim 	ctx->srp_ctx.B = NULL;
215*1f13597dSJung-uk Kim 	ctx->srp_ctx.A = NULL;
216*1f13597dSJung-uk Kim 	ctx->srp_ctx.a = NULL;
217*1f13597dSJung-uk Kim 	ctx->srp_ctx.b = NULL;
218*1f13597dSJung-uk Kim 	ctx->srp_ctx.v = NULL;
219*1f13597dSJung-uk Kim 	ctx->srp_ctx.login = NULL;
220*1f13597dSJung-uk Kim 	ctx->srp_ctx.srp_Mask = 0;
221*1f13597dSJung-uk Kim 	ctx->srp_ctx.info = NULL;
222*1f13597dSJung-uk Kim 	ctx->srp_ctx.strength = SRP_MINIMAL_N;
223*1f13597dSJung-uk Kim 
224*1f13597dSJung-uk Kim 	return (1);
225*1f13597dSJung-uk Kim 	}
226*1f13597dSJung-uk Kim 
227*1f13597dSJung-uk Kim /* server side */
228*1f13597dSJung-uk Kim int SSL_srp_server_param_with_username(SSL *s, int *ad)
229*1f13597dSJung-uk Kim 	{
230*1f13597dSJung-uk Kim 	unsigned char b[SSL_MAX_MASTER_KEY_LENGTH];
231*1f13597dSJung-uk Kim 	int al;
232*1f13597dSJung-uk Kim 
233*1f13597dSJung-uk Kim 	*ad = SSL_AD_UNKNOWN_PSK_IDENTITY;
234*1f13597dSJung-uk Kim 	if ((s->srp_ctx.TLS_ext_srp_username_callback !=NULL) &&
235*1f13597dSJung-uk Kim 		((al = s->srp_ctx.TLS_ext_srp_username_callback(s, ad, s->srp_ctx.SRP_cb_arg))!=SSL_ERROR_NONE))
236*1f13597dSJung-uk Kim 			return al;
237*1f13597dSJung-uk Kim 
238*1f13597dSJung-uk Kim 	*ad = SSL_AD_INTERNAL_ERROR;
239*1f13597dSJung-uk Kim 	if ((s->srp_ctx.N == NULL) ||
240*1f13597dSJung-uk Kim 		(s->srp_ctx.g == NULL) ||
241*1f13597dSJung-uk Kim 		(s->srp_ctx.s == NULL) ||
242*1f13597dSJung-uk Kim 		(s->srp_ctx.v == NULL))
243*1f13597dSJung-uk Kim 		return SSL3_AL_FATAL;
244*1f13597dSJung-uk Kim 
245*1f13597dSJung-uk Kim 	RAND_bytes(b, sizeof(b));
246*1f13597dSJung-uk Kim 	s->srp_ctx.b = BN_bin2bn(b,sizeof(b),NULL);
247*1f13597dSJung-uk Kim 	OPENSSL_cleanse(b,sizeof(b));
248*1f13597dSJung-uk Kim 
249*1f13597dSJung-uk Kim 	/* Calculate:  B = (kv + g^b) % N  */
250*1f13597dSJung-uk Kim 
251*1f13597dSJung-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)?
252*1f13597dSJung-uk Kim 			SSL_ERROR_NONE:SSL3_AL_FATAL;
253*1f13597dSJung-uk Kim 	}
254*1f13597dSJung-uk Kim 
255*1f13597dSJung-uk Kim /* If the server just has the raw password, make up a verifier entry on the fly */
256*1f13597dSJung-uk Kim int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass, const char *grp)
257*1f13597dSJung-uk Kim 	{
258*1f13597dSJung-uk Kim 	SRP_gN *GN = SRP_get_default_gN(grp);
259*1f13597dSJung-uk Kim 	if(GN == NULL) return -1;
260*1f13597dSJung-uk Kim 	s->srp_ctx.N = BN_dup(GN->N);
261*1f13597dSJung-uk Kim 	s->srp_ctx.g = BN_dup(GN->g);
262*1f13597dSJung-uk Kim 	if(s->srp_ctx.v != NULL)
263*1f13597dSJung-uk Kim 		{
264*1f13597dSJung-uk Kim 		BN_clear_free(s->srp_ctx.v);
265*1f13597dSJung-uk Kim 		s->srp_ctx.v = NULL;
266*1f13597dSJung-uk Kim 		}
267*1f13597dSJung-uk Kim 	if(s->srp_ctx.s != NULL)
268*1f13597dSJung-uk Kim 		{
269*1f13597dSJung-uk Kim 		BN_clear_free(s->srp_ctx.s);
270*1f13597dSJung-uk Kim 		s->srp_ctx.s = NULL;
271*1f13597dSJung-uk Kim 		}
272*1f13597dSJung-uk Kim 	if(!SRP_create_verifier_BN(user, pass, &s->srp_ctx.s, &s->srp_ctx.v, GN->N, GN->g)) return -1;
273*1f13597dSJung-uk Kim 
274*1f13597dSJung-uk Kim 	return 1;
275*1f13597dSJung-uk Kim 	}
276*1f13597dSJung-uk Kim 
277*1f13597dSJung-uk Kim int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
278*1f13597dSJung-uk Kim 			     BIGNUM *sa, BIGNUM *v, char *info)
279*1f13597dSJung-uk Kim 	{
280*1f13597dSJung-uk Kim 	if (N!= NULL)
281*1f13597dSJung-uk Kim 		{
282*1f13597dSJung-uk Kim 		if (s->srp_ctx.N != NULL)
283*1f13597dSJung-uk Kim 			{
284*1f13597dSJung-uk Kim 			if (!BN_copy(s->srp_ctx.N,N))
285*1f13597dSJung-uk Kim 				{
286*1f13597dSJung-uk Kim 				BN_free(s->srp_ctx.N);
287*1f13597dSJung-uk Kim 				s->srp_ctx.N = NULL;
288*1f13597dSJung-uk Kim 				}
289*1f13597dSJung-uk Kim 			}
290*1f13597dSJung-uk Kim 		else
291*1f13597dSJung-uk Kim 			s->srp_ctx.N = BN_dup(N);
292*1f13597dSJung-uk Kim 		}
293*1f13597dSJung-uk Kim 	if (g!= NULL)
294*1f13597dSJung-uk Kim 		{
295*1f13597dSJung-uk Kim 		if (s->srp_ctx.g != NULL)
296*1f13597dSJung-uk Kim 			{
297*1f13597dSJung-uk Kim 			if (!BN_copy(s->srp_ctx.g,g))
298*1f13597dSJung-uk Kim 				{
299*1f13597dSJung-uk Kim 				BN_free(s->srp_ctx.g);
300*1f13597dSJung-uk Kim 				s->srp_ctx.g = NULL;
301*1f13597dSJung-uk Kim 				}
302*1f13597dSJung-uk Kim 			}
303*1f13597dSJung-uk Kim 		else
304*1f13597dSJung-uk Kim 			s->srp_ctx.g = BN_dup(g);
305*1f13597dSJung-uk Kim 		}
306*1f13597dSJung-uk Kim 	if (sa!= NULL)
307*1f13597dSJung-uk Kim 		{
308*1f13597dSJung-uk Kim 		if (s->srp_ctx.s != NULL)
309*1f13597dSJung-uk Kim 			{
310*1f13597dSJung-uk Kim 			if (!BN_copy(s->srp_ctx.s,sa))
311*1f13597dSJung-uk Kim 				{
312*1f13597dSJung-uk Kim 				BN_free(s->srp_ctx.s);
313*1f13597dSJung-uk Kim 				s->srp_ctx.s = NULL;
314*1f13597dSJung-uk Kim 				}
315*1f13597dSJung-uk Kim 			}
316*1f13597dSJung-uk Kim 		else
317*1f13597dSJung-uk Kim 			s->srp_ctx.s = BN_dup(sa);
318*1f13597dSJung-uk Kim 		}
319*1f13597dSJung-uk Kim 	if (v!= NULL)
320*1f13597dSJung-uk Kim 		{
321*1f13597dSJung-uk Kim 		if (s->srp_ctx.v != NULL)
322*1f13597dSJung-uk Kim 			{
323*1f13597dSJung-uk Kim 			if (!BN_copy(s->srp_ctx.v,v))
324*1f13597dSJung-uk Kim 				{
325*1f13597dSJung-uk Kim 				BN_free(s->srp_ctx.v);
326*1f13597dSJung-uk Kim 				s->srp_ctx.v = NULL;
327*1f13597dSJung-uk Kim 				}
328*1f13597dSJung-uk Kim 			}
329*1f13597dSJung-uk Kim 		else
330*1f13597dSJung-uk Kim 			s->srp_ctx.v = BN_dup(v);
331*1f13597dSJung-uk Kim 		}
332*1f13597dSJung-uk Kim 	s->srp_ctx.info = info;
333*1f13597dSJung-uk Kim 
334*1f13597dSJung-uk Kim 	if (!(s->srp_ctx.N) ||
335*1f13597dSJung-uk Kim 		!(s->srp_ctx.g) ||
336*1f13597dSJung-uk Kim 		!(s->srp_ctx.s) ||
337*1f13597dSJung-uk Kim 		!(s->srp_ctx.v))
338*1f13597dSJung-uk Kim 		return -1;
339*1f13597dSJung-uk Kim 
340*1f13597dSJung-uk Kim 	return 1;
341*1f13597dSJung-uk Kim 	}
342*1f13597dSJung-uk Kim 
343*1f13597dSJung-uk Kim int SRP_generate_server_master_secret(SSL *s,unsigned char *master_key)
344*1f13597dSJung-uk Kim 	{
345*1f13597dSJung-uk Kim 	BIGNUM *K = NULL, *u = NULL;
346*1f13597dSJung-uk Kim 	int ret = -1, tmp_len;
347*1f13597dSJung-uk Kim 	unsigned char *tmp = NULL;
348*1f13597dSJung-uk Kim 
349*1f13597dSJung-uk Kim 	if (!SRP_Verify_A_mod_N(s->srp_ctx.A,s->srp_ctx.N))
350*1f13597dSJung-uk Kim 		goto err;
351*1f13597dSJung-uk Kim 	if (!(u = SRP_Calc_u(s->srp_ctx.A,s->srp_ctx.B,s->srp_ctx.N)))
352*1f13597dSJung-uk Kim 		goto err;
353*1f13597dSJung-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)))
354*1f13597dSJung-uk Kim 		goto err;
355*1f13597dSJung-uk Kim 
356*1f13597dSJung-uk Kim 	tmp_len = BN_num_bytes(K);
357*1f13597dSJung-uk Kim 	if ((tmp = OPENSSL_malloc(tmp_len)) == NULL)
358*1f13597dSJung-uk Kim 		goto err;
359*1f13597dSJung-uk Kim 	BN_bn2bin(K, tmp);
360*1f13597dSJung-uk Kim 	ret = s->method->ssl3_enc->generate_master_secret(s,master_key,tmp,tmp_len);
361*1f13597dSJung-uk Kim err:
362*1f13597dSJung-uk Kim 	if (tmp)
363*1f13597dSJung-uk Kim 		{
364*1f13597dSJung-uk Kim 		OPENSSL_cleanse(tmp,tmp_len) ;
365*1f13597dSJung-uk Kim 		OPENSSL_free(tmp);
366*1f13597dSJung-uk Kim 		}
367*1f13597dSJung-uk Kim 	BN_clear_free(K);
368*1f13597dSJung-uk Kim 	BN_clear_free(u);
369*1f13597dSJung-uk Kim 	return ret;
370*1f13597dSJung-uk Kim 	}
371*1f13597dSJung-uk Kim 
372*1f13597dSJung-uk Kim /* client side */
373*1f13597dSJung-uk Kim int SRP_generate_client_master_secret(SSL *s,unsigned char *master_key)
374*1f13597dSJung-uk Kim 	{
375*1f13597dSJung-uk Kim 	BIGNUM *x = NULL, *u = NULL, *K = NULL;
376*1f13597dSJung-uk Kim 	int ret = -1, tmp_len;
377*1f13597dSJung-uk Kim 	char *passwd = NULL;
378*1f13597dSJung-uk Kim 	unsigned char *tmp = NULL;
379*1f13597dSJung-uk Kim 
380*1f13597dSJung-uk Kim 	/* Checks if b % n == 0
381*1f13597dSJung-uk Kim 	 */
382*1f13597dSJung-uk Kim 	if (SRP_Verify_B_mod_N(s->srp_ctx.B,s->srp_ctx.N)==0) goto err;
383*1f13597dSJung-uk Kim 	if (!(u = SRP_Calc_u(s->srp_ctx.A,s->srp_ctx.B,s->srp_ctx.N))) goto err;
384*1f13597dSJung-uk Kim 	if (s->srp_ctx.SRP_give_srp_client_pwd_callback == NULL) goto err;
385*1f13597dSJung-uk Kim 	if (!(passwd = s->srp_ctx.SRP_give_srp_client_pwd_callback(s, s->srp_ctx.SRP_cb_arg))) goto err;
386*1f13597dSJung-uk Kim 	if (!(x = SRP_Calc_x(s->srp_ctx.s,s->srp_ctx.login,passwd))) goto err;
387*1f13597dSJung-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;
388*1f13597dSJung-uk Kim 
389*1f13597dSJung-uk Kim 	tmp_len = BN_num_bytes(K);
390*1f13597dSJung-uk Kim 	if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) goto err;
391*1f13597dSJung-uk Kim 	BN_bn2bin(K, tmp);
392*1f13597dSJung-uk Kim 	ret = s->method->ssl3_enc->generate_master_secret(s,master_key,tmp,tmp_len);
393*1f13597dSJung-uk Kim err:
394*1f13597dSJung-uk Kim 	if (tmp)
395*1f13597dSJung-uk Kim 		{
396*1f13597dSJung-uk Kim 		OPENSSL_cleanse(tmp,tmp_len) ;
397*1f13597dSJung-uk Kim 		OPENSSL_free(tmp);
398*1f13597dSJung-uk Kim 		}
399*1f13597dSJung-uk Kim 	BN_clear_free(K);
400*1f13597dSJung-uk Kim 	BN_clear_free(x);
401*1f13597dSJung-uk Kim 	if (passwd)
402*1f13597dSJung-uk Kim 		{
403*1f13597dSJung-uk Kim 		OPENSSL_cleanse(passwd,strlen(passwd)) ;
404*1f13597dSJung-uk Kim 		OPENSSL_free(passwd);
405*1f13597dSJung-uk Kim 		}
406*1f13597dSJung-uk Kim 	BN_clear_free(u);
407*1f13597dSJung-uk Kim 	return ret;
408*1f13597dSJung-uk Kim 	}
409*1f13597dSJung-uk Kim 
410*1f13597dSJung-uk Kim int SRP_Calc_A_param(SSL *s)
411*1f13597dSJung-uk Kim 	{
412*1f13597dSJung-uk Kim 	unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH];
413*1f13597dSJung-uk Kim 
414*1f13597dSJung-uk Kim 	if (BN_num_bits(s->srp_ctx.N) < s->srp_ctx.strength)
415*1f13597dSJung-uk Kim 		return -1;
416*1f13597dSJung-uk Kim 
417*1f13597dSJung-uk Kim 	if (s->srp_ctx.SRP_verify_param_callback ==NULL &&
418*1f13597dSJung-uk Kim 		!SRP_check_known_gN_param(s->srp_ctx.g,s->srp_ctx.N))
419*1f13597dSJung-uk Kim 		return -1 ;
420*1f13597dSJung-uk Kim 
421*1f13597dSJung-uk Kim 	RAND_bytes(rnd, sizeof(rnd));
422*1f13597dSJung-uk Kim 	s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a);
423*1f13597dSJung-uk Kim 	OPENSSL_cleanse(rnd, sizeof(rnd));
424*1f13597dSJung-uk Kim 
425*1f13597dSJung-uk Kim 	if (!(s->srp_ctx.A = SRP_Calc_A(s->srp_ctx.a,s->srp_ctx.N,s->srp_ctx.g)))
426*1f13597dSJung-uk Kim 		return -1;
427*1f13597dSJung-uk Kim 
428*1f13597dSJung-uk Kim 	/* We can have a callback to verify SRP param!! */
429*1f13597dSJung-uk Kim 	if (s->srp_ctx.SRP_verify_param_callback !=NULL)
430*1f13597dSJung-uk Kim 		return s->srp_ctx.SRP_verify_param_callback(s,s->srp_ctx.SRP_cb_arg);
431*1f13597dSJung-uk Kim 
432*1f13597dSJung-uk Kim 	return 1;
433*1f13597dSJung-uk Kim 	}
434*1f13597dSJung-uk Kim 
435*1f13597dSJung-uk Kim BIGNUM *SSL_get_srp_g(SSL *s)
436*1f13597dSJung-uk Kim 	{
437*1f13597dSJung-uk Kim 	if (s->srp_ctx.g != NULL)
438*1f13597dSJung-uk Kim 		return s->srp_ctx.g;
439*1f13597dSJung-uk Kim 	return s->ctx->srp_ctx.g;
440*1f13597dSJung-uk Kim 	}
441*1f13597dSJung-uk Kim 
442*1f13597dSJung-uk Kim BIGNUM *SSL_get_srp_N(SSL *s)
443*1f13597dSJung-uk Kim 	{
444*1f13597dSJung-uk Kim 	if (s->srp_ctx.N != NULL)
445*1f13597dSJung-uk Kim 		return s->srp_ctx.N;
446*1f13597dSJung-uk Kim 	return s->ctx->srp_ctx.N;
447*1f13597dSJung-uk Kim 	}
448*1f13597dSJung-uk Kim 
449*1f13597dSJung-uk Kim char *SSL_get_srp_username(SSL *s)
450*1f13597dSJung-uk Kim 	{
451*1f13597dSJung-uk Kim 	if (s->srp_ctx.login != NULL)
452*1f13597dSJung-uk Kim 		return s->srp_ctx.login;
453*1f13597dSJung-uk Kim 	return s->ctx->srp_ctx.login;
454*1f13597dSJung-uk Kim 	}
455*1f13597dSJung-uk Kim 
456*1f13597dSJung-uk Kim char *SSL_get_srp_userinfo(SSL *s)
457*1f13597dSJung-uk Kim 	{
458*1f13597dSJung-uk Kim 	if (s->srp_ctx.info != NULL)
459*1f13597dSJung-uk Kim 		return s->srp_ctx.info;
460*1f13597dSJung-uk Kim 	return s->ctx->srp_ctx.info;
461*1f13597dSJung-uk Kim 	}
462*1f13597dSJung-uk Kim 
463*1f13597dSJung-uk Kim #define tls1_ctx_ctrl ssl3_ctx_ctrl
464*1f13597dSJung-uk Kim #define tls1_ctx_callback_ctrl ssl3_ctx_callback_ctrl
465*1f13597dSJung-uk Kim 
466*1f13597dSJung-uk Kim int SSL_CTX_set_srp_username(SSL_CTX *ctx,char *name)
467*1f13597dSJung-uk Kim 	{
468*1f13597dSJung-uk Kim 	return tls1_ctx_ctrl(ctx,SSL_CTRL_SET_TLS_EXT_SRP_USERNAME,0,name);
469*1f13597dSJung-uk Kim 	}
470*1f13597dSJung-uk Kim 
471*1f13597dSJung-uk Kim int SSL_CTX_set_srp_password(SSL_CTX *ctx,char *password)
472*1f13597dSJung-uk Kim 	{
473*1f13597dSJung-uk Kim 	return tls1_ctx_ctrl(ctx,SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD,0,password);
474*1f13597dSJung-uk Kim 	}
475*1f13597dSJung-uk Kim 
476*1f13597dSJung-uk Kim int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength)
477*1f13597dSJung-uk Kim 	{
478*1f13597dSJung-uk Kim 	return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH, strength,
479*1f13597dSJung-uk Kim 			     NULL);
480*1f13597dSJung-uk Kim 	}
481*1f13597dSJung-uk Kim 
482*1f13597dSJung-uk Kim int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx, int (*cb)(SSL *,void *))
483*1f13597dSJung-uk Kim 	{
484*1f13597dSJung-uk Kim 	return tls1_ctx_callback_ctrl(ctx,SSL_CTRL_SET_SRP_VERIFY_PARAM_CB,
485*1f13597dSJung-uk Kim 				      (void (*)(void))cb);
486*1f13597dSJung-uk Kim 	}
487*1f13597dSJung-uk Kim 
488*1f13597dSJung-uk Kim int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg)
489*1f13597dSJung-uk Kim 	{
490*1f13597dSJung-uk Kim 	return tls1_ctx_ctrl(ctx,SSL_CTRL_SET_SRP_ARG,0,arg);
491*1f13597dSJung-uk Kim 	}
492*1f13597dSJung-uk Kim 
493*1f13597dSJung-uk Kim int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
494*1f13597dSJung-uk Kim 				      int (*cb)(SSL *,int *,void *))
495*1f13597dSJung-uk Kim 	{
496*1f13597dSJung-uk Kim 	return tls1_ctx_callback_ctrl(ctx,SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB,
497*1f13597dSJung-uk Kim 				      (void (*)(void))cb);
498*1f13597dSJung-uk Kim 	}
499*1f13597dSJung-uk Kim 
500*1f13597dSJung-uk Kim int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx, char *(*cb)(SSL *,void *))
501*1f13597dSJung-uk Kim 	{
502*1f13597dSJung-uk Kim 	return tls1_ctx_callback_ctrl(ctx,SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB,
503*1f13597dSJung-uk Kim 				      (void (*)(void))cb);
504*1f13597dSJung-uk Kim 	}
505*1f13597dSJung-uk Kim 
506*1f13597dSJung-uk Kim #endif
507