SilcClientConnection conn,
SilcChannelEntry channel,
SilcChannelPrivateKey key,
+ SilcMessageFlags flags,
unsigned char *data,
unsigned int data_len,
int force_send)
SILC_LOG_DEBUG(("Sending packet to channel"));
- if (!channel || !channel->hmac ||
- (!channel->channel_key && !key && !channel->private_keys)) {
- client->ops->say(client, conn,
- "Cannot talk to channel: key does not exist");
- return;
- }
-
/* Take the key to be used */
if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
if (key) {
hmac = channel->hmac;
}
+ if (!cipher || !hmac)
+ return;
+
/* Generate IV */
iv_len = silc_cipher_get_block_len(cipher);
if (channel->iv[0] == '\0')
silc_hash_make(client->md5hash, channel->iv, iv_len, channel->iv);
/* Encode the channel payload. This also encrypts the message payload. */
- payload = silc_channel_payload_encode(data_len, data, iv_len,
- channel->iv, cipher, hmac,
- client->rng);
+ payload = silc_channel_message_payload_encode(flags, data_len, data, iv_len,
+ channel->iv, cipher, hmac);
/* Get data used in packet header encryption, keys and stuff. */
cipher = conn->send_key;
{
SilcClientConnection conn = (SilcClientConnection)sock->user_data;
SilcBuffer buffer = packet->buffer;
- SilcChannelPayload payload = NULL;
+ SilcChannelMessagePayload payload = NULL;
SilcChannelID *id = NULL;
SilcChannelEntry channel;
SilcChannelUser chu;
all private keys and check what decrypts correctly. */
if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
/* Parse the channel message payload. This also decrypts the payload */
- payload = silc_channel_payload_parse(buffer, channel->channel_key,
- channel->hmac);
+ payload = silc_channel_message_payload_parse(buffer, channel->channel_key,
+ channel->hmac);
if (!payload)
goto out;
} else if (channel->private_keys) {
silc_dlist_start(channel->private_keys);
while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
/* Parse the channel message payload. This also decrypts the payload */
- payload = silc_channel_payload_parse(buffer, entry->cipher,
- entry->hmac);
+ payload = silc_channel_message_payload_parse(buffer, entry->cipher,
+ entry->hmac);
if (payload)
break;
}
goto out;
}
- message = silc_channel_get_data(payload, NULL);
+ message = silc_channel_message_get_data(payload, NULL);
/* Find client entry */
silc_list_start(channel->clients);
/* Pass the message to application */
client->ops->channel_message(client, conn, found ? chu->client : NULL,
- channel, message);
+ channel,
+ silc_channel_message_get_flags(payload),
+ message);
out:
if (id)
if (client_id)
silc_free(client_id);
if (payload)
- silc_channel_payload_free(payload);
+ silc_channel_message_payload_free(payload);
}
/* Saves channel key from encoded `key_payload'. This is used when we
silc_hmac_set_key(channel->hmac, hash, silc_hash_len(channel->hmac->hash));
memset(hash, 0, sizeof(hash));
- /* Client is now joined to the channel */
- channel->on_channel = TRUE;
-
out:
silc_free(id);
silc_channel_key_payload_free(payload);
several private keys per one channel. In this case only some of the
clients on the channel may know the one key and only some the other key.
- if `cipher' and/or `hmac' is NULL then default values will be used
+ If `cipher' and/or `hmac' is NULL then default values will be used
(aes-256-cbc for cipher and hmac-sha1-96 for hmac).
The private key for channel is optional. If it is not set then the
{
SilcChannelPrivateKey entry;
unsigned char hash[32];
+ SilcSKEKeyMaterial *keymat;
if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
return FALSE;
if (!silc_hmac_is_supported(hmac))
return FALSE;
+ /* Produce the key material */
+ keymat = silc_calloc(1, sizeof(*keymat));
+ if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
+ client->md5hash, keymat)
+ != SILC_SKE_STATUS_OK)
+ return FALSE;
+
/* Remove the current key, if it exists. */
if (channel->channel_key) {
silc_cipher_free(channel->channel_key);
channel->key = NULL;
channel->key_len = 0;
}
- if (channel->hmac)
+ if (channel->hmac) {
silc_hmac_free(channel->hmac);
+ channel->hmac = NULL;
+ }
if (!channel->private_keys)
channel->private_keys = silc_dlist_init();
/* Save the key */
entry = silc_calloc(1, sizeof(*entry));
- entry->key = silc_calloc(key_len, sizeof(*entry->key));
- memcpy(entry->key, key, key_len);
- entry->key_len = key_len;
+ entry->key = silc_calloc(keymat->enc_key_len / 8, sizeof(*entry->key));
+ memcpy(entry->key, keymat->send_enc_key, keymat->enc_key_len / 8);
+ entry->key_len = keymat->enc_key_len / 8;
/* Allocate the cipher and set the key*/
silc_cipher_alloc(cipher, &entry->cipher);
- silc_cipher_set_key(entry->cipher, key, key_len * 8);
+ silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
/* Generate HMAC key from the channel key data and set it */
silc_hmac_alloc(hmac, NULL, &entry->hmac);
- silc_hash_make(entry->hmac->hash, key, key_len, hash);
+ silc_hash_make(entry->hmac->hash, entry->key, entry->key_len, hash);
silc_hmac_set_key(entry->hmac, hash, silc_hash_len(entry->hmac->hash));
memset(hash, 0, sizeof(hash));
if (!channel->curr_key)
channel->curr_key = entry;
+ /* Free the key material */
+ silc_ske_free_key_material(keymat);
+
return TRUE;
}