View | Details | Raw Unified | Return to bug 40189 | Differences between
and this patch

Collapse All | Expand All

(-)a/CHANGES (-1 / +18 lines)
 Lines 4-10    Link Here 
4
4
5
 Changes between 1.0.1r and 1.0.1s [xx XXX xxxx]
5
 Changes between 1.0.1r and 1.0.1s [xx XXX xxxx]
6
6
7
  *)
7
  *) Disable SRP fake user seed to address a server memory leak.
8
9
     Add a new method SRP_VBASE_get1_by_user that handles the seed properly.
10
11
     SRP_VBASE_get_by_user had inconsistent memory management behaviour.
12
     In order to fix an unavoidable memory leak, SRP_VBASE_get_by_user
13
     was changed to ignore the "fake user" SRP seed, even if the seed
14
     is configured.
15
16
     Users should use SRP_VBASE_get1_by_user instead. Note that in
17
     SRP_VBASE_get1_by_user, caller must free the returned value. Note
18
     also that even though configuring the SRP seed attempts to hide
19
     invalid usernames by continuing the handshake with fake
20
     credentials, this behaviour is not constant time and no strong
21
     guarantees are made that the handshake is indistinguishable from
22
     that of a valid user.
23
     (CVE-2016-0798)
24
     [Emilia Käsper]
8
25
9
 Changes between 1.0.1q and 1.0.1r [28 Jan 2016]
26
 Changes between 1.0.1q and 1.0.1r [28 Jan 2016]
10
27
(-)a/apps/s_server.c (-14 / +25 lines)
 Lines 416-421   typedef struct srpsrvparm_st { Link Here 
416
static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
416
static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
417
{
417
{
418
    srpsrvparm *p = (srpsrvparm *) arg;
418
    srpsrvparm *p = (srpsrvparm *) arg;
419
    int ret = SSL3_AL_FATAL;
420
419
    if (p->login == NULL && p->user == NULL) {
421
    if (p->login == NULL && p->user == NULL) {
420
        p->login = SSL_get_srp_username(s);
422
        p->login = SSL_get_srp_username(s);
421
        BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login);
423
        BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login);
 Lines 424-444   static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) Link Here 
424
426
425
    if (p->user == NULL) {
427
    if (p->user == NULL) {
426
        BIO_printf(bio_err, "User %s doesn't exist\n", p->login);
428
        BIO_printf(bio_err, "User %s doesn't exist\n", p->login);
427
        return SSL3_AL_FATAL;
429
        goto err;
428
    }
430
    }
431
429
    if (SSL_set_srp_server_param
432
    if (SSL_set_srp_server_param
430
        (s, p->user->N, p->user->g, p->user->s, p->user->v,
433
        (s, p->user->N, p->user->g, p->user->s, p->user->v,
431
         p->user->info) < 0) {
434
         p->user->info) < 0) {
432
        *ad = SSL_AD_INTERNAL_ERROR;
435
        *ad = SSL_AD_INTERNAL_ERROR;
433
        return SSL3_AL_FATAL;
436
        goto err;
434
    }
437
    }
435
    BIO_printf(bio_err,
438
    BIO_printf(bio_err,
436
               "SRP parameters set: username = \"%s\" info=\"%s\" \n",
439
               "SRP parameters set: username = \"%s\" info=\"%s\" \n",
437
               p->login, p->user->info);
440
               p->login, p->user->info);
438
    /* need to check whether there are memory leaks */
441
    ret = SSL_ERROR_NONE;
442
443
err:
444
    SRP_user_pwd_free(p->user);
439
    p->user = NULL;
445
    p->user = NULL;
440
    p->login = NULL;
446
    p->login = NULL;
441
    return SSL_ERROR_NONE;
447
    return ret;
442
}
448
}
443
449
444
#endif
450
#endif
 Lines 2244-2252   static int sv_body(char *hostname, int s, unsigned char *context) Link Here 
2244
#ifndef OPENSSL_NO_SRP
2250
#ifndef OPENSSL_NO_SRP
2245
                while (SSL_get_error(con, k) == SSL_ERROR_WANT_X509_LOOKUP) {
2251
                while (SSL_get_error(con, k) == SSL_ERROR_WANT_X509_LOOKUP) {
2246
                    BIO_printf(bio_s_out, "LOOKUP renego during write\n");
2252
                    BIO_printf(bio_s_out, "LOOKUP renego during write\n");
2253
                    SRP_user_pwd_free(srp_callback_parm.user);
2247
                    srp_callback_parm.user =
2254
                    srp_callback_parm.user =
2248
                        SRP_VBASE_get_by_user(srp_callback_parm.vb,
2255
                        SRP_VBASE_get1_by_user(srp_callback_parm.vb,
2249
                                              srp_callback_parm.login);
2256
                                               srp_callback_parm.login);
2250
                    if (srp_callback_parm.user)
2257
                    if (srp_callback_parm.user)
2251
                        BIO_printf(bio_s_out, "LOOKUP done %s\n",
2258
                        BIO_printf(bio_s_out, "LOOKUP done %s\n",
2252
                                   srp_callback_parm.user->info);
2259
                                   srp_callback_parm.user->info);
 Lines 2300-2308   static int sv_body(char *hostname, int s, unsigned char *context) Link Here 
2300
#ifndef OPENSSL_NO_SRP
2307
#ifndef OPENSSL_NO_SRP
2301
                while (SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
2308
                while (SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
2302
                    BIO_printf(bio_s_out, "LOOKUP renego during read\n");
2309
                    BIO_printf(bio_s_out, "LOOKUP renego during read\n");
2310
                    SRP_user_pwd_free(srp_callback_parm.user);
2303
                    srp_callback_parm.user =
2311
                    srp_callback_parm.user =
2304
                        SRP_VBASE_get_by_user(srp_callback_parm.vb,
2312
                        SRP_VBASE_get1_by_user(srp_callback_parm.vb,
2305
                                              srp_callback_parm.login);
2313
                                               srp_callback_parm.login);
2306
                    if (srp_callback_parm.user)
2314
                    if (srp_callback_parm.user)
2307
                        BIO_printf(bio_s_out, "LOOKUP done %s\n",
2315
                        BIO_printf(bio_s_out, "LOOKUP done %s\n",
2308
                                   srp_callback_parm.user->info);
2316
                                   srp_callback_parm.user->info);
 Lines 2387-2395   static int init_ssl_connection(SSL *con) Link Here 
2387
    while (i <= 0 && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
2395
    while (i <= 0 && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
2388
        BIO_printf(bio_s_out, "LOOKUP during accept %s\n",
2396
        BIO_printf(bio_s_out, "LOOKUP during accept %s\n",
2389
                   srp_callback_parm.login);
2397
                   srp_callback_parm.login);
2398
        SRP_user_pwd_free(srp_callback_parm.user);
2390
        srp_callback_parm.user =
2399
        srp_callback_parm.user =
2391
            SRP_VBASE_get_by_user(srp_callback_parm.vb,
2400
            SRP_VBASE_get1_by_user(srp_callback_parm.vb,
2392
                                  srp_callback_parm.login);
2401
                                   srp_callback_parm.login);
2393
        if (srp_callback_parm.user)
2402
        if (srp_callback_parm.user)
2394
            BIO_printf(bio_s_out, "LOOKUP done %s\n",
2403
            BIO_printf(bio_s_out, "LOOKUP done %s\n",
2395
                       srp_callback_parm.user->info);
2404
                       srp_callback_parm.user->info);
 Lines 2616-2624   static int www_body(char *hostname, int s, unsigned char *context) Link Here 
2616
                   && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
2625
                   && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
2617
                BIO_printf(bio_s_out, "LOOKUP during accept %s\n",
2626
                BIO_printf(bio_s_out, "LOOKUP during accept %s\n",
2618
                           srp_callback_parm.login);
2627
                           srp_callback_parm.login);
2628
                SRP_user_pwd_free(srp_callback_parm.user);
2619
                srp_callback_parm.user =
2629
                srp_callback_parm.user =
2620
                    SRP_VBASE_get_by_user(srp_callback_parm.vb,
2630
                    SRP_VBASE_get1_by_user(srp_callback_parm.vb,
2621
                                          srp_callback_parm.login);
2631
                                           srp_callback_parm.login);
2622
                if (srp_callback_parm.user)
2632
                if (srp_callback_parm.user)
2623
                    BIO_printf(bio_s_out, "LOOKUP done %s\n",
2633
                    BIO_printf(bio_s_out, "LOOKUP done %s\n",
2624
                               srp_callback_parm.user->info);
2634
                               srp_callback_parm.user->info);
 Lines 2658-2666   static int www_body(char *hostname, int s, unsigned char *context) Link Here 
2658
                if (BIO_should_io_special(io)
2668
                if (BIO_should_io_special(io)
2659
                    && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
2669
                    && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
2660
                    BIO_printf(bio_s_out, "LOOKUP renego during read\n");
2670
                    BIO_printf(bio_s_out, "LOOKUP renego during read\n");
2671
                    SRP_user_pwd_free(srp_callback_parm.user);
2661
                    srp_callback_parm.user =
2672
                    srp_callback_parm.user =
2662
                        SRP_VBASE_get_by_user(srp_callback_parm.vb,
2673
                        SRP_VBASE_get1_by_user(srp_callback_parm.vb,
2663
                                              srp_callback_parm.login);
2674
                                               srp_callback_parm.login);
2664
                    if (srp_callback_parm.user)
2675
                    if (srp_callback_parm.user)
2665
                        BIO_printf(bio_s_out, "LOOKUP done %s\n",
2676
                        BIO_printf(bio_s_out, "LOOKUP done %s\n",
2666
                                   srp_callback_parm.user->info);
2677
                                   srp_callback_parm.user->info);
(-)a/crypto/srp/srp.h (+10 lines)
 Lines 82-97   typedef struct SRP_gN_cache_st { Link Here 
82
DECLARE_STACK_OF(SRP_gN_cache)
82
DECLARE_STACK_OF(SRP_gN_cache)
83
83
84
typedef struct SRP_user_pwd_st {
84
typedef struct SRP_user_pwd_st {
85
    /* Owned by us. */
85
    char *id;
86
    char *id;
86
    BIGNUM *s;
87
    BIGNUM *s;
87
    BIGNUM *v;
88
    BIGNUM *v;
89
    /* Not owned by us. */
88
    const BIGNUM *g;
90
    const BIGNUM *g;
89
    const BIGNUM *N;
91
    const BIGNUM *N;
92
    /* Owned by us. */
90
    char *info;
93
    char *info;
91
} SRP_user_pwd;
94
} SRP_user_pwd;
92
95
93
DECLARE_STACK_OF(SRP_user_pwd)
96
DECLARE_STACK_OF(SRP_user_pwd)
94
97
98
void SRP_user_pwd_free(SRP_user_pwd *user_pwd);
99
95
typedef struct SRP_VBASE_st {
100
typedef struct SRP_VBASE_st {
96
    STACK_OF(SRP_user_pwd) *users_pwd;
101
    STACK_OF(SRP_user_pwd) *users_pwd;
97
    STACK_OF(SRP_gN_cache) *gN_cache;
102
    STACK_OF(SRP_gN_cache) *gN_cache;
 Lines 115-121   DECLARE_STACK_OF(SRP_gN) Link Here 
115
SRP_VBASE *SRP_VBASE_new(char *seed_key);
120
SRP_VBASE *SRP_VBASE_new(char *seed_key);
116
int SRP_VBASE_free(SRP_VBASE *vb);
121
int SRP_VBASE_free(SRP_VBASE *vb);
117
int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file);
122
int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file);
123
124
/* This method ignores the configured seed and fails for an unknown user. */
118
SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username);
125
SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username);
126
/* NOTE: unlike in SRP_VBASE_get_by_user, caller owns the returned pointer.*/
127
SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username);
128
119
char *SRP_create_verifier(const char *user, const char *pass, char **salt,
129
char *SRP_create_verifier(const char *user, const char *pass, char **salt,
120
                          char **verifier, const char *N, const char *g);
130
                          char **verifier, const char *N, const char *g);
121
int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,
131
int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,
(-)a/crypto/srp/srp_vfy.c (-5 / +52 lines)
 Lines 185-191   static char *t_tob64(char *dst, const unsigned char *src, int size) Link Here 
185
    return olddst;
185
    return olddst;
186
}
186
}
187
187
188
static void SRP_user_pwd_free(SRP_user_pwd *user_pwd)
188
void SRP_user_pwd_free(SRP_user_pwd *user_pwd)
189
{
189
{
190
    if (user_pwd == NULL)
190
    if (user_pwd == NULL)
191
        return;
191
        return;
 Lines 247-252   static int SRP_user_pwd_set_sv_BN(SRP_user_pwd *vinfo, BIGNUM *s, BIGNUM *v) Link Here 
247
    return (vinfo->s != NULL && vinfo->v != NULL);
247
    return (vinfo->s != NULL && vinfo->v != NULL);
248
}
248
}
249
249
250
static SRP_user_pwd *srp_user_pwd_dup(SRP_user_pwd *src)
251
{
252
    SRP_user_pwd *ret;
253
254
    if (src == NULL)
255
        return NULL;
256
    if ((ret = SRP_user_pwd_new()) == NULL)
257
        return NULL;
258
259
    SRP_user_pwd_set_gN(ret, src->g, src->N);
260
    if (!SRP_user_pwd_set_ids(ret, src->id, src->info)
261
        || !SRP_user_pwd_set_sv_BN(ret, BN_dup(src->s), BN_dup(src->v))) {
262
            SRP_user_pwd_free(ret);
263
            return NULL;
264
    }
265
    return ret;
266
}
267
250
SRP_VBASE *SRP_VBASE_new(char *seed_key)
268
SRP_VBASE *SRP_VBASE_new(char *seed_key)
251
{
269
{
252
    SRP_VBASE *vb = (SRP_VBASE *)OPENSSL_malloc(sizeof(SRP_VBASE));
270
    SRP_VBASE *vb = (SRP_VBASE *)OPENSSL_malloc(sizeof(SRP_VBASE));
 Lines 468-488   int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file) Link Here 
468
486
469
}
487
}
470
488
471
SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username)
489
static SRP_user_pwd *find_user(SRP_VBASE *vb, char *username)
472
{
490
{
473
    int i;
491
    int i;
474
    SRP_user_pwd *user;
492
    SRP_user_pwd *user;
475
    unsigned char digv[SHA_DIGEST_LENGTH];
476
    unsigned char digs[SHA_DIGEST_LENGTH];
477
    EVP_MD_CTX ctxt;
478
493
479
    if (vb == NULL)
494
    if (vb == NULL)
480
        return NULL;
495
        return NULL;
496
481
    for (i = 0; i < sk_SRP_user_pwd_num(vb->users_pwd); i++) {
497
    for (i = 0; i < sk_SRP_user_pwd_num(vb->users_pwd); i++) {
482
        user = sk_SRP_user_pwd_value(vb->users_pwd, i);
498
        user = sk_SRP_user_pwd_value(vb->users_pwd, i);
483
        if (strcmp(user->id, username) == 0)
499
        if (strcmp(user->id, username) == 0)
484
            return user;
500
            return user;
485
    }
501
    }
502
503
    return NULL;
504
}
505
506
/*
507
 * This method ignores the configured seed and fails for an unknown user.
508
 * Ownership of the returned pointer is not released to the caller.
509
 * In other words, caller must not free the result.
510
 */
511
SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username)
512
{
513
    return find_user(vb, username);
514
}
515
516
/*
517
 * Ownership of the returned pointer is released to the caller.
518
 * In other words, caller must free the result once done.
519
 */
520
SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username)
521
{
522
    SRP_user_pwd *user;
523
    unsigned char digv[SHA_DIGEST_LENGTH];
524
    unsigned char digs[SHA_DIGEST_LENGTH];
525
    EVP_MD_CTX ctxt;
526
527
    if (vb == NULL)
528
        return NULL;
529
530
    if ((user = find_user(vb, username)) != NULL)
531
        return srp_user_pwd_dup(user);
532
486
    if ((vb->seed_key == NULL) ||
533
    if ((vb->seed_key == NULL) ||
487
        (vb->default_g == NULL) || (vb->default_N == NULL))
534
        (vb->default_g == NULL) || (vb->default_N == NULL))
488
        return NULL;
535
        return NULL;
(-)a/util/libeay.num (+2 lines)
 Lines 1807-1812   ASN1_UTCTIME_get 2350 NOEXIST::FUNCTION: Link Here 
1807
X509_REQ_digest                         2362	EXIST::FUNCTION:EVP
1807
X509_REQ_digest                         2362	EXIST::FUNCTION:EVP
1808
X509_CRL_digest                         2391	EXIST::FUNCTION:EVP
1808
X509_CRL_digest                         2391	EXIST::FUNCTION:EVP
1809
ASN1_STRING_clear_free                  2392	EXIST::FUNCTION:
1809
ASN1_STRING_clear_free                  2392	EXIST::FUNCTION:
1810
SRP_VBASE_get1_by_user                  2393	EXIST::FUNCTION:SRP
1811
SRP_user_pwd_free                       2394	EXIST::FUNCTION:SRP
1810
d2i_ASN1_SET_OF_PKCS7                   2397	NOEXIST::FUNCTION:
1812
d2i_ASN1_SET_OF_PKCS7                   2397	NOEXIST::FUNCTION:
1811
X509_ALGOR_cmp                          2398	EXIST::FUNCTION:
1813
X509_ALGOR_cmp                          2398	EXIST::FUNCTION:
1812
EVP_CIPHER_CTX_set_key_length           2399	EXIST::FUNCTION:
1814
EVP_CIPHER_CTX_set_key_length           2399	EXIST::FUNCTION:

Return to bug 40189