#define NETSCAPE_HANG_BUG
#include <stdio.h>
+#include <openssl/crypto.h>
#include "ssl_locl.h"
#include "kssl_lcl.h"
#include <openssl/buffer.h>
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,
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;
+#endif
RAND_add(&Time,sizeof(Time),0);
ERR_clear_error();
switch (s->state)
{
case SSL_ST_RENEGOTIATE:
- s->new_session=1;
+ s->renegotiate=1;
/* s->state=SSL_ST_ACCEPT; */
case SSL_ST_BEFORE:
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
+ {
+ int extension_error = 0,al;
+
+ 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_ACCEPT,SSL_R_CLIENTHELLO_TLSEXT);
+ goto end;
+ }
+ }
+#endif
- s->new_session = 2;
+ s->renegotiate = 2;
s->state=SSL3_ST_SW_SRVR_HELLO_A;
s->init_num=0;
break;
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))
* hint if provided */
#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)
* the client uses its key from the certificate
* for key exchange.
*/
-#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NPN)
+#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
s->state=SSL3_ST_SR_FINISHED_A;
#else
if (s->s3->next_proto_neg_seen)
ret=ssl3_get_cert_verify(s);
if (ret <= 0) goto end;
-#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NPN)
+#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
s->state=SSL3_ST_SR_FINISHED_A;
#else
if (s->s3->next_proto_neg_seen)
s->init_num=0;
break;
-#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NPN)
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
case SSL3_ST_SR_NEXT_PROTO_A:
case SSL3_ST_SR_NEXT_PROTO_B:
ret=ssl3_get_next_proto(s);
s->state=SSL3_ST_SW_FLUSH;
if (s->hit)
{
-#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NPN)
+#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
#else
if (s->s3->next_proto_neg_seen)
s->init_num=0;
- if (s->new_session == 2) /* skipped if we just sent a HelloRequest */
+ if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */
{
/* actually not necessarily a 'new' session unless
* SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
+ s->renegotiate=0;
s->new_session=0;
ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
* 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;
}
break;
}
}
+/* Disabled because it can be used in a ciphersuite downgrade
+ * attack: CVE-2010-4180.
+ */
+#if 0
if (j == 0 && (s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1))
{
/* Special case as client bug workaround: the previously used cipher may
j = 1;
}
}
+#endif
if (j == 0)
{
/* we need to have the cipher in the cipher
goto f_err;
}
s->s3->tmp.new_cipher=c;
+ /* check whether we should disable session resumption */
+ if (s->not_resumable_session_cb != NULL)
+ s->session->not_resumable=s->not_resumable_session_cb(s,
+ ((c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH)) != 0));
+ if (s->session->not_resumable)
+ /* do not send a session ticket */
+ s->tlsext_ticket_expected = 0;
}
else
{
* if session caching is disabled so existing functionality
* is unaffected.
*/
- if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
- && !s->hit)
+ if (s->session->not_resumable ||
+ (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
+ && !s->hit))
s->session->session_id_length=0;
sl=s->session->session_id_length;
BN_CTX *bn_ctx = NULL;
#endif
EVP_PKEY *pkey;
+ const EVP_MD *md = NULL;
unsigned char *p,*d;
int al,i;
unsigned long type;
}
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];
}
if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
{
- if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
+ if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher,&md))
== NULL)
{
al=SSL_AD_DECODE_ERROR;
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];
(unsigned char *)encodedPoint,
encodedlen);
OPENSSL_free(encodedPoint);
+ encodedPoint = NULL;
p += encodedlen;
}
#endif
/* n is the length of the params, they start at &(d[4])
* and p points to the space at the end. */
#ifndef OPENSSL_NO_RSA
- if (pkey->type == EVP_PKEY_RSA)
+ if (pkey->type == EVP_PKEY_RSA
+ && s->version < TLS1_2_VERSION)
{
q=md_buf;
j=0;
{
EVP_DigestInit_ex(&md_ctx,(num == 2)
?s->ctx->md5:s->ctx->sha1, NULL);
+ EVP_MD_CTX_set_flags(&md_ctx,
+ EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
EVP_DigestUpdate(&md_ctx,&(d[4]),n);
}
else
#endif
-#if !defined(OPENSSL_NO_DSA)
- if (pkey->type == EVP_PKEY_DSA)
+ if (md)
{
- /* lets do DSS */
- EVP_SignInit_ex(&md_ctx,EVP_dss1(), NULL);
- EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
- EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
- EVP_SignUpdate(&md_ctx,&(d[4]),n);
- if (!EVP_SignFinal(&md_ctx,&(p[2]),
- (unsigned int *)&i,pkey))
+ /* For TLS1.2 and later send signature
+ * algorithm */
+ if (s->version >= TLS1_2_VERSION)
{
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_DSA);
- goto err;
+ if (!tls12_get_sigandhash(p, pkey, md))
+ {
+ /* Should never happen */
+ al=SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
+ p+=2;
}
- s2n(i,p);
- n+=i+2;
- }
- else
+#ifdef SSL_DEBUG
+ fprintf(stderr, "Using hash %s\n",
+ EVP_MD_name(md));
#endif
-#if !defined(OPENSSL_NO_ECDSA)
- if (pkey->type == EVP_PKEY_EC)
- {
- /* let's do ECDSA */
- EVP_SignInit_ex(&md_ctx,EVP_ecdsa(), NULL);
+ EVP_SignInit_ex(&md_ctx, md, NULL);
EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
EVP_SignUpdate(&md_ctx,&(d[4]),n);
if (!EVP_SignFinal(&md_ctx,&(p[2]),
(unsigned int *)&i,pkey))
{
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_ECDSA);
+ SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_EVP);
goto err;
}
s2n(i,p);
n+=i+2;
+ if (s->version >= TLS1_2_VERSION)
+ n+= 2;
}
else
-#endif
{
/* Is this error check actually needed? */
al=SSL_AD_HANDSHAKE_FAILURE;
}
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_CLIENT_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_CLIENT_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_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ p+=i;
+ }
+ else
+#endif /* OPENSSL_NO_SRP */
if (alg_k & SSL_kGOST)
{
int ret = 0;
EVP_PKEY_CTX *pkey_ctx;
- EVP_PKEY *client_pub_pkey = NULL;
+ EVP_PKEY *client_pub_pkey = NULL, *pk = NULL;
unsigned char premaster_secret[32], *start;
- size_t outlen=32, inlen;
+ size_t outlen=32, inlen;
+ unsigned long alg_a;
/* Get our certificate private key*/
- pkey_ctx = EVP_PKEY_CTX_new(s->cert->key->privatekey,NULL);
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+ if (alg_a & SSL_aGOST94)
+ pk = s->cert->pkeys[SSL_PKEY_GOST94].privatekey;
+ else if (alg_a & SSL_aGOST01)
+ pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
+
+ pkey_ctx = EVP_PKEY_CTX_new(pk,NULL);
EVP_PKEY_decrypt_init(pkey_ctx);
/* If client certificate is present and is of the same type, maybe
* use it for key exchange. Don't mind errors from
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
int ssl3_get_next_proto(SSL *s)
{
int ok;
- unsigned proto_len, padding_len;
+ int proto_len, padding_len;
long n;
const unsigned char *p;
SSL3_ST_SR_NEXT_PROTO_A,
SSL3_ST_SR_NEXT_PROTO_B,
SSL3_MT_NEXT_PROTO,
- 129,
+ 514, /* See the payload format below */
&ok);
if (!ok)