11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * Copyright 2005 Nokia. All rights reserved. 41cb0ef41Sopenharmony_ci * 51cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 61cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 71cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 81cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 91cb0ef41Sopenharmony_ci */ 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ci/* 121cb0ef41Sopenharmony_ci * This file is to enable backwards compatibility for the SRP features of 131cb0ef41Sopenharmony_ci * s_client, s_server and ciphers. All of those features are deprecated and will 141cb0ef41Sopenharmony_ci * eventually disappear. In the meantime, to continue to support them, we 151cb0ef41Sopenharmony_ci * need to access deprecated SRP APIs. 161cb0ef41Sopenharmony_ci */ 171cb0ef41Sopenharmony_ci#define OPENSSL_SUPPRESS_DEPRECATED 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ci#include <openssl/bn.h> 201cb0ef41Sopenharmony_ci#include <openssl/bio.h> 211cb0ef41Sopenharmony_ci#include <openssl/ssl.h> 221cb0ef41Sopenharmony_ci#include <openssl/srp.h> 231cb0ef41Sopenharmony_ci#include "apps_ui.h" 241cb0ef41Sopenharmony_ci#include "apps.h" 251cb0ef41Sopenharmony_ci#include "s_apps.h" 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_cistatic int srp_Verify_N_and_g(const BIGNUM *N, const BIGNUM *g) 281cb0ef41Sopenharmony_ci{ 291cb0ef41Sopenharmony_ci BN_CTX *bn_ctx = BN_CTX_new(); 301cb0ef41Sopenharmony_ci BIGNUM *p = BN_new(); 311cb0ef41Sopenharmony_ci BIGNUM *r = BN_new(); 321cb0ef41Sopenharmony_ci int ret = 331cb0ef41Sopenharmony_ci g != NULL && N != NULL && bn_ctx != NULL && BN_is_odd(N) && 341cb0ef41Sopenharmony_ci BN_check_prime(N, bn_ctx, NULL) == 1 && 351cb0ef41Sopenharmony_ci p != NULL && BN_rshift1(p, N) && 361cb0ef41Sopenharmony_ci /* p = (N-1)/2 */ 371cb0ef41Sopenharmony_ci BN_check_prime(p, bn_ctx, NULL) == 1 && 381cb0ef41Sopenharmony_ci r != NULL && 391cb0ef41Sopenharmony_ci /* verify g^((N-1)/2) == -1 (mod N) */ 401cb0ef41Sopenharmony_ci BN_mod_exp(r, g, p, N, bn_ctx) && 411cb0ef41Sopenharmony_ci BN_add_word(r, 1) && BN_cmp(r, N) == 0; 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci BN_free(r); 441cb0ef41Sopenharmony_ci BN_free(p); 451cb0ef41Sopenharmony_ci BN_CTX_free(bn_ctx); 461cb0ef41Sopenharmony_ci return ret; 471cb0ef41Sopenharmony_ci} 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci/*- 501cb0ef41Sopenharmony_ci * This callback is used here for two purposes: 511cb0ef41Sopenharmony_ci * - extended debugging 521cb0ef41Sopenharmony_ci * - making some primality tests for unknown groups 531cb0ef41Sopenharmony_ci * The callback is only called for a non default group. 541cb0ef41Sopenharmony_ci * 551cb0ef41Sopenharmony_ci * An application does not need the call back at all if 561cb0ef41Sopenharmony_ci * only the standard groups are used. In real life situations, 571cb0ef41Sopenharmony_ci * client and server already share well known groups, 581cb0ef41Sopenharmony_ci * thus there is no need to verify them. 591cb0ef41Sopenharmony_ci * Furthermore, in case that a server actually proposes a group that 601cb0ef41Sopenharmony_ci * is not one of those defined in RFC 5054, it is more appropriate 611cb0ef41Sopenharmony_ci * to add the group to a static list and then compare since 621cb0ef41Sopenharmony_ci * primality tests are rather cpu consuming. 631cb0ef41Sopenharmony_ci */ 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_cistatic int ssl_srp_verify_param_cb(SSL *s, void *arg) 661cb0ef41Sopenharmony_ci{ 671cb0ef41Sopenharmony_ci SRP_ARG *srp_arg = (SRP_ARG *)arg; 681cb0ef41Sopenharmony_ci BIGNUM *N = NULL, *g = NULL; 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci if (((N = SSL_get_srp_N(s)) == NULL) || ((g = SSL_get_srp_g(s)) == NULL)) 711cb0ef41Sopenharmony_ci return 0; 721cb0ef41Sopenharmony_ci if (srp_arg->debug || srp_arg->msg || srp_arg->amp == 1) { 731cb0ef41Sopenharmony_ci BIO_printf(bio_err, "SRP parameters:\n"); 741cb0ef41Sopenharmony_ci BIO_printf(bio_err, "\tN="); 751cb0ef41Sopenharmony_ci BN_print(bio_err, N); 761cb0ef41Sopenharmony_ci BIO_printf(bio_err, "\n\tg="); 771cb0ef41Sopenharmony_ci BN_print(bio_err, g); 781cb0ef41Sopenharmony_ci BIO_printf(bio_err, "\n"); 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci if (SRP_check_known_gN_param(g, N)) 821cb0ef41Sopenharmony_ci return 1; 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci if (srp_arg->amp == 1) { 851cb0ef41Sopenharmony_ci if (srp_arg->debug) 861cb0ef41Sopenharmony_ci BIO_printf(bio_err, 871cb0ef41Sopenharmony_ci "SRP param N and g are not known params, going to check deeper.\n"); 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci /* 901cb0ef41Sopenharmony_ci * The srp_moregroups is a real debugging feature. Implementors 911cb0ef41Sopenharmony_ci * should rather add the value to the known ones. The minimal size 921cb0ef41Sopenharmony_ci * has already been tested. 931cb0ef41Sopenharmony_ci */ 941cb0ef41Sopenharmony_ci if (BN_num_bits(g) <= BN_BITS && srp_Verify_N_and_g(N, g)) 951cb0ef41Sopenharmony_ci return 1; 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci BIO_printf(bio_err, "SRP param N and g rejected.\n"); 981cb0ef41Sopenharmony_ci return 0; 991cb0ef41Sopenharmony_ci} 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci#define PWD_STRLEN 1024 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_cistatic char *ssl_give_srp_client_pwd_cb(SSL *s, void *arg) 1041cb0ef41Sopenharmony_ci{ 1051cb0ef41Sopenharmony_ci SRP_ARG *srp_arg = (SRP_ARG *)arg; 1061cb0ef41Sopenharmony_ci char *pass = app_malloc(PWD_STRLEN + 1, "SRP password buffer"); 1071cb0ef41Sopenharmony_ci PW_CB_DATA cb_tmp; 1081cb0ef41Sopenharmony_ci int l; 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci cb_tmp.password = (char *)srp_arg->srppassin; 1111cb0ef41Sopenharmony_ci cb_tmp.prompt_info = "SRP user"; 1121cb0ef41Sopenharmony_ci if ((l = password_callback(pass, PWD_STRLEN, 0, &cb_tmp)) < 0) { 1131cb0ef41Sopenharmony_ci BIO_printf(bio_err, "Can't read Password\n"); 1141cb0ef41Sopenharmony_ci OPENSSL_free(pass); 1151cb0ef41Sopenharmony_ci return NULL; 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci *(pass + l) = '\0'; 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci return pass; 1201cb0ef41Sopenharmony_ci} 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ciint set_up_srp_arg(SSL_CTX *ctx, SRP_ARG *srp_arg, int srp_lateuser, int c_msg, 1231cb0ef41Sopenharmony_ci int c_debug) 1241cb0ef41Sopenharmony_ci{ 1251cb0ef41Sopenharmony_ci if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg->srplogin)) { 1261cb0ef41Sopenharmony_ci BIO_printf(bio_err, "Unable to set SRP username\n"); 1271cb0ef41Sopenharmony_ci return 0; 1281cb0ef41Sopenharmony_ci } 1291cb0ef41Sopenharmony_ci srp_arg->msg = c_msg; 1301cb0ef41Sopenharmony_ci srp_arg->debug = c_debug; 1311cb0ef41Sopenharmony_ci SSL_CTX_set_srp_cb_arg(ctx, &srp_arg); 1321cb0ef41Sopenharmony_ci SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb); 1331cb0ef41Sopenharmony_ci SSL_CTX_set_srp_strength(ctx, srp_arg->strength); 1341cb0ef41Sopenharmony_ci if (c_msg || c_debug || srp_arg->amp == 0) 1351cb0ef41Sopenharmony_ci SSL_CTX_set_srp_verify_param_callback(ctx, ssl_srp_verify_param_cb); 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci return 1; 1381cb0ef41Sopenharmony_ci} 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_cistatic char *dummy_srp(SSL *ssl, void *arg) 1411cb0ef41Sopenharmony_ci{ 1421cb0ef41Sopenharmony_ci return ""; 1431cb0ef41Sopenharmony_ci} 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_civoid set_up_dummy_srp(SSL_CTX *ctx) 1461cb0ef41Sopenharmony_ci{ 1471cb0ef41Sopenharmony_ci SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp); 1481cb0ef41Sopenharmony_ci} 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci/* 1511cb0ef41Sopenharmony_ci * This callback pretends to require some asynchronous logic in order to 1521cb0ef41Sopenharmony_ci * obtain a verifier. When the callback is called for a new connection we 1531cb0ef41Sopenharmony_ci * return with a negative value. This will provoke the accept etc to return 1541cb0ef41Sopenharmony_ci * with an LOOKUP_X509. The main logic of the reinvokes the suspended call 1551cb0ef41Sopenharmony_ci * (which would normally occur after a worker has finished) and we set the 1561cb0ef41Sopenharmony_ci * user parameters. 1571cb0ef41Sopenharmony_ci */ 1581cb0ef41Sopenharmony_cistatic int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) 1591cb0ef41Sopenharmony_ci{ 1601cb0ef41Sopenharmony_ci srpsrvparm *p = (srpsrvparm *) arg; 1611cb0ef41Sopenharmony_ci int ret = SSL3_AL_FATAL; 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci if (p->login == NULL && p->user == NULL) { 1641cb0ef41Sopenharmony_ci p->login = SSL_get_srp_username(s); 1651cb0ef41Sopenharmony_ci BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login); 1661cb0ef41Sopenharmony_ci return -1; 1671cb0ef41Sopenharmony_ci } 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci if (p->user == NULL) { 1701cb0ef41Sopenharmony_ci BIO_printf(bio_err, "User %s doesn't exist\n", p->login); 1711cb0ef41Sopenharmony_ci goto err; 1721cb0ef41Sopenharmony_ci } 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci if (SSL_set_srp_server_param 1751cb0ef41Sopenharmony_ci (s, p->user->N, p->user->g, p->user->s, p->user->v, 1761cb0ef41Sopenharmony_ci p->user->info) < 0) { 1771cb0ef41Sopenharmony_ci *ad = SSL_AD_INTERNAL_ERROR; 1781cb0ef41Sopenharmony_ci goto err; 1791cb0ef41Sopenharmony_ci } 1801cb0ef41Sopenharmony_ci BIO_printf(bio_err, 1811cb0ef41Sopenharmony_ci "SRP parameters set: username = \"%s\" info=\"%s\" \n", 1821cb0ef41Sopenharmony_ci p->login, p->user->info); 1831cb0ef41Sopenharmony_ci ret = SSL_ERROR_NONE; 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci err: 1861cb0ef41Sopenharmony_ci SRP_user_pwd_free(p->user); 1871cb0ef41Sopenharmony_ci p->user = NULL; 1881cb0ef41Sopenharmony_ci p->login = NULL; 1891cb0ef41Sopenharmony_ci return ret; 1901cb0ef41Sopenharmony_ci} 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ciint set_up_srp_verifier_file(SSL_CTX *ctx, srpsrvparm *srp_callback_parm, 1931cb0ef41Sopenharmony_ci char *srpuserseed, char *srp_verifier_file) 1941cb0ef41Sopenharmony_ci{ 1951cb0ef41Sopenharmony_ci int ret; 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci srp_callback_parm->vb = SRP_VBASE_new(srpuserseed); 1981cb0ef41Sopenharmony_ci srp_callback_parm->user = NULL; 1991cb0ef41Sopenharmony_ci srp_callback_parm->login = NULL; 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci if (srp_callback_parm->vb == NULL) { 2021cb0ef41Sopenharmony_ci BIO_printf(bio_err, "Failed to initialize SRP verifier file \n"); 2031cb0ef41Sopenharmony_ci return 0; 2041cb0ef41Sopenharmony_ci } 2051cb0ef41Sopenharmony_ci if ((ret = 2061cb0ef41Sopenharmony_ci SRP_VBASE_init(srp_callback_parm->vb, 2071cb0ef41Sopenharmony_ci srp_verifier_file)) != SRP_NO_ERROR) { 2081cb0ef41Sopenharmony_ci BIO_printf(bio_err, 2091cb0ef41Sopenharmony_ci "Cannot initialize SRP verifier file \"%s\":ret=%d\n", 2101cb0ef41Sopenharmony_ci srp_verifier_file, ret); 2111cb0ef41Sopenharmony_ci return 0; 2121cb0ef41Sopenharmony_ci } 2131cb0ef41Sopenharmony_ci SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback); 2141cb0ef41Sopenharmony_ci SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm); 2151cb0ef41Sopenharmony_ci SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb); 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci return 1; 2181cb0ef41Sopenharmony_ci} 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_civoid lookup_srp_user(srpsrvparm *srp_callback_parm, BIO *bio_s_out) 2211cb0ef41Sopenharmony_ci{ 2221cb0ef41Sopenharmony_ci SRP_user_pwd_free(srp_callback_parm->user); 2231cb0ef41Sopenharmony_ci srp_callback_parm->user = SRP_VBASE_get1_by_user(srp_callback_parm->vb, 2241cb0ef41Sopenharmony_ci srp_callback_parm->login); 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci if (srp_callback_parm->user != NULL) 2271cb0ef41Sopenharmony_ci BIO_printf(bio_s_out, "LOOKUP done %s\n", 2281cb0ef41Sopenharmony_ci srp_callback_parm->user->info); 2291cb0ef41Sopenharmony_ci else 2301cb0ef41Sopenharmony_ci BIO_printf(bio_s_out, "LOOKUP not successful\n"); 2311cb0ef41Sopenharmony_ci} 232