Coverage Report

Created: 2025-06-13 06:58

/src/openssl31/ssl/tls_srp.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
3
 * Copyright (c) 2004, EdelKey Project. 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
 * Originally written by Christophe Renou and Peter Sylvester,
11
 * for the EdelKey project.
12
 */
13
14
/*
15
 * We need to use the SRP deprecated APIs in order to implement the SSL SRP
16
 * APIs - which are themselves deprecated.
17
 */
18
#define OPENSSL_SUPPRESS_DEPRECATED
19
20
#include <openssl/crypto.h>
21
#include <openssl/rand.h>
22
#include <openssl/err.h>
23
#include "ssl_local.h"
24
25
#ifndef OPENSSL_NO_SRP
26
# include <openssl/srp.h>
27
28
/*
29
 * The public API SSL_CTX_SRP_CTX_free() is deprecated so we use
30
 * ssl_ctx_srp_ctx_free_intern() internally.
31
 */
32
int ssl_ctx_srp_ctx_free_intern(SSL_CTX *ctx)
33
79.3k
{
34
79.3k
    if (ctx == NULL)
35
0
        return 0;
36
79.3k
    OPENSSL_free(ctx->srp_ctx.login);
37
79.3k
    OPENSSL_free(ctx->srp_ctx.info);
38
79.3k
    BN_free(ctx->srp_ctx.N);
39
79.3k
    BN_free(ctx->srp_ctx.g);
40
79.3k
    BN_free(ctx->srp_ctx.s);
41
79.3k
    BN_free(ctx->srp_ctx.B);
42
79.3k
    BN_free(ctx->srp_ctx.A);
43
79.3k
    BN_free(ctx->srp_ctx.a);
44
79.3k
    BN_free(ctx->srp_ctx.b);
45
79.3k
    BN_free(ctx->srp_ctx.v);
46
79.3k
    memset(&ctx->srp_ctx, 0, sizeof(ctx->srp_ctx));
47
79.3k
    ctx->srp_ctx.strength = SRP_MINIMAL_N;
48
79.3k
    return 1;
49
79.3k
}
50
51
int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx)
52
0
{
53
0
    return ssl_ctx_srp_ctx_free_intern(ctx);
54
0
}
55
56
/*
57
 * The public API SSL_SRP_CTX_free() is deprecated so we use
58
 * ssl_srp_ctx_free_intern() internally.
59
 */
60
int ssl_srp_ctx_free_intern(SSL *s)
61
79.2k
{
62
79.2k
    if (s == NULL)
63
0
        return 0;
64
79.2k
    OPENSSL_free(s->srp_ctx.login);
65
79.2k
    OPENSSL_free(s->srp_ctx.info);
66
79.2k
    BN_free(s->srp_ctx.N);
67
79.2k
    BN_free(s->srp_ctx.g);
68
79.2k
    BN_free(s->srp_ctx.s);
69
79.2k
    BN_free(s->srp_ctx.B);
70
79.2k
    BN_free(s->srp_ctx.A);
71
79.2k
    BN_free(s->srp_ctx.a);
72
79.2k
    BN_free(s->srp_ctx.b);
73
79.2k
    BN_free(s->srp_ctx.v);
74
79.2k
    memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
75
79.2k
    s->srp_ctx.strength = SRP_MINIMAL_N;
76
79.2k
    return 1;
77
79.2k
}
78
79
int SSL_SRP_CTX_free(SSL *s)
80
0
{
81
0
    return ssl_srp_ctx_free_intern(s);
82
0
}
83
84
/*
85
 * The public API SSL_SRP_CTX_init() is deprecated so we use
86
 * ssl_srp_ctx_init_intern() internally.
87
 */
88
int ssl_srp_ctx_init_intern(SSL *s)
89
79.2k
{
90
79.2k
    SSL_CTX *ctx;
91
92
79.2k
    if ((s == NULL) || ((ctx = s->ctx) == NULL))
93
0
        return 0;
94
95
79.2k
    memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
96
97
79.2k
    s->srp_ctx.SRP_cb_arg = ctx->srp_ctx.SRP_cb_arg;
98
    /* set client Hello login callback */
99
79.2k
    s->srp_ctx.TLS_ext_srp_username_callback =
100
79.2k
        ctx->srp_ctx.TLS_ext_srp_username_callback;
101
    /* set SRP N/g param callback for verification */
102
79.2k
    s->srp_ctx.SRP_verify_param_callback =
103
79.2k
        ctx->srp_ctx.SRP_verify_param_callback;
104
    /* set SRP client passwd callback */
105
79.2k
    s->srp_ctx.SRP_give_srp_client_pwd_callback =
106
79.2k
        ctx->srp_ctx.SRP_give_srp_client_pwd_callback;
107
108
79.2k
    s->srp_ctx.strength = ctx->srp_ctx.strength;
109
110
79.2k
    if (((ctx->srp_ctx.N != NULL) &&
111
79.2k
         ((s->srp_ctx.N = BN_dup(ctx->srp_ctx.N)) == NULL)) ||
112
79.2k
        ((ctx->srp_ctx.g != NULL) &&
113
79.2k
         ((s->srp_ctx.g = BN_dup(ctx->srp_ctx.g)) == NULL)) ||
114
79.2k
        ((ctx->srp_ctx.s != NULL) &&
115
79.2k
         ((s->srp_ctx.s = BN_dup(ctx->srp_ctx.s)) == NULL)) ||
116
79.2k
        ((ctx->srp_ctx.B != NULL) &&
117
79.2k
         ((s->srp_ctx.B = BN_dup(ctx->srp_ctx.B)) == NULL)) ||
118
79.2k
        ((ctx->srp_ctx.A != NULL) &&
119
79.2k
         ((s->srp_ctx.A = BN_dup(ctx->srp_ctx.A)) == NULL)) ||
120
79.2k
        ((ctx->srp_ctx.a != NULL) &&
121
79.2k
         ((s->srp_ctx.a = BN_dup(ctx->srp_ctx.a)) == NULL)) ||
122
79.2k
        ((ctx->srp_ctx.v != NULL) &&
123
79.2k
         ((s->srp_ctx.v = BN_dup(ctx->srp_ctx.v)) == NULL)) ||
124
79.2k
        ((ctx->srp_ctx.b != NULL) &&
125
79.2k
         ((s->srp_ctx.b = BN_dup(ctx->srp_ctx.b)) == NULL))) {
126
0
        ERR_raise(ERR_LIB_SSL, ERR_R_BN_LIB);
127
0
        goto err;
128
0
    }
129
79.2k
    if ((ctx->srp_ctx.login != NULL) &&
130
79.2k
        ((s->srp_ctx.login = OPENSSL_strdup(ctx->srp_ctx.login)) == NULL)) {
131
0
        ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
132
0
        goto err;
133
0
    }
134
79.2k
    if ((ctx->srp_ctx.info != NULL) &&
135
79.2k
        ((s->srp_ctx.info = OPENSSL_strdup(ctx->srp_ctx.info)) == NULL)) {
136
0
        ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
137
0
        goto err;
138
0
    }
139
79.2k
    s->srp_ctx.srp_Mask = ctx->srp_ctx.srp_Mask;
140
141
79.2k
    return 1;
142
0
 err:
143
0
    OPENSSL_free(s->srp_ctx.login);
144
0
    OPENSSL_free(s->srp_ctx.info);
145
0
    BN_free(s->srp_ctx.N);
146
0
    BN_free(s->srp_ctx.g);
147
0
    BN_free(s->srp_ctx.s);
148
0
    BN_free(s->srp_ctx.B);
149
0
    BN_free(s->srp_ctx.A);
150
0
    BN_free(s->srp_ctx.a);
151
0
    BN_free(s->srp_ctx.b);
152
0
    BN_free(s->srp_ctx.v);
153
0
    memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
154
0
    return 0;
155
79.2k
}
156
157
int SSL_SRP_CTX_init(SSL *s)
158
0
{
159
0
    return ssl_srp_ctx_init_intern(s);
160
0
}
161
162
/*
163
 * The public API SSL_CTX_SRP_CTX_init() is deprecated so we use
164
 * ssl_ctx_srp_ctx_init_intern() internally.
165
 */
166
int ssl_ctx_srp_ctx_init_intern(SSL_CTX *ctx)
167
79.3k
{
168
79.3k
    if (ctx == NULL)
169
0
        return 0;
170
171
79.3k
    memset(&ctx->srp_ctx, 0, sizeof(ctx->srp_ctx));
172
79.3k
    ctx->srp_ctx.strength = SRP_MINIMAL_N;
173
174
79.3k
    return 1;
175
79.3k
}
176
177
int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx)
178
0
{
179
0
    return ssl_ctx_srp_ctx_init_intern(ctx);
180
0
}
181
182
/* server side */
183
/*
184
 * The public API SSL_srp_server_param_with_username() is deprecated so we use
185
 * ssl_srp_server_param_with_username_intern() internally.
186
 */
187
int ssl_srp_server_param_with_username_intern(SSL *s, int *ad)
188
0
{
189
0
    unsigned char b[SSL_MAX_MASTER_KEY_LENGTH];
190
0
    int al;
191
192
0
    *ad = SSL_AD_UNKNOWN_PSK_IDENTITY;
193
0
    if ((s->srp_ctx.TLS_ext_srp_username_callback != NULL) &&
194
0
        ((al =
195
0
          s->srp_ctx.TLS_ext_srp_username_callback(s, ad,
196
0
                                                   s->srp_ctx.SRP_cb_arg)) !=
197
0
         SSL_ERROR_NONE))
198
0
        return al;
199
200
0
    *ad = SSL_AD_INTERNAL_ERROR;
201
0
    if ((s->srp_ctx.N == NULL) ||
202
0
        (s->srp_ctx.g == NULL) ||
203
0
        (s->srp_ctx.s == NULL) || (s->srp_ctx.v == NULL))
204
0
        return SSL3_AL_FATAL;
205
206
0
    if (RAND_priv_bytes_ex(s->ctx->libctx, b, sizeof(b), 0) <= 0)
207
0
        return SSL3_AL_FATAL;
208
0
    s->srp_ctx.b = BN_bin2bn(b, sizeof(b), NULL);
209
0
    OPENSSL_cleanse(b, sizeof(b));
210
211
    /* Calculate:  B = (kv + g^b) % N  */
212
213
0
    return ((s->srp_ctx.B =
214
0
             SRP_Calc_B_ex(s->srp_ctx.b, s->srp_ctx.N, s->srp_ctx.g,
215
0
                           s->srp_ctx.v, s->ctx->libctx, s->ctx->propq)) !=
216
0
            NULL) ? SSL_ERROR_NONE : SSL3_AL_FATAL;
217
0
}
218
219
int SSL_srp_server_param_with_username(SSL *s, int *ad)
220
0
{
221
0
    return ssl_srp_server_param_with_username_intern(s, ad);
222
0
}
223
224
/*
225
 * If the server just has the raw password, make up a verifier entry on the
226
 * fly
227
 */
228
int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
229
                                const char *grp)
230
0
{
231
0
    SRP_gN *GN = SRP_get_default_gN(grp);
232
0
    if (GN == NULL)
233
0
        return -1;
234
0
    s->srp_ctx.N = BN_dup(GN->N);
235
0
    s->srp_ctx.g = BN_dup(GN->g);
236
0
    BN_clear_free(s->srp_ctx.v);
237
0
    s->srp_ctx.v = NULL;
238
0
    BN_clear_free(s->srp_ctx.s);
239
0
    s->srp_ctx.s = NULL;
240
0
    if (!SRP_create_verifier_BN_ex(user, pass, &s->srp_ctx.s, &s->srp_ctx.v,
241
0
                                   s->srp_ctx.N, s->srp_ctx.g, s->ctx->libctx,
242
0
                                   s->ctx->propq))
243
0
        return -1;
244
245
0
    return 1;
246
0
}
247
248
int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
249
                             BIGNUM *sa, BIGNUM *v, char *info)
250
0
{
251
0
    if (N != NULL) {
252
0
        if (s->srp_ctx.N != NULL) {
253
0
            if (!BN_copy(s->srp_ctx.N, N)) {
254
0
                BN_free(s->srp_ctx.N);
255
0
                s->srp_ctx.N = NULL;
256
0
            }
257
0
        } else
258
0
            s->srp_ctx.N = BN_dup(N);
259
0
    }
260
0
    if (g != NULL) {
261
0
        if (s->srp_ctx.g != NULL) {
262
0
            if (!BN_copy(s->srp_ctx.g, g)) {
263
0
                BN_free(s->srp_ctx.g);
264
0
                s->srp_ctx.g = NULL;
265
0
            }
266
0
        } else
267
0
            s->srp_ctx.g = BN_dup(g);
268
0
    }
269
0
    if (sa != NULL) {
270
0
        if (s->srp_ctx.s != NULL) {
271
0
            if (!BN_copy(s->srp_ctx.s, sa)) {
272
0
                BN_free(s->srp_ctx.s);
273
0
                s->srp_ctx.s = NULL;
274
0
            }
275
0
        } else
276
0
            s->srp_ctx.s = BN_dup(sa);
277
0
    }
278
0
    if (v != NULL) {
279
0
        if (s->srp_ctx.v != NULL) {
280
0
            if (!BN_copy(s->srp_ctx.v, v)) {
281
0
                BN_free(s->srp_ctx.v);
282
0
                s->srp_ctx.v = NULL;
283
0
            }
284
0
        } else
285
0
            s->srp_ctx.v = BN_dup(v);
286
0
    }
287
0
    if (info != NULL) {
288
0
        if (s->srp_ctx.info)
289
0
            OPENSSL_free(s->srp_ctx.info);
290
0
        if ((s->srp_ctx.info = OPENSSL_strdup(info)) == NULL)
291
0
            return -1;
292
0
    }
293
294
0
    if (!(s->srp_ctx.N) ||
295
0
        !(s->srp_ctx.g) || !(s->srp_ctx.s) || !(s->srp_ctx.v))
296
0
        return -1;
297
298
0
    return 1;
299
0
}
300
301
int srp_generate_server_master_secret(SSL *s)
302
0
{
303
0
    BIGNUM *K = NULL, *u = NULL;
304
0
    int ret = 0, tmp_len = 0;
305
0
    unsigned char *tmp = NULL;
306
307
0
    if (!SRP_Verify_A_mod_N(s->srp_ctx.A, s->srp_ctx.N))
308
0
        goto err;
309
0
    if ((u = SRP_Calc_u_ex(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N,
310
0
                           s->ctx->libctx, s->ctx->propq)) == NULL)
311
0
        goto err;
312
0
    if ((K = SRP_Calc_server_key(s->srp_ctx.A, s->srp_ctx.v, u, s->srp_ctx.b,
313
0
                                 s->srp_ctx.N)) == NULL)
314
0
        goto err;
315
316
0
    tmp_len = BN_num_bytes(K);
317
0
    if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) {
318
0
        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
319
0
        goto err;
320
0
    }
321
0
    BN_bn2bin(K, tmp);
322
    /* Calls SSLfatal() as required */
323
0
    ret = ssl_generate_master_secret(s, tmp, tmp_len, 1);
324
0
 err:
325
0
    BN_clear_free(K);
326
0
    BN_clear_free(u);
327
0
    return ret;
328
0
}
329
330
/* client side */
331
int srp_generate_client_master_secret(SSL *s)
332
0
{
333
0
    BIGNUM *x = NULL, *u = NULL, *K = NULL;
334
0
    int ret = 0, tmp_len = 0;
335
0
    char *passwd = NULL;
336
0
    unsigned char *tmp = NULL;
337
338
    /*
339
     * Checks if b % n == 0
340
     */
341
0
    if (SRP_Verify_B_mod_N(s->srp_ctx.B, s->srp_ctx.N) == 0
342
0
            || (u = SRP_Calc_u_ex(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N,
343
0
                                  s->ctx->libctx, s->ctx->propq))
344
0
               == NULL
345
0
            || s->srp_ctx.SRP_give_srp_client_pwd_callback == NULL) {
346
0
        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
347
0
        goto err;
348
0
    }
349
0
    if ((passwd = s->srp_ctx.SRP_give_srp_client_pwd_callback(s,
350
0
                                                      s->srp_ctx.SRP_cb_arg))
351
0
            == NULL) {
352
0
        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CALLBACK_FAILED);
353
0
        goto err;
354
0
    }
355
0
    if ((x = SRP_Calc_x_ex(s->srp_ctx.s, s->srp_ctx.login, passwd,
356
0
                           s->ctx->libctx, s->ctx->propq)) == NULL
357
0
            || (K = SRP_Calc_client_key_ex(s->srp_ctx.N, s->srp_ctx.B,
358
0
                                           s->srp_ctx.g, x,
359
0
                                           s->srp_ctx.a, u,
360
0
                                           s->ctx->libctx,
361
0
                                           s->ctx->propq)) == NULL) {
362
0
        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
363
0
        goto err;
364
0
    }
365
366
0
    tmp_len = BN_num_bytes(K);
367
0
    if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) {
368
0
        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
369
0
        goto err;
370
0
    }
371
0
    BN_bn2bin(K, tmp);
372
    /* Calls SSLfatal() as required */
373
0
    ret = ssl_generate_master_secret(s, tmp, tmp_len, 1);
374
0
 err:
375
0
    BN_clear_free(K);
376
0
    BN_clear_free(x);
377
0
    if (passwd != NULL)
378
0
        OPENSSL_clear_free(passwd, strlen(passwd));
379
0
    BN_clear_free(u);
380
0
    return ret;
381
0
}
382
383
int srp_verify_server_param(SSL *s)
384
0
{
385
0
    SRP_CTX *srp = &s->srp_ctx;
386
    /*
387
     * Sanity check parameters: we can quickly check B % N == 0 by checking B
388
     * != 0 since B < N
389
     */
390
0
    if (BN_ucmp(srp->g, srp->N) >= 0 || BN_ucmp(srp->B, srp->N) >= 0
391
0
        || BN_is_zero(srp->B)) {
392
0
        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_DATA);
393
0
        return 0;
394
0
    }
395
396
0
    if (BN_num_bits(srp->N) < srp->strength) {
397
0
        SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_R_INSUFFICIENT_SECURITY);
398
0
        return 0;
399
0
    }
400
401
0
    if (srp->SRP_verify_param_callback) {
402
0
        if (srp->SRP_verify_param_callback(s, srp->SRP_cb_arg) <= 0) {
403
0
            SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_R_CALLBACK_FAILED);
404
0
            return 0;
405
0
        }
406
0
    } else if (!SRP_check_known_gN_param(srp->g, srp->N)) {
407
0
        SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY,
408
0
                 SSL_R_INSUFFICIENT_SECURITY);
409
0
        return 0;
410
0
    }
411
412
0
    return 1;
413
0
}
414
415
/*
416
 * The public API SRP_Calc_A_param() is deprecated so we use
417
 * ssl_srp_calc_a_param_intern() internally.
418
 */
419
int ssl_srp_calc_a_param_intern(SSL *s)
420
0
{
421
0
    unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH];
422
423
0
    if (RAND_priv_bytes_ex(s->ctx->libctx, rnd, sizeof(rnd), 0) <= 0)
424
0
        return 0;
425
0
    s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a);
426
0
    OPENSSL_cleanse(rnd, sizeof(rnd));
427
428
0
    if (!(s->srp_ctx.A = SRP_Calc_A(s->srp_ctx.a, s->srp_ctx.N, s->srp_ctx.g)))
429
0
        return 0;
430
431
0
    return 1;
432
0
}
433
434
int SRP_Calc_A_param(SSL *s)
435
0
{
436
0
    return ssl_srp_calc_a_param_intern(s);
437
0
}
438
439
BIGNUM *SSL_get_srp_g(SSL *s)
440
0
{
441
0
    if (s->srp_ctx.g != NULL)
442
0
        return s->srp_ctx.g;
443
0
    return s->ctx->srp_ctx.g;
444
0
}
445
446
BIGNUM *SSL_get_srp_N(SSL *s)
447
0
{
448
0
    if (s->srp_ctx.N != NULL)
449
0
        return s->srp_ctx.N;
450
0
    return s->ctx->srp_ctx.N;
451
0
}
452
453
char *SSL_get_srp_username(SSL *s)
454
0
{
455
0
    if (s->srp_ctx.login != NULL)
456
0
        return s->srp_ctx.login;
457
0
    return s->ctx->srp_ctx.login;
458
0
}
459
460
char *SSL_get_srp_userinfo(SSL *s)
461
0
{
462
0
    if (s->srp_ctx.info != NULL)
463
0
        return s->srp_ctx.info;
464
0
    return s->ctx->srp_ctx.info;
465
0
}
466
467
0
# define tls1_ctx_ctrl ssl3_ctx_ctrl
468
0
# define tls1_ctx_callback_ctrl ssl3_ctx_callback_ctrl
469
470
int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name)
471
0
{
472
0
    return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_USERNAME, 0, name);
473
0
}
474
475
int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password)
476
0
{
477
0
    return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD, 0, password);
478
0
}
479
480
int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength)
481
0
{
482
0
    return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH, strength,
483
0
                         NULL);
484
0
}
485
486
int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx,
487
                                          int (*cb) (SSL *, void *))
488
0
{
489
0
    return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_SRP_VERIFY_PARAM_CB,
490
0
                                  (void (*)(void))cb);
491
0
}
492
493
int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg)
494
0
{
495
0
    return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_SRP_ARG, 0, arg);
496
0
}
497
498
int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
499
                                      int (*cb) (SSL *, int *, void *))
500
0
{
501
0
    return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB,
502
0
                                  (void (*)(void))cb);
503
0
}
504
505
int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx,
506
                                        char *(*cb) (SSL *, void *))
507
0
{
508
0
    return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB,
509
0
                                  (void (*)(void))cb);
510
0
}
511
512
#endif