notify. Affected file lib/silcclient/client_notify.c.
Fixes bug in '@' character handling in a nickname.
+ * Added support for automatically parsing signature from
+ the message payload. Added new function
+ silc_message_get_signature to return the payload to
+ application. Affected files lib/silccore/silcmessage.[ch].
+
+ * Changed the private_message and channel_message client
+ operations to deliver the SilcMessagePayload to the
+ application too. Application can use it fe. to get the
+ signature from the message for verification. Affected
+ file lib/silcclient/silcclient.h, client_channel.c and
+ client_prvmsg.c.
+
+ * Redefined the signed payload for message payloads.
+ Updated protocol specs and implemented.
+
Mon Dec 2 16:28:29 EET 2002 Pekka Riikonen <priikone@silcnet.org>
* Fixed wrong invite and ban list handling in server command
@SYNTAX:msg@
-Sends a private message to someone.
+Sends a private message to other user in the network.
+
+It is possible to digitally sign your messages. The receiver
+may then verify the message with your public key. By default
+messages are not signed. If you want your private messages
+to be signed you SMSG command instead of this MSG command.
+
+If -channel option is provided then this command actually
+send channel message to the specified channel. The message
+IS NOT private message, it is normal channel message. It is
+also possible to digitally sign channel messages by using
+SMSG command or by doing /set sign_channel_messages on, in
+which case _all_ channel messages will be signed.
Example:
/MSG Toni Hi, what's up?
-See also: QUERY
+See also: QUERY SMSG
--- /dev/null
+
+@SYNTAX:smsg@
+
+Sends a signed private message to other user in the network.
+The message will be digitally signed and the receiver may verify
+the message by using your public key.
+
+If -channel option is provided then this command actually
+send channel message to the specified channel. The message
+IS NOT private message, it is normal channel message. Also this
+message will be signed and can be verified by using your public
+key.
+
+Example:
+
+/SMSG Foobar Very authenticated message
+
+See also: MSG QUERY
cmd_params_free(free_arg);
}
-/* SYNTAX: MSG [-<server tag>] [-channel | -nick] <targets> <message> */
+/* SYNTAX: MSG [-channel] <target> <message> */
static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
{
GHashTable *optlist;
void silc_channel_message(SilcClient client, SilcClientConnection conn,
SilcClientEntry sender, SilcChannelEntry channel,
+ SilcMessagePayload payload,
SilcMessageFlags flags, const unsigned char *message,
SilcUInt32 message_len)
{
nick = silc_nicklist_insert(chanrec, chu, FALSE);
}
+ /* If the messages is digitally signed, verify it, if possible. */
+ if (flags & SILC_MESSAGE_FLAG_SIGNED) {
+ SilcMessageSignedPayload sig = silc_message_get_signature(payload);
+/*
+ if (sig) {
+ if (silc_message_signed_verify(sig, payload, client->public_key,
+ client->sha1hash) != SILC_AUTH_OK)
+ silc_say_error(("Could not verify signature in message"));
+ }
+*/
+ }
+
if (flags & SILC_MESSAGE_FLAG_DATA) {
/* MIME object received, try to display it as well as we can */
char type[128], enc[128];
sender received in the packet. */
void silc_private_message(SilcClient client, SilcClientConnection conn,
- SilcClientEntry sender, SilcMessageFlags flags,
+ SilcClientEntry sender, SilcMessagePayload payload,
+ SilcMessageFlags flags,
const unsigned char *message,
SilcUInt32 message_len)
{
snprintf(userhost, sizeof(userhost) - 1, "%s@%s",
sender->username, sender->hostname);
+ /* If the messages is digitally signed, verify it, if possible. */
+ if (flags & SILC_MESSAGE_FLAG_SIGNED) {
+ SilcMessageSignedPayload sig = silc_message_get_signature(payload);
+ if (sig) {
+
+ }
+ }
+
if (flags & SILC_MESSAGE_FLAG_DATA) {
/* MIME object received, try to display it as well as we can */
char type[128], enc[128];
void silc_channel_message(SilcClient client, SilcClientConnection conn,
SilcClientEntry sender,
SilcChannelEntry channel,
+ SilcMessagePayload payload,
SilcMessageFlags flags,
const unsigned char *message,
SilcUInt32 message_len);
void silc_private_message(SilcClient client, SilcClientConnection conn,
SilcClientEntry sender,
+ SilcMessagePayload payload,
SilcMessageFlags flags,
const unsigned char *message,
SilcUInt32 message_len);
void silc_servers_reconnect_deinit(void);
static void silc_send_channel(SILC_SERVER_REC *server,
- char *channel, char *msg)
+ char *channel, char *msg,
+ SilcMessageFlags flags)
{
SILC_CHANNEL_REC *rec;
}
silc_client_send_channel_message(silc_client, server->conn, rec->entry,
- NULL, SILC_MESSAGE_FLAG_UTF8,
- msg, strlen(msg), TRUE);
+ NULL, flags, msg, strlen(msg), TRUE);
}
typedef struct {
}
static void silc_send_msg(SILC_SERVER_REC *server, char *nick, char *msg,
- int msg_len, SilcMessageFlags flags)
+ int msg_len, SilcMessageFlags flags)
{
PRIVMSG_REC *rec;
SilcClientEntry *clients;
}
if (target_type == SEND_TARGET_CHANNEL)
- silc_send_channel(server, target, message ? message : msg);
+ silc_send_channel(server, target, message ? message : msg,
+ SILC_MESSAGE_FLAG_UTF8);
else
silc_send_msg(server, target, message ? message : msg,
message ? strlen(message) : strlen(msg),
/* SYNTAX: WATCH [<-add | -del> <nickname>] */
/* SYNTAX: STATS */
/* SYNTAX: ATTR [<-del> <option> [{ <value>}]] */
+/* SYNTAX: SMSG [<-channel>] <target> <message> */
void silc_command_exec(SILC_SERVER_REC *server,
const char *command, const char *args)
signal_stop();
}
+/* SMSG command, to send digitally signed messages */
+
+static void command_smsg(const char *data, SILC_SERVER_REC *server,
+ WI_ITEM_REC *item)
+{
+ GHashTable *optlist;
+ char *target, *origtarget, *msg;
+ void *free_arg;
+ int free_ret, target_type;
+
+ g_return_if_fail(data != NULL);
+ if (server == NULL || !server->connected)
+ cmd_param_error(CMDERR_NOT_CONNECTED);
+
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS |
+ PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST,
+ "msg", &optlist, &target, &msg))
+ return;
+ if (*target == '\0' || *msg == '\0')
+ cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
+
+ origtarget = target;
+ free_ret = FALSE;
+
+ if (strcmp(target, "*") == 0) {
+ if (item == NULL)
+ cmd_param_error(CMDERR_NOT_JOINED);
+
+ target_type = IS_CHANNEL(item) ?
+ SEND_TARGET_CHANNEL : SEND_TARGET_NICK;
+ target = (char *) window_item_get_target(item);
+ } else if (g_hash_table_lookup(optlist, "channel") != NULL) {
+ target_type = SEND_TARGET_CHANNEL;
+ } else {
+ target_type = server_ischannel(SERVER(server), target) ?
+ SEND_TARGET_CHANNEL : SEND_TARGET_NICK;
+ }
+
+ if (target != NULL) {
+ char *message = NULL;
+ int len;
+
+ if (!silc_term_utf8()) {
+ len = silc_utf8_encoded_len(msg, strlen(msg), SILC_STRING_LANGUAGE);
+ message = silc_calloc(len + 1, sizeof(*message));
+ g_return_if_fail(message != NULL);
+ silc_utf8_encode(msg, strlen(msg), SILC_STRING_LANGUAGE, message, len);
+ }
+
+ if (target_type == SEND_TARGET_CHANNEL)
+ silc_send_channel(server, target, message ? message : msg,
+ SILC_MESSAGE_FLAG_UTF8 |
+ SILC_MESSAGE_FLAG_SIGNED);
+ else
+ silc_send_msg(server, target, message ? message : msg,
+ message ? strlen(message) : strlen(msg),
+ SILC_MESSAGE_FLAG_UTF8 |
+ SILC_MESSAGE_FLAG_SIGNED);
+ silc_free(message);
+ }
+
+ signal_emit(target != NULL && target_type == SEND_TARGET_CHANNEL ?
+ "message own_public" : "message own_private", 4,
+ server, msg, target, origtarget);
+
+ if (free_ret && target != NULL) g_free(target);
+ cmd_params_free(free_arg);
+}
+
/* FILE command */
SILC_TASK_CALLBACK(silc_client_file_close_later)
command_bind_silc("watch", MODULE_NAME, (SIGNAL_FUNC) command_self);
command_bind_silc("stats", MODULE_NAME, (SIGNAL_FUNC) command_self);
command_bind_silc("attr", MODULE_NAME, (SIGNAL_FUNC) command_attr);
+ command_bind_silc("smsg", MODULE_NAME, (SIGNAL_FUNC) command_smsg);
command_set_options("connect", "+silcnet");
}
command_unbind("watch", (SIGNAL_FUNC) command_self);
command_unbind("stats", (SIGNAL_FUNC) command_self);
command_unbind("attr", (SIGNAL_FUNC) command_attr);
+ command_unbind("smsg", (SIGNAL_FUNC) command_smsg);
}
void silc_server_free_ftp(SILC_SERVER_REC *server,
/* Get the ban list */
tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
- if (tmp) {
+ if (tmp && len > 2) {
SilcArgumentPayload iargs;
SilcUInt16 iargc;
SILC_GET16_MSB(iargc, tmp);
}
memcpy(iv, data + (data_len - iv_len - mac_len), iv_len);
- silc_message_payload_encrypt(data, data_len - iv_len, iv, iv_len,
- channel->channel_key, channel->hmac);
+ silc_message_payload_encrypt(data, data_len - iv_len, data_len,
+ iv, iv_len, channel->channel_key,
+ channel->hmac);
}
return TRUE;
/* Encode the message payload. This also encrypts the message payload. */
payload = silc_message_payload_encode(flags, data, data_len, TRUE, FALSE,
- cipher, hmac, client->rng);
+ cipher, hmac, client->rng, NULL,
+ client->private_key, client->sha1hash);
/* Get data used in packet header encryption, keys and stuff. */
cipher = conn->internal->send_key;
/* Pass the message to application */
client->internal->ops->channel_message(
- client, conn, clients[0], channel,
- silc_message_get_flags(res->payload),
- message, message_len);
+ client, conn, clients[0], channel, res->payload,
+ silc_message_get_flags(res->payload),
+ message, message_len);
}
out:
/* Pass the message to application */
client->internal->ops->channel_message(
- client, conn, client_entry, channel,
- silc_message_get_flags(payload),
- message, message_len);
+ client, conn, client_entry, channel, payload,
+ silc_message_get_flags(payload),
+ message, message_len);
out:
silc_free(id);
static void
silc_channel_message(SilcClient client, SilcClientConnection conn,
SilcClientEntry sender, SilcChannelEntry channel,
- SilcMessageFlags flags, const unsigned char *message,
- SilcUInt32 message_len)
+ SilcMessagePayload payload, SilcMessageFlags flags,
+ const unsigned char *message, SilcUInt32 message_len)
{
}
static void
silc_private_message(SilcClient client, SilcClientConnection conn,
- SilcClientEntry sender, SilcMessageFlags flags,
- const unsigned char *message,
+ SilcClientEntry sender, SilcMessagePayload payload,
+ SilcMessageFlags flags, const unsigned char *message,
SilcUInt32 message_len)
{
!client_entry->generated,
TRUE, client_entry->send_key,
client_entry->hmac_send,
- client->rng);
+ client->rng, NULL, client->private_key,
+ client->sha1hash);
/* If we don't have private message specific key then private messages
are just as any normal packet thus call normal packet sending. If
/* Pass the private message to application */
message = silc_message_get_data(payload, &message_len);
- client->internal->ops->private_message(client, conn, remote_client, flags,
- message, message_len);
+ client->internal->ops->private_message(client, conn, remote_client, payload,
+ flags, message, message_len);
/* See if we are away (gone). If we are away we will reply to the
sender with the set away message. */
(like it may tell the message is multimedia message). */
void (*channel_message)(SilcClient client, SilcClientConnection conn,
SilcClientEntry sender, SilcChannelEntry channel,
- SilcMessageFlags flags,
+ SilcMessagePayload payload, SilcMessageFlags flags,
const unsigned char *message,
SilcUInt32 message_len);
can be interpreted (like it may tell the message is multimedia
message). */
void (*private_message)(SilcClient client, SilcClientConnection conn,
- SilcClientEntry sender, SilcMessageFlags flags,
+ SilcClientEntry sender, SilcMessagePayload payload,
+ SilcMessageFlags flags,
const unsigned char *message,
SilcUInt32 message_len);
* keys are set then the first key (the key that was added first as
* private key) is used.
*
+ * If the `flags' includes SILC_MESSAGE_FLAG_SIGNED the message will be
+ * digitally signed with the SILC key pair.
+ *
***/
void silc_client_send_channel_message(SilcClient client,
SilcClientConnection conn,
* message. The `data' is the private message. If the `force_send' is
* TRUE the packet is sent immediately.
*
+ * If the `flags' includes SILC_MESSAGE_FLAG_SIGNED the message will be
+ * digitally signed with the SILC key pair.
+ *
***/
void silc_client_send_private_message(SilcClient client,
SilcClientConnection conn,
unsigned char *pad;
unsigned char *iv;
unsigned char *mac;
- /*SilcMessageSignedPayload sig;*/
+ SilcMessageSignedPayload sig;
};
/* Decrypts the Message Payload. The `data' is the actual Message Payload */
SilcHmac hmac,
bool check_mac)
{
- SilcUInt32 mac_len = 0, iv_len = 0;
+ SilcUInt32 mac_len = 0, iv_len = 0, block_len, pad_len;
unsigned char *mac, mac2[32];
-
+ unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *ivp;
+ SilcUInt16 len;
+
mac_len = silc_hmac_len(hmac);
/* IV is present for channel messages and private messages when static
SILC_LOG_DEBUG(("MAC is Ok"));
}
- /* Decrypt the message */
- silc_cipher_decrypt(cipher, data, data, data_len - iv_len - mac_len,
- (iv_len ? data + (data_len - iv_len - mac_len) : NULL));
+ /* Get pointer to the IV */
+ ivp = (iv_len ? data + (data_len - iv_len - mac_len) :
+ silc_cipher_get_iv(cipher));
+
+ /* Decrypt first block to get data length. We need to do this since
+ there might be extra data at the end of the payload which is not
+ encrypted (like the signature payload). */
+ block_len = silc_cipher_get_block_len(cipher);
+ memcpy(iv, ivp, block_len);
+ silc_cipher_decrypt(cipher, data, data, 16, iv);
+
+ /* Decrypt rest of the message */
+ SILC_GET16_MSB(len, data + 2);
+ pad_len = SILC_MESSAGE_PAD(6 + len);
+ if (6 + len + pad_len > 16 &&
+ 6 + len + pad_len + mac_len + iv_len <= data_len) {
+ silc_cipher_set_iv(cipher, iv);
+ silc_cipher_decrypt(cipher, data + 16, data + 16,
+ (6 + len + pad_len) - 16, NULL);
+ }
+
return TRUE;
}
newp->iv_len = iv_len;
+ SILC_LOG_HEXDUMP(("foo"), buffer.data, buffer.len);
+
+ /* Parse Signed Message Payload if provided */
+ if (newp->flags & SILC_MESSAGE_FLAG_SIGNED &&
+ newp->data_len + newp->pad_len + 6 + mac_len + iv_len < buffer.len) {
+ silc_buffer_pull(&buffer, 6 + newp->data_len + newp->pad_len);
+ newp->sig =
+ silc_message_signed_payload_parse(buffer.data,
+ buffer.len - iv_len - mac_len);
+ silc_buffer_push(&buffer, 6 + newp->data_len + newp->pad_len);
+ }
+
return newp;
err:
/* This function is used to encrypt the Messsage Payload which is
the `data' and `data_len'. This is used internally by the Message
Payload encoding routines but application may call this too if needed.
- The `data_len' is the data lenght which is used to create MAC out of. */
+ The `true_len' is the data length which is used to create MAC out of. */
bool silc_message_payload_encrypt(unsigned char *data,
SilcUInt32 data_len,
+ SilcUInt32 true_len,
unsigned char *iv,
SilcUInt32 iv_len,
SilcCipher cipher,
/* Encrypt payload of the packet. If the IV is added to packet do
not encrypt that. */
- silc_cipher_encrypt(cipher, data, data, data_len - iv_len,
- iv_len ? iv : NULL);
+ silc_cipher_encrypt(cipher, data, data, data_len, iv_len ? iv : NULL);
/* Compute the MAC of the encrypted message data */
silc_hmac_init(hmac);
- silc_hmac_update(hmac, data, data_len);
+ silc_hmac_update(hmac, data, true_len);
silc_hmac_final(hmac, mac, &mac_len);
/* Put rest of the data to the payload */
- silc_buffer_set(&buf, data, data_len + mac_len);
- silc_buffer_pull(&buf, data_len);
+ silc_buffer_set(&buf, data, true_len + mac_len);
+ silc_buffer_pull(&buf, true_len);
silc_buffer_put(&buf, mac, mac_len);
return TRUE;
bool private_message,
SilcCipher cipher,
SilcHmac hmac,
- SilcRng rng)
+ SilcRng rng,
+ SilcPublicKey public_key,
+ SilcPrivateKey private_key,
+ SilcHash hash)
{
int i;
SilcBuffer buffer;
SilcUInt32 len, pad_len = 0, mac_len = 0, iv_len = 0;
unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
+ SilcBuffer sig = NULL;
SILC_LOG_DEBUG(("Encoding Message Payload"));
}
/* Encode the Message Payload */
- silc_buffer_pull_tail(buffer, 6 + data_len + pad_len + iv_len);
+ silc_buffer_pull_tail(buffer, 6 + data_len + pad_len);
silc_buffer_format(buffer,
SILC_STR_UI_SHORT(flags),
SILC_STR_UI_SHORT(data_len),
SILC_STR_UI_XNSTRING(data, data_len),
SILC_STR_UI_SHORT(pad_len),
SILC_STR_UI_XNSTRING(pad, pad_len),
- SILC_STR_UI_XNSTRING(iv, iv_len),
SILC_STR_END);
memset(pad, 0, sizeof(pad));
- /* Now encrypt the Message Payload */
+ /* Sign the message if wanted */
+ if (flags & SILC_MESSAGE_FLAG_SIGNED && private_key && hash) {
+ sig = silc_message_signed_payload_encode(buffer->data, buffer->len,
+ public_key, private_key, hash);
+ if (sig) {
+ buffer = silc_buffer_realloc(buffer, buffer->truelen + sig->len);
+ if (buffer) {
+ silc_buffer_pull(buffer, 6 + data_len + pad_len);
+ silc_buffer_pull_tail(buffer, sig->len);
+ silc_buffer_put(buffer, sig->data, sig->len);
+ silc_buffer_push(buffer, 6 + data_len + pad_len);
+ }
+ }
+ }
+
+ /* Put IV */
+ silc_buffer_pull(buffer, 6 + data_len + pad_len + (sig ? sig->len : 0));
+ silc_buffer_pull_tail(buffer, iv_len);
+ silc_buffer_format(buffer,
+ SILC_STR_UI_XNSTRING(iv, iv_len),
+ SILC_STR_END);
+ silc_buffer_push(buffer, 6 + data_len + pad_len + (sig ? sig->len : 0));
+
+ SILC_LOG_HEXDUMP(("foo"), buffer->data, buffer->len);
+
+ /* Now encrypt the Message Payload and compute MAC */
if (cipher) {
- if (!silc_message_payload_encrypt(buffer->data, buffer->len,
- iv, iv_len, cipher, hmac)) {
+ if (!silc_message_payload_encrypt(buffer->data,
+ buffer->len - iv_len -
+ (sig ? sig->len : 0),
+ buffer->len, iv, iv_len,
+ cipher, hmac)) {
silc_buffer_free(buffer);
+ silc_buffer_free(sig);
return NULL;
}
}
silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer) - buffer->len);
+ silc_buffer_free(sig);
return buffer;
}
memset(payload->data, 0, payload->data_len);
silc_free(payload->data);
}
+ if (payload->sig)
+ silc_message_signed_payload_free(payload->sig);
silc_free(payload->pad);
silc_free(payload);
}
return payload->iv;
}
+/* Return signature of the message */
+
+const SilcMessageSignedPayload
+silc_message_get_signature(SilcMessagePayload payload)
+{
+ return (const SilcMessageSignedPayload)payload->sig;
+}
+
/******************************************************************************
SILC_MESSAGE_FLAG_SIGNED Payload
SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
+ SILC_LOG_HEXDUMP(("sig payload"), data, data_len);
+
silc_buffer_set(&buffer, (unsigned char *)data, data_len);
sig = silc_calloc(1, sizeof(*sig));
if (!sig)
SILC_STR_END);
if (ret == -1 || sig->pk_len > data_len - 4) {
silc_message_signed_payload_free(sig);
+ SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
+ "Payload"));
return NULL;
}
SILC_STR_END);
if (ret == -1) {
silc_message_signed_payload_free(sig);
+ SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
return NULL;
}
silc_buffer_push(&buffer, 4);
/* Signature must be provided */
if (sig->sign_len < 1) {
+ SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
+ "Payload"));
silc_message_signed_payload_free(sig);
return NULL;
}
SilcUInt32 message_payload_len,
SilcPublicKey public_key,
SilcPrivateKey private_key,
- SilcHash hash,
- bool include_public_key)
+ SilcHash hash)
{
SilcBuffer buffer, sign;
SilcPKCS pkcs;
if (!message_payload || !message_payload_len || !private_key || !hash)
return NULL;
- if (include_public_key && !public_key)
- return NULL;
-
- if (include_public_key)
+
+ if (public_key)
pk = silc_pkcs_public_key_encode(public_key, &pk_len);
/* Now we support only SILC style public key */
/* Allocate PKCS object */
if (!silc_pkcs_alloc(private_key->name, &pkcs)) {
+ SILC_LOG_ERROR(("Could not allocated PKCS"));
silc_buffer_clear(sign);
silc_buffer_free(sign);
silc_free(pk);
if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
!silc_pkcs_sign_with_hash(pkcs, hash, sign->data, sign->len, auth_data,
&auth_len)) {
+ SILC_LOG_ERROR(("Could not compute signature"));
silc_buffer_clear(sign);
silc_buffer_free(sign);
silc_pkcs_free(pkcs);
return NULL;
}
- silc_buffer_format(sign,
+ silc_buffer_format(buffer,
SILC_STR_UI_SHORT(pk_len),
SILC_STR_UI_SHORT(pk_type),
SILC_STR_END);
if (pk_len && pk) {
- silc_buffer_pull(sign, 4);
- silc_buffer_format(sign,
+ silc_buffer_pull(buffer, 4);
+ silc_buffer_format(buffer,
SILC_STR_UI_XNSTRING(pk, pk_len),
SILC_STR_END);
- silc_buffer_push(sign, 4);
+ silc_buffer_push(buffer, 4);
}
- silc_buffer_pull(sign, 4 + pk_len);
- silc_buffer_format(sign,
+ silc_buffer_pull(buffer, 4 + pk_len);
+ silc_buffer_format(buffer,
SILC_STR_UI_SHORT(auth_len),
SILC_STR_UI_XNSTRING(auth_data, auth_len),
SILC_STR_END);
- silc_buffer_push(sign, 4 + pk_len);
+ silc_buffer_push(buffer, 4 + pk_len);
+
+ SILC_LOG_HEXDUMP(("sig payload"), buffer->data, buffer->len);
memset(auth_data, 0, sizeof(auth_data));
silc_pkcs_free(pkcs);
void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
{
- if (sig) {
- memset(sig->sign_data, 0, sig->sign_len);
- silc_free(sig->sign_data);
- silc_free(sig->pk_data);
- silc_free(sig);
- }
+ memset(sig->sign_data, 0, sig->sign_len);
+ silc_free(sig->sign_data);
+ silc_free(sig->pk_data);
+ silc_free(sig);
}
/* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
return ret;
/* Generate the signature verification data, the Message Payload */
- tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len +
- message->iv_len);
+ tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len);
silc_buffer_format(tmp,
SILC_STR_UI_SHORT(message->flags),
SILC_STR_UI_SHORT(message->data_len),
SILC_STR_UI_XNSTRING(message->data, message->data_len),
SILC_STR_UI_SHORT(message->pad_len),
SILC_STR_UI_XNSTRING(message->pad, message->pad_len),
- SILC_STR_UI_XNSTRING(message->iv, message->iv_len),
SILC_STR_END);
sign = silc_message_signed_encode_data(tmp->data, tmp->len,
sig->pk_data, sig->pk_len,
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 -2002 Pekka Riikonen
+ Copyright (C) 1997 - 2002 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
***/
typedef struct SilcMessagePayloadStruct *SilcMessagePayload;
+/****s* silccore/SilcMessageAPI/SilcMessageSignedPayload
+ *
+ * NAME
+ *
+ * typedef struct SilcMessageSignedPayloadStruct *SilcMessageSignedPayload;
+ *
+ *
+ * DESCRIPTION
+ *
+ * This context represents the SILC_MESSAGE_FLAG_SIGNED Payload which
+ * is used with channel messages and private messages to indicate that
+ * the message is digitally signed. This payload may include the
+ * message sender's public key and it includes the digital signature.
+ * This payload MUST NOT be used in any other context except with
+ * channel and private message sending and reception.
+ *
+ ***/
+typedef struct SilcMessageSignedPayloadStruct *SilcMessageSignedPayload;
+
/****d* silccore/SilcMessageAPI/SilcMessageFlags
*
* NAME
*
* bool silc_message_payload_encrypt(unsigned char *data,
* SilcUInt32 data_len,
+ * SilcUInt32 true_len,
* unsigned char *iv,
* SilcUInt32 iv_len,
* SilcCipher cipher,
* This function is used to encrypt the Messsage Payload which is
* the `data' and `data_len'. The `data_len' is the data length which
* is used to create MAC out of. The `data' MUST have additional space
- * after `data_len' bytes for the MAC which is appended to the data.
+ * after `true_len' bytes for the MAC which is appended to the data.
*
* This is usually used by the Message Payload interface itself but can
* be called by the appliation if separate encryption process is required.
***/
bool silc_message_payload_encrypt(unsigned char *data,
SilcUInt32 data_len,
+ SilcUInt32 true_len,
unsigned char *iv,
SilcUInt32 iv_len,
SilcCipher cipher,
* bool private_message,
* SilcCipher cipher,
* SilcHmac hmac,
- * SilcRng rng);
+ * SilcRng rng,
+ * SilcPublicKey public_key,
+ * SilcPrivateKey private_key,
+ * SilcHash hash);
*
* DESCRIPTION
*
* message that will be encrypted with session keys (no private message
* key) then `cipher' and `hmac' is NULL and this merely encodes the
* payload buffer, and the caller must encrypt the packet later.
- *
* If `rng' is NULL then global RNG is used, if non-NULL then the
* `rng' is used (for IV and padding generation).
*
+ * The `public_key', `private_key' and `hash' are provided only if the
+ * flags includes SILC_MESSAGE_FLAG_SIGNED, in which case the message
+ * will be digitally signed. If `public_key' is non-NULL then it will
+ * be included in the message. The `private_message' and `hash' MUST
+ * be provided. The `hash' SHOULD be SHA1.
+ *
***/
SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
const unsigned char *data,
bool private_message,
SilcCipher cipher,
SilcHmac hmac,
- SilcRng rng);
+ SilcRng rng,
+ SilcPublicKey public_key,
+ SilcPrivateKey private_key,
+ SilcHash hash);
/****f* silccore/SilcMessageAPI/silc_message_payload_free
*
***/
unsigned char *silc_message_get_iv(SilcMessagePayload payload);
-/****s* silccore/SilcMessageAPI/SilcMessageSignedPayload
+/****f* silccore/SilcMessageAPI/silc_message_get_signature
*
- * NAME
- *
- * typedef struct SilcMessageSignedPayloadStruct *SilcMessageSignedPayload;
+ * SYNOPSIS
*
+ * const SilcMessageSignedPayload
+ * silc_message_get_signature(SilcMessagePayload payload);
*
* DESCRIPTION
*
- * This context represents the SILC_MESSAGE_FLAG_SIGNED Payload which
- * is used with channel messages and private messages to indicate that
- * the message is digitally signed. This payload may include the
- * message sender's public key and it includes the digital signature.
- * This payload MUST NOT be used in any other context except with
- * channel and private message sending and reception.
+ * Returns the pointer to the signature of the message if the
+ * SILC_MESSAGE_FLAG_SIGNED was set. If the flag is set and this
+ * function returns NULL then error had occurred and the signature
+ * could not be retrieved from the message.
+ *
+ * The caller SHOULD verify the signature by calling the
+ * silc_message_signed_verify function.
*
***/
-typedef struct SilcMessageSignedPayloadStruct *SilcMessageSignedPayload;
+const SilcMessageSignedPayload
+silc_message_get_signature(SilcMessagePayload payload);
/****f* silccore/SilcMessageAPI/silc_message_signed_payload_parse
*
*
* DESCRIPTION
*
- * Parses the SILC_MESSAGE_FLAG_SIGNED Payload from the `data' of
+ * Parses the SilcMessageSignedPayload Payload from the `data' of
* length of `data_len' bytes. The `data' must be payload without
* the actual message payload. Returns the parsed payload or NULL
- * on error. Caller must free the returned payload.
+ * on error. Caller must free the returned payload. Application
+ * usually does not need to call this since the function
+ * silc_message_payload_parse calls this automatically for signed
+ * messages.
*
***/
SilcMessageSignedPayload
* SilcUInt32 message_payload_len,
* SilcPublicKey public_key,
* SilcPrivateKey private_key,
- * bool include_public_key);
+ * SilcHash hash);
*
* DESCRIPTION
*
- * Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the
+ * Encodes the SilcMessageSignedPayload Payload and computes the
* digital signature. The `message_payload' is the message data that
* is used in the signature computation. The encoding of the buffer
- * is specified in the SILC protocol. If `include_public_key' is
- * TRUE then the public key included in the payload. The `private_key'
+ * is specified in the SILC protocol. If `public_key' is provided
+ * then the public key included in the payload. The `private_key'
* is used to produce the signature. This function returns the encoded
* payload with the signature or NULL on error. Caller must free the
- * returned buffer.
+ * returned buffer. The `hash' SHOULD be SHA-1 hash function.
+ *
+ * Application usually does not need to call this since the function
+ * silc_message_payload_encode calls this automatically if the caller
+ * wants to sign the message.
*
***/
SilcBuffer
SilcUInt32 message_payload_len,
SilcPublicKey public_key,
SilcPrivateKey private_key,
- SilcHash hash,
- bool include_public_key);
+ SilcHash hash);
/****f* silccore/SilcMessageAPI/silc_message_signed_payload_free
*
*
* DESCRIPTION
*
- * Frees the SILC_MESSAGE_FLAG_SIGNED Payload.
+ * Frees the SilcMessageSignedPayload Payload.
*
***/
void silc_message_signed_payload_free(SilcMessageSignedPayload sig);
* DESCRIPTION
*
* This routine can be used to verify the signature found in
- * SILC_MESSAGE_FLAG_SIGNED Payload. This returns SILC_AUTH_OK if the
+ * SilcMessageSignedPayload Payload. This returns SILC_AUTH_OK if the
* signature verification was successful.
*
***/
*
* DESCRIPTION
*
- * Returns the public key from the SILC_MESSAGE_FLAG_SIGNED Payload
+ * Returns the public key from the SilcMessageSignedPayload Payload
* or NULL if it does not include public key. The caller must free
* the returned public key.
*
static void
silc_channel_message(SilcClient client, SilcClientConnection conn,
SilcClientEntry sender, SilcChannelEntry channel,
+ SilcMessagePayload payload,
SilcMessageFlags flags, const unsigned char *message,
SilcUInt32 message_len)
{
static void
silc_private_message(SilcClient client, SilcClientConnection conn,
- SilcClientEntry sender, SilcMessageFlags flags,
+ SilcClientEntry sender, SilcMessagePayload payload,
+ SilcMessageFlags flags,
const unsigned char *message,
SilcUInt32 message_len)
{