diff options
author | Ben Laurie <ben@openssl.org> | 2011-03-16 11:26:40 +0000 |
---|---|---|
committer | Ben Laurie <ben@openssl.org> | 2011-03-16 11:26:40 +0000 |
commit | a149b2466e8adb97b1fe855d189bac58d3b654dd (patch) | |
tree | a8c1960c89edb19bcd34a71aa875cb0f2930e96a /ssl/s3_srvr.c | |
parent | 13e230d50546a964b5090c1e5df80cc7faf8821c (diff) |
Add SRP.
Diffstat (limited to 'ssl/s3_srvr.c')
-rw-r--r-- | ssl/s3_srvr.c | 140 |
1 files changed, 135 insertions, 5 deletions
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 1b99a946a7..758f090a87 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -179,6 +179,31 @@ static const SSL_METHOD *ssl3_get_server_method(int ver) return(NULL); } +#ifndef OPENSSL_NO_SRP +static int SSL_check_srp_ext_ClientHello(SSL *s, int *ad) + { + int ret = SSL_ERROR_NONE; + + *ad = SSL_AD_UNRECOGNIZED_NAME; + + if ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) && + (s->srp_ctx.TLS_ext_srp_username_callback != NULL)) + { + if(s->srp_ctx.login == NULL) + { + /* There isn't any srp login extension !!! */ + ret = SSL3_AL_WARNING; + *ad = SSL_AD_MISSING_SRP_USERNAME; + } + else + { + ret = SSL_srp_server_param_with_username(s,ad); + } + } + return ret; + } +#endif + IMPLEMENT_ssl3_meth_func(SSLv3_server_method, ssl3_accept, ssl_undefined_function, @@ -191,6 +216,10 @@ int ssl3_accept(SSL *s) void (*cb)(const SSL *ssl,int type,int val)=NULL; int ret= -1; int new_state,state,skip=0; +#ifndef OPENSSL_NO_SRP + int srp_no_username=0; + int extension_error,al; +#endif RAND_add(&Time,sizeof(Time),0); ERR_clear_error(); @@ -311,10 +340,34 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_CLNT_HELLO_A: case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_C: +#ifndef OPENSSL_NO_SRP + case SSL3_ST_SR_CLNT_HELLO_SRP_USERNAME: +#endif s->shutdown=0; ret=ssl3_get_client_hello(s); if (ret <= 0) goto end; +#ifndef OPENSSL_NO_SRP + extension_error = 0; + if ((al = SSL_check_srp_ext_ClientHello(s,&extension_error)) != SSL_ERROR_NONE) + { + ssl3_send_alert(s,al,extension_error); + if (extension_error == SSL_AD_MISSING_SRP_USERNAME) + { + if (srp_no_username) goto end; + ERR_clear_error(); + srp_no_username = 1; + s->state=SSL3_ST_SR_CLNT_HELLO_SRP_USERNAME; + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + if ((ret=BIO_flush(s->wbio)) <= 0) goto end; + s->init_num=0; + break; + } + ret = -1; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); + goto end; + } +#endif s->renegotiate = 2; s->state=SSL3_ST_SW_SRVR_HELLO_A; @@ -345,7 +398,7 @@ int ssl3_accept(SSL *s) case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: /* Check if it is anon DH or anon ECDH, */ - /* normal PSK or KRB5 */ + /* normal PSK or KRB5 or SRP */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK) && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)) @@ -410,6 +463,10 @@ int ssl3_accept(SSL *s) #ifndef OPENSSL_NO_PSK || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) #endif +#ifndef OPENSSL_NO_SRP + /* SRP: send ServerKeyExchange */ + || (alg_k & SSL_kSRP) +#endif || (alg_k & (SSL_kDHr|SSL_kDHd|SSL_kEDH)) || (alg_k & SSL_kEECDH) || ((alg_k & SSL_kRSA) @@ -803,7 +860,11 @@ int ssl3_get_client_hello(SSL *s) * If we are SSLv3, we will respond with SSLv3, even if prompted with * TLSv1. */ - if (s->state == SSL3_ST_SR_CLNT_HELLO_A) + if (s->state == SSL3_ST_SR_CLNT_HELLO_A +#ifndef OPENSSL_NO_SRP + || (s->state == SSL3_ST_SR_CLNT_HELLO_SRP_USERNAME) +#endif + ) { s->state=SSL3_ST_SR_CLNT_HELLO_B; } @@ -1668,14 +1729,37 @@ int ssl3_send_server_key_exchange(SSL *s) } else #endif /* !OPENSSL_NO_PSK */ +#ifndef OPENSSL_NO_SRP + if (type & SSL_kSRP) + { + if ((s->srp_ctx.N == NULL) || + (s->srp_ctx.g == NULL) || + (s->srp_ctx.s == NULL) || + (s->srp_ctx.B == NULL)) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_SRP_PARAM); + goto err; + } + r[0]=s->srp_ctx.N; + r[1]=s->srp_ctx.g; + r[2]=s->srp_ctx.s; + r[3]=s->srp_ctx.B; + } + else +#endif { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); goto f_err; } - for (i=0; r[i] != NULL; i++) + for (i=0; r[i] != NULL && i<4; i++) { nr[i]=BN_num_bytes(r[i]); +#ifndef OPENSSL_NO_SRP + if ((i == 2) && (type & SSL_kSRP)) + n+=1+nr[i]; + else +#endif n+=2+nr[i]; } @@ -1704,8 +1788,16 @@ int ssl3_send_server_key_exchange(SSL *s) d=(unsigned char *)s->init_buf->data; p= &(d[4]); - for (i=0; r[i] != NULL; i++) + for (i=0; r[i] != NULL && i<4; i++) { +#ifndef OPENSSL_NO_SRP + if ((i == 2) && (type & SSL_kSRP)) + { + *p = nr[i]; + p++; + } + else +#endif s2n(nr[i],p); BN_bn2bin(r[i],p); p+=nr[i]; @@ -2581,6 +2673,44 @@ int ssl3_get_client_key_exchange(SSL *s) } else #endif +#ifndef OPENSSL_NO_SRP + if (alg_k & SSL_kSRP) + { + int param_len; + + n2s(p,i); + param_len=i+2; + if (param_len > n) + { + al=SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_A_LENGTH); + goto f_err; + } + if (!(s->srp_ctx.A=BN_bin2bn(p,i,NULL))) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB); + goto err; + } + if (s->session->srp_username != NULL) + OPENSSL_free(s->session->srp_username); + s->session->srp_username = BUF_strdup(s->srp_ctx.login); + if (s->session->srp_username == NULL) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if ((s->session->master_key_length = SRP_generate_server_master_secret(s,s->session->master_key))<0) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); + goto err; + } + + p+=i; + } + else +#endif /* OPENSSL_NO_SRP */ if (alg_k & SSL_kGOST) { int ret = 0; @@ -2664,7 +2794,7 @@ int ssl3_get_client_key_exchange(SSL *s) return(1); f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); -#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_ECDH) +#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_ECDH) || defined(OPENSSL_NO_SRP) err: #endif #ifndef OPENSSL_NO_ECDH |