1 /* 2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * Copyright 2005 Nokia. All rights reserved. 4 * 5 * Licensed under the Apache License 2.0 (the "License"). You may not use 6 * this file except in compliance with the License. You can obtain a copy 7 * in the file LICENSE in the source distribution or at 8 * https://www.openssl.org/source/license.html 9 */ 10 11 /* 12 * This file is to enable backwards compatibility for the SRP features of 13 * s_client, s_server and ciphers. All of those features are deprecated and will 14 * eventually disappear. In the meantime, to continue to support them, we 15 * need to access deprecated SRP APIs. 16 */ 17 #define OPENSSL_SUPPRESS_DEPRECATED 18 19 #include <openssl/bn.h> 20 #include <openssl/bio.h> 21 #include <openssl/ssl.h> 22 #include <openssl/srp.h> 23 #include "apps_ui.h" 24 #include "apps.h" 25 #include "s_apps.h" 26 27 static int srp_Verify_N_and_g(const BIGNUM *N, const BIGNUM *g) 28 { 29 BN_CTX *bn_ctx = BN_CTX_new(); 30 BIGNUM *p = BN_new(); 31 BIGNUM *r = BN_new(); 32 int ret = 33 g != NULL && N != NULL && bn_ctx != NULL && BN_is_odd(N) && 34 BN_check_prime(N, bn_ctx, NULL) == 1 && 35 p != NULL && BN_rshift1(p, N) && 36 /* p = (N-1)/2 */ 37 BN_check_prime(p, bn_ctx, NULL) == 1 && 38 r != NULL && 39 /* verify g^((N-1)/2) == -1 (mod N) */ 40 BN_mod_exp(r, g, p, N, bn_ctx) && 41 BN_add_word(r, 1) && BN_cmp(r, N) == 0; 42 43 BN_free(r); 44 BN_free(p); 45 BN_CTX_free(bn_ctx); 46 return ret; 47 } 48 49 /*- 50 * This callback is used here for two purposes: 51 * - extended debugging 52 * - making some primality tests for unknown groups 53 * The callback is only called for a non default group. 54 * 55 * An application does not need the call back at all if 56 * only the standard groups are used. In real life situations, 57 * client and server already share well known groups, 58 * thus there is no need to verify them. 59 * Furthermore, in case that a server actually proposes a group that 60 * is not one of those defined in RFC 5054, it is more appropriate 61 * to add the group to a static list and then compare since 62 * primality tests are rather cpu consuming. 63 */ 64 65 static int ssl_srp_verify_param_cb(SSL *s, void *arg) 66 { 67 SRP_ARG *srp_arg = (SRP_ARG *)arg; 68 BIGNUM *N = NULL, *g = NULL; 69 70 if (((N = SSL_get_srp_N(s)) == NULL) || ((g = SSL_get_srp_g(s)) == NULL)) 71 return 0; 72 if (srp_arg->debug || srp_arg->msg || srp_arg->amp == 1) { 73 BIO_printf(bio_err, "SRP parameters:\n"); 74 BIO_printf(bio_err, "\tN="); 75 BN_print(bio_err, N); 76 BIO_printf(bio_err, "\n\tg="); 77 BN_print(bio_err, g); 78 BIO_printf(bio_err, "\n"); 79 } 80 81 if (SRP_check_known_gN_param(g, N)) 82 return 1; 83 84 if (srp_arg->amp == 1) { 85 if (srp_arg->debug) 86 BIO_printf(bio_err, 87 "SRP param N and g are not known params, going to check deeper.\n"); 88 89 /* 90 * The srp_moregroups is a real debugging feature. Implementors 91 * should rather add the value to the known ones. The minimal size 92 * has already been tested. 93 */ 94 if (BN_num_bits(g) <= BN_BITS && srp_Verify_N_and_g(N, g)) 95 return 1; 96 } 97 BIO_printf(bio_err, "SRP param N and g rejected.\n"); 98 return 0; 99 } 100 101 #define PWD_STRLEN 1024 102 103 static char *ssl_give_srp_client_pwd_cb(SSL *s, void *arg) 104 { 105 SRP_ARG *srp_arg = (SRP_ARG *)arg; 106 char *pass = app_malloc(PWD_STRLEN + 1, "SRP password buffer"); 107 PW_CB_DATA cb_tmp; 108 int l; 109 110 cb_tmp.password = (char *)srp_arg->srppassin; 111 cb_tmp.prompt_info = "SRP user"; 112 if ((l = password_callback(pass, PWD_STRLEN, 0, &cb_tmp)) < 0) { 113 BIO_printf(bio_err, "Can't read Password\n"); 114 OPENSSL_free(pass); 115 return NULL; 116 } 117 *(pass + l) = '\0'; 118 119 return pass; 120 } 121 122 int set_up_srp_arg(SSL_CTX *ctx, SRP_ARG *srp_arg, int srp_lateuser, int c_msg, 123 int c_debug) 124 { 125 if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg->srplogin)) { 126 BIO_printf(bio_err, "Unable to set SRP username\n"); 127 return 0; 128 } 129 srp_arg->msg = c_msg; 130 srp_arg->debug = c_debug; 131 SSL_CTX_set_srp_cb_arg(ctx, &srp_arg); 132 SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb); 133 SSL_CTX_set_srp_strength(ctx, srp_arg->strength); 134 if (c_msg || c_debug || srp_arg->amp == 0) 135 SSL_CTX_set_srp_verify_param_callback(ctx, ssl_srp_verify_param_cb); 136 137 return 1; 138 } 139 140 static char *dummy_srp(SSL *ssl, void *arg) 141 { 142 return ""; 143 } 144 145 void set_up_dummy_srp(SSL_CTX *ctx) 146 { 147 SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp); 148 } 149 150 /* 151 * This callback pretends to require some asynchronous logic in order to 152 * obtain a verifier. When the callback is called for a new connection we 153 * return with a negative value. This will provoke the accept etc to return 154 * with an LOOKUP_X509. The main logic of the reinvokes the suspended call 155 * (which would normally occur after a worker has finished) and we set the 156 * user parameters. 157 */ 158 static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) 159 { 160 srpsrvparm *p = (srpsrvparm *) arg; 161 int ret = SSL3_AL_FATAL; 162 163 if (p->login == NULL && p->user == NULL) { 164 p->login = SSL_get_srp_username(s); 165 BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login); 166 return -1; 167 } 168 169 if (p->user == NULL) { 170 BIO_printf(bio_err, "User %s doesn't exist\n", p->login); 171 goto err; 172 } 173 174 if (SSL_set_srp_server_param 175 (s, p->user->N, p->user->g, p->user->s, p->user->v, 176 p->user->info) < 0) { 177 *ad = SSL_AD_INTERNAL_ERROR; 178 goto err; 179 } 180 BIO_printf(bio_err, 181 "SRP parameters set: username = \"%s\" info=\"%s\" \n", 182 p->login, p->user->info); 183 ret = SSL_ERROR_NONE; 184 185 err: 186 SRP_user_pwd_free(p->user); 187 p->user = NULL; 188 p->login = NULL; 189 return ret; 190 } 191 192 int set_up_srp_verifier_file(SSL_CTX *ctx, srpsrvparm *srp_callback_parm, 193 char *srpuserseed, char *srp_verifier_file) 194 { 195 int ret; 196 197 srp_callback_parm->vb = SRP_VBASE_new(srpuserseed); 198 srp_callback_parm->user = NULL; 199 srp_callback_parm->login = NULL; 200 201 if (srp_callback_parm->vb == NULL) { 202 BIO_printf(bio_err, "Failed to initialize SRP verifier file \n"); 203 return 0; 204 } 205 if ((ret = 206 SRP_VBASE_init(srp_callback_parm->vb, 207 srp_verifier_file)) != SRP_NO_ERROR) { 208 BIO_printf(bio_err, 209 "Cannot initialize SRP verifier file \"%s\":ret=%d\n", 210 srp_verifier_file, ret); 211 return 0; 212 } 213 SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback); 214 SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm); 215 SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb); 216 217 return 1; 218 } 219 220 void lookup_srp_user(srpsrvparm *srp_callback_parm, BIO *bio_s_out) 221 { 222 SRP_user_pwd_free(srp_callback_parm->user); 223 srp_callback_parm->user = SRP_VBASE_get1_by_user(srp_callback_parm->vb, 224 srp_callback_parm->login); 225 226 if (srp_callback_parm->user != NULL) 227 BIO_printf(bio_s_out, "LOOKUP done %s\n", 228 srp_callback_parm->user->info); 229 else 230 BIO_printf(bio_s_out, "LOOKUP not successful\n"); 231 } 232