SilcPacketContext packetdata;
SilcCipher cipher;
SilcHmac hmac;
+ int block_len;
SILC_LOG_DEBUG(("Sending private message"));
/* Get data used in the encryption */
cipher = client_entry->send_key;
hmac = conn->hmac_send;
+ block_len = silc_cipher_get_block_len(cipher);
/* Set the packet context pointers. */
packetdata.flags = SILC_PACKET_FLAG_PRIVMSG_KEY;
packetdata.src_id_len + packetdata.dst_id_len;
packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
packetdata.src_id_len +
- packetdata.dst_id_len));
+ packetdata.dst_id_len), block_len);
/* Prepare outgoing data buffer for packet sending */
silc_packet_send_prepare(sock,
silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
/* Create the outgoing packet */
- silc_packet_assemble(&packetdata);
+ silc_packet_assemble(&packetdata, cipher);
/* Encrypt the header and padding of the packet. */
cipher = conn->send_key;
- silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
+ silc_packet_encrypt(cipher, hmac, conn->psn_send++,
+ sock->outbuf, SILC_PACKET_HEADER_LEN +
packetdata.src_id_len + packetdata.dst_id_len +
packetdata.padlen);
sock->outbuf->data, sock->outbuf->len);
/* Now actually send the packet */
- silc_client_packet_send_real(client, sock, force_send, FALSE);
+ silc_client_packet_send_real(client, sock, force_send);
silc_free(packetdata.dst_id);
out:
{
SilcPacketContext *packet = (SilcPacketContext *)context;
+ if (!clients) {
+ silc_packet_context_free(packet);
+ return;
+ }
+
silc_client_private_message(client, conn->sock, packet);
silc_packet_context_free(packet);
}
{
SilcClientConnection conn = (SilcClientConnection)sock->user_data;
SilcPrivateMessagePayload payload = NULL;
- SilcIDCacheEntry id_cache;
SilcClientID *remote_id = NULL;
SilcClientEntry remote_client;
SilcMessageFlags flags;
goto out;
/* Check whether we know this client already */
- if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)remote_id,
- NULL, NULL,
- silc_hash_client_id_compare, NULL,
- &id_cache)) {
+ remote_client = silc_client_get_client_by_id(client, conn, remote_id);
+ if (!remote_client || !remote_client->nickname) {
+ if (remote_client) {
+ if (remote_client->status & SILC_CLIENT_STATUS_RESOLVING) {
+ remote_client->status &= ~SILC_CLIENT_STATUS_RESOLVING;
+ goto out;
+ }
+ remote_client->status |= SILC_CLIENT_STATUS_RESOLVING;
+ }
+
/* Resolve the client info */
silc_client_get_client_by_id_resolve(client, conn, remote_id,
silc_client_private_message_cb,
return;
}
- remote_client = (SilcClientEntry)id_cache->context;
-
/* Parse the payload and decrypt it also if private message key is set */
- payload = silc_private_message_payload_parse(packet->buffer,
- remote_client->send_key);
+ payload = silc_private_message_payload_parse(packet->buffer->data,
+ packet->buffer->len,
+ remote_client->receive_key);
if (!payload) {
silc_free(remote_id);
return;
flags = silc_private_message_get_flags(payload);
/* Pass the private message to application */
- client->ops->private_message(client, conn, remote_client, flags,
- silc_private_message_get_message(payload,
- NULL));
+ client->internal->ops->private_message(
+ client, conn, remote_client, flags,
+ silc_private_message_get_message(payload,
+ NULL));
/* See if we are away (gone). If we are away we will reply to the
sender with the set away message. */
out:
if (payload)
silc_private_message_payload_free(payload);
- if (remote_id)
- silc_free(remote_id);
+ silc_free(remote_id);
}
/* Function that actually employes the received private message key */
/* Now take the key in use */
if (!silc_client_add_private_message_key(client, conn, clients[0],
- cipher, key, key_len, FALSE))
+ cipher, key, key_len, FALSE, TRUE))
goto out;
/* Print some info for application */
- client->ops->say(client, conn,
- "Received private message key from %s%s%s %s%s%s",
- clients[0]->nickname,
- clients[0]->server ? "@" : "",
- clients[0]->server ? clients[0]->server : "",
- clients[0]->username ? "(" : "",
- clients[0]->username ? clients[0]->username : "",
- clients[0]->username ? ")" : "");
+ client->internal->ops->say(
+ client, conn, SILC_CLIENT_MESSAGE_AUDIT,
+ "Received private message key from %s%s%s %s%s%s",
+ clients[0]->nickname,
+ clients[0]->server ? "@" : "",
+ clients[0]->server ? clients[0]->server : "",
+ clients[0]->username ? "(" : "",
+ clients[0]->username ? clients[0]->username : "",
+ clients[0]->username ? ")" : "");
out:
silc_packet_context_free(packet);
requirements of the SILC protocol are met. The API, however, allows
to allocate any cipher.
+ If `responder' is TRUE then the sending and receiving keys will be
+ set according the client being the receiver of the private key. If
+ FALSE the client is being the sender (or negotiator) of the private
+ key.
+
It is not necessary to set key for normal private message usage. If the
key is not set then the private messages are encrypted using normal
session keys. Setting the private key, however, increases the security.
char *cipher,
unsigned char *key,
uint32 key_len,
- int generate_key)
+ bool generate_key,
+ bool responder)
{
unsigned char private_key[32];
uint32 len;
return FALSE;
if (!cipher)
- cipher = "aes-256-cbc";
+ cipher = SILC_DEFAULT_CIPHER;
/* Check the requested cipher */
if (!silc_cipher_is_supported(cipher))
}
/* Save the key */
- client_entry->key = silc_calloc(key_len, sizeof(*client_entry->key));
- memcpy(client_entry->key, key, key_len);
+ client_entry->key = silc_memdup(key, key_len);
client_entry->key_len = key_len;
/* Produce the key material as the protocol defines */
keymat = silc_calloc(1, sizeof(*keymat));
if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
- client->md5hash, keymat)
+ client->internal->md5hash, keymat)
!= SILC_SKE_STATUS_OK)
return FALSE;
silc_cipher_alloc(cipher, &client_entry->receive_key);
/* Set the keys */
- silc_cipher_set_key(client_entry->send_key, keymat->send_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(client_entry->send_key, keymat->send_iv);
- silc_cipher_set_key(client_entry->receive_key, keymat->receive_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(client_entry->receive_key, keymat->receive_iv);
+ if (responder == TRUE) {
+ silc_cipher_set_key(client_entry->send_key, keymat->receive_enc_key,
+ keymat->enc_key_len);
+ silc_cipher_set_iv(client_entry->send_key, keymat->receive_iv);
+ silc_cipher_set_key(client_entry->receive_key, keymat->send_enc_key,
+ keymat->enc_key_len);
+ silc_cipher_set_iv(client_entry->receive_key, keymat->send_iv);
+ } else {
+ silc_cipher_set_key(client_entry->send_key, keymat->send_enc_key,
+ keymat->enc_key_len);
+ silc_cipher_set_iv(client_entry->send_key, keymat->send_iv);
+ silc_cipher_set_key(client_entry->receive_key, keymat->receive_enc_key,
+ keymat->enc_key_len);
+ silc_cipher_set_iv(client_entry->receive_key, keymat->receive_iv);
+ }
/* Free the key material */
silc_ske_free_key_material(keymat);
SilcClientConnection conn,
SilcClientEntry client_entry,
char *cipher,
- SilcSKEKeyMaterial *key)
+ SilcSKEKeyMaterial *key,
+ bool responder)
{
assert(client_entry);
return FALSE;
if (!cipher)
- cipher = "aes-256-cbc";
+ cipher = SILC_DEFAULT_CIPHER;
/* Check the requested cipher */
if (!silc_cipher_is_supported(cipher))
silc_cipher_alloc(cipher, &client_entry->receive_key);
/* Set the keys */
- silc_cipher_set_key(client_entry->send_key, key->send_enc_key,
- key->enc_key_len);
- silc_cipher_set_iv(client_entry->send_key, key->send_iv);
- silc_cipher_set_key(client_entry->receive_key, key->receive_enc_key,
- key->enc_key_len);
- silc_cipher_set_iv(client_entry->receive_key, key->receive_iv);
+ if (responder == TRUE) {
+ silc_cipher_set_key(client_entry->send_key, key->receive_enc_key,
+ key->enc_key_len);
+ silc_cipher_set_iv(client_entry->send_key, key->receive_iv);
+ silc_cipher_set_key(client_entry->receive_key, key->send_enc_key,
+ key->enc_key_len);
+ silc_cipher_set_iv(client_entry->receive_key, key->send_iv);
+ } else {
+ silc_cipher_set_key(client_entry->send_key, key->send_enc_key,
+ key->enc_key_len);
+ silc_cipher_set_iv(client_entry->send_key, key->send_iv);
+ silc_cipher_set_key(client_entry->receive_key, key->receive_enc_key,
+ key->enc_key_len);
+ silc_cipher_set_iv(client_entry->receive_key, key->receive_iv);
+ }
return TRUE;
}