static const SSL_METHOD *ssl3_get_client_method(int ver);
static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b);
-#ifndef OPENSSL_NO_TLSEXT
-static int ssl3_check_finished(SSL *s);
-#endif
static const SSL_METHOD *ssl3_get_client_method(int ver)
{
{
BUF_MEM *buf=NULL;
unsigned long Time=(unsigned long)time(NULL);
- long num1;
void (*cb)(const SSL *ssl,int type,int val)=NULL;
int ret= -1;
int new_state,state,skip=0;
s->state=SSL3_ST_CW_CHANGE_A;
s->s3->change_cipher_spec=0;
}
+ if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY)
+ {
+ s->state=SSL3_ST_CW_CHANGE_A;
+ s->s3->change_cipher_spec=0;
+ }
s->init_num=0;
break;
break;
case SSL3_ST_CW_FLUSH:
- /* number of bytes to be flushed */
- num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL);
- if (num1 > 0)
+ s->rwstate=SSL_WRITING;
+ if (BIO_flush(s->wbio) <= 0)
{
- s->rwstate=SSL_WRITING;
- num1=BIO_flush(s->wbio);
- if (num1 <= 0) { ret= -1; goto end; }
- s->rwstate=SSL_NOTHING;
+ ret= -1;
+ goto end;
}
-
+ s->rwstate=SSL_NOTHING;
s->state=s->s3->tmp.next_state;
break;
buf=(unsigned char *)s->init_buf->data;
if (s->state == SSL3_ST_CW_CLNT_HELLO_A)
{
- if ((s->session == NULL) ||
- (s->session->ssl_version != s->version) ||
- (s->session->not_resumable))
+ SSL_SESSION *sess = s->session;
+ if ((sess == NULL) ||
+ (sess->ssl_version != s->version) ||
+#ifdef OPENSSL_NO_TLSEXT
+ !sess->session_id_length ||
+#else
+ (!sess->session_id_length && !sess->tlsext_tick) ||
+#endif
+ (sess->not_resumable))
{
if (!ssl_get_new_session(s,0))
goto err;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
goto f_err;
}
+ /* If compression is disabled we'd better not try to resume a session
+ * using compression.
+ */
+ if (s->session->compress_meth != 0)
+ {
+ al=SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_INCONSISTENT_COMPRESSION);
+ goto f_err;
+ }
#else
j= *(p++);
- if ((j == 0) || (s->options & SSL_OP_NO_COMPRESSION))
+ if (s->hit && j != s->session->compress_meth)
+ {
+ al=SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
+ goto f_err;
+ }
+ if (j == 0)
comp=NULL;
+ else if (s->options & SSL_OP_NO_COMPRESSION)
+ {
+ al=SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_COMPRESSION_DISABLED);
+ goto f_err;
+ }
else
comp=ssl3_comp_find(s->ctx->comp_methods,j);
#ifndef OPENSSL_NO_TLSEXT
/* TLS extensions*/
- if (s->version > SSL3_VERSION)
+ if (s->version >= SSL3_VERSION)
{
if (!ssl_parse_serverhello_tlsext(s,&p,d,n, &al))
{
SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
+
p=d=(unsigned char *)s->init_msg;
n2l(p, s->session->tlsext_tick_lifetime_hint);
n2s(p, ticklen);
}
memcpy(s->session->tlsext_tick, p, ticklen);
s->session->tlsext_ticklen = ticklen;
-
+ /* There are two ways to detect a resumed ticket sesion.
+ * One is to set an appropriate session ID and then the server
+ * must return a match in ServerHello. This allows the normal
+ * client session ID matching to work and we know much
+ * earlier that the ticket has been accepted.
+ *
+ * The other way is to set zero length session ID when the
+ * ticket is presented and rely on the handshake to determine
+ * session resumption.
+ *
+ * We choose the former approach because this fits in with
+ * assumptions elsewhere in OpenSSL. The session ID is set
+ * to the SHA256 (or SHA1 is SHA256 is disabled) hash of the
+ * ticket.
+ */
+ EVP_Digest(p, ticklen,
+ s->session->session_id, &s->session->session_id_length,
+#ifndef OPENSSL_NO_SHA256
+ EVP_sha256(), NULL);
+#else
+ EVP_sha1(), NULL);
+#endif
ret=1;
return(ret);
f_err:
krb5_data *enc_ticket;
krb5_data authenticator, *authp = NULL;
EVP_CIPHER_CTX ciph_ctx;
- EVP_CIPHER *enc = NULL;
+ const EVP_CIPHER *enc = NULL;
unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
unsigned char epms[SSL_MAX_MASTER_KEY_LENGTH
sizeof tmp_buf);
EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl);
outl += padl;
- if (outl > sizeof epms)
+ if (outl > (int)sizeof epms)
{
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
size_t msglen;
unsigned int md_len;
int keytype;
- unsigned char premaster_secret[32],shared_ukm[32];
+ unsigned char premaster_secret[32],shared_ukm[32], tmp[256];
EVP_MD_CTX *ukm_hash;
EVP_PKEY *pub_key;
/* Generate session key */
RAND_bytes(premaster_secret,32);
/* If we have client certificate, use its secret as peer key */
- if (s->cert->key->privatekey) {
- if (EVP_PKEY_derive_set_peer(pkey_ctx,s->cert->key->privatekey) <0) {
+ if (s->s3->tmp.cert_req && s->cert->key->privatekey) {
+ if (EVP_PKEY_derive_set_peer(pkey_ctx,s->cert->key->privatekey) <=0) {
/* If there was an error - just ignore it. Ephemeral key
* would be used
*/
ERR_clear_error();
- } else {
- /* Set flag "client cert key is used for key
- * exchange"*/
- }
+ }
}
/* Compute shared IV and store it in algorithm-specific
* context data */
/* Make GOST keytransport blob message */
/*Encapsulate it into sequence */
*(p++)=V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
- *(p++)=0x81;
- msglen=256;
- if (EVP_PKEY_encrypt(pkey_ctx,(unsigned char *)p+1,&msglen,premaster_secret,32)<0) {
+ msglen=255;
+ if (EVP_PKEY_encrypt(pkey_ctx,tmp,&msglen,premaster_secret,32)<0) {
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
SSL_R_LIBRARY_BUG);
goto err;
- }
- *(p++)= msglen & 0xff;
- n=msglen+3;
+ }
+ if (msglen >= 0x80)
+ {
+ *(p++)=0x81;
+ *(p++)= msglen & 0xff;
+ n=msglen+3;
+ }
+ else
+ {
+ *(p++)= msglen & 0xff;
+ n=msglen+2;
+ }
+ memcpy(p, tmp, msglen);
+ /* Check if pubkey from client certificate was used */
+ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
+ {
+ /* Set flag "skip certificate verify" */
+ s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
+ }
EVP_PKEY_CTX_free(pkey_ctx);
s->session->master_key_length=
s->method->ssl3_enc->generate_master_secret(s,
s->method->ssl3_enc->cert_verify_mac(s,
NID_id_GostR3411_94,
data);
- if (!EVP_PKEY_sign(pctx,signbuf,&sigsize,data,32)) {
+ if (EVP_PKEY_sign(pctx, signbuf, &sigsize, data, 32) <= 0) {
SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
ERR_R_INTERNAL_ERROR);
goto err;
*/
#ifndef OPENSSL_NO_TLSEXT
-static int ssl3_check_finished(SSL *s)
+int ssl3_check_finished(SSL *s)
{
int ok;
long n;