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