+Wed Jun 27 00:10:33 EEST 2001 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed a fatal bug in private message sending and reception
+ encryption and decryption when using private message keys.
+ The implementation was incorrect and did not follow the
+ specification. It causd that some of the message were
+ lost since it did not use the sending and receiving keys
+ as the protocol suggests. This has been fixed and will cause
+ incompatibilities with older clients when sending private
+ message encrypted with private message keys. Affected files
+ lib/silcclient/client_prvmsg.c, lib/silcclient/client_keyagr.c
+ and various other in Irssi SILC Client.
+
+ Added `responder' boolean argument to the functions
+ silc_client_add_private_message_key[_ske] to indicate when
+ the key is added as responder or initiator of the key
+ negotiation.
+
Tue Jun 26 19:23:07 EEST 2001 Pekka Riikonen <priikone@silcnet.org>
* Removed the silc_ske_check_version function and created
is in process when we get timeout. Affected file is
lib/silcclient/client_keyagr.c.
+ * Do not resolve the client ID forever if it returns in the
+ first time that such client does not exist. This was done
+ for example with private message. Affected file is
+ lib/silcclient/client_prvmsg.c.
+
Mon Jun 25 21:42:51 EEST 2001 Pekka Riikonen <priikone@silcnet.org>
* Do not add regex.h for WIN32. The affected file
typedef struct {
int type; /* 1 = msg, 2 = channel */
+ bool responder;
SILC_SERVER_REC *server;
} *KeyInternal;
/* Set the private key for this client */
silc_client_del_private_message_key(client, conn, client_entry);
silc_client_add_private_message_key_ske(client, conn, client_entry,
- NULL, key);
+ NULL, key, i->responder);
printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
SILCTXT_KEY_AGREEMENT_PRIVMSG,
client_entry->nickname);
argv[5], argv[4],
argv_lens[4],
(argv[4][0] == '*' ?
- TRUE : FALSE));
+ TRUE : FALSE), FALSE);
else
silc_client_add_private_message_key(silc_client, conn, client_entry,
NULL, argv[4],
argv_lens[4],
(argv[4][0] == '*' ?
- TRUE : FALSE));
+ TRUE : FALSE), FALSE);
/* Send the key to the remote client so that it starts using it
too. */
if (command == 4 && client_entry) {
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
SILCTXT_KEY_AGREEMENT, argv[2]);
+ internal->responder = TRUE;
silc_client_send_key_agreement(silc_client, conn, client_entry, hostname,
port, 120, keyagr_completion, internal);
+ if (!hostname)
+ silc_free(internal);
goto out;
}
if (command == 5 && client_entry && hostname) {
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
+ internal->responder = FALSE;
silc_client_perform_key_agreement(silc_client, conn, client_entry,
hostname, port, keyagr_completion,
internal);
If remote side decides to ignore the request the `completion' will be
called after the specified timeout, `timeout_secs'.
+ NOTE: If the `hostname' and the `port' was not provided the `completion'
+ will not be called at all since this does nothing more than sending
+ a packet to the remote host.
+
NOTE: There can be only one active key agreement for one client entry.
Before setting new one, the old one must be finished (it is finished
after calling the completion callback) or the function
{
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);
}
/* 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);
+ remote_client->receive_key);
if (!payload) {
silc_free(remote_id);
return;
/* 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 */
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;
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);
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;
}
* char *cipher,
* unsigned char *key,
* uint32 key_len,
- * int generate_key);
+ * bool generate_key,
+ * bool responder);
*
* DESCRIPTION
*
* 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);
/****f* silcclient/SilcClientAPI/silc_client_add_private_message_key_ske
*
*
* DESCRIPTION
*
- * Same as above but takes the key material from the SKE key material
- * structure. This structure is received if the application uses the
- * silc_client_send_key_agreement to negotiate the key material. The
- * `cipher' SHOULD be provided as it is negotiated also in the SKE
- * protocol.
+ * Same as silc_client_add_private_message_key but takes the key material
+ * from the SKE key material structure. This structure is received if
+ * the application uses the silc_client_send_key_agreement to negotiate
+ * the key material. The `cipher' SHOULD be provided as it is negotiated
+ * also in the SKE protocol.
*
***/
int silc_client_add_private_message_key_ske(SilcClient client,
SilcClientConnection conn,
SilcClientEntry client_entry,
char *cipher,
- SilcSKEKeyMaterial *key);
+ SilcSKEKeyMaterial *key,
+ bool responder);
/****f* silcclient/SilcClientAPI/silc_client_send_private_message_key
*
* If remote side decides to ignore the request the `completion' will be
* called after the specified timeout, `timeout_secs'.
*
+ * NOTE: If the `hostname' and the `port' was not provided the `completion'
+ * will not be called at all since this does nothing more than sending
+ * a packet to the remote host.
+ *
* NOTE: There can be only one active key agreement for one client entry.
* Before setting new one, the old one must be finished (it is finished
* after calling the completion callback) or the function
SILC_STR_UI16_NSTRING_ALLOC(&new->message,
&new->message_len),
SILC_STR_END);
- if (ret == -1)
+ if (ret == -1) {
+ SILC_LOG_ERROR(("Incorrect private message payload"));
goto err;
+ }
if ((new->message_len < 1 || new->message_len > buffer->len)) {
SILC_LOG_ERROR(("Incorrect private message payload in packet, "