Ejemplo n.º 1
0
static int get_server_hello(SSL *s)
	{
	unsigned char *buf;
	unsigned char *p;
	int i,j;
	unsigned long len;
	STACK_OF(SSL_CIPHER) *sk=NULL,*cl, *prio, *allow;

	buf=(unsigned char *)s->init_buf->data;
	p=buf;
	if (s->state == SSL2_ST_GET_SERVER_HELLO_A)
		{
		i=ssl2_read(s,(char *)&(buf[s->init_num]),11-s->init_num);
		if (i < (11-s->init_num)) 
			return(ssl2_part_read(s,SSL_F_GET_SERVER_HELLO,i));
		s->init_num = 11;

		if (*(p++) != SSL2_MT_SERVER_HELLO)
			{
			if (p[-1] != SSL2_MT_ERROR)
				{
				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
				SSLerr(SSL_F_GET_SERVER_HELLO,
					SSL_R_READ_WRONG_PACKET_TYPE);
				}
			else
				SSLerr(SSL_F_GET_SERVER_HELLO,
					SSL_R_PEER_ERROR);
			return(-1);
			}
#ifdef __APPLE_CC__
		/* The Rhapsody 5.5 (a.k.a. MacOS X) compiler bug
		 * workaround. <*****@*****.**> */
		s->hit=(i=*(p++))?1:0;
#else
		s->hit=(*(p++))?1:0;
#endif
		s->s2->tmp.cert_type= *(p++);
		n2s(p,i);
		if (i < s->version) s->version=i;
		n2s(p,i); s->s2->tmp.cert_length=i;
		n2s(p,i); s->s2->tmp.csl=i;
		n2s(p,i); s->s2->tmp.conn_id_length=i;
		s->state=SSL2_ST_GET_SERVER_HELLO_B;
		}

	/* SSL2_ST_GET_SERVER_HELLO_B */
	len = 11 + (unsigned long)s->s2->tmp.cert_length + (unsigned long)s->s2->tmp.csl + (unsigned long)s->s2->tmp.conn_id_length;
	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
		{
		SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_MESSAGE_TOO_LONG);
		return -1;
		}
	j = (int)len - s->init_num;
	i = ssl2_read(s,(char *)&(buf[s->init_num]),j);
	if (i != j) return(ssl2_part_read(s,SSL_F_GET_SERVER_HELLO,i));
	if (s->msg_callback)
		s->msg_callback(0, s->version, 0, buf, (size_t)len, s, s->msg_callback_arg); /* SERVER-HELLO */

	/* things are looking good */

	p = buf + 11;
	if (s->hit)
		{
		if (s->s2->tmp.cert_length != 0) 
			{
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_LENGTH_NOT_ZERO);
			return(-1);
			}
		if (s->s2->tmp.cert_type != 0)
			{
			if (!(s->options &
				SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG))
				{
				SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_TYPE_NOT_ZERO);
				return(-1);
				}
			}
		if (s->s2->tmp.csl != 0)
			{
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CIPHER_LIST_NOT_ZERO);
			return(-1);
			}
		}
	else
		{
#ifdef undef
		/* very bad */
		memset(s->session->session_id,0,
			SSL_MAX_SSL_SESSION_ID_LENGTH_IN_BYTES);
		s->session->session_id_length=0;
		*/
#endif

		/* we need to do this in case we were trying to reuse a 
		 * client session but others are already reusing it.
		 * If this was a new 'blank' session ID, the session-id
		 * length will still be 0 */
		if (s->session->session_id_length > 0)
			{
			if (!ssl_get_new_session(s,0))
				{
				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
				return(-1);
				}
			}

		if (ssl2_set_certificate(s,s->s2->tmp.cert_type,
			s->s2->tmp.cert_length,p) <= 0)
			{
			ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE);
			return(-1);
			}
		p+=s->s2->tmp.cert_length;

		if (s->s2->tmp.csl == 0)
			{
			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_LIST);
			return(-1);
			}

		/* We have just received a list of ciphers back from the
		 * server.  We need to get the ones that match, then select
		 * the one we want the most :-). */

		/* load the ciphers */
		sk=ssl_bytes_to_cipher_list(s,p,s->s2->tmp.csl,
					    &s->session->ciphers);
		p+=s->s2->tmp.csl;
		if (sk == NULL)
			{
			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
			SSLerr(SSL_F_GET_SERVER_HELLO,ERR_R_MALLOC_FAILURE);
			return(-1);
			}

		(void)sk_SSL_CIPHER_set_cmp_func(sk,ssl_cipher_ptr_id_cmp);

		/* get the array of ciphers we will accept */
		cl=SSL_get_ciphers(s);
		(void)sk_SSL_CIPHER_set_cmp_func(cl,ssl_cipher_ptr_id_cmp);

		/*
		 * If server preference flag set, choose the first
		 * (highest priority) cipher the server sends, otherwise
		 * client preference has priority.
		 */
		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
		    {
		    prio = sk;
		    allow = cl;
		    }
		else
		    {
		    prio = cl;
		    allow = sk;
		    }
		/* In theory we could have ciphers sent back that we
		 * don't want to use but that does not matter since we
		 * will check against the list we originally sent and
		 * for performance reasons we should not bother to match
		 * the two lists up just to check. */
		for (i=0; i<sk_SSL_CIPHER_num(prio); i++)
			{
			if (sk_SSL_CIPHER_find(allow,
					     sk_SSL_CIPHER_value(prio,i)) >= 0)
				break;
			}

		if (i >= sk_SSL_CIPHER_num(prio))
			{
			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_MATCH);
			return(-1);
			}
		s->session->cipher=sk_SSL_CIPHER_value(prio,i);


		if (s->session->peer != NULL) /* can't happen*/
			{
			ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
			SSLerr(SSL_F_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
			return(-1);
			}

		s->session->peer = s->session->sess_cert->peer_key->x509;
		/* peer_key->x509 has been set by ssl2_set_certificate. */
		CRYPTO_add(&s->session->peer->references, 1, CRYPTO_LOCK_X509);
		}

	if (s->session->sess_cert == NULL 
      || s->session->peer != s->session->sess_cert->peer_key->x509)
		/* can't happen */
		{
		ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
		SSLerr(SSL_F_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
		return(-1);
		}
		
	s->s2->conn_id_length=s->s2->tmp.conn_id_length;
	if (s->s2->conn_id_length > sizeof s->s2->conn_id)
		{
		ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
		SSLerr(SSL_F_GET_SERVER_HELLO, SSL_R_SSL2_CONNECTION_ID_TOO_LONG);
		return -1;
		}
	memcpy(s->s2->conn_id,p,s->s2->tmp.conn_id_length);
	return(1);
	}
Ejemplo n.º 2
0
int
dtls1_client_hello(SSL *s)
{
	unsigned char *buf;
	unsigned char *p, *d;
	unsigned int i;
	unsigned long l;

	buf = (unsigned char *)s->init_buf->data;
	if (s->state == SSL3_ST_CW_CLNT_HELLO_A) {
		SSL_SESSION *sess = s->session;
		if ((s->session == NULL) ||
		    (s->session->ssl_version != s->version) ||
		    (!sess->session_id_length && !sess->tlsext_tick) ||
		    (s->session->not_resumable)) {
			if (!ssl_get_new_session(s, 0))
				goto err;
		}
		/* else use the pre-loaded session */

		p = s->s3->client_random;

		/* if client_random is initialized, reuse it, we are
		 * required to use same upon reply to HelloVerify */
		for (i = 0; p[i]=='\0' && i < sizeof(s->s3->client_random); i++)
			;
		if (i == sizeof(s->s3->client_random))
			RAND_pseudo_bytes(p, sizeof(s->s3->client_random));

		/* Do the message type and length last */
		d = p = &(buf[DTLS1_HM_HEADER_LENGTH]);

		*(p++) = s->version >> 8;
		*(p++) = s->version&0xff;
		s->client_version = s->version;

		/* Random stuff */
		memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
		p += SSL3_RANDOM_SIZE;

		/* Session ID */
		if (s->new_session)
			i = 0;
		else
			i = s->session->session_id_length;
		*(p++) = i;
		if (i != 0) {
			if (i > sizeof s->session->session_id) {
				SSLerr(SSL_F_DTLS1_CLIENT_HELLO,
				    ERR_R_INTERNAL_ERROR);
				goto err;
			}
			memcpy(p, s->session->session_id, i);
			p += i;
		}

		/* cookie stuff */
		if (s->d1->cookie_len > sizeof(s->d1->cookie)) {
			SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
			goto err;
		}
		*(p++) = s->d1->cookie_len;
		memcpy(p, s->d1->cookie, s->d1->cookie_len);
		p += s->d1->cookie_len;

		/* Ciphers supported */
		i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &(p[2]), 0);
		if (i == 0) {
			SSLerr(SSL_F_DTLS1_CLIENT_HELLO,
			    SSL_R_NO_CIPHERS_AVAILABLE);
			goto err;
		}
		s2n(i, p);
		p += i;

		/* add in (no) COMPRESSION */
		*(p++) = 1;
		*(p++) = 0; /* Add the NULL method */

		if ((p = ssl_add_clienthello_tlsext(s, p,
		    buf + SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) {
			SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
			goto err;
		}

		l = (p - d);
		d = buf;

		d = dtls1_set_message_header(s, d, SSL3_MT_CLIENT_HELLO,
		    l, 0, l);

		s->state = SSL3_ST_CW_CLNT_HELLO_B;
		/* number of bytes to write */
		s->init_num = p - buf;
		s->init_off = 0;

		/* buffer the message to handle re-xmits */
		dtls1_buffer_message(s, 0);
	}
Ejemplo n.º 3
0
static int client_hello(SSL *s, int fastopen, struct sockaddr_in sa)
	{
	unsigned char *buf;
	unsigned char *p,*d;
/*	CIPHER **cipher;*/
	int i,n,j;

	buf=(unsigned char *)s->init_buf->data;
	if (s->state == SSL2_ST_SEND_CLIENT_HELLO_A)
		{
		if ((s->session == NULL) ||
			(s->session->ssl_version != s->version))
			{
			if (!ssl_get_new_session(s,0))
				{
				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
				return(-1);
				}
			}
		/* else use the pre-loaded session */

		p=buf;					/* header */
		d=p+9;					/* data section */
		*(p++)=SSL2_MT_CLIENT_HELLO;		/* type */
		s2n(SSL2_VERSION,p);			/* version */
		n=j=0;

		n=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),d,0);
		d+=n;

		if (n == 0)
			{
			SSLerr(SSL_F_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
			return(-1);
			}

		s2n(n,p);			/* cipher spec num bytes */

		if ((s->session->session_id_length > 0) &&
			(s->session->session_id_length <=
			SSL2_MAX_SSL_SESSION_ID_LENGTH))
			{
			i=s->session->session_id_length;
			s2n(i,p);		/* session id length */
			memcpy(d,s->session->session_id,(unsigned int)i);
			d+=i;
			}
		else
			{
			s2n(0,p);
			}

		s->s2->challenge_length=SSL2_CHALLENGE_LENGTH;
		s2n(SSL2_CHALLENGE_LENGTH,p);		/* challenge length */
		/*challenge id data*/
		if (RAND_pseudo_bytes(s->s2->challenge,SSL2_CHALLENGE_LENGTH) <= 0)
			return -1;
		memcpy(d,s->s2->challenge,SSL2_CHALLENGE_LENGTH);
		d+=SSL2_CHALLENGE_LENGTH;

		s->state=SSL2_ST_SEND_CLIENT_HELLO_B;
		s->init_num=d-buf;
		s->init_off=0;
		}
	/* SSL2_ST_SEND_CLIENT_HELLO_B */
	return(ssl2_do_write(s));
	}
Ejemplo n.º 4
0
//key: 32 bytes
//iv: 16 bytes
//mac_secret: 20 bytes
SSL* get_live_ssl_obj(char *master_key, size_t master_key_len, uint16_t cipher_suite, unsigned char *server_random, unsigned char *client_random)
{
    static SSL_CTX *ctx = 0;
    // TODO(ewust/SPTelex): probably having a single context is ok?
    if (!ctx) {
      /* Build our SSL context*/
      //ctx=initialize_ctx(KEYFILE,PASSWORD);
      SSL_library_init();
      SSL_load_error_strings();
      //extern BIO *bio_err;
    //bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
      ctx = SSL_CTX_new(TLSv1_2_server_method());
    }
    SSL *ssl = SSL_new(ctx);
    if (!ssl) {
      fprintf(stderr, "could not init ssl...\n");
      exit(-1);
    }

    //ssl->telex_client_random = "hello, worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n";

    //if (is_server) {
      ssl->type = SSL_ST_ACCEPT;
      ssl->method = TLSv1_2_server_method();
    /*} else {
      ssl->type = SSL_ST_CONNECT;
      ssl->method = TLSv1_client_method();
    } */
    ssl->rwstate = SSL_NOTHING;
    ssl->in_handshake = 0; /* We're simulating having finished SSL_connect. */
    ssl->handshake_func = ssl3_connect;
    ssl->server = 0;

    ssl->new_session = 0;
    ssl->quiet_shutdown = 0;
    ssl->shutdown = 0;

    ssl->state = SSL_ST_OK;
    ssl->rstate = SSL_ST_READ_HEADER;

    /* Handshake stuff, we're not doing a handshake. */
    ssl->init_buf = ssl->init_msg = NULL;
    ssl->init_num = ssl->init_off = 0;

    assert(ssl->packet == NULL);
    assert(ssl->packet_length == 0);

    // Set by SSL_new.
    assert(ssl->read_ahead == 0);
    assert(ssl->msg_callback == NULL);

    // Set by SSL_clear.
    assert(ssl->hit == 0);

    // Let's not touch ssl->param; it's set by SSL_new.

    // Set by SSL_new.
    assert(ssl->cipher_list == NULL);
    assert(ssl->cipher_list_by_id == NULL);

    //assert(ssl->mac_flags == 0);

    // Set by SSL clear.
    assert(ssl->enc_read_ctx == NULL);
    assert(ssl->read_hash == NULL);
    assert(ssl->expand == NULL);
    assert(ssl->enc_write_ctx == NULL);
    assert(ssl->write_hash == NULL);
    assert(ssl->compress == NULL);

    // Let's leave ssl->cert alone; should be set by SSL_new.
    // Let's leave ssl->sid_ctx_length alone; should be set by SSL_new.

    if (!ssl_get_new_session(ssl, 0)) {
      fprintf(stderr, "Couldn't get session\n");
      exit(-1);
    }

    // verify_mode and verify_callback are set by SSL_new.

    assert(ssl->info_callback == NULL); // ?
    assert(ssl->error == 0);
    assert(ssl->error_code == 0);
    //assert(ssl->psk_client_callback == NULL);
    //assert(ssl->psk_server_callback == NULL);

    assert(ssl->ctx);

    ssl->verify_result = X509_V_OK;  // Just say the cert's valid.

    // ssl->ex_data is a TODO.
    // Set by SSL_new (big memset to 0).
    assert(ssl->client_CA == NULL);

    assert(ssl->references == 1);
    //ssl->options is set in SSL_new.
    //ssl->mode is set in SSL_new.
    //ssl->max_cert_list is set in SSL_new.

    // TODO(ewust/SPTelex): would this be TLS 1.0 or TLS 1.2?
    ssl->client_version = ssl->version;
    //  ssl->max_send_fragment is set in SSL_new.

    // In SSL_new:
    assert(ssl->tlsext_status_type == -1);
    assert(ssl->tlsext_status_expected == 0);
    assert(ssl->servername_done == 0);
    assert(ssl->tlsext_ocsp_resplen == -1);
    assert(ssl->tlsext_ticket_expected == 0);

    // TODO(ewust/SPTelex): might be needed; but we already have master key?
#if 0
    // The elliptic curve stuff below probably isn't necessary if
    // we're not using an elliptic curve cipher.
    ssl->tlsext_ecpointformatlist_length = 3;

    ssl->tlsext_ecpointformatlist = OPENSSL_malloc(3);
    memcpy(ssl->tlsext_ecpointformatlist, "\x00\x01\x02", 3);
    ssl->tlsext_ellipticcurvelist_length = 50;
    
    ssl->tlsext_ellipticcurvelist = OPENSSL_malloc(50);
    memcpy(ssl->tlsext_ellipticcurvelist, "\x00\x01\x00\x02\x00\x03\x00" 
           "\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00"
           "\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00"
           "\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19", 50);
#endif

    //ssl->tls_opaque_prf_input_len = 0;
    
    ssl->initial_ctx = ssl->ctx;
    

    // This is done by ssl3_new.
    //memset(ssl->s3, 0, sizeof(*ssl->s3));


    // TODO(SPTelex): don't think 1.2 in GCM needs this
    ssl->s3->need_empty_fragments = 1;

    //SSL3_BUFFER is {buf, len, offset, left};
    //ssl->s3->rbuf.buf = NULL; //TODO these buffers are set up by first call to read
    //ssl->s3->rrec = 0x16; //TODO?
    //ssl->s3->wbuf.buf = NULL; //TODO same with these for first call to write
    //ssl->s3->wrec = 0x16; //TODO?

    // swolchok: We don't want to set this stuff, it's for pending writes.
#if 0
    ssl->s3->wpend_tot = 16;
    ssl->s3->wpend_type = 22;
    ssl->s3->wpend_ret = 16;
#endif
    
    ssl->s3->wpend_buf = NULL; //TODO

    ssl3_setup_buffers(ssl);

    //assert(ssl->s3->handshake_dgst == NULL); //TODO; swolchok: should be free.


    ssl->s3->tmp.message_size = 12;
    ssl->s3->tmp.message_type = 20;
    ssl->s3->tmp.new_cipher = NULL; //TODO

    ssl->s3->tmp.next_state = 4576; //hehe
    ssl->s3->tmp.new_sym_enc = NULL; //TODO
    ssl->s3->tmp.new_hash = NULL;   //TODO

//ssl->s3->tmp.new_mac_pkey_type = 855;
//ssl->s3->tmp.new_mac_secret_size = 20;

    if (!ssl_get_new_session(ssl, 0)) {
      fprintf(stderr, "Couldn't initialize session\n");
      exit(-1);
    }

#if 0
        c = malloc(sizeof(EVP_CIPHER));
        //ssl->s3->tmp.new_sym_enc = c;
        
        c->nid = 427;
        c->block_size = 16;
        c->key_len = 32;
        c->iv_len = 16;
        c->flags = 2;
        //c->init = aes_init_key;
        //c->do_cipher = aes_256_cbc_cipher;
        c->cleanup = 0;
        c->ctx_size = 244;
        //c->set_asn1_parameters = EVP_CIPHER_set_asn1_iv;
        //c->get_asn1_parameters = EVP_CIPHER_get_asn1_iv;
        c->ctrl = 0;
        c->app_data = NULL;
#endif

#if 0
        memset(ssl->enc_write_ctx, 0, sizeof(EVP_CIPHER_CTX));
        ssl->enc_write_ctx->cipher = NULL;
        ssl->enc_write_ctx->engine = NULL;
        ssl->enc_write_ctx->encrypt = 1;
        ssl->enc_write_ctx->buf_len = 0;
        ssl->enc_write_ctx->oiv; //TODO
        ssl->enc_write_ctx->iv; //TODO
        ssl->enc_write_ctx->key_len = 32;
        ssl->enc_write_ctx->cipher_data; //TODO
        ssl->enc_write_ctx->block_mask = 0x0f; 
 

        memset(ssl->enc_read_ctx, 0, sizeof(EVP_CIPHER_CTX));
        ssl->enc_read_ctx->cipher = NULL;  //they can share, for all i care
        ssl->enc_read_ctx->engine = NULL;
        ssl->enc_read_ctx->encrypt = 0;
        ssl->enc_read_ctx->buf_len = 0;
        ssl->enc_read_ctx->oiv; //TODO
        ssl->enc_read_ctx->iv; //TODO
        ssl->enc_read_ctx->key_len = 32;
        ssl->enc_read_ctx->cipher_data; //TODO
        ssl->enc_read_ctx->block_mask = 0x0f;
       

        EVP_CipherInit_ex(ssl->enc_write_ctx, c, NULL, &ssl->s3->tmp.key_block[40],
                          &ssl->s3->tmp.key_block[104], 1);

        EVP_CipherInit_ex(ssl->enc_read_ctx, c, NULL, &ssl->s3->tmp.key_block[72],
                          &ssl->s3->tmp.key_block[120], 0);
#endif

        //BIO setup
        SSL_set_bio(ssl, BIO_new(BIO_s_mem()), BIO_new(BIO_s_mem()));

#if 0  // Don't need to copy in secrets now, but the layout is handy to know.
        memcpy(&ssl->s3->tmp.key_block[0], write->mac_secret, 20);
        memcpy(&ssl->s3->tmp.key_block[40], write->key, 32);
        memcpy(&ssl->s3->tmp.key_block[104], write->iv, 16);

        memcpy(&ssl->s3->tmp.key_block[20], read->mac_secret, 20);
        memcpy(&ssl->s3->tmp.key_block[72], read->key, 32);
        memcpy(&ssl->s3->tmp.key_block[120], read->iv, 16);
#endif
        // TODO(ewust/SPTelex)
        memcpy(ssl->s3->client_random, client_random, 32);
        memcpy(ssl->s3->server_random, server_random, 32);

        if (!switch_to_telex_crypto(ssl, master_key,
                                    master_key_len, cipher_suite)) {
          fprintf(stderr, "Couldn't change to telex crypto!\n");
          exit(-1);
        }
    return ssl;
}
Ejemplo n.º 5
0
static int ssl23_client_hello(SSL *s)
	{
	unsigned char *buf;
	unsigned char *p,*d;
	int i,j,ch_len;
	unsigned long Time,l;
	int ssl2_compat;
	int version = 0, version_major, version_minor;
	SSL_COMP *comp;
	int ret;

	ssl2_compat = (s->options & SSL_OP_NO_SSLv2) ? 0 : 1;

	if (!(s->options & SSL_OP_NO_TLSv1))
		{
		version = TLS1_VERSION;
		}
	else if (!(s->options & SSL_OP_NO_SSLv3))
		{
		version = SSL3_VERSION;
		}
	else if (!(s->options & SSL_OP_NO_SSLv2))
		{
		version = SSL2_VERSION;
		}

	buf=(unsigned char *)s->init_buf->data;
	if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
		{
#if 0
		/* don't reuse session-id's */
		if (!ssl_get_new_session(s,0))
			{
			return(-1);
			}
#endif

		p=s->s3->client_random;
		Time=(unsigned long)time(NULL);		/* Time */
		l2n(Time,p);
		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
			return -1;

		if (version == TLS1_VERSION)
			{
			version_major = TLS1_VERSION_MAJOR;
			version_minor = TLS1_VERSION_MINOR;
			}
		else if (version == SSL3_VERSION)
			{
			version_major = SSL3_VERSION_MAJOR;
			version_minor = SSL3_VERSION_MINOR;
			}
		else if (version == SSL2_VERSION)
			{
			version_major = SSL2_VERSION_MAJOR;
			version_minor = SSL2_VERSION_MINOR;
			}
		else
			{
			SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_PROTOCOLS_AVAILABLE);
			return(-1);
			}

		s->client_version = version;

		if (ssl2_compat)
			{
			/* create SSL 2.0 compatible Client Hello */

			/* two byte record header will be written last */
			d = &(buf[2]);
			p = d + 9; /* leave space for message type, version, individual length fields */

			*(d++) = SSL2_MT_CLIENT_HELLO;
			*(d++) = version_major;
			*(d++) = version_minor;
			
			/* Ciphers supported */
			i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),p,0);
			if (i == 0)
				{
				/* no ciphers */
				SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
				return -1;
				}
			s2n(i,d);
			p+=i;
			
			/* put in the session-id length (zero since there is no reuse) */
#if 0
			s->session->session_id_length=0;
#endif
			s2n(0,d);

			if (s->options & SSL_OP_NETSCAPE_CHALLENGE_BUG)
				ch_len=SSL2_CHALLENGE_LENGTH;
			else
				ch_len=SSL2_MAX_CHALLENGE_LENGTH;

			/* write out sslv2 challenge */
			if (SSL3_RANDOM_SIZE < ch_len)
				i=SSL3_RANDOM_SIZE;
			else
				i=ch_len;
			s2n(i,d);
			memset(&(s->s3->client_random[0]),0,SSL3_RANDOM_SIZE);
			if (RAND_pseudo_bytes(&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i) <= 0)
				return -1;

			memcpy(p,&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i);
			p+=i;

			i= p- &(buf[2]);
			buf[0]=((i>>8)&0xff)|0x80;
			buf[1]=(i&0xff);

			/* number of bytes to write */
			s->init_num=i+2;
			s->init_off=0;

			ssl3_finish_mac(s,&(buf[2]),i);
			}
		else
			{
			/* create Client Hello in SSL 3.0/TLS 1.0 format */

			/* do the record header (5 bytes) and handshake message header (4 bytes) last */
			d = p = &(buf[9]);
			
			*(p++) = version_major;
			*(p++) = version_minor;

			/* Random stuff */
			memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
			p += SSL3_RANDOM_SIZE;

			/* Session ID (zero since there is no reuse) */
			*(p++) = 0;

			/* Ciphers supported (using SSL 3.0/TLS 1.0 format) */
			i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),ssl3_put_cipher_by_char);
			if (i == 0)
				{
				SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
				return -1;
				}
			s2n(i,p);
			p+=i;

			/* COMPRESSION */
			if (s->ctx->comp_methods == NULL)
				j=0;
			else
				j=sk_SSL_COMP_num(s->ctx->comp_methods);
			*(p++)=1+j;
			for (i=0; i<j; i++)
				{
				comp=sk_SSL_COMP_value(s->ctx->comp_methods,i);
				*(p++)=comp->id;
				}
			*(p++)=0; /* Add the NULL method */
			
			l = p-d;
			*p = 42;

			/* fill in 4-byte handshake header */
			d=&(buf[5]);
			*(d++)=SSL3_MT_CLIENT_HELLO;
			l2n3(l,d);

			l += 4;

			if (l > SSL3_RT_MAX_PLAIN_LENGTH)
				{
				SSLerr(SSL_F_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
				return -1;
				}
			
			/* fill in 5-byte record header */
			d=buf;
			*(d++) = SSL3_RT_HANDSHAKE;
			*(d++) = version_major;
			*(d++) = version_minor; /* arguably we should send the *lowest* suported version here
			                         * (indicating, e.g., TLS 1.0 in "SSL 3.0 format") */
			s2n((int)l,d);

			/* number of bytes to write */
			s->init_num=p-buf;
			s->init_off=0;

			ssl3_finish_mac(s,&(buf[5]), s->init_num - 5);
			}

		s->state=SSL23_ST_CW_CLNT_HELLO_B;
		s->init_off=0;
		}
Ejemplo n.º 6
0
static int ssl23_client_hello(SSL *s)
	{
	unsigned char *buf;
	unsigned char *p,*d;
	int i,ch_len;
	unsigned long Time,l;
	int ssl2_compat;
	int version = 0, version_major, version_minor;
#ifndef OPENSSL_NO_COMP
	int j;
	SSL_COMP *comp;
#endif
	int ret;
	unsigned long mask, options = s->options;

	ssl2_compat = (options & SSL_OP_NO_SSLv2) ? 0 : 1;

	if (ssl2_compat && ssl23_no_ssl2_ciphers(s))
		ssl2_compat = 0;

	/*
	 * SSL_OP_NO_X disables all protocols above X *if* there are
	 * some protocols below X enabled. This is required in order
	 * to maintain "version capability" vector contiguous. So
	 * that if application wants to disable TLS1.0 in favour of
	 * TLS1>=1, it would be insufficient to pass SSL_NO_TLSv1, the
	 * answer is SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2.
	 */
	mask =	SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1
#if !defined(OPENSSL_NO_SSL3)
		|SSL_OP_NO_SSLv3
#endif
#if !defined(OPENSSL_NO_SSL2)
		|(ssl2_compat?SSL_OP_NO_SSLv2:0)
#endif
		;
#if !defined(OPENSSL_NO_TLS1_2_CLIENT)
	version = TLS1_2_VERSION;

	if ((options & SSL_OP_NO_TLSv1_2) && (options & mask) != mask)
		version = TLS1_1_VERSION;
#else
	version = TLS1_1_VERSION;
#endif
	mask &= ~SSL_OP_NO_TLSv1_1;
	if ((options & SSL_OP_NO_TLSv1_1) && (options & mask) != mask)
		version = TLS1_VERSION;
	mask &= ~SSL_OP_NO_TLSv1;
#if !defined(OPENSSL_NO_SSL3)
	if ((options & SSL_OP_NO_TLSv1) && (options & mask) != mask)
		version = SSL3_VERSION;
	mask &= ~SSL_OP_NO_SSLv3;
#endif
#if !defined(OPENSSL_NO_SSL2)
	if ((options & SSL_OP_NO_SSLv3) && (options & mask) != mask)
		version = SSL2_VERSION;
#endif

#ifndef OPENSSL_NO_TLSEXT
	if (version != SSL2_VERSION)
		{
		/* have to disable SSL 2.0 compatibility if we need TLS extensions */

		if (s->tlsext_hostname != NULL)
			ssl2_compat = 0;
		if (s->tlsext_status_type != -1)
			ssl2_compat = 0;
#ifdef TLSEXT_TYPE_opaque_prf_input
		if (s->ctx->tlsext_opaque_prf_input_callback != 0 || s->tlsext_opaque_prf_input != NULL)
			ssl2_compat = 0;
#endif
		if (s->ctx->custom_cli_ext_records_count != 0)
			ssl2_compat = 0;
		if (s->ctx->cli_supp_data_records_count != 0)
			ssl2_compat = 0;
		}
#endif

	buf=(unsigned char *)s->init_buf->data;
	if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
		{
#if 0
		/* don't reuse session-id's */
		if (!ssl_get_new_session(s,0))
			{
			return(-1);
			}
#endif

		p=s->s3->client_random;
		Time=(unsigned long)time(NULL);		/* Time */
		l2n(Time,p);
		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
			return -1;

		if (version == TLS1_2_VERSION)
			{
			version_major = TLS1_2_VERSION_MAJOR;
			version_minor = TLS1_2_VERSION_MINOR;
			}
		else if (tls1_suiteb(s))
			{
			SSLerr(SSL_F_SSL23_CLIENT_HELLO,
					SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE);
			return -1;
			}
		else if (version == TLS1_1_VERSION)
			{
			version_major = TLS1_1_VERSION_MAJOR;
			version_minor = TLS1_1_VERSION_MINOR;
			}
		else if (version == TLS1_VERSION)
			{
			version_major = TLS1_VERSION_MAJOR;
			version_minor = TLS1_VERSION_MINOR;
			}
#ifdef OPENSSL_FIPS
		else if(FIPS_mode())
			{
			SSLerr(SSL_F_SSL23_CLIENT_HELLO,
					SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE);
			return -1;
			}
#endif
		else if (version == SSL3_VERSION)
			{
			version_major = SSL3_VERSION_MAJOR;
			version_minor = SSL3_VERSION_MINOR;
			}
		else if (version == SSL2_VERSION)
			{
			version_major = SSL2_VERSION_MAJOR;
			version_minor = SSL2_VERSION_MINOR;
			}
		else
			{
			SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_PROTOCOLS_AVAILABLE);
			return(-1);
			}

		s->client_version = version;

		if (ssl2_compat)
			{
			/* create SSL 2.0 compatible Client Hello */

			/* two byte record header will be written last */
			d = &(buf[2]);
			p = d + 9; /* leave space for message type, version, individual length fields */

			*(d++) = SSL2_MT_CLIENT_HELLO;
			*(d++) = version_major;
			*(d++) = version_minor;
			
			/* Ciphers supported */
			i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),p,0);
			if (i == 0)
				{
				/* no ciphers */
				SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
				return -1;
				}
			s2n(i,d);
			p+=i;
			
			/* put in the session-id length (zero since there is no reuse) */
#if 0
			s->session->session_id_length=0;
#endif
			s2n(0,d);

			if (s->options & SSL_OP_NETSCAPE_CHALLENGE_BUG)
				ch_len=SSL2_CHALLENGE_LENGTH;
			else
				ch_len=SSL2_MAX_CHALLENGE_LENGTH;

			/* write out sslv2 challenge */
			/* Note that ch_len must be <= SSL3_RANDOM_SIZE (32),
			   because it is one of SSL2_MAX_CHALLENGE_LENGTH (32)
			   or SSL2_MAX_CHALLENGE_LENGTH (16), but leave the
			   check in for futurproofing */
			if (SSL3_RANDOM_SIZE < ch_len)
				i=SSL3_RANDOM_SIZE;
			else
				i=ch_len;
			s2n(i,d);
			memset(&(s->s3->client_random[0]),0,SSL3_RANDOM_SIZE);
			if (RAND_pseudo_bytes(&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i) <= 0)
				return -1;

			memcpy(p,&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i);
			p+=i;

			i= p- &(buf[2]);
			buf[0]=((i>>8)&0xff)|0x80;
			buf[1]=(i&0xff);

			/* number of bytes to write */
			s->init_num=i+2;
			s->init_off=0;

			ssl3_finish_mac(s,&(buf[2]),i);
			}
		else
			{
			/* create Client Hello in SSL 3.0/TLS 1.0 format */

			/* do the record header (5 bytes) and handshake message header (4 bytes) last */
			d = p = &(buf[9]);
			
			*(p++) = version_major;
			*(p++) = version_minor;

			/* Random stuff */
			memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
			p += SSL3_RANDOM_SIZE;

			/* Session ID (zero since there is no reuse) */
			*(p++) = 0;

			/* Ciphers supported (using SSL 3.0/TLS 1.0 format) */
			i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),ssl3_put_cipher_by_char);
			if (i == 0)
				{
				SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
				return -1;
				}
#ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH
			/* Some servers hang if client hello > 256 bytes
			 * as hack workaround chop number of supported ciphers
			 * to keep it well below this if we use TLS v1.2
			 */
			if (TLS1_get_version(s) >= TLS1_2_VERSION
				&& i > OPENSSL_MAX_TLS1_2_CIPHER_LENGTH)
				i = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1;
#endif
			s2n(i,p);
			p+=i;

			/* COMPRESSION */
#ifdef OPENSSL_NO_COMP
			*(p++)=1;
#else
			if ((s->options & SSL_OP_NO_COMPRESSION)
						|| !s->ctx->comp_methods)
				j=0;
			else
				j=sk_SSL_COMP_num(s->ctx->comp_methods);
			*(p++)=1+j;
			for (i=0; i<j; i++)
				{
				comp=sk_SSL_COMP_value(s->ctx->comp_methods,i);
				*(p++)=comp->id;
				}
#endif
			*(p++)=0; /* Add the NULL method */

#ifndef OPENSSL_NO_TLSEXT
			/* TLS extensions*/
			if (ssl_prepare_clienthello_tlsext(s) <= 0)
				{
				SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
				return -1;
				}
			if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
				{
				SSLerr(SSL_F_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
				return -1;
				}
#endif
			
			l = p-d;

			/* fill in 4-byte handshake header */
			d=&(buf[5]);
			*(d++)=SSL3_MT_CLIENT_HELLO;
			l2n3(l,d);

			l += 4;

			if (l > SSL3_RT_MAX_PLAIN_LENGTH)
				{
				SSLerr(SSL_F_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
				return -1;
				}
			
			/* fill in 5-byte record header */
			d=buf;
			*(d++) = SSL3_RT_HANDSHAKE;
			*(d++) = version_major;
			/* Some servers hang if we use long client hellos
			 * and a record number > TLS 1.0.
			 */
			if (TLS1_get_client_version(s) > TLS1_VERSION)
				*(d++) = 1;
			else
				*(d++) = version_minor;
			s2n((int)l,d);

			/* number of bytes to write */
			s->init_num=p-buf;
			s->init_off=0;

			ssl3_finish_mac(s,&(buf[5]), s->init_num - 5);
			}

		s->state=SSL23_ST_CW_CLNT_HELLO_B;
		s->init_off=0;
		}
Ejemplo n.º 7
0
static int ssl23_get_server_hello(SSL *s)
	{
	char buf[8];
	unsigned char *p;
	int i;
	int n;

	n=ssl23_read_bytes(s,7);

	if (n != 7) return(n);
	p=s->packet;

	memcpy(buf,p,n);

	if ((p[0] & 0x80) && (p[2] == SSL2_MT_SERVER_HELLO) &&
		(p[5] == 0x00) && (p[6] == 0x02))
		{
		OPENSSL_PUT_ERROR(SSL, ssl23_get_server_hello, SSL_R_UNSUPPORTED_PROTOCOL);
		goto err;
		}
	else if (p[1] == SSL3_VERSION_MAJOR &&
	         p[2] <= TLS1_2_VERSION_MINOR &&
	         ((p[0] == SSL3_RT_HANDSHAKE && p[5] == SSL3_MT_SERVER_HELLO) ||
	          (p[0] == SSL3_RT_ALERT && p[3] == 0 && p[4] == 2)))
		{
		/* we have sslv3 or tls1 (server hello or alert) */

		if ((p[2] == SSL3_VERSION_MINOR) &&
			!(s->options & SSL_OP_NO_SSLv3))
			{
			s->version=SSL3_VERSION;
			s->method=SSLv3_client_method();
			}
		else if ((p[2] == TLS1_VERSION_MINOR) &&
			!(s->options & SSL_OP_NO_TLSv1))
			{
			s->version=TLS1_VERSION;
			s->method=TLSv1_client_method();
			}
		else if ((p[2] == TLS1_1_VERSION_MINOR) &&
			!(s->options & SSL_OP_NO_TLSv1_1))
			{
			s->version=TLS1_1_VERSION;
			s->method=TLSv1_1_client_method();
			}
		else if ((p[2] == TLS1_2_VERSION_MINOR) &&
			!(s->options & SSL_OP_NO_TLSv1_2))
			{
			s->version=TLS1_2_VERSION;
			s->method=TLSv1_2_client_method();
			}
		else
			{
			OPENSSL_PUT_ERROR(SSL, ssl23_get_server_hello, SSL_R_UNSUPPORTED_PROTOCOL);
			goto err;
			}

		if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING)
			{
			/* fatal alert */

			void (*cb)(const SSL *ssl,int type,int val)=NULL;
			int j;

			if (s->info_callback != NULL)
				cb=s->info_callback;
			else if (s->ctx->info_callback != NULL)
				cb=s->ctx->info_callback;
 
			i=p[5];
			if (cb != NULL)
				{
				j=(i<<8)|p[6];
				cb(s,SSL_CB_READ_ALERT,j);
				}
			
			if (s->msg_callback)
				{
				s->msg_callback(0, s->version, SSL3_RT_HEADER, p, 5, s, s->msg_callback_arg);
				s->msg_callback(0, s->version, SSL3_RT_ALERT, p+5, 2, s, s->msg_callback_arg);
				}

			s->rwstate=SSL_NOTHING;
			OPENSSL_PUT_ERROR(SSL, ssl23_get_server_hello, SSL_AD_REASON_OFFSET + p[6]);
			goto err;
			}

		if (!ssl_init_wbio_buffer(s,1)) goto err;

		/* we are in this state */
		s->state=SSL3_ST_CR_SRVR_HELLO_A;

		/* put the 7 bytes we have read into the input buffer
		 * for SSLv3 */
		s->rstate=SSL_ST_READ_HEADER;
		s->packet_length=n;
		if (s->s3->rbuf.buf == NULL)
			if (!ssl3_setup_read_buffer(s))
				goto err;
		s->packet= &(s->s3->rbuf.buf[0]);
		memcpy(s->packet,buf,n);
		s->s3->rbuf.left=n;
		s->s3->rbuf.offset=0;

		s->handshake_func=s->method->ssl_connect;
		}
	else
		{
		OPENSSL_PUT_ERROR(SSL, ssl23_get_server_hello, SSL_R_UNKNOWN_PROTOCOL);
		goto err;
		}
	s->init_num=0;

	/* If there was no session to resume, now that the final version is
	 * determined, insert a fresh one. */
	if (s->session == NULL && !ssl_get_new_session(s,0))
		goto err;

	return(SSL_connect(s));
err:
	return(-1);
	}
Ejemplo n.º 8
0
static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;
  /* The short record header extension is incompatible with early data. */
  if (ssl->s3->skip_early_data && ssl->s3->short_header) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
    return ssl_hs_error;
  }

  SSL_CLIENT_HELLO client_hello;
  if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
                             ssl->init_num)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
    return ssl_hs_error;
  }

  /* Negotiate the cipher suite. */
  ssl->s3->tmp.new_cipher = choose_tls13_cipher(ssl, &client_hello);
  if (ssl->s3->tmp.new_cipher == NULL) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
    return ssl_hs_error;
  }

  /* Decode the ticket if we agree on a PSK key exchange mode. */
  uint8_t alert = SSL_AD_DECODE_ERROR;
  SSL_SESSION *session = NULL;
  CBS pre_shared_key, binders;
  if (hs->accept_psk_mode &&
      ssl_client_hello_get_extension(&client_hello, &pre_shared_key,
                                     TLSEXT_TYPE_pre_shared_key)) {
    /* Verify that the pre_shared_key extension is the last extension in
     * ClientHello. */
    if (CBS_data(&pre_shared_key) + CBS_len(&pre_shared_key) !=
        client_hello.extensions + client_hello.extensions_len) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_PRE_SHARED_KEY_MUST_BE_LAST);
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
      return ssl_hs_error;
    }

    if (!ssl_ext_pre_shared_key_parse_clienthello(hs, &session, &binders,
                                                  &alert, &pre_shared_key)) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
      return ssl_hs_error;
    }
  }

  if (session != NULL &&
      !ssl_session_is_resumable(ssl, session)) {
    SSL_SESSION_free(session);
    session = NULL;
  }

  /* Set up the new session, either using the original one as a template or
   * creating a fresh one. */
  if (session == NULL) {
    if (!ssl_get_new_session(hs, 1 /* server */)) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
      return ssl_hs_error;
    }

    ssl->s3->new_session->cipher = ssl->s3->tmp.new_cipher;

    /* On new sessions, stash the SNI value in the session. */
    if (hs->hostname != NULL) {
      OPENSSL_free(ssl->s3->new_session->tlsext_hostname);
      ssl->s3->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
      if (ssl->s3->new_session->tlsext_hostname == NULL) {
        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
        return ssl_hs_error;
      }
    }
  } else {
    /* Check the PSK binder. */
    if (!tls13_verify_psk_binder(ssl, session, &binders)) {
      SSL_SESSION_free(session);
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
      return ssl_hs_error;
    }

    /* Only authentication information carries over in TLS 1.3. */
    ssl->s3->new_session = SSL_SESSION_dup(session, SSL_SESSION_DUP_AUTH_ONLY);
    if (ssl->s3->new_session == NULL) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
      return ssl_hs_error;
    }
    ssl->s3->session_reused = 1;
    SSL_SESSION_free(session);

    /* Resumption incorporates fresh key material, so refresh the timeout. */
    ssl_session_renew_timeout(ssl, ssl->s3->new_session,
                              ssl->initial_ctx->session_psk_dhe_timeout);
  }

  if (ssl->ctx->dos_protection_cb != NULL &&
      ssl->ctx->dos_protection_cb(&client_hello) == 0) {
    /* Connection rejected for DOS reasons. */
    OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
    return ssl_hs_error;
  }

  /* HTTP/2 negotiation depends on the cipher suite, so ALPN negotiation was
   * deferred. Complete it now. */
  if (!ssl_negotiate_alpn(hs, &alert, &client_hello)) {
    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
    return ssl_hs_error;
  }

  /* The PRF hash is now known. Set up the key schedule and hash the
   * ClientHello. */
  size_t hash_len =
      EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
  if (!tls13_init_key_schedule(hs) ||
      !ssl_hash_current_message(ssl)) {
    return ssl_hs_error;
  }

  /* Incorporate the PSK into the running secret. */
  if (ssl->s3->session_reused) {
    if (!tls13_advance_key_schedule(hs, ssl->s3->new_session->master_key,
                                    ssl->s3->new_session->master_key_length)) {
      return ssl_hs_error;
    }
  } else if (!tls13_advance_key_schedule(hs, kZeroes, hash_len)) {
    return ssl_hs_error;
  }

  ssl->method->received_flight(ssl);

  /* Resolve ECDHE and incorporate it into the secret. */
  int need_retry;
  if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) {
    if (need_retry) {
      hs->tls13_state = state_send_hello_retry_request;
      return ssl_hs_ok;
    }
    return ssl_hs_error;
  }

  hs->tls13_state = state_send_server_hello;
  return ssl_hs_ok;
}
Ejemplo n.º 9
0
static int ssl23_get_server_hello(SSL *s)
{
    unsigned char buf[8];
    unsigned char *p;
    int i;
    int n;

    n = ssl23_read_bytes(s, 7);

    if (n != 7)
        return (n);
    p = RECORD_LAYER_get_packet(&s->rlayer);

    memcpy(buf, p, n);

    if (p[1] == SSL3_VERSION_MAJOR &&
        p[2] <= TLS1_2_VERSION_MINOR &&
        ((p[0] == SSL3_RT_HANDSHAKE && p[5] == SSL3_MT_SERVER_HELLO) ||
         (p[0] == SSL3_RT_ALERT && p[3] == 0 && p[4] == 2))) {
        /* we have sslv3 or tls1 (server hello or alert) */

#ifndef OPENSSL_NO_SSL3
        if ((p[2] == SSL3_VERSION_MINOR) && !(s->options & SSL_OP_NO_SSLv3)) {
            if (FIPS_mode()) {
                SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,
                       SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE);
                goto err;
            }
            s->version = SSL3_VERSION;
            s->method = SSLv3_client_method();
        } else
#endif
        if ((p[2] == TLS1_VERSION_MINOR) && !(s->options & SSL_OP_NO_TLSv1)) {
            s->version = TLS1_VERSION;
            s->method = TLSv1_client_method();
        } else if ((p[2] == TLS1_1_VERSION_MINOR) &&
                   !(s->options & SSL_OP_NO_TLSv1_1)) {
            s->version = TLS1_1_VERSION;
            s->method = TLSv1_1_client_method();
        } else if ((p[2] == TLS1_2_VERSION_MINOR) &&
                   !(s->options & SSL_OP_NO_TLSv1_2)) {
            s->version = TLS1_2_VERSION;
            s->method = TLSv1_2_client_method();
        } else {
            SSLerr(SSL_F_SSL23_GET_SERVER_HELLO, SSL_R_UNSUPPORTED_PROTOCOL);
            goto err;
        }

        /* ensure that TLS_MAX_VERSION is up-to-date */
        OPENSSL_assert(s->version <= TLS_MAX_VERSION);

        if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
            SSLerr(SSL_F_SSL23_GET_SERVER_HELLO, SSL_R_VERSION_TOO_LOW);
            goto err;
        }

        if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING) {
            /* fatal alert */

            void (*cb) (const SSL *ssl, int type, int val) = NULL;
            int j;

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

            i = p[5];
            if (cb != NULL) {
                j = (i << 8) | p[6];
                cb(s, SSL_CB_READ_ALERT, j);
            }

            if (s->msg_callback) {
                s->msg_callback(0, s->version, SSL3_RT_HEADER, p, 5, s,
                                s->msg_callback_arg);
                s->msg_callback(0, s->version, SSL3_RT_ALERT, p + 5, 2, s,
                                s->msg_callback_arg);
            }

            s->rwstate = SSL_NOTHING;
            SSLerr(SSL_F_SSL23_GET_SERVER_HELLO, SSL_AD_REASON_OFFSET + p[6]);
            goto err;
        }

        if (!ssl_init_wbio_buffer(s, 1))
            goto err;

        /* we are in this state */
        s->state = SSL3_ST_CR_SRVR_HELLO_A;

        /*
         * put the 7 bytes we have read into the input buffer for SSLv3
         */
        if (!RECORD_LAYER_set_data(&s->rlayer, buf, n))
            goto err;

        s->handshake_func = s->method->ssl_connect;
    } else {
        SSLerr(SSL_F_SSL23_GET_SERVER_HELLO, SSL_R_UNKNOWN_PROTOCOL);
        goto err;
    }
    s->init_num = 0;

    /*
     * Since, if we are sending a ssl23 client hello, we are not reusing a
     * session-id
     */
    if (!ssl_get_new_session(s, 0))
        goto err;

    return (SSL_connect(s));
 err:
    return (-1);
}
Ejemplo n.º 10
0
static int ssl23_client_hello(SSL *s)
{
    uint8_t *buf;
    uint8_t *p, *d;
    unsigned long l;
    int version = 0, version_major, version_minor;
    int ret, al;
    unsigned long mask, options = s->options;
    size_t outlen;

    /*
     * SSL_OP_NO_X disables all protocols above X *if* there are
     * some protocols below X enabled. This is required in order
     * to maintain "version capability" vector contiguous. So
     * that if application wants to disable TLS1.0 in favour of
     * TLS1>=1, it would be insufficient to pass SSL_NO_TLSv1, the
     * answer is SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2.
     */
    mask = SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1 | SSL_OP_NO_SSLv3;
    version = TLS1_2_VERSION;

    if ((options & SSL_OP_NO_TLSv1_2) && (options & mask) != mask)
        version = TLS1_1_VERSION;
    mask &= ~SSL_OP_NO_TLSv1_1;
    if ((options & SSL_OP_NO_TLSv1_1) && (options & mask) != mask)
        version = TLS1_VERSION;
    mask &= ~SSL_OP_NO_TLSv1;

    buf = (uint8_t *)s->init_buf->data;
    if (s->state == SSL23_ST_CW_CLNT_HELLO_A) {
        /*
         * Since we're sending s23 client hello, we're not reusing a session, as
         * we'd be using the method from the saved session instead
         */
        if (!ssl_get_new_session(s, 0)) {
            return -1;
        }

        p = s->s3->client_random;
        if (ssl_fill_hello_random(s, p, SSL3_RANDOM_SIZE) <= 0) {
            SSLerr(SSL_F_SSL23_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
            return -1;
        }

        if (version == TLS1_2_VERSION) {
            version_major = TLS1_2_VERSION_MAJOR;
            version_minor = TLS1_2_VERSION_MINOR;
        } else if (tls1_suiteb(s)) {
            SSLerr(SSL_F_SSL23_CLIENT_HELLO,
                   SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE);
            return -1;
        } else if (version == TLS1_1_VERSION) {
            version_major = TLS1_1_VERSION_MAJOR;
            version_minor = TLS1_1_VERSION_MINOR;
        } else if (version == TLS1_VERSION) {
            version_major = TLS1_VERSION_MAJOR;
            version_minor = TLS1_VERSION_MINOR;
        } else {
            SSLerr(SSL_F_SSL23_CLIENT_HELLO, SSL_R_NO_PROTOCOLS_AVAILABLE);
            return (-1);
        }

        s->client_version = version;

        /* create Client Hello in SSL 3.0/TLS 1.0 format */

        /*
         * Do the record header (5 bytes) and handshake
         * message header (4 bytes) last
         */
        d = p = &(buf[SSL3_RT_HEADER_LENGTH + SSL3_HM_HEADER_LENGTH]);

        *(p++) = version_major;
        *(p++) = version_minor;

        /* Random stuff */
        memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
        p += SSL3_RANDOM_SIZE;

        /* Session ID (zero since there is no reuse) */
        *(p++) = 0;

        /* Ciphers supported (using SSL 3.0/TLS 1.0 format) */
        if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &p[2],
                                      buf - &p[2] + SSL3_RT_MAX_PLAIN_LENGTH,
                                      &outlen))
            return -1;
        if (outlen == 0) {
            SSLerr(SSL_F_SSL23_CLIENT_HELLO, SSL_R_NO_CIPHERS_AVAILABLE);
            return -1;
        }
#ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH
        /*
         * Some servers hang if client hello > 256 bytes
         * as hack workaround chop number of supported ciphers
         * to keep it well below this if we use TLS v1.2
         */
        if (TLS1_get_version(s) >= TLS1_2_VERSION && i > OPENSSL_MAX_TLS1_2_CIPHER_LENGTH)
            i = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1;
#endif
        s2n(outlen, p);
        p += outlen;

        /* add in (no) COMPRESSION */
        *(p++) = 1;
        /* Add the NULL method */
        *(p++) = 0;

        /* TLS extensions*/
        if (ssl_prepare_clienthello_tlsext(s) <= 0) {
            SSLerr(SSL_F_SSL23_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
            return -1;
        }
        p = ssl_add_clienthello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH,
                                       &al);
        if (p == NULL) {
            ssl3_send_alert(s, SSL3_AL_FATAL, al);
            SSLerr(SSL_F_SSL23_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
            return -1;
        }

        l = p - d;

        /* fill in 4-byte handshake header */
        d = &(buf[SSL3_RT_HEADER_LENGTH]);
        *(d++) = SSL3_MT_CLIENT_HELLO;
        l2n3(l, d);

        l += 4;

        if (l > SSL3_RT_MAX_PLAIN_LENGTH) {
            SSLerr(SSL_F_SSL23_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
            return -1;
        }

        /* fill in 5-byte record header */
        d = buf;
        *(d++) = SSL3_RT_HANDSHAKE;
        *(d++) = version_major;

        /*
         * Some servers hang if we use long client hellos
         * and a record number > TLS 1.0.
         */
        if (TLS1_get_client_version(s) > TLS1_VERSION)
            *(d++) = 1;
        else
            *(d++) = version_minor;
        s2n((int)l, d);

        /* number of bytes to write */
        s->init_num = p - buf;
        s->init_off = 0;

        tls1_finish_mac(s, &(buf[SSL3_RT_HEADER_LENGTH]),
            s->init_num - SSL3_RT_HEADER_LENGTH);

        s->state = SSL23_ST_CW_CLNT_HELLO_B;
        s->init_off = 0;
    }

    /* SSL3_ST_CW_CLNT_HELLO_B */
    ret = ssl23_write_bytes(s);

    if ((ret >= 2) && s->msg_callback) {
        /* Client Hello has been sent; tell msg_callback */
        s->msg_callback(1, version, SSL3_RT_HEADER, s->init_buf->data, 5, s,
                        s->msg_callback_arg);
        s->msg_callback(1, version, SSL3_RT_HANDSHAKE, s->init_buf->data + 5,
                        ret - 5, s, s->msg_callback_arg);
    }

    return ret;
}
Ejemplo n.º 11
0
static enum ssl_hs_wait_t do_process_client_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
  if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
    return ssl_hs_error;
  }

  struct ssl_early_callback_ctx client_hello;
  if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg,
                               ssl->init_num)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
    return ssl_hs_error;
  }

  assert(ssl->s3->have_version);

  /* Load the client random. */
  if (client_hello.random_len != SSL3_RANDOM_SIZE) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return -1;
  }
  memcpy(ssl->s3->client_random, client_hello.random, client_hello.random_len);

  uint8_t alert = SSL_AD_DECODE_ERROR;
  SSL_SESSION *session = NULL;
  CBS pre_shared_key;
  if (ssl_early_callback_get_extension(&client_hello, &pre_shared_key,
                                       TLSEXT_TYPE_pre_shared_key) &&
      !ssl_ext_pre_shared_key_parse_clienthello(ssl, &session, &alert,
                                                &pre_shared_key)) {
    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
    return 0;
  }

  uint16_t resumption_cipher;
  if (session != NULL &&
      /* We currently only support ECDHE-PSK resumption. */
      ((session->ticket_flags & SSL_TICKET_ALLOW_DHE_RESUMPTION) == 0 ||
       /* Only resume if the session's version matches. */
       session->ssl_version != ssl->version ||
       !ssl_cipher_get_ecdhe_psk_cipher(session->cipher, &resumption_cipher) ||
       !ssl_client_cipher_list_contains_cipher(&client_hello,
                                               resumption_cipher))) {
    SSL_SESSION_free(session);
    session = NULL;
  }

  if (session == NULL) {
    if (!ssl_get_new_session(ssl, 1 /* server */)) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
      return ssl_hs_error;
    }
  } else {
    /* Only authentication information carries over in TLS 1.3. */
    ssl->s3->new_session = SSL_SESSION_dup(session, SSL_SESSION_DUP_AUTH_ONLY);
    if (ssl->s3->new_session == NULL) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
      return ssl_hs_error;
    }
    ssl->s3->session_reused = 1;
    SSL_SESSION_free(session);
  }

  if (ssl->ctx->dos_protection_cb != NULL &&
      ssl->ctx->dos_protection_cb(&client_hello) == 0) {
    /* Connection rejected for DOS reasons. */
    OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
    return ssl_hs_error;
  }

  /* TLS 1.3 requires the peer only advertise the null compression. */
  if (client_hello.compression_methods_len != 1 ||
      client_hello.compression_methods[0] != 0) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMPRESSION_LIST);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
    return ssl_hs_error;
  }

  /* TLS extensions. */
  if (!ssl_parse_clienthello_tlsext(ssl, &client_hello)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
    return ssl_hs_error;
  }

  hs->state = state_select_parameters;
  return ssl_hs_ok;
}
Ejemplo n.º 12
0
static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;
  SSL_CLIENT_HELLO client_hello;
  if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
                             ssl->init_num)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
    return ssl_hs_error;
  }

  uint8_t alert = SSL_AD_DECODE_ERROR;
  SSL_SESSION *session = NULL;
  switch (select_session(hs, &alert, &session, &ssl->s3->ticket_age_skew,
                         &client_hello)) {
    case ssl_ticket_aead_ignore_ticket:
      assert(session == NULL);
      if (!ssl_get_new_session(hs, 1 /* server */)) {
        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
        return ssl_hs_error;
      }
      break;

    case ssl_ticket_aead_success:
      /* Carry over authentication information from the previous handshake into
       * a fresh session. */
      hs->new_session = SSL_SESSION_dup(session, SSL_SESSION_DUP_AUTH_ONLY);

      if (/* Early data must be acceptable for this ticket. */
          ssl->cert->enable_early_data &&
          session->ticket_max_early_data != 0 &&
          /* The client must have offered early data. */
          hs->early_data_offered &&
          /* Channel ID is incompatible with 0-RTT. */
          !ssl->s3->tlsext_channel_id_valid &&
          /* The negotiated ALPN must match the one in the ticket. */
          ssl->s3->alpn_selected_len == session->early_alpn_len &&
          OPENSSL_memcmp(ssl->s3->alpn_selected, session->early_alpn,
                         ssl->s3->alpn_selected_len) == 0) {
        ssl->early_data_accepted = 1;
      }

      SSL_SESSION_free(session);
      if (hs->new_session == NULL) {
        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
        return ssl_hs_error;
      }

      ssl->s3->session_reused = 1;

      /* Resumption incorporates fresh key material, so refresh the timeout. */
      ssl_session_renew_timeout(ssl, hs->new_session,
                                ssl->session_ctx->session_psk_dhe_timeout);
      break;

    case ssl_ticket_aead_error:
      ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
      return ssl_hs_error;

    case ssl_ticket_aead_retry:
      hs->tls13_state = state_select_session;
      return ssl_hs_pending_ticket;
  }

  /* Record connection properties in the new session. */
  hs->new_session->cipher = hs->new_cipher;

  if (hs->hostname != NULL) {
    OPENSSL_free(hs->new_session->tlsext_hostname);
    hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
    if (hs->new_session->tlsext_hostname == NULL) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
      return ssl_hs_error;
    }
  }

  /* Store the initial negotiated ALPN in the session. */
  if (ssl->s3->alpn_selected != NULL) {
    hs->new_session->early_alpn =
        BUF_memdup(ssl->s3->alpn_selected, ssl->s3->alpn_selected_len);
    if (hs->new_session->early_alpn == NULL) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
      return ssl_hs_error;
    }
    hs->new_session->early_alpn_len = ssl->s3->alpn_selected_len;
  }

  if (ssl->ctx->dos_protection_cb != NULL &&
      ssl->ctx->dos_protection_cb(&client_hello) == 0) {
    /* Connection rejected for DOS reasons. */
    OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
    return ssl_hs_error;
  }

  /* Incorporate the PSK into the running secret. */
  if (ssl->s3->session_reused) {
    if (!tls13_advance_key_schedule(hs, hs->new_session->master_key,
                                    hs->new_session->master_key_length)) {
      return ssl_hs_error;
    }
  } else if (!tls13_advance_key_schedule(hs, kZeroes, hs->hash_len)) {
    return ssl_hs_error;
  }

  if (ssl->early_data_accepted) {
    if (!tls13_derive_early_secrets(hs)) {
      return ssl_hs_error;
    }
  } else if (hs->early_data_offered) {
    ssl->s3->skip_early_data = 1;
  }

  ssl->method->received_flight(ssl);

  /* Resolve ECDHE and incorporate it into the secret. */
  int need_retry;
  if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) {
    if (need_retry) {
      ssl->early_data_accepted = 0;
      ssl->s3->skip_early_data = 1;
      hs->tls13_state = state_send_hello_retry_request;
      return ssl_hs_ok;
    }
    return ssl_hs_error;
  }

  hs->tls13_state = state_send_server_hello;
  return ssl_hs_ok;
}
Ejemplo n.º 13
0
static int
ssl23_client_hello(SSL *s)
{
	unsigned char *buf;
	unsigned char *p, *d;
	int i;
	unsigned long l;
	int version = 0, version_major, version_minor;
#ifndef OPENSSL_NO_COMP
	int j;
	SSL_COMP *comp;
#endif
	int ret;
	unsigned long mask, options = s->options;

	/*
	 * SSL_OP_NO_X disables all protocols above X *if* there are
	 * some protocols below X enabled. This is required in order
	 * to maintain "version capability" vector contiguous. So
	 * that if application wants to disable TLS1.0 in favour of
	 * TLS1>=1, it would be insufficient to pass SSL_NO_TLSv1, the
	 * answer is SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2.
	 */
	mask = SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3;
#if !defined(OPENSSL_NO_TLS1_2_CLIENT)
	version = TLS1_2_VERSION;

	if ((options & SSL_OP_NO_TLSv1_2) && (options & mask) != mask)
		version = TLS1_1_VERSION;
#else
	version = TLS1_1_VERSION;
#endif
	mask &= ~SSL_OP_NO_TLSv1_1;
	if ((options & SSL_OP_NO_TLSv1_1) && (options & mask) != mask)
		version = TLS1_VERSION;
	mask &= ~SSL_OP_NO_TLSv1;
	if ((options & SSL_OP_NO_TLSv1) && (options & mask) != mask)
		version = SSL3_VERSION;
	mask &= ~SSL_OP_NO_SSLv3;

	buf = (unsigned char *)s->init_buf->data;
	if (s->state == SSL23_ST_CW_CLNT_HELLO_A) {
#if 0
		/* don't reuse session-id's */
		if (!ssl_get_new_session(s, 0)) {
			return (-1);
		}
#endif

		p = s->s3->client_random;
		if (ssl_fill_hello_random(s, 0, p, SSL3_RANDOM_SIZE) <= 0)
			return -1;

		if (version == TLS1_2_VERSION) {
			version_major = TLS1_2_VERSION_MAJOR;
			version_minor = TLS1_2_VERSION_MINOR;
		} else if (version == TLS1_1_VERSION) {
			version_major = TLS1_1_VERSION_MAJOR;
			version_minor = TLS1_1_VERSION_MINOR;
		} else if (version == TLS1_VERSION) {
			version_major = TLS1_VERSION_MAJOR;
			version_minor = TLS1_VERSION_MINOR;
		} else if (version == SSL3_VERSION) {
			version_major = SSL3_VERSION_MAJOR;
			version_minor = SSL3_VERSION_MINOR;
		} else {
			SSLerr(SSL_F_SSL23_CLIENT_HELLO, SSL_R_NO_PROTOCOLS_AVAILABLE);
			return (-1);
		}

		s->client_version = version;

		/* create Client Hello in SSL 3.0/TLS 1.0 format */

		/*
		 * Do the record header (5 bytes) and handshake
		 * message header (4 bytes) last
		 */
		d = p = &(buf[9]);

		*(p++) = version_major;
		*(p++) = version_minor;

		/* Random stuff */
		memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
		p += SSL3_RANDOM_SIZE;

		/* Session ID (zero since there is no reuse) */
		*(p++) = 0;

		/* Ciphers supported (using SSL 3.0/TLS 1.0 format) */
		i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &(p[2]),
		    ssl3_put_cipher_by_char);
		if (i == 0) {
			SSLerr(SSL_F_SSL23_CLIENT_HELLO,
			    SSL_R_NO_CIPHERS_AVAILABLE);
			return -1;
		}
#ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH
		/*
		 * Some servers hang if client hello > 256 bytes
		 * as hack workaround chop number of supported ciphers
		 * to keep it well below this if we use TLS v1.2
		 */
		if (TLS1_get_version(s) >= TLS1_2_VERSION &&
		    i > OPENSSL_MAX_TLS1_2_CIPHER_LENGTH)
			i = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1;
#endif
		s2n(i, p);
		p += i;

		/* COMPRESSION */
#ifdef OPENSSL_NO_COMP
		*(p++) = 1;
#else
		if ((s->options & SSL_OP_NO_COMPRESSION) ||
		    !s->ctx->comp_methods)
			j = 0;
		else
			j = sk_SSL_COMP_num(s->ctx->comp_methods);
		*(p++) = 1 + j;
		for (i = 0; i < j; i++) {
			comp = sk_SSL_COMP_value(s->ctx->comp_methods, i);
			*(p++) = comp->id;
		}
#endif
		/* Add the NULL method */
		*(p++) = 0;

#ifndef OPENSSL_NO_TLSEXT
		/* TLS extensions*/
		if (ssl_prepare_clienthello_tlsext(s) <= 0) {
			SSLerr(SSL_F_SSL23_CLIENT_HELLO,
			    SSL_R_CLIENTHELLO_TLSEXT);
			return -1;
		}
		if ((p = ssl_add_clienthello_tlsext(s, p,
		    buf + SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) {
			SSLerr(SSL_F_SSL23_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
			return -1;
		}
#endif

		l = p - d;

		/* fill in 4-byte handshake header */
		d = &(buf[5]);
		*(d++) = SSL3_MT_CLIENT_HELLO;
		l2n3(l, d);

		l += 4;

		if (l > SSL3_RT_MAX_PLAIN_LENGTH) {
			SSLerr(SSL_F_SSL23_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
			return -1;
		}

		/* fill in 5-byte record header */
		d = buf;
		*(d++) = SSL3_RT_HANDSHAKE;
		*(d++) = version_major;

		/*
		 * Some servers hang if we use long client hellos
		 * and a record number > TLS 1.0.
		 */
		if (TLS1_get_client_version(s) > TLS1_VERSION)
			*(d++) = 1;
		else
			*(d++) = version_minor;
		s2n((int)l, d);

		/* number of bytes to write */
		s->init_num = p - buf;
		s->init_off = 0;

		ssl3_finish_mac(s, &(buf[5]), s->init_num - 5);

		s->state = SSL23_ST_CW_CLNT_HELLO_B;
		s->init_off = 0;
	}

	/* SSL3_ST_CW_CLNT_HELLO_B */
	ret = ssl23_write_bytes(s);

	if ((ret >= 2) && s->msg_callback) {
		/* Client Hello has been sent; tell msg_callback */

		s->msg_callback(1, version, SSL3_RT_HANDSHAKE,
		    s->init_buf->data + 5, ret - 5, s, s->msg_callback_arg);
	}

	return ret;
}
Ejemplo n.º 14
0
int
dtls1_client_hello(SSL *s)
{
	unsigned char *bufend, *d, *p;
	unsigned int i;

	if (s->state == SSL3_ST_CW_CLNT_HELLO_A) {
		SSL_SESSION *sess = s->session;

		if ((s->session == NULL) ||
		    (s->session->ssl_version != s->version) ||
		    (!sess->session_id_length && !sess->tlsext_tick) ||
		    (s->session->not_resumable)) {
			if (!ssl_get_new_session(s, 0))
				goto err;
		}
		/* else use the pre-loaded session */

		p = s->s3->client_random;

		/* if client_random is initialized, reuse it, we are
		 * required to use same upon reply to HelloVerify */
		for (i = 0; p[i]=='\0' && i < sizeof(s->s3->client_random); i++)
			;
		if (i == sizeof(s->s3->client_random))
			arc4random_buf(p, sizeof(s->s3->client_random));

		d = p = ssl3_handshake_msg_start(s, SSL3_MT_CLIENT_HELLO);

		*(p++) = s->version >> 8;
		*(p++) = s->version&0xff;
		s->client_version = s->version;

		/* Random stuff */
		memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
		p += SSL3_RANDOM_SIZE;

		/* Session ID */
		if (s->new_session)
			i = 0;
		else
			i = s->session->session_id_length;
		*(p++) = i;
		if (i != 0) {
			if (i > sizeof s->session->session_id) {
				SSLerr(SSL_F_DTLS1_CLIENT_HELLO,
				    ERR_R_INTERNAL_ERROR);
				goto err;
			}
			memcpy(p, s->session->session_id, i);
			p += i;
		}

		/* cookie stuff */
		if (s->d1->cookie_len > sizeof(s->d1->cookie)) {
			SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
			goto err;
		}
		*(p++) = s->d1->cookie_len;
		memcpy(p, s->d1->cookie, s->d1->cookie_len);
		p += s->d1->cookie_len;

		/* Ciphers supported */
		i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &p[2]);
		if (i == 0) {
			SSLerr(SSL_F_DTLS1_CLIENT_HELLO,
			    SSL_R_NO_CIPHERS_AVAILABLE);
			goto err;
		}
		s2n(i, p);
		p += i;

		/* add in (no) COMPRESSION */
		*(p++) = 1;
		*(p++) = 0; /* Add the NULL method */

		bufend = (unsigned char *)s->init_buf->data +
		    SSL3_RT_MAX_PLAIN_LENGTH;
		if ((p = ssl_add_clienthello_tlsext(s, p, bufend)) == NULL) {
			SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
			goto err;
		}

		ssl3_handshake_msg_finish(s, p - d);

		s->state = SSL3_ST_CW_CLNT_HELLO_B;
	}