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