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();
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->renegotiate = 2;
s->state=SSL3_ST_SW_SRVR_HELLO_A;
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)
skip=1;
s->s3->tmp.cert_request=0;
s->state=SSL3_ST_SW_SRVR_DONE_A;
+ if (s->s3->handshake_buffer)
+ if (!ssl3_digest_cached_records(s))
+ return -1;
}
else
{
#endif
s->init_num = 0;
}
+ else if (TLS1_get_version(s) >= TLS1_2_VERSION)
+ {
+ s->state=SSL3_ST_SR_CERT_VRFY_A;
+ s->init_num=0;
+ if (!s->session->peer)
+ break;
+ /* For TLS v1.2 freeze the handshake buffer
+ * at this point and digest cached records.
+ */
+ if (!s->s3->handshake_buffer)
+ {
+ SSLerr(SSL_F_SSL3_ACCEPT,ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
+ if (!ssl3_digest_cached_records(s))
+ return -1;
+ }
else
{
int offset=0;
* 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;
}
s->s3->tmp.new_cipher=s->session->cipher;
}
- if (!ssl3_digest_cached_records(s))
- goto f_err;
+ if (TLS1_get_version(s) < TLS1_2_VERSION || !(s->verify_mode & SSL_VERIFY_PEER))
+ {
+ if (!ssl3_digest_cached_records(s))
+ goto f_err;
+ }
/* we now have the following setup.
* client_random
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
+ && TLS1_get_version(s) < 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 (TLS1_get_version(s) >= 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 (TLS1_get_version(s) >= TLS1_2_VERSION)
+ n+= 2;
}
else
-#endif
{
/* Is this error check actually needed? */
al=SSL_AD_HANDSHAKE_FAILURE;
p+=n;
n++;
+ if (TLS1_get_version(s) >= TLS1_2_VERSION)
+ {
+ nl = tls12_get_req_sig_algs(s, p + 2);
+ s2n(nl, p);
+ p += nl + 2;
+ n += nl + 2;
+ }
+
off=n;
p+=2;
n+=2;
}
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;
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
long n;
int type=0,i,j;
X509 *peer;
+ const EVP_MD *md = NULL;
+ EVP_MD_CTX mctx;
+ EVP_MD_CTX_init(&mctx);
n=s->method->ssl_get_message(s,
SSL3_ST_SR_CERT_VRFY_A,
}
else
{
+ if (TLS1_get_version(s) >= TLS1_2_VERSION)
+ {
+ int sigalg = tls12_get_sigid(pkey);
+ /* Should never happen */
+ if (sigalg == -1)
+ {
+ SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
+ al=SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ /* Check key type is consistent with signature */
+ if (sigalg != (int)p[1])
+ {
+ SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_TYPE);
+ al=SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+ md = tls12_get_hash(p[0]);
+ if (md == NULL)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNKNOWN_DIGEST);
+ al=SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+#ifdef SSL_DEBUG
+fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
+#endif
+ p += 2;
+ n -= 2;
+ }
n2s(p,i);
n-=2;
if (i > n)
goto f_err;
}
+ if (TLS1_get_version(s) >= TLS1_2_VERSION)
+ {
+ long hdatalen = 0;
+ void *hdata;
+ hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+ if (hdatalen <= 0)
+ {
+ SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+ al=SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+#ifdef SSL_DEBUG
+ fprintf(stderr, "Using TLS 1.2 with client verify alg %s\n",
+ EVP_MD_name(md));
+#endif
+ if (!EVP_VerifyInit_ex(&mctx, md, NULL)
+ || !EVP_VerifyUpdate(&mctx, hdata, hdatalen))
+ {
+ SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_EVP_LIB);
+ al=SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+
+ if (EVP_VerifyFinal(&mctx, p , i, pkey) <= 0)
+ {
+ al=SSL_AD_DECRYPT_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_SIGNATURE);
+ goto f_err;
+ }
+ }
+ else
#ifndef OPENSSL_NO_RSA
if (pkey->type == EVP_PKEY_RSA)
{
ssl3_send_alert(s,SSL3_AL_FATAL,al);
}
end:
+ if (s->s3->handshake_buffer)
+ {
+ BIO_free(s->s3->handshake_buffer);
+ s->s3->handshake_buffer = NULL;
+ s->s3->flags &= ~TLS1_FLAGS_KEEP_HANDSHAKE;
+ }
+ EVP_MD_CTX_cleanup(&mctx);
EVP_PKEY_free(pkey);
return(ret);
}
al=SSL_AD_HANDSHAKE_FAILURE;
goto f_err;
}
+ /* No client certificate so digest cached records */
+ if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s))
+ {
+ al=SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
}
else
{