コード例 #1
0
ファイル: matrix.c プロジェクト: dkogan/PDL
void GSR(const int n, double **A) {

  int      i, j, k;     /* counters     */
  double   dot; 

  for(k=0; k<n; k++) {               /* orthogonalisation */
    for(j=(k+1); j<n; j++) {
      dot=0.0;                       /* dot product <Aj, Ak> */ 
      for(i=0; i<n; i++) 
	dot+=A[i][j]*A[i][k];
      for(i=0; i<n; i++)
	A[i][j]-=A[i][k]/dot;
    } /* for j */
  } /* for k */

  for(k=0; k<n; k++) {              /* normalisation */
    dot=0.0;                        /* Compute (L2 norm) */
    for(i=0; i<n; i++)
      dot+=A[i][k]*A[i][k];
    dot=sqrt(dot);
    if (dot==0.0) 
      SSLerror("Norm = 0 in routine GSR");
    for(i=0; i<n; i++)
      A[i][k]/=dot;
  } /* for k */
} /* GSR */
コード例 #2
0
ファイル: ssl_rsa.c プロジェクト: libressl-portable/openbsd
int
SSL_use_certificate(SSL *ssl, X509 *x)
{
	if (x == NULL) {
		SSLerror(ssl, ERR_R_PASSED_NULL_PARAMETER);
		return (0);
	}
	return (ssl_set_cert(ssl->cert, x));
}
コード例 #3
0
ファイル: matrix.c プロジェクト: dkogan/PDL
SSL_Complex *SSL_ComplexVectorAlloc(const int n) {

  SSL_Complex *temp;

  temp=(SSL_Complex *)calloc(n, sizeof(SSL_Complex));
  if (temp==NULL) 
    SSLerror("No memory available in routine SSL_ComplexVectorAlloc");
  return temp;
} /* SSL_ComplexVectorAlloc */
コード例 #4
0
ファイル: matrix.c プロジェクト: dkogan/PDL
double *VectorAlloc(const int n) {

  double *temp;

  temp=(double *)calloc(n, sizeof(double));
  if (temp==NULL)
    SSLerror("No memory available in routine VectorAlloc");
  return temp;
} /* VectorAlloc */
コード例 #5
0
ファイル: matrix.c プロジェクト: dkogan/PDL
int *IntVectorAlloc(const int n) {

  int *temp;

  temp=(int *)calloc(n, sizeof(int));
  if (temp==NULL)
    SSLerror("No memory available in routine IntVectorAlloc");
  return temp;
} /* IntVectorAlloc */
コード例 #6
0
ファイル: d1_clnt.c プロジェクト: mr-moai-2016/znk_project
int
dtls1_get_hello_verify(SSL *s)
{
	long n;
	int al, ok = 0;
	size_t cookie_len;
	uint16_t ssl_version;
	CBS hello_verify_request, cookie;

	n = s->method->internal->ssl_get_message(s, DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A,
	    DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B, -1, s->internal->max_cert_list, &ok);

	if (!ok)
		return ((int)n);

	if (S3I(s)->tmp.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) {
		D1I(s)->send_cookie = 0;
		S3I(s)->tmp.reuse_message = 1;
		return (1);
	}

	if (n < 0)
		goto truncated;

	CBS_init(&hello_verify_request, s->internal->init_msg, n);

	if (!CBS_get_u16(&hello_verify_request, &ssl_version))
		goto truncated;

	if (ssl_version != s->version) {
		SSLerror(s, SSL_R_WRONG_SSL_VERSION);
		s->version = (s->version & 0xff00) | (ssl_version & 0xff);
		al = SSL_AD_PROTOCOL_VERSION;
		goto f_err;
	}

	if (!CBS_get_u8_length_prefixed(&hello_verify_request, &cookie))
		goto truncated;

	if (!CBS_write_bytes(&cookie, D1I(s)->cookie,
	    sizeof(D1I(s)->cookie), &cookie_len)) {
		D1I(s)->cookie_len = 0;
		al = SSL_AD_ILLEGAL_PARAMETER;
		goto f_err;
	}
	D1I(s)->cookie_len = cookie_len;
	D1I(s)->send_cookie = 1;

	return 1;

truncated:
	al = SSL_AD_DECODE_ERROR;
f_err:
	ssl3_send_alert(s, SSL3_AL_FATAL, al);
	return -1;
}
コード例 #7
0
ファイル: ssl_rsa.c プロジェクト: libressl-portable/openbsd
int
SSL_use_certificate_file(SSL *ssl, const char *file, int type)
{
	int j;
	BIO *in;
	int ret = 0;
	X509 *x = NULL;

	in = BIO_new(BIO_s_file_internal());
	if (in == NULL) {
		SSLerror(ssl, ERR_R_BUF_LIB);
		goto end;
	}

	if (BIO_read_filename(in, file) <= 0) {
		SSLerror(ssl, ERR_R_SYS_LIB);
		goto end;
	}
	if (type == SSL_FILETYPE_ASN1) {
		j = ERR_R_ASN1_LIB;
		x = d2i_X509_bio(in, NULL);
	} else if (type == SSL_FILETYPE_PEM) {
		j = ERR_R_PEM_LIB;
		x = PEM_read_bio_X509(in, NULL,
		    ssl->ctx->default_passwd_callback,
		    ssl->ctx->default_passwd_callback_userdata);
	} else {
		SSLerror(ssl, SSL_R_BAD_SSL_FILETYPE);
		goto end;
	}

	if (x == NULL) {
		SSLerror(ssl, j);
		goto end;
	}

	ret = SSL_use_certificate(ssl, x);
end:
	X509_free(x);
	BIO_free(in);
	return (ret);
}
コード例 #8
0
ファイル: ssl_rsa.c プロジェクト: libressl-portable/openbsd
int
SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey)
{
	int ret;

	if (pkey == NULL) {
		SSLerror(ssl, ERR_R_PASSED_NULL_PARAMETER);
		return (0);
	}
	ret = ssl_set_pkey(ssl->cert, pkey);
	return (ret);
}
コード例 #9
0
ファイル: ssl_rsa.c プロジェクト: libressl-portable/openbsd
int
SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type)
{
	int j, ret = 0;
	BIO *in;
	EVP_PKEY *pkey = NULL;

	in = BIO_new(BIO_s_file_internal());
	if (in == NULL) {
		SSLerror(ssl, ERR_R_BUF_LIB);
		goto end;
	}

	if (BIO_read_filename(in, file) <= 0) {
		SSLerror(ssl, ERR_R_SYS_LIB);
		goto end;
	}
	if (type == SSL_FILETYPE_PEM) {
		j = ERR_R_PEM_LIB;
		pkey = PEM_read_bio_PrivateKey(in, NULL,
		    ssl->ctx->default_passwd_callback,
		    ssl->ctx->default_passwd_callback_userdata);
	} else if (type == SSL_FILETYPE_ASN1) {
		j = ERR_R_ASN1_LIB;
		pkey = d2i_PrivateKey_bio(in, NULL);
	} else {
		SSLerror(ssl, SSL_R_BAD_SSL_FILETYPE);
		goto end;
	}
	if (pkey == NULL) {
		SSLerror(ssl, j);
		goto end;
	}
	ret = SSL_use_PrivateKey(ssl, pkey);
	EVP_PKEY_free(pkey);
end:
	BIO_free(in);
	return (ret);
}
コード例 #10
0
ファイル: ssl_rsa.c プロジェクト: libressl-portable/openbsd
int
SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa)
{
	EVP_PKEY *pkey;
	int ret;

	if (rsa == NULL) {
		SSLerror(ssl, ERR_R_PASSED_NULL_PARAMETER);
		return (0);
	}
	if ((pkey = EVP_PKEY_new()) == NULL) {
		SSLerror(ssl, ERR_R_EVP_LIB);
		return (0);
	}

	RSA_up_ref(rsa);
	EVP_PKEY_assign_RSA(pkey, rsa);

	ret = ssl_set_pkey(ssl->cert, pkey);
	EVP_PKEY_free(pkey);
	return (ret);
}
コード例 #11
0
ファイル: ssl_rsa.c プロジェクト: libressl-portable/openbsd
int
SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, long len)
{
	int ret;
	RSA *rsa;

	if ((rsa = d2i_RSAPrivateKey(NULL, &d, (long)len)) == NULL) {
		SSLerror(ssl, ERR_R_ASN1_LIB);
		return (0);
	}

	ret = SSL_use_RSAPrivateKey(ssl, rsa);
	RSA_free(rsa);
	return (ret);
}
コード例 #12
0
ファイル: ssl_rsa.c プロジェクト: libressl-portable/openbsd
int
SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, long len)
{
	int ret;
	EVP_PKEY *pkey;

	if ((pkey = d2i_PrivateKey(type, NULL, &d, (long)len)) == NULL) {
		SSLerror(ssl, ERR_R_ASN1_LIB);
		return (0);
	}

	ret = SSL_use_PrivateKey(ssl, pkey);
	EVP_PKEY_free(pkey);
	return (ret);
}
コード例 #13
0
ファイル: ssl_rsa.c プロジェクト: libressl-portable/openbsd
int
SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len)
{
	X509 *x;
	int ret;

	x = d2i_X509(NULL, &d, (long)len);
	if (x == NULL) {
		SSLerror(ssl, ERR_R_ASN1_LIB);
		return (0);
	}

	ret = SSL_use_certificate(ssl, x);
	X509_free(x);
	return (ret);
}
コード例 #14
0
ファイル: ssl_sess.c プロジェクト: bbbrumley/openbsd
int
SSL_set_session(SSL *s, SSL_SESSION *session)
{
	int ret = 0;
	const SSL_METHOD *meth;

	if (session != NULL) {
		meth = s->ctx->method->internal->get_ssl_method(session->ssl_version);
		if (meth == NULL)
			meth = s->method->internal->get_ssl_method(session->ssl_version);
		if (meth == NULL) {
			SSLerror(s, SSL_R_UNABLE_TO_FIND_SSL_METHOD);
			return (0);
		}

		if (meth != s->method) {
			if (!SSL_set_ssl_method(s, meth))
				return (0);
		}

		/* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/
		CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION);
		if (s->session != NULL)
			SSL_SESSION_free(s->session);
		s->session = session;
		s->verify_result = s->session->verify_result;
		/* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/
		ret = 1;
	} else {
		if (s->session != NULL) {
			SSL_SESSION_free(s->session);
			s->session = NULL;
		}

		meth = s->ctx->method;
		if (meth != s->method) {
			if (!SSL_set_ssl_method(s, meth))
				return (0);
		}
		ret = 1;
	}
	return (ret);
}
コード例 #15
0
ファイル: d1_lib.c プロジェクト: 2trill2spill/nextgen
int
dtls1_check_timeout_num(SSL *s)
{
	D1I(s)->timeout.num_alerts++;

	/* Reduce MTU after 2 unsuccessful retransmissions */
	if (D1I(s)->timeout.num_alerts > 2) {
		D1I(s)->mtu = BIO_ctrl(SSL_get_wbio(s),
		    BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);

	}

	if (D1I(s)->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
		/* fail the connection, enough alerts have been sent */
		SSLerror(SSL_R_READ_TIMEOUT_EXPIRED);
		return -1;
	}

	return 0;
}
コード例 #16
0
ファイル: ssl_sess.c プロジェクト: bbbrumley/openbsd
int
ssl_get_new_session(SSL *s, int session)
{
	unsigned int tmp;
	SSL_SESSION *ss = NULL;
	GEN_SESSION_CB cb = def_generate_session_id;

	/* This gets used by clients and servers. */

	if ((ss = SSL_SESSION_new()) == NULL)
		return (0);

	/* If the context has a default timeout, use it */
	if (s->session_ctx->session_timeout == 0)
		ss->timeout = SSL_get_default_timeout(s);
	else
		ss->timeout = s->session_ctx->session_timeout;

	if (s->session != NULL) {
		SSL_SESSION_free(s->session);
		s->session = NULL;
	}

	if (session) {
		switch (s->version) {
		case TLS1_VERSION:
		case TLS1_1_VERSION:
		case TLS1_2_VERSION:
		case DTLS1_VERSION:
			ss->ssl_version = s->version;
			ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
			break;
		default:
			SSLerror(s, SSL_R_UNSUPPORTED_SSL_VERSION);
			SSL_SESSION_free(ss);
			return (0);
		}

		/* If RFC4507 ticket use empty session ID. */
		if (s->internal->tlsext_ticket_expected) {
			ss->session_id_length = 0;
			goto sess_id_done;
		}

		/* Choose which callback will set the session ID. */
		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
		if (s->internal->generate_session_id)
			cb = s->internal->generate_session_id;
		else if (s->session_ctx->internal->generate_session_id)
			cb = s->session_ctx->internal->generate_session_id;
		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);

		/* Choose a session ID. */
		tmp = ss->session_id_length;
		if (!cb(s, ss->session_id, &tmp)) {
			/* The callback failed */
			SSLerror(s, SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
			SSL_SESSION_free(ss);
			return (0);
		}

		/*
		 * Don't allow the callback to set the session length to zero.
		 * nor set it higher than it was.
		 */
		if (!tmp || (tmp > ss->session_id_length)) {
			/* The callback set an illegal length */
			SSLerror(s, SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
			SSL_SESSION_free(ss);
			return (0);
		}
		ss->session_id_length = tmp;

		/* Finally, check for a conflict. */
		if (SSL_has_matching_session_id(s, ss->session_id,
			ss->session_id_length)) {
			SSLerror(s, SSL_R_SSL_SESSION_ID_CONFLICT);
			SSL_SESSION_free(ss);
			return (0);
		}

sess_id_done:
		if (s->tlsext_hostname) {
			ss->tlsext_hostname = strdup(s->tlsext_hostname);
			if (ss->tlsext_hostname == NULL) {
				SSLerror(s, ERR_R_INTERNAL_ERROR);
				SSL_SESSION_free(ss);
				return 0;
			}
		}
	} else {
		ss->session_id_length = 0;
	}

	if (s->sid_ctx_length > sizeof ss->sid_ctx) {
		SSLerror(s, ERR_R_INTERNAL_ERROR);
		SSL_SESSION_free(ss);
		return 0;
	}

	memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length);
	ss->sid_ctx_length = s->sid_ctx_length;
	s->session = ss;
	ss->ssl_version = s->version;
	ss->verify_result = X509_V_OK;

	return (1);
}
コード例 #17
0
ファイル: ssl_sess.c プロジェクト: bbbrumley/openbsd
/*
 * ssl_get_prev attempts to find an SSL_SESSION to be used to resume this
 * connection. It is only called by servers.
 *
 *   session_id: points at the session ID in the ClientHello. This code will
 *       read past the end of this in order to parse out the session ticket
 *       extension, if any.
 *   len: the length of the session ID.
 *   limit: a pointer to the first byte after the ClientHello.
 *
 * Returns:
 *   -1: error
 *    0: a session may have been found.
 *
 * Side effects:
 *   - If a session is found then s->session is pointed at it (after freeing
 *     an existing session if need be) and s->verify_result is set from the
 *     session.
 *   - Both for new and resumed sessions, s->internal->tlsext_ticket_expected is set
 *     to 1 if the server should issue a new session ticket (to 0 otherwise).
 */
int
ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
    const unsigned char *limit)
{
	SSL_SESSION *ret = NULL;
	int fatal = 0;
	int try_session_cache = 1;
	int r;

	/* This is used only by servers. */

	if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
		goto err;

	if (len == 0)
		try_session_cache = 0;

	/* Sets s->internal->tlsext_ticket_expected. */
	r = tls1_process_ticket(s, session_id, len, limit, &ret);
	switch (r) {
	case -1: /* Error during processing */
		fatal = 1;
		goto err;
	case 0: /* No ticket found */
	case 1: /* Zero length ticket found */
		break; /* Ok to carry on processing session id. */
	case 2: /* Ticket found but not decrypted. */
	case 3: /* Ticket decrypted, *ret has been set. */
		try_session_cache = 0;
		break;
	default:
		abort();
	}

	if (try_session_cache && ret == NULL &&
	    !(s->session_ctx->internal->session_cache_mode &
	     SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) {
		SSL_SESSION data;
		data.ssl_version = s->version;
		data.session_id_length = len;
		memcpy(data.session_id, session_id, len);

		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
		ret = lh_SSL_SESSION_retrieve(s->session_ctx->internal->sessions, &data);
		if (ret != NULL) {
			/* Don't allow other threads to steal it. */
			CRYPTO_add(&ret->references, 1,
			    CRYPTO_LOCK_SSL_SESSION);
		}
		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);

		if (ret == NULL)
			s->session_ctx->internal->stats.sess_miss++;
	}

	if (try_session_cache && ret == NULL &&
	    s->session_ctx->internal->get_session_cb != NULL) {
		int copy = 1;

		if ((ret = s->session_ctx->internal->get_session_cb(s,
		    session_id, len, &copy))) {
			s->session_ctx->internal->stats.sess_cb_hit++;

			/*
			 * Increment reference count now if the session
			 * callback asks us to do so (note that if the session
			 * structures returned by the callback are shared
			 * between threads, it must handle the reference count
			 * itself [i.e. copy == 0], or things won't be
			 * thread-safe).
			 */
			if (copy)
				CRYPTO_add(&ret->references, 1,
				    CRYPTO_LOCK_SSL_SESSION);

			/*
			 * Add the externally cached session to the internal
			 * cache as well if and only if we are supposed to.
			 */
			if (!(s->session_ctx->internal->session_cache_mode &
			    SSL_SESS_CACHE_NO_INTERNAL_STORE))
				/*
				 * The following should not return 1,
				 * otherwise, things are very strange.
				 */
				SSL_CTX_add_session(s->session_ctx, ret);
		}
	}

	if (ret == NULL)
		goto err;

	/* Now ret is non-NULL and we own one of its reference counts. */

	if (ret->sid_ctx_length != s->sid_ctx_length ||
	    timingsafe_memcmp(ret->sid_ctx,
		s->sid_ctx, ret->sid_ctx_length) != 0) {
		/* We have the session requested by the client, but we don't
		 * want to use it in this context. */
		goto err; /* treat like cache miss */
	}

	if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) {
		/*
		 * We can't be sure if this session is being used out of
		 * context, which is especially important for SSL_VERIFY_PEER.
		 * The application should have used
		 * SSL[_CTX]_set_session_id_context.
		 *
		 * For this error case, we generate an error instead of treating
		 * the event like a cache miss (otherwise it would be easy for
		 * applications to effectively disable the session cache by
		 * accident without anyone noticing).
		 */
		SSLerror(s, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
		fatal = 1;
		goto err;
	}

	if (ret->cipher == NULL) {
		ret->cipher = ssl3_get_cipher_by_id(ret->cipher_id);
		if (ret->cipher == NULL)
			goto err;
	}

	if (ret->timeout < (time(NULL) - ret->time)) {
		/* timeout */
		s->session_ctx->internal->stats.sess_timeout++;
		if (try_session_cache) {
			/* session was from the cache, so remove it */
			SSL_CTX_remove_session(s->session_ctx, ret);
		}
		goto err;
	}

	s->session_ctx->internal->stats.sess_hit++;

	if (s->session != NULL)
		SSL_SESSION_free(s->session);
	s->session = ret;
	s->verify_result = s->session->verify_result;
	return 1;

err:
	if (ret != NULL) {
		SSL_SESSION_free(ret);
		if (!try_session_cache) {
			/*
			 * The session was from a ticket, so we should
			 * issue a ticket for the new session.
			 */
			s->internal->tlsext_ticket_expected = 1;
		}
	}
	if (fatal)
		return -1;
	else
		return 0;
}
コード例 #18
0
ファイル: d1_clnt.c プロジェクト: soundsrc/git-lfs-server
int
dtls1_connect(SSL *s)
{
	void (*cb)(const SSL *ssl, int type, int val) = NULL;
	int ret = -1;
	int new_state, state, skip = 0;

	ERR_clear_error();
	errno = 0;

	if (s->internal->info_callback != NULL)
		cb = s->internal->info_callback;
	else if (s->ctx->internal->info_callback != NULL)
		cb = s->ctx->internal->info_callback;

	s->internal->in_handshake++;
	if (!SSL_in_init(s) || SSL_in_before(s))
		SSL_clear(s);


	for (;;) {
		state = S3I(s)->hs.state;

		switch (S3I(s)->hs.state) {
		case SSL_ST_RENEGOTIATE:
			s->internal->renegotiate = 1;
			S3I(s)->hs.state = SSL_ST_CONNECT;
			s->ctx->internal->stats.sess_connect_renegotiate++;
			/* break */
		case SSL_ST_BEFORE:
		case SSL_ST_CONNECT:
		case SSL_ST_BEFORE|SSL_ST_CONNECT:
		case SSL_ST_OK|SSL_ST_CONNECT:

			s->server = 0;
			if (cb != NULL)
				cb(s, SSL_CB_HANDSHAKE_START, 1);

			if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00)) {
				SSLerror(s, ERR_R_INTERNAL_ERROR);
				ret = -1;
				goto end;
			}

			/* s->version=SSL3_VERSION; */
			s->internal->type = SSL_ST_CONNECT;

			if (!ssl3_setup_init_buffer(s)) {
				ret = -1;
				goto end;
			}
			if (!ssl3_setup_buffers(s)) {
				ret = -1;
				goto end;
			}
			if (!ssl_init_wbio_buffer(s, 0)) {
				ret = -1;
				goto end;
			}

			/* don't push the buffering BIO quite yet */

			S3I(s)->hs.state = SSL3_ST_CW_CLNT_HELLO_A;
			s->ctx->internal->stats.sess_connect++;
			s->internal->init_num = 0;
			/* mark client_random uninitialized */
			memset(s->s3->client_random, 0,
			    sizeof(s->s3->client_random));
			D1I(s)->send_cookie = 0;
			s->internal->hit = 0;
			break;


		case SSL3_ST_CW_CLNT_HELLO_A:
		case SSL3_ST_CW_CLNT_HELLO_B:

			s->internal->shutdown = 0;

			/* every DTLS ClientHello resets Finished MAC */
			if (!tls1_init_finished_mac(s)) {
				ret = -1;
				goto end;
			}

			dtls1_start_timer(s);
			ret = ssl3_client_hello(s);
			if (ret <= 0)
				goto end;

			if (D1I(s)->send_cookie) {
				S3I(s)->hs.state = SSL3_ST_CW_FLUSH;
				S3I(s)->hs.next_state = SSL3_ST_CR_SRVR_HELLO_A;
			} else
				S3I(s)->hs.state = SSL3_ST_CR_SRVR_HELLO_A;

			s->internal->init_num = 0;

			/* turn on buffering for the next lot of output */
			if (s->bbio != s->wbio)
				s->wbio = BIO_push(s->bbio, s->wbio);

			break;

		case SSL3_ST_CR_SRVR_HELLO_A:
		case SSL3_ST_CR_SRVR_HELLO_B:
			ret = ssl3_get_server_hello(s);
			if (ret <= 0)
				goto end;
			else {
				if (s->internal->hit) {

					S3I(s)->hs.state = SSL3_ST_CR_FINISHED_A;
				} else
					S3I(s)->hs.state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
			}
			s->internal->init_num = 0;
			break;

		case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
		case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:

			ret = dtls1_get_hello_verify(s);
			if (ret <= 0)
				goto end;
			dtls1_stop_timer(s);
			if ( D1I(s)->send_cookie) /* start again, with a cookie */
				S3I(s)->hs.state = SSL3_ST_CW_CLNT_HELLO_A;
			else
				S3I(s)->hs.state = SSL3_ST_CR_CERT_A;
			s->internal->init_num = 0;
			break;

		case SSL3_ST_CR_CERT_A:
		case SSL3_ST_CR_CERT_B:
			ret = ssl3_check_finished(s);
			if (ret <= 0)
				goto end;
			if (ret == 2) {
				s->internal->hit = 1;
				if (s->internal->tlsext_ticket_expected)
					S3I(s)->hs.state = SSL3_ST_CR_SESSION_TICKET_A;
				else
					S3I(s)->hs.state = SSL3_ST_CR_FINISHED_A;
				s->internal->init_num = 0;
				break;
			}
			/* Check if it is anon DH. */
			if (!(S3I(s)->hs.new_cipher->algorithm_auth &
			    SSL_aNULL)) {
				ret = ssl3_get_server_certificate(s);
				if (ret <= 0)
					goto end;
				if (s->internal->tlsext_status_expected)
					S3I(s)->hs.state = SSL3_ST_CR_CERT_STATUS_A;
				else
					S3I(s)->hs.state = SSL3_ST_CR_KEY_EXCH_A;
			} else {
				skip = 1;
				S3I(s)->hs.state = SSL3_ST_CR_KEY_EXCH_A;
			}
			s->internal->init_num = 0;
			break;

		case SSL3_ST_CR_KEY_EXCH_A:
		case SSL3_ST_CR_KEY_EXCH_B:
			ret = ssl3_get_server_key_exchange(s);
			if (ret <= 0)
				goto end;
			S3I(s)->hs.state = SSL3_ST_CR_CERT_REQ_A;
			s->internal->init_num = 0;

			/* at this point we check that we have the
			 * required stuff from the server */
			if (!ssl3_check_cert_and_algorithm(s)) {
				ret = -1;
				goto end;
			}
			break;

		case SSL3_ST_CR_CERT_REQ_A:
		case SSL3_ST_CR_CERT_REQ_B:
			ret = ssl3_get_certificate_request(s);
			if (ret <= 0)
				goto end;
			S3I(s)->hs.state = SSL3_ST_CR_SRVR_DONE_A;
			s->internal->init_num = 0;
			break;

		case SSL3_ST_CR_SRVR_DONE_A:
		case SSL3_ST_CR_SRVR_DONE_B:
			ret = ssl3_get_server_done(s);
			if (ret <= 0)
				goto end;
			dtls1_stop_timer(s);
			if (S3I(s)->tmp.cert_req)
				S3I(s)->hs.next_state = SSL3_ST_CW_CERT_A;
			else
				S3I(s)->hs.next_state = SSL3_ST_CW_KEY_EXCH_A;
			s->internal->init_num = 0;
			S3I(s)->hs.state = S3I(s)->hs.next_state;
			break;

		case SSL3_ST_CW_CERT_A:
		case SSL3_ST_CW_CERT_B:
		case SSL3_ST_CW_CERT_C:
		case SSL3_ST_CW_CERT_D:
			dtls1_start_timer(s);
			ret = ssl3_send_client_certificate(s);
			if (ret <= 0)
				goto end;
			S3I(s)->hs.state = SSL3_ST_CW_KEY_EXCH_A;
			s->internal->init_num = 0;
			break;

		case SSL3_ST_CW_KEY_EXCH_A:
		case SSL3_ST_CW_KEY_EXCH_B:
			dtls1_start_timer(s);
			ret = ssl3_send_client_key_exchange(s);
			if (ret <= 0)
				goto end;

			/* EAY EAY EAY need to check for DH fix cert
			 * sent back */
			/* For TLS, cert_req is set to 2, so a cert chain
			 * of nothing is sent, but no verify packet is sent */
			if (S3I(s)->tmp.cert_req == 1) {
				S3I(s)->hs.state = SSL3_ST_CW_CERT_VRFY_A;
			} else {
				S3I(s)->hs.state = SSL3_ST_CW_CHANGE_A;
				S3I(s)->change_cipher_spec = 0;
			}

			s->internal->init_num = 0;
			break;

		case SSL3_ST_CW_CERT_VRFY_A:
		case SSL3_ST_CW_CERT_VRFY_B:
			dtls1_start_timer(s);
			ret = ssl3_send_client_verify(s);
			if (ret <= 0)
				goto end;
			S3I(s)->hs.state = SSL3_ST_CW_CHANGE_A;
			s->internal->init_num = 0;
			S3I(s)->change_cipher_spec = 0;
			break;

		case SSL3_ST_CW_CHANGE_A:
		case SSL3_ST_CW_CHANGE_B:
			if (!s->internal->hit)
				dtls1_start_timer(s);
			ret = dtls1_send_change_cipher_spec(s,
			    SSL3_ST_CW_CHANGE_A, SSL3_ST_CW_CHANGE_B);
			if (ret <= 0)
				goto end;

			S3I(s)->hs.state = SSL3_ST_CW_FINISHED_A;
			s->internal->init_num = 0;

			s->session->cipher = S3I(s)->hs.new_cipher;
			if (!tls1_setup_key_block(s)) {
				ret = -1;
				goto end;
			}

			if (!tls1_change_cipher_state(s,
			    SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
				ret = -1;
				goto end;
			}


			dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
			break;

		case SSL3_ST_CW_FINISHED_A:
		case SSL3_ST_CW_FINISHED_B:
			if (!s->internal->hit)
				dtls1_start_timer(s);
			ret = ssl3_send_finished(s,
			    SSL3_ST_CW_FINISHED_A, SSL3_ST_CW_FINISHED_B,
			    TLS_MD_CLIENT_FINISH_CONST,
			    TLS_MD_CLIENT_FINISH_CONST_SIZE);
			if (ret <= 0)
				goto end;
			S3I(s)->hs.state = SSL3_ST_CW_FLUSH;

			/* clear flags */
			s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER;
			if (s->internal->hit) {
				S3I(s)->hs.next_state = SSL_ST_OK;
				if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED) {
					S3I(s)->hs.state = SSL_ST_OK;
					s->s3->flags |= SSL3_FLAGS_POP_BUFFER;
					S3I(s)->delay_buf_pop_ret = 0;
				}
			} else {

				/* Allow NewSessionTicket if ticket expected */
				if (s->internal->tlsext_ticket_expected)
					S3I(s)->hs.next_state =
					    SSL3_ST_CR_SESSION_TICKET_A;
				else
					S3I(s)->hs.next_state =
					    SSL3_ST_CR_FINISHED_A;
			}
			s->internal->init_num = 0;
			break;

		case SSL3_ST_CR_SESSION_TICKET_A:
		case SSL3_ST_CR_SESSION_TICKET_B:
			ret = ssl3_get_new_session_ticket(s);
			if (ret <= 0)
				goto end;
			S3I(s)->hs.state = SSL3_ST_CR_FINISHED_A;
			s->internal->init_num = 0;
			break;

		case SSL3_ST_CR_CERT_STATUS_A:
		case SSL3_ST_CR_CERT_STATUS_B:
			ret = ssl3_get_cert_status(s);
			if (ret <= 0)
				goto end;
			S3I(s)->hs.state = SSL3_ST_CR_KEY_EXCH_A;
			s->internal->init_num = 0;
			break;

		case SSL3_ST_CR_FINISHED_A:
		case SSL3_ST_CR_FINISHED_B:
			D1I(s)->change_cipher_spec_ok = 1;
			ret = ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A,
			    SSL3_ST_CR_FINISHED_B);
			if (ret <= 0)
				goto end;
			dtls1_stop_timer(s);

			if (s->internal->hit)
				S3I(s)->hs.state = SSL3_ST_CW_CHANGE_A;
			else
				S3I(s)->hs.state = SSL_ST_OK;


			s->internal->init_num = 0;
			break;

		case SSL3_ST_CW_FLUSH:
			s->internal->rwstate = SSL_WRITING;
			if (BIO_flush(s->wbio) <= 0) {
				/* If the write error was fatal, stop trying */
				if (!BIO_should_retry(s->wbio)) {
					s->internal->rwstate = SSL_NOTHING;
					S3I(s)->hs.state = S3I(s)->hs.next_state;
				}

				ret = -1;
				goto end;
			}
			s->internal->rwstate = SSL_NOTHING;
			S3I(s)->hs.state = S3I(s)->hs.next_state;
			break;

		case SSL_ST_OK:
			/* clean a few things up */
			tls1_cleanup_key_block(s);

			/* If we are not 'joining' the last two packets,
			 * remove the buffering now */
			if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
				ssl_free_wbio_buffer(s);
			/* else do it later in ssl3_write */

			s->internal->init_num = 0;
			s->internal->renegotiate = 0;
			s->internal->new_session = 0;

			ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
			if (s->internal->hit)
				s->ctx->internal->stats.sess_hit++;

			ret = 1;
			/* s->server=0; */
			s->internal->handshake_func = dtls1_connect;
			s->ctx->internal->stats.sess_connect_good++;

			if (cb != NULL)
				cb(s, SSL_CB_HANDSHAKE_DONE, 1);

			/* done with handshaking */
			D1I(s)->handshake_read_seq = 0;
			D1I(s)->next_handshake_write_seq = 0;
			goto end;
			/* break; */

		default:
			SSLerror(s, SSL_R_UNKNOWN_STATE);
			ret = -1;
			goto end;
			/* break; */
		}

		/* did we do anything */
		if (!S3I(s)->tmp.reuse_message && !skip) {
			if (s->internal->debug) {
				if ((ret = BIO_flush(s->wbio)) <= 0)
					goto end;
			}

			if ((cb != NULL) && (S3I(s)->hs.state != state)) {
				new_state = S3I(s)->hs.state;
				S3I(s)->hs.state = state;
				cb(s, SSL_CB_CONNECT_LOOP, 1);
				S3I(s)->hs.state = new_state;
			}
		}
		skip = 0;
	}

end:
	s->internal->in_handshake--;
	if (cb != NULL)
		cb(s, SSL_CB_CONNECT_EXIT, ret);

	return (ret);
}