Esempio n. 1
0
int
_gnutls_encrypt_session_ticket(gnutls_session_t session,
			       const gnutls_datum_t *state,
			       gnutls_datum_t *ticket_data)
{
	cipher_hd_st cipher_hd;
	gnutls_datum_t IV;
	gnutls_datum_t encrypted_state = {NULL,0};
	uint8_t iv[TICKET_IV_SIZE];
	gnutls_datum_t stek_cipher_key, stek_mac_key, stek_key_name;
	struct ticket_st ticket;
	int ret;

	encrypted_state.size = ((state->size + TICKET_BLOCK_SIZE - 1) / TICKET_BLOCK_SIZE) * TICKET_BLOCK_SIZE;
	ticket_data->size = TICKET_KEY_NAME_SIZE + TICKET_IV_SIZE + 2 +
	    encrypted_state.size + TICKET_MAC_SIZE;
	ticket_data->data = gnutls_calloc(1, ticket_data->size);
	if (!ticket_data->data) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}
	encrypted_state.data = ticket_data->data + TICKET_KEY_NAME_SIZE + TICKET_IV_SIZE + 2;
	memcpy(encrypted_state.data, state->data, state->size);

	/* Retrieve ticket encryption keys */
	if (_gnutls_get_session_ticket_encryption_key(session,
						      &stek_key_name,
						      &stek_mac_key,
						      &stek_cipher_key) < 0) {
		ret = GNUTLS_E_ENCRYPTION_FAILED;
		goto cleanup;
	}

	/* Encrypt state */
	IV.data = iv;
	IV.size = TICKET_IV_SIZE;

	ret = gnutls_rnd(GNUTLS_RND_NONCE, iv, TICKET_IV_SIZE);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret =
	    _gnutls_cipher_init(&cipher_hd,
				cipher_to_entry(TICKET_CIPHER),
				&stek_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, stek_key_name.data, stek_key_name.size);
	memcpy(ticket.IV, IV.data, IV.size);
	ticket.encrypted_state_len = encrypted_state.size;
	ticket.encrypted_state = encrypted_state.data;

	ret = digest_ticket(&stek_mac_key, &ticket, ticket.mac);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup2;
	}

	encrypted_state.data = NULL;

	pack_ticket(&ticket, ticket_data);

	ret = 0;

cleanup2:
	_gnutls_cipher_deinit(&cipher_hd);

cleanup:
	_gnutls_free_datum(&encrypted_state);

	return ret;
}
Esempio n. 2
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;
}
Esempio n. 3
0
int
_gnutls_decrypt_session_ticket(gnutls_session_t session,
			       const gnutls_datum_t *ticket_data,
			       gnutls_datum_t *state)
{
	cipher_hd_st cipher_hd;
	gnutls_datum_t IV;
	gnutls_datum_t stek_key_name, stek_cipher_key, stek_mac_key;
	uint8_t cmac[TICKET_MAC_SIZE];
	struct ticket_st ticket;
	int ret;

	/* callers must have that checked */
	assert(!(session->internals.flags & GNUTLS_NO_TICKETS));

	/* Retrieve ticket decryption keys */
	if (_gnutls_get_session_ticket_decryption_key(session,
						      ticket_data,
						      &stek_key_name,
						      &stek_mac_key,
						      &stek_cipher_key) < 0)
		return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);

	ret = unpack_ticket(ticket_data, &ticket);
	if (ret < 0)
		return ret;

	/* If the key name of the ticket does not match the one that is currently active,
	   issue a new ticket. */
	if (memcmp
	    (ticket.key_name, stek_key_name.data,
	     stek_key_name.size)) {
		ret = GNUTLS_E_DECRYPTION_FAILED;
		goto cleanup;
	}

	/* Check the integrity of ticket */
	ret = digest_ticket(&stek_mac_key, &ticket, cmac);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	if (memcmp(ticket.mac, cmac, TICKET_MAC_SIZE)) {
		ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
		goto cleanup;
	}

	if (ticket.encrypted_state_len % TICKET_BLOCK_SIZE != 0) {
		ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
		goto cleanup;
	}

	/* Decrypt encrypted_state */
	IV.data = ticket.IV;
	IV.size = TICKET_IV_SIZE;
	ret =
	    _gnutls_cipher_init(&cipher_hd,
				cipher_to_entry(TICKET_CIPHER),
				&stek_cipher_key, &IV, 0);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = _gnutls_cipher_decrypt(&cipher_hd, ticket.encrypted_state,
				     ticket.encrypted_state_len);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup2;
	}

	state->data = ticket.encrypted_state;
	state->size = ticket.encrypted_state_len;

	ticket.encrypted_state = NULL;

	ret = 0;

cleanup2:
	_gnutls_cipher_deinit(&cipher_hd);

cleanup:
	deinit_ticket(&ticket);

	return ret;

}
Esempio n. 4
0
static int
decrypt_ticket(gnutls_session_t session, session_ticket_ext_st * priv,
               struct ticket_st *ticket)
{
    cipher_hd_st cipher_hd;
    gnutls_datum_t key, IV, state, mac_secret;
    uint8_t cmac[MAC_SIZE];
    time_t timestamp = gnutls_time(0);
    int ret;

    /* Check the integrity of ticket */
    mac_secret.data = (void *) &priv->key[MAC_SECRET_POS];
    mac_secret.size = MAC_SECRET_SIZE;
    ret = digest_ticket(&mac_secret, ticket, cmac);
    if (ret < 0)
        return gnutls_assert_val(ret);

    if (memcmp(ticket->mac, cmac, MAC_SIZE))
        return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);

    if (ticket->encrypted_state_len % BLOCK_SIZE != 0)
        return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);

    /* Decrypt encrypted_state */
    key.data = (void *) &priv->key[KEY_POS];
    key.size = CIPHER_KEY_SIZE;
    IV.data = ticket->IV;
    IV.size = IV_SIZE;
    ret =
        _gnutls_cipher_init(&cipher_hd,
                            cipher_to_entry(CIPHER),
                            &key, &IV, 0);
    if (ret < 0) {
        gnutls_assert();
        return ret;
    }
    ret = _gnutls_cipher_decrypt(&cipher_hd, ticket->encrypted_state,
                                 ticket->encrypted_state_len);
    if (ret < 0) {
        gnutls_assert();
        goto cleanup;
    }

    /* Unpack security parameters. */
    state.data = ticket->encrypted_state;
    state.size = ticket->encrypted_state_len;
    ret = _gnutls_session_unpack(session, &state);
    if (ret < 0) {
        gnutls_assert();
        goto cleanup;
    }

    if (timestamp -
            session->internals.resumed_security_parameters.timestamp >
            session->internals.expire_time
            || session->internals.resumed_security_parameters.timestamp >
            timestamp) {
        gnutls_assert();
        ret = GNUTLS_E_EXPIRED;
        goto cleanup;
    }

    ret = _gnutls_check_resumed_params(session);
    if (ret < 0) {
        gnutls_assert();
        goto cleanup;
    }

    session->internals.resumed = RESUME_TRUE;

    ret = 0;
cleanup:
    _gnutls_cipher_deinit(&cipher_hd);

    return ret;

}