16f9291ceSJung-uk Kim /*
2*b077aed3SPierre Pronchery * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
3e71b7053SJung-uk Kim * Copyright (c) 2004, EdelKey Project. All Rights Reserved.
4e71b7053SJung-uk Kim *
5*b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
6e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy
7e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at
8e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html
9e71b7053SJung-uk Kim *
10e71b7053SJung-uk Kim * Originally written by Christophe Renou and Peter Sylvester,
11e71b7053SJung-uk Kim * for the EdelKey project.
121f13597dSJung-uk Kim */
131f13597dSJung-uk Kim
14*b077aed3SPierre Pronchery /*
15*b077aed3SPierre Pronchery * We need to use the SRP deprecated APIs in order to implement the SSL SRP
16*b077aed3SPierre Pronchery * APIs - which are themselves deprecated.
17*b077aed3SPierre Pronchery */
18*b077aed3SPierre Pronchery #define OPENSSL_SUPPRESS_DEPRECATED
19*b077aed3SPierre Pronchery
20e71b7053SJung-uk Kim #include <openssl/crypto.h>
211f13597dSJung-uk Kim #include <openssl/rand.h>
221f13597dSJung-uk Kim #include <openssl/err.h>
2317f01e99SJung-uk Kim #include "ssl_local.h"
24e71b7053SJung-uk Kim
25e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SRP
26e71b7053SJung-uk Kim # include <openssl/srp.h>
271f13597dSJung-uk Kim
28*b077aed3SPierre Pronchery /*
29*b077aed3SPierre Pronchery * The public API SSL_CTX_SRP_CTX_free() is deprecated so we use
30*b077aed3SPierre Pronchery * ssl_ctx_srp_ctx_free_intern() internally.
31*b077aed3SPierre Pronchery */
ssl_ctx_srp_ctx_free_intern(SSL_CTX * ctx)32*b077aed3SPierre Pronchery int ssl_ctx_srp_ctx_free_intern(SSL_CTX *ctx)
331f13597dSJung-uk Kim {
341f13597dSJung-uk Kim if (ctx == NULL)
351f13597dSJung-uk Kim return 0;
361f13597dSJung-uk Kim OPENSSL_free(ctx->srp_ctx.login);
37e71b7053SJung-uk Kim OPENSSL_free(ctx->srp_ctx.info);
381f13597dSJung-uk Kim BN_free(ctx->srp_ctx.N);
391f13597dSJung-uk Kim BN_free(ctx->srp_ctx.g);
401f13597dSJung-uk Kim BN_free(ctx->srp_ctx.s);
411f13597dSJung-uk Kim BN_free(ctx->srp_ctx.B);
421f13597dSJung-uk Kim BN_free(ctx->srp_ctx.A);
431f13597dSJung-uk Kim BN_free(ctx->srp_ctx.a);
441f13597dSJung-uk Kim BN_free(ctx->srp_ctx.b);
451f13597dSJung-uk Kim BN_free(ctx->srp_ctx.v);
46e71b7053SJung-uk Kim memset(&ctx->srp_ctx, 0, sizeof(ctx->srp_ctx));
471f13597dSJung-uk Kim ctx->srp_ctx.strength = SRP_MINIMAL_N;
48e71b7053SJung-uk Kim return 1;
491f13597dSJung-uk Kim }
501f13597dSJung-uk Kim
SSL_CTX_SRP_CTX_free(SSL_CTX * ctx)51*b077aed3SPierre Pronchery int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx)
52*b077aed3SPierre Pronchery {
53*b077aed3SPierre Pronchery return ssl_ctx_srp_ctx_free_intern(ctx);
54*b077aed3SPierre Pronchery }
55*b077aed3SPierre Pronchery
56*b077aed3SPierre Pronchery /*
57*b077aed3SPierre Pronchery * The public API SSL_SRP_CTX_free() is deprecated so we use
58*b077aed3SPierre Pronchery * ssl_srp_ctx_free_intern() internally.
59*b077aed3SPierre Pronchery */
ssl_srp_ctx_free_intern(SSL * s)60*b077aed3SPierre Pronchery int ssl_srp_ctx_free_intern(SSL *s)
611f13597dSJung-uk Kim {
621f13597dSJung-uk Kim if (s == NULL)
631f13597dSJung-uk Kim return 0;
641f13597dSJung-uk Kim OPENSSL_free(s->srp_ctx.login);
65e71b7053SJung-uk Kim OPENSSL_free(s->srp_ctx.info);
661f13597dSJung-uk Kim BN_free(s->srp_ctx.N);
671f13597dSJung-uk Kim BN_free(s->srp_ctx.g);
681f13597dSJung-uk Kim BN_free(s->srp_ctx.s);
691f13597dSJung-uk Kim BN_free(s->srp_ctx.B);
701f13597dSJung-uk Kim BN_free(s->srp_ctx.A);
711f13597dSJung-uk Kim BN_free(s->srp_ctx.a);
721f13597dSJung-uk Kim BN_free(s->srp_ctx.b);
731f13597dSJung-uk Kim BN_free(s->srp_ctx.v);
74e71b7053SJung-uk Kim memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
751f13597dSJung-uk Kim s->srp_ctx.strength = SRP_MINIMAL_N;
76e71b7053SJung-uk Kim return 1;
771f13597dSJung-uk Kim }
781f13597dSJung-uk Kim
SSL_SRP_CTX_free(SSL * s)79*b077aed3SPierre Pronchery int SSL_SRP_CTX_free(SSL *s)
80*b077aed3SPierre Pronchery {
81*b077aed3SPierre Pronchery return ssl_srp_ctx_free_intern(s);
82*b077aed3SPierre Pronchery }
83*b077aed3SPierre Pronchery
84*b077aed3SPierre Pronchery /*
85*b077aed3SPierre Pronchery * The public API SSL_SRP_CTX_init() is deprecated so we use
86*b077aed3SPierre Pronchery * ssl_srp_ctx_init_intern() internally.
87*b077aed3SPierre Pronchery */
ssl_srp_ctx_init_intern(SSL * s)88*b077aed3SPierre Pronchery int ssl_srp_ctx_init_intern(SSL *s)
891f13597dSJung-uk Kim {
901f13597dSJung-uk Kim SSL_CTX *ctx;
911f13597dSJung-uk Kim
921f13597dSJung-uk Kim if ((s == NULL) || ((ctx = s->ctx) == NULL))
931f13597dSJung-uk Kim return 0;
94e71b7053SJung-uk Kim
95e71b7053SJung-uk Kim memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
96e71b7053SJung-uk Kim
971f13597dSJung-uk Kim s->srp_ctx.SRP_cb_arg = ctx->srp_ctx.SRP_cb_arg;
981f13597dSJung-uk Kim /* set client Hello login callback */
996f9291ceSJung-uk Kim s->srp_ctx.TLS_ext_srp_username_callback =
1006f9291ceSJung-uk Kim ctx->srp_ctx.TLS_ext_srp_username_callback;
1011f13597dSJung-uk Kim /* set SRP N/g param callback for verification */
1026f9291ceSJung-uk Kim s->srp_ctx.SRP_verify_param_callback =
1036f9291ceSJung-uk Kim ctx->srp_ctx.SRP_verify_param_callback;
1041f13597dSJung-uk Kim /* set SRP client passwd callback */
1056f9291ceSJung-uk Kim s->srp_ctx.SRP_give_srp_client_pwd_callback =
1066f9291ceSJung-uk Kim ctx->srp_ctx.SRP_give_srp_client_pwd_callback;
1071f13597dSJung-uk Kim
1081f13597dSJung-uk Kim s->srp_ctx.strength = ctx->srp_ctx.strength;
1091f13597dSJung-uk Kim
1101f13597dSJung-uk Kim if (((ctx->srp_ctx.N != NULL) &&
1111f13597dSJung-uk Kim ((s->srp_ctx.N = BN_dup(ctx->srp_ctx.N)) == NULL)) ||
1121f13597dSJung-uk Kim ((ctx->srp_ctx.g != NULL) &&
1131f13597dSJung-uk Kim ((s->srp_ctx.g = BN_dup(ctx->srp_ctx.g)) == NULL)) ||
1141f13597dSJung-uk Kim ((ctx->srp_ctx.s != NULL) &&
1151f13597dSJung-uk Kim ((s->srp_ctx.s = BN_dup(ctx->srp_ctx.s)) == NULL)) ||
1161f13597dSJung-uk Kim ((ctx->srp_ctx.B != NULL) &&
1171f13597dSJung-uk Kim ((s->srp_ctx.B = BN_dup(ctx->srp_ctx.B)) == NULL)) ||
1181f13597dSJung-uk Kim ((ctx->srp_ctx.A != NULL) &&
1191f13597dSJung-uk Kim ((s->srp_ctx.A = BN_dup(ctx->srp_ctx.A)) == NULL)) ||
1201f13597dSJung-uk Kim ((ctx->srp_ctx.a != NULL) &&
1211f13597dSJung-uk Kim ((s->srp_ctx.a = BN_dup(ctx->srp_ctx.a)) == NULL)) ||
1221f13597dSJung-uk Kim ((ctx->srp_ctx.v != NULL) &&
1231f13597dSJung-uk Kim ((s->srp_ctx.v = BN_dup(ctx->srp_ctx.v)) == NULL)) ||
1241f13597dSJung-uk Kim ((ctx->srp_ctx.b != NULL) &&
1256f9291ceSJung-uk Kim ((s->srp_ctx.b = BN_dup(ctx->srp_ctx.b)) == NULL))) {
126*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_BN_LIB);
1271f13597dSJung-uk Kim goto err;
1281f13597dSJung-uk Kim }
1291f13597dSJung-uk Kim if ((ctx->srp_ctx.login != NULL) &&
130e71b7053SJung-uk Kim ((s->srp_ctx.login = OPENSSL_strdup(ctx->srp_ctx.login)) == NULL)) {
131*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
132e71b7053SJung-uk Kim goto err;
133e71b7053SJung-uk Kim }
134e71b7053SJung-uk Kim if ((ctx->srp_ctx.info != NULL) &&
135*b077aed3SPierre Pronchery ((s->srp_ctx.info = OPENSSL_strdup(ctx->srp_ctx.info)) == NULL)) {
136*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
1371f13597dSJung-uk Kim goto err;
1381f13597dSJung-uk Kim }
1391f13597dSJung-uk Kim s->srp_ctx.srp_Mask = ctx->srp_ctx.srp_Mask;
1401f13597dSJung-uk Kim
141e71b7053SJung-uk Kim return 1;
1421f13597dSJung-uk Kim err:
1431f13597dSJung-uk Kim OPENSSL_free(s->srp_ctx.login);
144e71b7053SJung-uk Kim OPENSSL_free(s->srp_ctx.info);
1451f13597dSJung-uk Kim BN_free(s->srp_ctx.N);
1461f13597dSJung-uk Kim BN_free(s->srp_ctx.g);
1471f13597dSJung-uk Kim BN_free(s->srp_ctx.s);
1481f13597dSJung-uk Kim BN_free(s->srp_ctx.B);
1491f13597dSJung-uk Kim BN_free(s->srp_ctx.A);
1501f13597dSJung-uk Kim BN_free(s->srp_ctx.a);
1511f13597dSJung-uk Kim BN_free(s->srp_ctx.b);
1521f13597dSJung-uk Kim BN_free(s->srp_ctx.v);
153e71b7053SJung-uk Kim memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
154e71b7053SJung-uk Kim return 0;
1551f13597dSJung-uk Kim }
1561f13597dSJung-uk Kim
SSL_SRP_CTX_init(SSL * s)157*b077aed3SPierre Pronchery int SSL_SRP_CTX_init(SSL *s)
158*b077aed3SPierre Pronchery {
159*b077aed3SPierre Pronchery return ssl_srp_ctx_init_intern(s);
160*b077aed3SPierre Pronchery }
161*b077aed3SPierre Pronchery
162*b077aed3SPierre Pronchery /*
163*b077aed3SPierre Pronchery * The public API SSL_CTX_SRP_CTX_init() is deprecated so we use
164*b077aed3SPierre Pronchery * ssl_ctx_srp_ctx_init_intern() internally.
165*b077aed3SPierre Pronchery */
ssl_ctx_srp_ctx_init_intern(SSL_CTX * ctx)166*b077aed3SPierre Pronchery int ssl_ctx_srp_ctx_init_intern(SSL_CTX *ctx)
1671f13597dSJung-uk Kim {
1681f13597dSJung-uk Kim if (ctx == NULL)
1691f13597dSJung-uk Kim return 0;
1701f13597dSJung-uk Kim
171e71b7053SJung-uk Kim memset(&ctx->srp_ctx, 0, sizeof(ctx->srp_ctx));
1721f13597dSJung-uk Kim ctx->srp_ctx.strength = SRP_MINIMAL_N;
1731f13597dSJung-uk Kim
174e71b7053SJung-uk Kim return 1;
1751f13597dSJung-uk Kim }
1761f13597dSJung-uk Kim
SSL_CTX_SRP_CTX_init(SSL_CTX * ctx)177*b077aed3SPierre Pronchery int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx)
178*b077aed3SPierre Pronchery {
179*b077aed3SPierre Pronchery return ssl_ctx_srp_ctx_init_intern(ctx);
180*b077aed3SPierre Pronchery }
181*b077aed3SPierre Pronchery
1821f13597dSJung-uk Kim /* server side */
183*b077aed3SPierre Pronchery /*
184*b077aed3SPierre Pronchery * The public API SSL_srp_server_param_with_username() is deprecated so we use
185*b077aed3SPierre Pronchery * ssl_srp_server_param_with_username_intern() internally.
186*b077aed3SPierre Pronchery */
ssl_srp_server_param_with_username_intern(SSL * s,int * ad)187*b077aed3SPierre Pronchery int ssl_srp_server_param_with_username_intern(SSL *s, int *ad)
1881f13597dSJung-uk Kim {
1891f13597dSJung-uk Kim unsigned char b[SSL_MAX_MASTER_KEY_LENGTH];
1901f13597dSJung-uk Kim int al;
1911f13597dSJung-uk Kim
1921f13597dSJung-uk Kim *ad = SSL_AD_UNKNOWN_PSK_IDENTITY;
1931f13597dSJung-uk Kim if ((s->srp_ctx.TLS_ext_srp_username_callback != NULL) &&
1946f9291ceSJung-uk Kim ((al =
1956f9291ceSJung-uk Kim s->srp_ctx.TLS_ext_srp_username_callback(s, ad,
1966f9291ceSJung-uk Kim s->srp_ctx.SRP_cb_arg)) !=
1976f9291ceSJung-uk Kim SSL_ERROR_NONE))
1981f13597dSJung-uk Kim return al;
1991f13597dSJung-uk Kim
2001f13597dSJung-uk Kim *ad = SSL_AD_INTERNAL_ERROR;
2011f13597dSJung-uk Kim if ((s->srp_ctx.N == NULL) ||
2021f13597dSJung-uk Kim (s->srp_ctx.g == NULL) ||
2036f9291ceSJung-uk Kim (s->srp_ctx.s == NULL) || (s->srp_ctx.v == NULL))
2041f13597dSJung-uk Kim return SSL3_AL_FATAL;
2051f13597dSJung-uk Kim
206*b077aed3SPierre Pronchery if (RAND_priv_bytes_ex(s->ctx->libctx, b, sizeof(b), 0) <= 0)
20709286989SJung-uk Kim return SSL3_AL_FATAL;
2081f13597dSJung-uk Kim s->srp_ctx.b = BN_bin2bn(b, sizeof(b), NULL);
2091f13597dSJung-uk Kim OPENSSL_cleanse(b, sizeof(b));
2101f13597dSJung-uk Kim
2111f13597dSJung-uk Kim /* Calculate: B = (kv + g^b) % N */
2121f13597dSJung-uk Kim
2136f9291ceSJung-uk Kim return ((s->srp_ctx.B =
214*b077aed3SPierre Pronchery SRP_Calc_B_ex(s->srp_ctx.b, s->srp_ctx.N, s->srp_ctx.g,
215*b077aed3SPierre Pronchery s->srp_ctx.v, s->ctx->libctx, s->ctx->propq)) !=
2166f9291ceSJung-uk Kim NULL) ? SSL_ERROR_NONE : SSL3_AL_FATAL;
2171f13597dSJung-uk Kim }
2181f13597dSJung-uk Kim
SSL_srp_server_param_with_username(SSL * s,int * ad)219*b077aed3SPierre Pronchery int SSL_srp_server_param_with_username(SSL *s, int *ad)
220*b077aed3SPierre Pronchery {
221*b077aed3SPierre Pronchery return ssl_srp_server_param_with_username_intern(s, ad);
222*b077aed3SPierre Pronchery }
223*b077aed3SPierre Pronchery
2246f9291ceSJung-uk Kim /*
2256f9291ceSJung-uk Kim * If the server just has the raw password, make up a verifier entry on the
2266f9291ceSJung-uk Kim * fly
2276f9291ceSJung-uk Kim */
SSL_set_srp_server_param_pw(SSL * s,const char * user,const char * pass,const char * grp)2286f9291ceSJung-uk Kim int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
2296f9291ceSJung-uk Kim const char *grp)
2301f13597dSJung-uk Kim {
2311f13597dSJung-uk Kim SRP_gN *GN = SRP_get_default_gN(grp);
2326f9291ceSJung-uk Kim if (GN == NULL)
2336f9291ceSJung-uk Kim return -1;
2341f13597dSJung-uk Kim s->srp_ctx.N = BN_dup(GN->N);
2351f13597dSJung-uk Kim s->srp_ctx.g = BN_dup(GN->g);
2361f13597dSJung-uk Kim BN_clear_free(s->srp_ctx.v);
2371f13597dSJung-uk Kim s->srp_ctx.v = NULL;
2381f13597dSJung-uk Kim BN_clear_free(s->srp_ctx.s);
2391f13597dSJung-uk Kim s->srp_ctx.s = NULL;
240*b077aed3SPierre Pronchery if (!SRP_create_verifier_BN_ex(user, pass, &s->srp_ctx.s, &s->srp_ctx.v,
241*b077aed3SPierre Pronchery s->srp_ctx.N, s->srp_ctx.g, s->ctx->libctx,
242*b077aed3SPierre Pronchery s->ctx->propq))
2436f9291ceSJung-uk Kim return -1;
2441f13597dSJung-uk Kim
2451f13597dSJung-uk Kim return 1;
2461f13597dSJung-uk Kim }
2471f13597dSJung-uk Kim
SSL_set_srp_server_param(SSL * s,const BIGNUM * N,const BIGNUM * g,BIGNUM * sa,BIGNUM * v,char * info)2481f13597dSJung-uk Kim int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
2491f13597dSJung-uk Kim BIGNUM *sa, BIGNUM *v, char *info)
2501f13597dSJung-uk Kim {
2516f9291ceSJung-uk Kim if (N != NULL) {
2526f9291ceSJung-uk Kim if (s->srp_ctx.N != NULL) {
2536f9291ceSJung-uk Kim if (!BN_copy(s->srp_ctx.N, N)) {
2541f13597dSJung-uk Kim BN_free(s->srp_ctx.N);
2551f13597dSJung-uk Kim s->srp_ctx.N = NULL;
2561f13597dSJung-uk Kim }
2576f9291ceSJung-uk Kim } else
2581f13597dSJung-uk Kim s->srp_ctx.N = BN_dup(N);
2591f13597dSJung-uk Kim }
2606f9291ceSJung-uk Kim if (g != NULL) {
2616f9291ceSJung-uk Kim if (s->srp_ctx.g != NULL) {
2626f9291ceSJung-uk Kim if (!BN_copy(s->srp_ctx.g, g)) {
2631f13597dSJung-uk Kim BN_free(s->srp_ctx.g);
2641f13597dSJung-uk Kim s->srp_ctx.g = NULL;
2651f13597dSJung-uk Kim }
2666f9291ceSJung-uk Kim } else
2671f13597dSJung-uk Kim s->srp_ctx.g = BN_dup(g);
2681f13597dSJung-uk Kim }
2696f9291ceSJung-uk Kim if (sa != NULL) {
2706f9291ceSJung-uk Kim if (s->srp_ctx.s != NULL) {
2716f9291ceSJung-uk Kim if (!BN_copy(s->srp_ctx.s, sa)) {
2721f13597dSJung-uk Kim BN_free(s->srp_ctx.s);
2731f13597dSJung-uk Kim s->srp_ctx.s = NULL;
2741f13597dSJung-uk Kim }
2756f9291ceSJung-uk Kim } else
2761f13597dSJung-uk Kim s->srp_ctx.s = BN_dup(sa);
2771f13597dSJung-uk Kim }
2786f9291ceSJung-uk Kim if (v != NULL) {
2796f9291ceSJung-uk Kim if (s->srp_ctx.v != NULL) {
2806f9291ceSJung-uk Kim if (!BN_copy(s->srp_ctx.v, v)) {
2811f13597dSJung-uk Kim BN_free(s->srp_ctx.v);
2821f13597dSJung-uk Kim s->srp_ctx.v = NULL;
2831f13597dSJung-uk Kim }
2846f9291ceSJung-uk Kim } else
2851f13597dSJung-uk Kim s->srp_ctx.v = BN_dup(v);
2861f13597dSJung-uk Kim }
287e71b7053SJung-uk Kim if (info != NULL) {
288e71b7053SJung-uk Kim if (s->srp_ctx.info)
289e71b7053SJung-uk Kim OPENSSL_free(s->srp_ctx.info);
290*b077aed3SPierre Pronchery if ((s->srp_ctx.info = OPENSSL_strdup(info)) == NULL)
291e71b7053SJung-uk Kim return -1;
292e71b7053SJung-uk Kim }
2931f13597dSJung-uk Kim
2941f13597dSJung-uk Kim if (!(s->srp_ctx.N) ||
2956f9291ceSJung-uk Kim !(s->srp_ctx.g) || !(s->srp_ctx.s) || !(s->srp_ctx.v))
2961f13597dSJung-uk Kim return -1;
2971f13597dSJung-uk Kim
2981f13597dSJung-uk Kim return 1;
2991f13597dSJung-uk Kim }
3001f13597dSJung-uk Kim
srp_generate_server_master_secret(SSL * s)301e71b7053SJung-uk Kim int srp_generate_server_master_secret(SSL *s)
3021f13597dSJung-uk Kim {
3031f13597dSJung-uk Kim BIGNUM *K = NULL, *u = NULL;
304*b077aed3SPierre Pronchery int ret = 0, tmp_len = 0;
3051f13597dSJung-uk Kim unsigned char *tmp = NULL;
3061f13597dSJung-uk Kim
3071f13597dSJung-uk Kim if (!SRP_Verify_A_mod_N(s->srp_ctx.A, s->srp_ctx.N))
3081f13597dSJung-uk Kim goto err;
309*b077aed3SPierre Pronchery if ((u = SRP_Calc_u_ex(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N,
310*b077aed3SPierre Pronchery s->ctx->libctx, s->ctx->propq)) == NULL)
3111f13597dSJung-uk Kim goto err;
312e71b7053SJung-uk Kim if ((K = SRP_Calc_server_key(s->srp_ctx.A, s->srp_ctx.v, u, s->srp_ctx.b,
313e71b7053SJung-uk Kim s->srp_ctx.N)) == NULL)
3141f13597dSJung-uk Kim goto err;
3151f13597dSJung-uk Kim
3161f13597dSJung-uk Kim tmp_len = BN_num_bytes(K);
317e71b7053SJung-uk Kim if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) {
318*b077aed3SPierre Pronchery SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
3191f13597dSJung-uk Kim goto err;
3201f13597dSJung-uk Kim }
321e71b7053SJung-uk Kim BN_bn2bin(K, tmp);
322e71b7053SJung-uk Kim /* Calls SSLfatal() as required */
323e71b7053SJung-uk Kim ret = ssl_generate_master_secret(s, tmp, tmp_len, 1);
324e71b7053SJung-uk Kim err:
3251f13597dSJung-uk Kim BN_clear_free(K);
3261f13597dSJung-uk Kim BN_clear_free(u);
3271f13597dSJung-uk Kim return ret;
3281f13597dSJung-uk Kim }
3291f13597dSJung-uk Kim
3301f13597dSJung-uk Kim /* client side */
srp_generate_client_master_secret(SSL * s)331e71b7053SJung-uk Kim int srp_generate_client_master_secret(SSL *s)
3321f13597dSJung-uk Kim {
3331f13597dSJung-uk Kim BIGNUM *x = NULL, *u = NULL, *K = NULL;
334*b077aed3SPierre Pronchery int ret = 0, tmp_len = 0;
3351f13597dSJung-uk Kim char *passwd = NULL;
3361f13597dSJung-uk Kim unsigned char *tmp = NULL;
3371f13597dSJung-uk Kim
3386f9291ceSJung-uk Kim /*
3396f9291ceSJung-uk Kim * Checks if b % n == 0
3401f13597dSJung-uk Kim */
341e71b7053SJung-uk Kim if (SRP_Verify_B_mod_N(s->srp_ctx.B, s->srp_ctx.N) == 0
342*b077aed3SPierre Pronchery || (u = SRP_Calc_u_ex(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N,
343*b077aed3SPierre Pronchery s->ctx->libctx, s->ctx->propq))
344e71b7053SJung-uk Kim == NULL
345e71b7053SJung-uk Kim || s->srp_ctx.SRP_give_srp_client_pwd_callback == NULL) {
346*b077aed3SPierre Pronchery SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
3476f9291ceSJung-uk Kim goto err;
348e71b7053SJung-uk Kim }
349e71b7053SJung-uk Kim if ((passwd = s->srp_ctx.SRP_give_srp_client_pwd_callback(s,
350e71b7053SJung-uk Kim s->srp_ctx.SRP_cb_arg))
351e71b7053SJung-uk Kim == NULL) {
352*b077aed3SPierre Pronchery SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CALLBACK_FAILED);
3536f9291ceSJung-uk Kim goto err;
354e71b7053SJung-uk Kim }
355*b077aed3SPierre Pronchery if ((x = SRP_Calc_x_ex(s->srp_ctx.s, s->srp_ctx.login, passwd,
356*b077aed3SPierre Pronchery s->ctx->libctx, s->ctx->propq)) == NULL
357*b077aed3SPierre Pronchery || (K = SRP_Calc_client_key_ex(s->srp_ctx.N, s->srp_ctx.B,
358e71b7053SJung-uk Kim s->srp_ctx.g, x,
359*b077aed3SPierre Pronchery s->srp_ctx.a, u,
360*b077aed3SPierre Pronchery s->ctx->libctx,
361*b077aed3SPierre Pronchery s->ctx->propq)) == NULL) {
362*b077aed3SPierre Pronchery SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
3636f9291ceSJung-uk Kim goto err;
364e71b7053SJung-uk Kim }
3651f13597dSJung-uk Kim
3661f13597dSJung-uk Kim tmp_len = BN_num_bytes(K);
367e71b7053SJung-uk Kim if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) {
368*b077aed3SPierre Pronchery SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
3696f9291ceSJung-uk Kim goto err;
3701f13597dSJung-uk Kim }
371e71b7053SJung-uk Kim BN_bn2bin(K, tmp);
372e71b7053SJung-uk Kim /* Calls SSLfatal() as required */
373e71b7053SJung-uk Kim ret = ssl_generate_master_secret(s, tmp, tmp_len, 1);
374e71b7053SJung-uk Kim err:
3751f13597dSJung-uk Kim BN_clear_free(K);
3761f13597dSJung-uk Kim BN_clear_free(x);
377e71b7053SJung-uk Kim if (passwd != NULL)
378e71b7053SJung-uk Kim OPENSSL_clear_free(passwd, strlen(passwd));
3791f13597dSJung-uk Kim BN_clear_free(u);
3801f13597dSJung-uk Kim return ret;
3811f13597dSJung-uk Kim }
3821f13597dSJung-uk Kim
srp_verify_server_param(SSL * s)383e71b7053SJung-uk Kim int srp_verify_server_param(SSL *s)
384a93cbc2bSJung-uk Kim {
385a93cbc2bSJung-uk Kim SRP_CTX *srp = &s->srp_ctx;
3866f9291ceSJung-uk Kim /*
3876f9291ceSJung-uk Kim * Sanity check parameters: we can quickly check B % N == 0 by checking B
3886f9291ceSJung-uk Kim * != 0 since B < N
389a93cbc2bSJung-uk Kim */
390a93cbc2bSJung-uk Kim if (BN_ucmp(srp->g, srp->N) >= 0 || BN_ucmp(srp->B, srp->N) >= 0
3916f9291ceSJung-uk Kim || BN_is_zero(srp->B)) {
392*b077aed3SPierre Pronchery SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_DATA);
393a93cbc2bSJung-uk Kim return 0;
394a93cbc2bSJung-uk Kim }
395a93cbc2bSJung-uk Kim
3966f9291ceSJung-uk Kim if (BN_num_bits(srp->N) < srp->strength) {
397*b077aed3SPierre Pronchery SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_R_INSUFFICIENT_SECURITY);
398a93cbc2bSJung-uk Kim return 0;
399a93cbc2bSJung-uk Kim }
400a93cbc2bSJung-uk Kim
4016f9291ceSJung-uk Kim if (srp->SRP_verify_param_callback) {
4026f9291ceSJung-uk Kim if (srp->SRP_verify_param_callback(s, srp->SRP_cb_arg) <= 0) {
403*b077aed3SPierre Pronchery SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_R_CALLBACK_FAILED);
404a93cbc2bSJung-uk Kim return 0;
405a93cbc2bSJung-uk Kim }
4066f9291ceSJung-uk Kim } else if (!SRP_check_known_gN_param(srp->g, srp->N)) {
407*b077aed3SPierre Pronchery SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY,
408e71b7053SJung-uk Kim SSL_R_INSUFFICIENT_SECURITY);
409a93cbc2bSJung-uk Kim return 0;
410a93cbc2bSJung-uk Kim }
411a93cbc2bSJung-uk Kim
412a93cbc2bSJung-uk Kim return 1;
413a93cbc2bSJung-uk Kim }
414a93cbc2bSJung-uk Kim
415*b077aed3SPierre Pronchery /*
416*b077aed3SPierre Pronchery * The public API SRP_Calc_A_param() is deprecated so we use
417*b077aed3SPierre Pronchery * ssl_srp_calc_a_param_intern() internally.
418*b077aed3SPierre Pronchery */
ssl_srp_calc_a_param_intern(SSL * s)419*b077aed3SPierre Pronchery int ssl_srp_calc_a_param_intern(SSL *s)
4201f13597dSJung-uk Kim {
4211f13597dSJung-uk Kim unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH];
4221f13597dSJung-uk Kim
423*b077aed3SPierre Pronchery if (RAND_priv_bytes_ex(s->ctx->libctx, rnd, sizeof(rnd), 0) <= 0)
424e71b7053SJung-uk Kim return 0;
4251f13597dSJung-uk Kim s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a);
4261f13597dSJung-uk Kim OPENSSL_cleanse(rnd, sizeof(rnd));
4271f13597dSJung-uk Kim
428e71b7053SJung-uk Kim if (!(s->srp_ctx.A = SRP_Calc_A(s->srp_ctx.a, s->srp_ctx.N, s->srp_ctx.g)))
429e71b7053SJung-uk Kim return 0;
4301f13597dSJung-uk Kim
4311f13597dSJung-uk Kim return 1;
4321f13597dSJung-uk Kim }
4331f13597dSJung-uk Kim
SRP_Calc_A_param(SSL * s)434*b077aed3SPierre Pronchery int SRP_Calc_A_param(SSL *s)
435*b077aed3SPierre Pronchery {
436*b077aed3SPierre Pronchery return ssl_srp_calc_a_param_intern(s);
437*b077aed3SPierre Pronchery }
438*b077aed3SPierre Pronchery
SSL_get_srp_g(SSL * s)4391f13597dSJung-uk Kim BIGNUM *SSL_get_srp_g(SSL *s)
4401f13597dSJung-uk Kim {
4411f13597dSJung-uk Kim if (s->srp_ctx.g != NULL)
4421f13597dSJung-uk Kim return s->srp_ctx.g;
4431f13597dSJung-uk Kim return s->ctx->srp_ctx.g;
4441f13597dSJung-uk Kim }
4451f13597dSJung-uk Kim
SSL_get_srp_N(SSL * s)4461f13597dSJung-uk Kim BIGNUM *SSL_get_srp_N(SSL *s)
4471f13597dSJung-uk Kim {
4481f13597dSJung-uk Kim if (s->srp_ctx.N != NULL)
4491f13597dSJung-uk Kim return s->srp_ctx.N;
4501f13597dSJung-uk Kim return s->ctx->srp_ctx.N;
4511f13597dSJung-uk Kim }
4521f13597dSJung-uk Kim
SSL_get_srp_username(SSL * s)4531f13597dSJung-uk Kim char *SSL_get_srp_username(SSL *s)
4541f13597dSJung-uk Kim {
4551f13597dSJung-uk Kim if (s->srp_ctx.login != NULL)
4561f13597dSJung-uk Kim return s->srp_ctx.login;
4571f13597dSJung-uk Kim return s->ctx->srp_ctx.login;
4581f13597dSJung-uk Kim }
4591f13597dSJung-uk Kim
SSL_get_srp_userinfo(SSL * s)4601f13597dSJung-uk Kim char *SSL_get_srp_userinfo(SSL *s)
4611f13597dSJung-uk Kim {
4621f13597dSJung-uk Kim if (s->srp_ctx.info != NULL)
4631f13597dSJung-uk Kim return s->srp_ctx.info;
4641f13597dSJung-uk Kim return s->ctx->srp_ctx.info;
4651f13597dSJung-uk Kim }
4661f13597dSJung-uk Kim
4671f13597dSJung-uk Kim # define tls1_ctx_ctrl ssl3_ctx_ctrl
4681f13597dSJung-uk Kim # define tls1_ctx_callback_ctrl ssl3_ctx_callback_ctrl
4691f13597dSJung-uk Kim
SSL_CTX_set_srp_username(SSL_CTX * ctx,char * name)4701f13597dSJung-uk Kim int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name)
4711f13597dSJung-uk Kim {
4721f13597dSJung-uk Kim return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_USERNAME, 0, name);
4731f13597dSJung-uk Kim }
4741f13597dSJung-uk Kim
SSL_CTX_set_srp_password(SSL_CTX * ctx,char * password)4751f13597dSJung-uk Kim int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password)
4761f13597dSJung-uk Kim {
4771f13597dSJung-uk Kim return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD, 0, password);
4781f13597dSJung-uk Kim }
4791f13597dSJung-uk Kim
SSL_CTX_set_srp_strength(SSL_CTX * ctx,int strength)4801f13597dSJung-uk Kim int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength)
4811f13597dSJung-uk Kim {
4821f13597dSJung-uk Kim return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH, strength,
4831f13597dSJung-uk Kim NULL);
4841f13597dSJung-uk Kim }
4851f13597dSJung-uk Kim
SSL_CTX_set_srp_verify_param_callback(SSL_CTX * ctx,int (* cb)(SSL *,void *))4866f9291ceSJung-uk Kim int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx,
4876f9291ceSJung-uk Kim int (*cb) (SSL *, void *))
4881f13597dSJung-uk Kim {
4891f13597dSJung-uk Kim return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_SRP_VERIFY_PARAM_CB,
4901f13597dSJung-uk Kim (void (*)(void))cb);
4911f13597dSJung-uk Kim }
4921f13597dSJung-uk Kim
SSL_CTX_set_srp_cb_arg(SSL_CTX * ctx,void * arg)4931f13597dSJung-uk Kim int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg)
4941f13597dSJung-uk Kim {
4951f13597dSJung-uk Kim return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_SRP_ARG, 0, arg);
4961f13597dSJung-uk Kim }
4971f13597dSJung-uk Kim
SSL_CTX_set_srp_username_callback(SSL_CTX * ctx,int (* cb)(SSL *,int *,void *))4981f13597dSJung-uk Kim int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
4991f13597dSJung-uk Kim int (*cb) (SSL *, int *, void *))
5001f13597dSJung-uk Kim {
5011f13597dSJung-uk Kim return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB,
5021f13597dSJung-uk Kim (void (*)(void))cb);
5031f13597dSJung-uk Kim }
5041f13597dSJung-uk Kim
SSL_CTX_set_srp_client_pwd_callback(SSL_CTX * ctx,char * (* cb)(SSL *,void *))5056f9291ceSJung-uk Kim int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx,
5066f9291ceSJung-uk Kim char *(*cb) (SSL *, void *))
5071f13597dSJung-uk Kim {
5081f13597dSJung-uk Kim return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB,
5091f13597dSJung-uk Kim (void (*)(void))cb);
5101f13597dSJung-uk Kim }
5111f13597dSJung-uk Kim
5121f13597dSJung-uk Kim #endif
513