Example #1
0
/**
 * gnutls_session_get_data2:
 * @session: is a #gnutls_session_t type.
 * @data: is a pointer to a datum that will hold the session.
 *
 * Returns all session parameters needed to be stored to support resumption.
 * The client should call this, and store the returned session data. A session
 * may be resumed later by calling gnutls_session_set_data().  
 *
 * The returned @data are allocated and must be released using gnutls_free().
 *
 * This function will fail if called prior to handshake completion. In
 * case of false start TLS, the handshake completes only after data have
 * been successfully received from the peer.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
 *   an error code is returned.
 **/
int
gnutls_session_get_data2(gnutls_session_t session, gnutls_datum_t *data)
{

	int ret;

	if (data == NULL) {
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
	}

	if (gnutls_session_is_resumed(session) && session->internals.resumption_data.data) {
		ret = _gnutls_set_datum(data, session->internals.resumption_data.data, session->internals.resumption_data.size);
		if (ret < 0)
			return gnutls_assert_val(ret);

		return 0;
	}

	if (session->internals.resumable == RESUME_FALSE)
		return GNUTLS_E_INVALID_SESSION;

	ret = _gnutls_session_pack(session, data);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	return 0;
}
Example #2
0
int _gnutls_server_register_current_session(gnutls_session_t session)
{
	gnutls_datum_t key;
	gnutls_datum_t content;
	int ret = 0;

	key.data = session->security_parameters.session_id;
	key.size = session->security_parameters.session_id_size;

	if (session->internals.resumable == RESUME_FALSE) {
		gnutls_assert();
		return GNUTLS_E_INVALID_SESSION;
	}

	if (session->security_parameters.session_id == NULL
	    || session->security_parameters.session_id_size == 0) {
		gnutls_assert();
		return GNUTLS_E_INVALID_SESSION;
	}

	ret = _gnutls_session_pack(session, &content);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret = store_session(session, key, content);
	_gnutls_free_datum(&content);

	return ret;
}
Example #3
0
static int
pack_ticket(gnutls_session_t session, tls13_ticket_st *ticket, gnutls_datum_t *packed)
{
	uint8_t *p;
	gnutls_datum_t state;
	int ret;

	ret = _gnutls_session_pack(session, &state);
	if (ret < 0)
		return gnutls_assert_val(ret);

	packed->size = 2 + 4 + 4 +
		1 + ticket->prf->output_size +
		1 + ticket->nonce_size + 2 + state.size + 12;

	packed->data = gnutls_malloc(packed->size);
	if (!packed->data) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	p = packed->data;

	_gnutls_write_uint16(ticket->prf->id, p);
	p += 2;
	_gnutls_write_uint32(ticket->age_add, p);
	p += 4;
	_gnutls_write_uint32(ticket->lifetime, p);
	p += 4;
	*p = ticket->prf->output_size;
	p += 1;
	memcpy(p, ticket->resumption_master_secret, ticket->prf->output_size);
	p += ticket->prf->output_size;
	*p = ticket->nonce_size;

	p += 1;
	memcpy(p, ticket->nonce, ticket->nonce_size);
	p += ticket->nonce_size;

	_gnutls_write_uint16(state.size, p);
	p += 2;

	memcpy(p, state.data, state.size);
	p += state.size;

	_gnutls_write_uint32((uint64_t) ticket->creation_time.tv_sec >> 32, p);
	p += 4;
	_gnutls_write_uint32(ticket->creation_time.tv_sec & 0xFFFFFFFF, p);
	p += 4;
	_gnutls_write_uint32(ticket->creation_time.tv_nsec, p);

	ret = 0;

 cleanup:
	gnutls_free(state.data);
	return ret;
}
Example #4
0
/*
 * Return zero if session tickets haven't been enabled.
 */
int _gnutls_send_new_session_ticket(gnutls_session_t session, int again)
{
	mbuffer_st *bufel = NULL;
	uint8_t *data = NULL, *p;
	int data_size = 0;
	int ret;
	gnutls_datum_t state = { NULL, 0 };
	uint16_t epoch_saved = session->security_parameters.epoch_write;
	gnutls_datum_t ticket_data;

	if (again == 0) {
		if (session->internals.flags & GNUTLS_NO_TICKETS)
			return 0;
		if (!session->internals.session_ticket_renew)
			return 0;

		_gnutls_handshake_log
		    ("HSK[%p]: sending session ticket\n", session);

		/* XXX: Temporarily set write algorithms to be used.
		   _gnutls_write_connection_state_init() does this job, but it also
		   triggers encryption, while NewSessionTicket should not be
		   encrypted in the record layer. */
		ret =
		    _gnutls_epoch_set_keys(session,
					   session->security_parameters.
					   epoch_next, 0);
		if (ret < 0) {
			gnutls_assert();
			return ret;
		}

		/* Under TLS1.2 with session tickets, the session ID is used for different
		 * purposes than the TLS1.0 session ID. Ensure that there is an internally
		 * set value which the server will see on the original and resumed sessions */
		if (session->internals.resumed != RESUME_TRUE) {
			ret = _gnutls_generate_session_id(session->security_parameters.
							  session_id,
							  &session->security_parameters.
							  session_id_size);
			if (ret < 0) {
				gnutls_assert();
				return ret;
			}
		}

		session->security_parameters.epoch_write =
		    session->security_parameters.epoch_next;

		/* Pack security parameters. */
		ret = _gnutls_session_pack(session, &state);
		if (ret < 0) {
			gnutls_assert();
			return ret;
		}

		/* Generate an encrypted ticket */
		ret = _gnutls_encrypt_session_ticket(session, &state, &ticket_data);
		session->security_parameters.epoch_write = epoch_saved;
		_gnutls_free_datum(&state);
		if (ret < 0) {
			gnutls_assert();
			return ret;
		}

		bufel =
		    _gnutls_handshake_alloc(session, 
					    4 + 2 + ticket_data.size);
		if (!bufel) {
			gnutls_assert();
			_gnutls_free_datum(&ticket_data);
			return GNUTLS_E_MEMORY_ERROR;
		}

		data = _mbuffer_get_udata_ptr(bufel);
		p = data;

		_gnutls_write_uint32(session->internals.expire_time, p);
		p += 4;

		_gnutls_write_uint16(ticket_data.size, p);
		p += 2;

		memcpy(p, ticket_data.data, ticket_data.size);
		p += ticket_data.size;

		_gnutls_free_datum(&ticket_data);

		data_size = p - data;

		session->internals.hsk_flags |= HSK_TLS12_TICKET_SENT;
	}
	return _gnutls_send_handshake(session, data_size ? bufel : NULL,
				      GNUTLS_HANDSHAKE_NEW_SESSION_TICKET);
}
Example #5
0
static int
encrypt_ticket(gnutls_session_t session, session_ticket_ext_st * priv,
               struct ticket_st *ticket)
{
    cipher_hd_st cipher_hd;
    gnutls_datum_t key, IV;
    gnutls_datum_t state = {NULL,0}, encrypted_state = {NULL,0};
    uint8_t iv[IV_SIZE];
    gnutls_datum_t mac_secret;
    uint32_t t;
    int ret;

    /* Pack security parameters. */
    ret = _gnutls_session_pack(session, &state);
    if (ret < 0) {
        gnutls_assert();
        return ret;
    }

    encrypted_state.size = ((state.size + BLOCK_SIZE - 1) / BLOCK_SIZE) * BLOCK_SIZE;
    encrypted_state.data = gnutls_calloc(1, encrypted_state.size);
    if (!encrypted_state.data) {
        gnutls_assert();
        ret = GNUTLS_E_MEMORY_ERROR;
        goto cleanup;
    }
    memcpy(encrypted_state.data, state.data, state.size);

    /* Encrypt state */
    key.data = (void *) &priv->key[KEY_POS];
    key.size = CIPHER_KEY_SIZE;
    IV.data = iv;
    IV.size = IV_SIZE;

    t = gnutls_time(0);
    memcpy(iv, &t, 4);
    ret = gnutls_rnd(GNUTLS_RND_NONCE, iv+4, IV_SIZE-4);
    if (ret < 0) {
        gnutls_assert();
        goto cleanup;
    }

    ret =
        _gnutls_cipher_init(&cipher_hd,
                            cipher_to_entry(CIPHER),
                            &key, &IV, 1);
    if (ret < 0) {
        gnutls_assert();
        goto cleanup;
    }

    ret = _gnutls_cipher_encrypt(&cipher_hd, encrypted_state.data,
                                 encrypted_state.size);
    if (ret < 0) {
        gnutls_assert();
        goto cleanup2;
    }


    /* Fill the ticket structure to compute MAC. */
    memcpy(ticket->key_name, &priv->key[NAME_POS], KEY_NAME_SIZE);
    memcpy(ticket->IV, IV.data, IV.size);
    ticket->encrypted_state_len = encrypted_state.size;
    ticket->encrypted_state = encrypted_state.data;

    mac_secret.data = &priv->key[MAC_SECRET_POS];
    mac_secret.size = MAC_SECRET_SIZE;
    ret = digest_ticket(&mac_secret, ticket, ticket->mac);
    if (ret < 0) {
        gnutls_assert();
        goto cleanup2;
    }

    encrypted_state.data = NULL;

    ret = 0;

cleanup2:
    _gnutls_cipher_deinit(&cipher_hd);

cleanup:
    _gnutls_free_datum(&state);
    _gnutls_free_datum(&encrypted_state);

    return ret;
}