Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2006 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
SilcHmac hmac;
unsigned char *iv;
SilcUInt16 payload_len;
+ SilcID *sid;
+ SilcID *rid;
} SilcMessageEncode;
silc_pkcs_private_key_get_len(private_key) / 8 : 0);
SilcUInt32 dlen = data_len + SILC_MESSAGE_HLEN + header_len + pklen + prlen;
- if (dlen > SILC_MESSAGE_MAX_LEN)
+ if (silc_unlikely(dlen > SILC_MESSAGE_MAX_LEN))
data_len -= (dlen - SILC_MESSAGE_MAX_LEN);
return data_len;
if (!pk)
return NULL;
}
- pk_type = silc_pkcs_get_type(public_key);
+ pk_type = silc_pkcs_get_type(private_key);
/* Encode the data to be signed */
sign = silc_message_signed_encode_data(message_payload,
/* Compute the hash and the signature. */
if (!silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign),
- auth_data, sizeof(auth_data) - 1, &auth_len, hash)) {
+ auth_data, sizeof(auth_data) - 1, &auth_len,
+ TRUE, hash)) {
SILC_LOG_ERROR(("Could not compute signature"));
silc_buffer_clear(sign);
silc_buffer_free(sign);
SilcBool static_key,
SilcCipher cipher,
SilcHmac hmac,
+ unsigned char *sender_id,
+ SilcUInt32 sender_id_len,
+ unsigned char *receiver_id,
+ SilcUInt32 receiver_id_len,
SilcBool check_mac)
{
SilcUInt32 mac_len, iv_len = 0, block_len;
if (!private_message || (private_message && static_key))
iv_len = block_len;
- if (data_len < (mac_len + iv_len + block_len))
+ if (silc_unlikely(data_len < (mac_len + iv_len + block_len)))
return FALSE;
- if (check_mac) {
+ if (silc_likely(check_mac)) {
/* Check the MAC of the message */
SILC_LOG_DEBUG(("Checking message MAC"));
silc_hmac_init(hmac);
silc_hmac_update(hmac, data, data_len - mac_len);
+ silc_hmac_update(hmac, sender_id, sender_id_len);
+ silc_hmac_update(hmac, receiver_id, receiver_id_len);
silc_hmac_final(hmac, mac, &mac_len);
- if (memcmp(data + (data_len - mac_len), mac, mac_len)) {
+ if (silc_unlikely(memcmp(data + (data_len - mac_len), mac, mac_len))) {
+#if 0
SILC_LOG_DEBUG(("Message MAC does not match"));
return FALSE;
+#else
+ /* Check for old style message MAC. Remove this check at some point. */
+ silc_hmac_init(hmac);
+ silc_hmac_update(hmac, data, data_len - mac_len);
+ silc_hmac_final(hmac, mac, &mac_len);
+ if (silc_unlikely(memcmp(data + (data_len - mac_len), mac, mac_len))) {
+ SILC_LOG_DEBUG(("Message MAC does not match"));
+#endif
+ return FALSE;
+ }
}
SILC_LOG_DEBUG(("MAC is Ok"));
}
silc_cipher_get_iv(cipher));
/* Decrypt block */
- if (!silc_cipher_decrypt(cipher, data, data, block_len, ivp)) {
+ if (silc_unlikely(!silc_cipher_decrypt(cipher, data, data, block_len,
+ ivp))) {
SILC_ASSERT(FALSE);
return FALSE;
}
totlen = 2;
SILC_GET16_MSB(len, data + totlen);
totlen += 2 + len;
- if (totlen + iv_len + mac_len + 2 > data_len)
+ if (silc_unlikely(totlen + iv_len + mac_len + 2 > data_len))
return FALSE;
totlen += 2;
if (totlen >= block_len)
- if (!silc_cipher_decrypt(cipher, data + block_len, data + block_len,
- (totlen - block_len) + SILC_MESSAGE_PAD(totlen),
- ivp)) {
+ if (silc_unlikely(!silc_cipher_decrypt(cipher, data + block_len,
+ data + block_len,
+ (totlen - block_len) +
+ SILC_MESSAGE_PAD(totlen), ivp))) {
SILC_ASSERT(FALSE);
return FALSE;
}
SilcBool static_key,
SilcCipher cipher,
SilcHmac hmac,
+ unsigned char *sender_id,
+ SilcUInt32 sender_id_len,
+ unsigned char *receiver_id,
+ SilcUInt32 receiver_id_len,
SilcStack stack,
SilcBool no_allocation,
SilcMessagePayload message)
silc_buffer_set(&buffer, payload, payload_len);
/* Decrypt the payload */
- if (cipher) {
+ if (silc_likely(cipher)) {
ret = silc_message_payload_decrypt(buffer.data, silc_buffer_len(&buffer),
private_message, static_key,
- cipher, hmac, TRUE);
- if (ret == FALSE)
+ cipher, hmac, sender_id,
+ sender_id_len, receiver_id,
+ receiver_id_len, TRUE);
+ if (silc_unlikely(ret == FALSE))
return NULL;
}
- if (hmac)
+ if (silc_likely(hmac))
mac_len = silc_hmac_len(hmac);
/* IV is present for all channel messages, and private messages when
if (!message) {
newp = message = silc_calloc(1, sizeof(*newp));
- if (!newp)
+ if (silc_unlikely(!newp))
return NULL;
}
memset(message, 0, sizeof(*message));
SILC_STR_UI16_NSTRING(&message->pad,
&message->pad_len),
SILC_STR_END);
- if (ret == -1)
+ if (silc_unlikely(ret == -1))
goto err;
- if ((message->data_len > silc_buffer_len(&buffer) - 6 - mac_len - iv_len) ||
- (message->pad_len + message->data_len > silc_buffer_len(&buffer) -
- 6 - mac_len - iv_len)) {
+ if (silc_unlikely((message->data_len > silc_buffer_len(&buffer) -
+ 6 - mac_len - iv_len) ||
+ (message->pad_len + message->data_len >
+ silc_buffer_len(&buffer) - 6 - mac_len - iv_len))) {
SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
goto err;
}
SilcUInt32 data_len,
SilcUInt32 true_len,
unsigned char *iv,
+ SilcID *sender_id,
+ SilcID *receiver_id,
SilcCipher cipher,
SilcHmac hmac)
{
+#if 0
+ unsigned char sid[32], rid[32];
+ SilcUInt32 sid_len = 0, rid_len = 0;
+#endif /* 0 */
+
/* Encrypt payload of the packet */
- if (!silc_cipher_encrypt(cipher, data, data, data_len, iv))
+ if (silc_unlikely(!silc_cipher_encrypt(cipher, data, data, data_len, iv)))
return FALSE;
+#if 0 /* For now this is disabled. Enable at 1.1.x or 1.2 at the latest. */
+ /* Encode IDs */
+ silc_id_id2str(&sender_id->u.client_id, SILC_ID_CLIENT, sid, sizeof(sid),
+ &sid_len);
+ if (receiver_id->type == SILC_ID_CLIENT)
+ silc_id_id2str(&receiver_id->u.client_id, SILC_ID_CLIENT, rid,
+ sizeof(rid), &rid_len);
+ else if (receiver_id->type == SILC_ID_CHANNEL)
+ silc_id_id2str(&receiver_id->u.channel_id, SILC_ID_CHANNEL, rid,
+ sizeof(rid), &rid_len);
+#endif /* 0 */
+
/* Compute the MAC of the encrypted message data */
silc_hmac_init(hmac);
silc_hmac_update(hmac, data, true_len);
+#if 0
+ silc_hmac_update(hmac, sid, sid_len);
+ silc_hmac_update(hmac, rid, rid_len);
+#endif /* 0 */
silc_hmac_final(hmac, data + true_len, NULL);
return TRUE;
return 0;
mac_len = silc_hmac_len(e->hmac);
- if (!silc_buffer_enlarge(buffer, mac_len))
+ if (silc_unlikely(!silc_buffer_enlarge(buffer, mac_len)))
return -1;
- if (!silc_message_payload_encrypt(buffer->head,
- e->payload_len,
- silc_buffer_headlen(buffer),
- e->iv, e->cipher, e->hmac))
+ if (silc_unlikely(!silc_message_payload_encrypt(buffer->head,
+ e->payload_len,
+ silc_buffer_headlen(buffer),
+ e->iv, e->sid, e->rid,
+ e->cipher, e->hmac)))
return -1;
return mac_len;
silc_buffer_headlen(buffer),
e->public_key, e->private_key,
e->hash);
- if (!sig)
+ if (silc_unlikely(!sig))
return -1;
len = silc_buffer_format(buffer,
SILC_STR_DATA(silc_buffer_data(sig),
silc_buffer_len(sig)),
SILC_STR_END);
- if (len < 0) {
+ if (silc_unlikely(len < 0)) {
silc_buffer_free(sig);
return -1;
}
SilcPublicKey public_key,
SilcPrivateKey private_key,
SilcHash hash,
+ SilcID *sender_id,
+ SilcID *receiver_id,
SilcBuffer buffer)
{
SilcUInt32 pad_len = 0, mac_len = 0, iv_len = 0;
SILC_LOG_DEBUG(("Encoding Message Payload"));
- if (!data_len)
+ if (silc_unlikely(!data_len))
return NULL;
- if (!private_message && (!cipher || !hmac))
+ if (silc_unlikely(!private_message && (!cipher || !hmac)))
return NULL;
if (!buffer) {
buf = buffer = silc_buffer_alloc(0);
- if (!buf)
+ if (silc_unlikely(!buf))
return NULL;
}
silc_buffer_reset(buffer);
e.hash = hash;
e.cipher = cipher;
e.hmac = hmac;
+ e.sid = sender_id;
+ e.rid = receiver_id;
e.iv = iv_len ? iv : NULL;
e.payload_len = 6 + data_len + pad_len;
void silc_message_payload_free(SilcMessagePayload payload)
{
+ silc_message_signed_payload_free(&payload->sig);
if (payload->data) {
memset(payload->data, 0, payload->data_len);
if (payload->allocated)
silc_free(payload->pad);
silc_free(payload);
}
- silc_message_signed_payload_free(&payload->sig);
}
/* Return flags */