Affected files silcd/server_util.[ch], silcd/server.c. and
silcd/backup_router.c.
+ * ROBODoc documented the lib/silccrypt/silchmac.h. Added new
+ function silc_hmac_init, silc_hmac_update, silc_hmac_final,
+ silc_hmac_get_hash and silc_hmac_get_name. Affected file
+ lib/silccrypt/silchmac.c.
+
Sun Oct 14 18:28:22 EDT 2001 Pekka Riikonen <priikone@silcnet.org>
* Assure that router cannot reroute the same channel message
channel_entry->channel_key ?
channel_entry->channel_key->cipher->name : "",
channel_entry->hmac ?
- channel_entry->hmac->hmac->name : "");
+ silc_hmac_get_name(channel_entry->hmac) : "");
g_free_not_null(chanrec->mode);
chanrec->mode = g_strdup(mode == NULL ? "" : mode);
signal_emit("channel mode changed", 1, chanrec);
mode = silc_client_chmode(modei,
channel->channel_key->cipher->name,
- channel->hmac->hmac->name);
+ silc_hmac_get_name(channel->hmac));
chanrec = silc_channel_find_entry(server, channel);
if (chanrec != NULL) {
strcat(buf, " ");
strcat(buf, " ");
- len = strlen(keys[k]->hmac->hmac->name);
- strncat(buf, keys[k]->hmac->hmac->name, len > 16 ? 16 : len);
+ len = strlen(silc_hmac_get_name(keys[k]->hmac));
+ strncat(buf, silc_hmac_get_name(keys[k]->hmac), len > 16 ? 16 : len);
if (len < 16)
for (i = 0; i < 16 - len; i++)
strcat(buf, " ");
10, channel->topic,
channel->topic ?
strlen(channel->topic) : 0,
- 11, channel->hmac->hmac->name,
- strlen(channel->hmac->hmac->name),
+ 11, silc_hmac_get_name(channel->hmac),
+ strlen(silc_hmac_get_name(channel->
+ hmac)),
12, tmp3, 4,
13, user_list->data, user_list->len,
14, mode_list->data,
FALSE : !server->standalone);
cipher = channel->channel_key->cipher->name;
- hmac = channel->hmac->hmac->name;
+ hmac = (char *)silc_hmac_get_name(channel->hmac);
}
}
/* Set the HMAC key out of current channel key. The client must do
this locally. */
- silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
+ silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
+ channel->key_len / 8,
hash);
silc_hmac_set_key(channel->hmac, hash,
- silc_hash_len(channel->hmac->hash));
+ silc_hash_len(silc_hmac_get_hash(channel->hmac)));
memset(hash, 0, sizeof(hash));
}
} else {
/* Set the HMAC key out of current channel key. The client must do
this locally. */
- silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
+ silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
+ channel->key_len / 8,
hash);
silc_hmac_set_key(channel->hmac, hash,
- silc_hash_len(channel->hmac->hash));
+ silc_hash_len(silc_hmac_get_hash(channel->hmac)));
memset(hash, 0, sizeof(hash));
}
}
if (entry->hmac_name && hmac) {
silc_free(entry->hmac_name);
- entry->hmac_name = strdup(hmac->hmac->name);
+ entry->hmac_name = strdup(silc_hmac_get_name(hmac));
}
/* Get the ban list */
SilcIDListData data = (SilcIDListData)entry;
data->send_key = idata->send_key;
data->receive_key = idata->receive_key;
- data->rekey = idata->rekey;
- data->hash = idata->hash;
data->hmac_send = idata->hmac_send;
data->hmac_receive = idata->hmac_receive;
+ data->psn_send = idata->psn_send;
+ data->psn_receive = idata->psn_receive;
+ data->hash = idata->hash;
data->public_key = idata->public_key;
+ data->rekey = idata->rekey;
data->last_receive = idata->last_receive;
data->last_sent = idata->last_sent;
data->status = idata->status;
SilcCipher send_key;
SilcCipher receive_key;
- /* Re-key context */
- SilcServerRekey rekey;
-
- /* Hash selected in the SKE protocol, NULL if not needed at all */
- SilcHash hash;
-
/* HMAC */
SilcHmac hmac_send;
SilcHmac hmac_receive;
+ /* Packet sequence numbers */
+ uint32 psn_send;
+ uint32 psn_receive;
+
+ /* Hash selected in the SKE protocol, NULL if not needed at all */
+ SilcHash hash;
+
/* Public key */
SilcPublicKey public_key;
+ /* Re-key context */
+ SilcServerRekey rekey;
+
long last_receive; /* Time last received data */
long last_sent; /* Time last sent data */
/* Set the HMAC key out of current channel key. The client must do
this locally. */
- silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
+ silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
+ channel->key_len / 8,
hash);
silc_hmac_set_key(channel->hmac, hash,
- silc_hash_len(channel->hmac->hash));
+ silc_hash_len(silc_hmac_get_hash(channel->hmac)));
memset(hash, 0, sizeof(hash));
}
+ packet->dst_id_len + packet->padlen);
silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
-
+
/* Re-encrypt packet */
silc_packet_encrypt(cipher, hmac, dst_sock->outbuf, buffer->len);
-
+
/* Send the packet */
silc_server_packet_send_real(server, dst_sock, FALSE);
}
/* Save HMAC key to be used in the communication. */
- if (!silc_hmac_alloc(hmac->hmac->name, NULL, &idata->hmac_send)) {
+ if (!silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL,
+ &idata->hmac_send)) {
silc_cipher_free(idata->send_key);
silc_cipher_free(idata->receive_key);
silc_hash_free(idata->hash);
SILC_LOG_INFO(("%s (%s) security properties: %s %s %s",
sock->hostname, sock->ip,
idata->send_key->cipher->name,
- idata->hmac_send->hmac->name,
+ (char *)silc_hmac_get_name(idata->hmac_send),
idata->hash->hash->name));
return TRUE;
}
if (send) {
- silc_hmac_alloc(idata->hmac_send->hmac->name, NULL, &idata->hmac_send);
+ silc_hmac_alloc((char *)silc_hmac_get_name(idata->hmac_send), NULL,
+ &idata->hmac_send);
silc_hmac_set_key(idata->hmac_send, keymat->hmac_key,
keymat->hmac_key_len);
} else {
/* Generate HMAC key from the channel key data and set it */
if (!channel->hmac)
silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac);
- silc_hash_make(channel->hmac->hash, channel->key, len, hash);
- silc_hmac_set_key(channel->hmac, hash, silc_hash_len(channel->hmac->hash));
+ silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, len, hash);
+ silc_hmac_set_key(channel->hmac, hash,
+ silc_hash_len(silc_hmac_get_hash(channel->hmac)));
memset(hash, 0, sizeof(hash));
if (server->server_type == SILC_ROUTER) {
/* Generate HMAC key from the channel key data and set it */
if (!channel->hmac)
silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac);
- silc_hash_make(channel->hmac->hash, tmp, tmp_len, hash);
- silc_hmac_set_key(channel->hmac, hash, silc_hash_len(channel->hmac->hash));
+ silc_hash_make(silc_hmac_get_hash(channel->hmac), tmp, tmp_len, hash);
+ silc_hmac_set_key(channel->hmac, hash,
+ silc_hash_len(silc_hmac_get_hash(channel->hmac)));
memset(hash, 0, sizeof(hash));
memset(tmp, 0, tmp_len);
channel = (SilcChannelEntry)id_cache->context;
}
- hmac = channel->hmac ? channel->hmac->hmac->name : SILC_DEFAULT_HMAC;
+ hmac = (channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) :
+ SILC_DEFAULT_HMAC);
/* Save the old key for a short period of time so that we can decrypt
channel message even after the rekey if some client would be sending
/* Generate HMAC key from the channel key data and set it */
silc_hmac_alloc(hmac, NULL, &channel->hmac);
- silc_hash_make(channel->hmac->hash, key, tmp_len, hash);
- silc_hmac_set_key(channel->hmac, hash, silc_hash_len(channel->hmac->hash));
+ silc_hash_make(silc_hmac_get_hash(channel->hmac), key, tmp_len, hash);
+ silc_hmac_set_key(channel->hmac, hash,
+ silc_hash_len(silc_hmac_get_hash(channel->hmac)));
memset(hash, 0, sizeof(hash));
out:
/* Generate HMAC key from the channel key data and set it */
silc_hmac_alloc(hmac, NULL, &entry->hmac);
- 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));
+ silc_hash_make(silc_hmac_get_hash(entry->hmac), entry->key,
+ entry->key_len, hash);
+ silc_hmac_set_key(entry->hmac, hash,
+ silc_hash_len(silc_hmac_get_hash(entry->hmac)));
memset(hash, 0, sizeof(hash));
/* Add to the private keys list */
if (!silc_hmac_alloc(tmp, NULL, &channel->hmac))
goto out;
- silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
+ silc_hash_make(silc_hmac_get_hash(channel->hmac),
+ channel->key, channel->key_len / 8,
hash);
silc_hmac_set_key(channel->hmac, hash,
- silc_hash_len(channel->hmac->hash));
+ silc_hash_len(silc_hmac_get_hash(channel->hmac)));
memset(hash, 0, sizeof(hash));
}
conn->rekey->ske_group = silc_ske_group_get_number(group);
/* Save HMAC key to be used in the communication. */
- silc_hmac_alloc(hmac->hmac->name, NULL, &conn->hmac_send);
+ silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL, &conn->hmac_send);
silc_hmac_set_key(conn->hmac_send, keymat->hmac_key, keymat->hmac_key_len);
conn->hmac_receive = conn->hmac_send;
}
if (send) {
- silc_hmac_alloc(conn->hmac_receive->hmac->name, NULL, &conn->hmac_send);
+ silc_hmac_alloc((char *)silc_hmac_get_name(conn->hmac_receive), NULL,
+ &conn->hmac_send);
silc_hmac_set_key(conn->hmac_send, keymat->hmac_key,
keymat->hmac_key_len);
} else {
/*
- silcpacket.c
+ silcpacket.c
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Pekka Riikonen <priikone@silcnet.org>
Copyright (C) 1997 - 2001 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; version 2 of the License.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
later time. If `force_send' is TRUE this attempts to write the data
directly to the network, if FALSE, this returns -2. */
-int silc_packet_send(SilcSocketConnection sock, int force_send)
+int silc_packet_send(SilcSocketConnection sock, bool force_send)
{
SILC_LOG_DEBUG(("Sending packet to %s:%d [%s]", sock->hostname,
sock->port,
data area thus this uses the length found in buffer, not the length
sent as argument. */
if (hmac) {
- silc_hmac_make(hmac, buffer->data, buffer->len, mac, &mac_len);
+ silc_hmac_init(hmac);
+ silc_hmac_update(hmac, buffer->data, buffer->len);
+ silc_hmac_final(hmac, mac, &mac_len);
silc_buffer_put_tail(buffer, mac, mac_len);
memset(mac, 0, sizeof(mac));
}
/* Allocate new buffer. This is done only once per connection. */
SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
- sock->outbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
+ if (totlen > SILC_PACKET_DEFAULT_SIZE)
+ sock->outbuf = silc_buffer_alloc(totlen);
+ else
+ sock->outbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
silc_buffer_pull_tail(sock->outbuf, totlen);
silc_buffer_pull(sock->outbuf, header_len + padlen);
} else {
return;
if (hmac)
- mac_len = hmac->hmac->len;
+ mac_len = silc_hmac_len(hmac);
/* Parse the packets from the data */
count = 0;
/* Compute HMAC of packet */
memset(mac, 0, sizeof(mac));
- silc_hmac_make(hmac, buffer->data, buffer->len, mac, &mac_len);
+ silc_hmac_init(hmac);
+ silc_hmac_update(hmac, buffer->data, buffer->len);
+ silc_hmac_final(hmac, mac, &mac_len);
/* Compare the HMAC's (buffer->tail has the packet's HMAC) */
if (memcmp(mac, buffer->tail, mac_len)) {
/* Pull MAC from packet before decryption */
if (hmac) {
- if ((buffer->len - hmac->hmac->len) > SILC_PACKET_MIN_LEN) {
- silc_buffer_push_tail(buffer, hmac->hmac->len);
+ if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
+ silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
} else {
SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
return FALSE;
/* Pull MAC from packet before decryption */
if (hmac) {
- if ((buffer->len - hmac->hmac->len) > SILC_PACKET_MIN_LEN) {
- silc_buffer_push_tail(buffer, hmac->hmac->len);
+ if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
+ silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
} else {
SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
return FALSE;
/*
- silcpacket.h
-
+ silcpacket.h
+
Author: Pekka Riikonen <priikone@silcnet.org>
-
+
Copyright (C) 1997 - 2001 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; version 2 of the License.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* SYNOPSIS
*
- * int silc_packet_send(SilcSocketConnection sock, int force_send);
+ * int silc_packet_send(SilcSocketConnection sock, bool force_send);
*
* DESCRIPTION
*
* directly to the network, if FALSE, this returns -2.
*
***/
-int silc_packet_send(SilcSocketConnection sock, int force_send);
+int silc_packet_send(SilcSocketConnection sock, bool force_send);
/****f* silccore/SilcPacketAPI/silc_packet_encrypt
*
/*
- silchmac.c
+ silchmac.c
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2001 Pekka Riikonen
+ Copyright (C) 1999 - 2001 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; version 2 of the License.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#include "silcincludes.h"
+/* HMAC context */
+struct SilcHmacStruct {
+ SilcHmacObject *hmac;
+ SilcHash hash;
+ bool allocated_hash; /* TRUE if the hash was allocated */
+
+ unsigned char *key;
+ uint32 key_len;
+
+ unsigned char inner_pad[64];
+ unsigned char outer_pad[64];
+ void *hash_context;
+};
+
/* List of dynamically registered HMACs. */
SilcDList silc_hmac_list = NULL;
{ NULL, 0 }
};
+static void silc_hmac_init_internal(SilcHmac hmac, unsigned char *key,
+ uint32 key_len)
+{
+ SilcHash hash = hmac->hash;
+ unsigned char hvalue[20];
+ int i;
+
+ memset(hmac->inner_pad, 0, sizeof(hmac->inner_pad));
+ memset(hmac->outer_pad, 0, sizeof(hmac->outer_pad));
+
+ /* If the key length is more than block size of the hash function, the
+ key is hashed. */
+ if (key_len > hash->hash->block_len) {
+ silc_hash_make(hash, key, key_len, hvalue);
+ key = hvalue;
+ key_len = hash->hash->hash_len;
+ }
+
+ /* Copy the key into the pads */
+ memcpy(hmac->inner_pad, key, key_len);
+ memcpy(hmac->outer_pad, key, key_len);
+
+ /* XOR the key with pads */
+ for (i = 0; i < hash->hash->block_len; i++) {
+ hmac->inner_pad[i] ^= 0x36;
+ hmac->outer_pad[i] ^= 0x5c;
+ }
+}
+
/* Registers a new HMAC into the SILC. This function is used at the
initialization of the SILC. */
if (hmac) {
if (hmac->allocated_hash)
silc_hash_free(hmac->hash);
+
+ if (hmac->key) {
+ memset(hmac->key, 0, hmac->key_len);
+ silc_free(hmac->key);
+ }
+
+ silc_free(hmac->hash_context);
silc_free(hmac);
}
}
return hmac->hmac->len;
}
+/* Get hash context */
+
+SilcHash silc_hmac_get_hash(SilcHmac hmac)
+{
+ return hmac->hash;
+}
+
+/* Return name of hmac */
+
+const char *silc_hmac_get_name(SilcHmac hmac)
+{
+ return hmac->hmac->name;
+}
+
/* Returns TRUE if HMAC `name' is supported. */
bool silc_hmac_is_supported(const char *name)
memcpy(hmac->key, key, key_len);
}
-/* Creates the HMAC. The created keyed hash value is returned to
- return_hash argument. */
-
-void silc_hmac_make_internal(SilcHmac hmac, unsigned char *data,
- uint32 data_len, unsigned char *key,
- uint32 key_len, unsigned char *return_hash)
-{
- SilcHash hash = hmac->hash;
- unsigned char inner_pad[64];
- unsigned char outer_pad[64];
- unsigned char hvalue[20], mac[20];
- void *hash_context;
- int i;
-
- SILC_LOG_DEBUG(("Making HMAC for message"));
-
- hash_context = silc_calloc(1, hash->hash->context_len());
-
- memset(inner_pad, 0, sizeof(inner_pad));
- memset(outer_pad, 0, sizeof(outer_pad));
-
- /* If the key length is more than block size of the hash function, the
- key is hashed. */
- if (key_len > hash->hash->block_len) {
- silc_hash_make(hash, key, key_len, hvalue);
- key = hvalue;
- key_len = hash->hash->hash_len;
- }
-
- /* Copy the key into the pads */
- memcpy(inner_pad, key, key_len);
- memcpy(outer_pad, key, key_len);
-
- /* XOR the key with pads */
- for (i = 0; i < hash->hash->block_len; i++) {
- inner_pad[i] ^= 0x36;
- outer_pad[i] ^= 0x5c;
- }
-
- /* Do the HMAC transform (too bad I can't do make_hash directly, sigh) */
- hash->hash->init(hash_context);
- hash->hash->update(hash_context, inner_pad, hash->hash->block_len);
- hash->hash->update(hash_context, data, data_len);
- hash->hash->final(hash_context, mac);
- hash->hash->init(hash_context);
- hash->hash->update(hash_context, outer_pad, hash->hash->block_len);
- hash->hash->update(hash_context, mac, hash->hash->hash_len);
- hash->hash->final(hash_context, mac);
- memcpy(return_hash, mac, hmac->hmac->len);
- memset(mac, 0, sizeof(mac));
- silc_free(hash_context);
-}
-
/* Create the HMAC. This is thee make_hmac function pointer. This
uses the internal key set with silc_hmac_set_key. */
uint32 data_len, unsigned char *return_hash,
uint32 *return_len)
{
- silc_hmac_make_internal(hmac, data, data_len, hmac->key,
- hmac->key_len, return_hash);
- if (return_len)
- *return_len = hmac->hmac->len;
+ SILC_LOG_DEBUG(("Making HMAC for message"));
+
+ silc_hmac_init(hmac);
+ silc_hmac_update(hmac, data, data_len);
+ silc_hmac_final(hmac, return_hash, return_len);
}
/* Creates HMAC just as above except that this doesn't use the internal
unsigned char *return_hash,
uint32 *return_len)
{
- silc_hmac_make_internal(hmac, data, data_len, key, key_len, return_hash);
- if (return_len)
- *return_len = hmac->hmac->len;
+ SILC_LOG_DEBUG(("Making HMAC for message"));
+
+ silc_hmac_init_with_key(hmac, key, key_len);
+ silc_hmac_update(hmac, data, data_len);
+ silc_hmac_final(hmac, return_hash, return_len);
}
/* Creates the HMAC just as above except that the hash value is truncated
{
unsigned char hvalue[20];
- silc_hmac_make_internal(hmac, data, data_len,
- hmac->key, hmac->key_len, hvalue);
+ SILC_LOG_DEBUG(("Making HMAC for message"));
+
+ silc_hmac_init(hmac);
+ silc_hmac_update(hmac, data, data_len);
+ silc_hmac_final(hmac, return_hash, NULL);
memcpy(return_hash, hvalue, truncated_len);
memset(hvalue, 0, sizeof(hvalue));
}
+
+/* Init HMAC for silc_hmac_update and silc_hmac_final. */
+
+void silc_hmac_init(SilcHmac hmac)
+{
+ silc_hmac_init_with_key(hmac, hmac->key, hmac->key_len);
+}
+
+/* Same as above but with specific key */
+
+void silc_hmac_init_with_key(SilcHmac hmac, const unsigned char *key,
+ uint32 key_len)
+{
+ SilcHash hash = hmac->hash;
+
+ silc_hmac_init_internal(hmac, hmac->key, hmac->key_len);
+
+ if (!hmac->hash_context)
+ hmac->hash_context = silc_calloc(1, hash->hash->context_len());
+
+ hash->hash->init(hmac->hash_context);
+ hash->hash->update(hmac->hash_context, hmac->inner_pad,
+ hash->hash->block_len);
+}
+
+/* Add data to be used in the MAC computation. */
+
+void silc_hmac_update(SilcHmac hmac, const unsigned char *data,
+ uint32 data_len)
+{
+ SilcHash hash = hmac->hash;
+ hash->hash->update(hmac->hash_context, (unsigned char *)data, data_len);
+}
+
+/* Compute the final MAC. */
+
+void silc_hmac_final(SilcHmac hmac, unsigned char *return_hash,
+ uint32 *return_len)
+{
+ SilcHash hash = hmac->hash;
+ unsigned char mac[20];
+
+ hash->hash->final(hmac->hash_context, mac);
+ hash->hash->init(hmac->hash_context);
+ hash->hash->update(hmac->hash_context, hmac->outer_pad,
+ hash->hash->block_len);
+ hash->hash->update(hmac->hash_context, mac, hash->hash->hash_len);
+ hash->hash->final(hmac->hash_context, mac);
+ memcpy(return_hash, mac, hmac->hmac->len);
+ memset(mac, 0, sizeof(mac));
+
+ if (return_len)
+ *return_len = hmac->hmac->len;
+}
/*
- silchmac.h
+ silchmac.h
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2001 Pekka Riikonen
+ Copyright (C) 1999 - 2001 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; version 2 of the License.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#ifndef SILCHMAC_H
#define SILCHMAC_H
-/*
- SILC HMAC object.
-
- This is the HMAC object to create keyed hash values for message
- authentication. These routines uses already implemented hash functions.
- HMAC's can be created using any hash function implemented in SILC. These
- routines were created according to RFC2104. Following short description
- of the fields:
-
- SilcHmacObject:
-
- char *name
-
- Name of the HMAC.
-
- uint32 len
-
- Length of the MAC the HMAC is to produce (bytes).
-
-
- SilcHmac:
-
- SilcHash hash
+/****h* silccrypt/SilcHMACAPI
+ *
+ * DESCRIPTION
+ *
+ * This is the interface for HMAC, or the keyed hash values, that are
+ * used for packet and message authentication. These routines uses
+ * already implemented hash functions from the SilcHashAPI. These
+ * routines were created according to RFC 2104.
+ *
+ ***/
- The hash object to tell what hash function to use with this HMAC.
-
- char allocated_hash
-
- TRUE if the `hash' was allocated and FALSE if it is static and
- must not be freed.
-
- unsigned char *key
- uint32 len
-
- The key and its length used to make the HMAC. This is set
- with silc_hmac_set_key function.
-
-*/
+/****s* silccrypt/SilcHMACAPI/SilcHmac
+ *
+ * NAME
+ *
+ * typedef struct SilcHmacStruct *SilcHmac;
+ *
+ * DESCRIPTION
+ *
+ * This context is the actual HMAC context and is allocated
+ * by silc_hmac_alloc and given as argument usually to all
+ * silc_hmac_* functions. It is freed by the silc_hmac_free
+ * function.
+ *
+ ***/
typedef struct SilcHmacStruct *SilcHmac;
+/****s* silccrypt/SilcHMACAPI/SilcHmacObject
+ *
+ * NAME
+ *
+ * typedef struct { ... } SilcHmacObject;
+ *
+ * DESCRIPTION
+ *
+ * This structure represents one HMAC. The HMAC's name and the
+ * MAC length is defined in the structure. This structure is
+ * then given as argument to the silc_hmac_register. That function
+ * is used to register all HMACs into SILC. They can be then
+ * allocated by the name found in this structure by calling the
+ * silc_hmac_alloc.
+ *
+ ***/
typedef struct {
char *name;
uint32 len;
} SilcHmacObject;
-struct SilcHmacStruct {
- SilcHmacObject *hmac;
- SilcHash hash;
- char allocated_hash;
- unsigned char *key;
- uint32 key_len;
-};
-
/* Marks for all hmacs. This can be used in silc_hmac_unregister
to unregister all hmacs at once. */
#define SILC_ALL_HMACS ((SilcHmacObject *)1)
#define SILC_DEFAULT_HMAC "hmac-sha1-96"
/* Prototypes */
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_register
+ *
+ * SYNOPSIS
+ *
+ * bool silc_hmac_register(SilcHmacObject *hmac);
+ *
+ * DESCRIPTION
+ *
+ * Registers a new HMAC into the SILC. This function is used at the
+ * initialization of the SILC. All registered HMACs should be
+ * unregistered with silc_hmac_unregister. The `hmac' includes the
+ * name of the HMAC and the length of the MAC. Usually this
+ * function is not called directly. Instead, application can call
+ * the silc_hmac_register_default to register all default HMACs
+ * that are builtin the sources. Returns FALSE on error.
+ *
+ ***/
bool silc_hmac_register(SilcHmacObject *hmac);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_unregister
+ *
+ * SYNOPSIS
+ *
+ * bool silc_hmac_unregister(SilcHmacObject *hmac);
+ *
+ * DESCRIPTION
+ *
+ * Unregister a HMAC from SILC by the HMAC structure `hmac'. This
+ * should be called for all registered HMAC's. Returns FALSE on
+ * error.
+ *
+ ***/
bool silc_hmac_unregister(SilcHmacObject *hmac);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_register_default
+ *
+ * SYNOPSIS
+ *
+ * bool silc_hmac_register_default(void);
+ *
+ * DESCRIPTION
+ *
+ * Registers all default HMACs into the SILC. These are the HMACs
+ * that are builtin in the sources. See the list of default HMACs
+ * in the silchmac.c source file. The application may use this
+ * to register default HMACs if specific HMAC in any specific order
+ * is not wanted (application's configuration usually may decide
+ * the order of the registration, in which case this should not be
+ * used).
+ *
+ ***/
bool silc_hmac_register_default(void);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_alloc
+ *
+ * SYNOPSIS
+ *
+ * bool silc_hmac_alloc(char *name, SilcHash hash, SilcHmac *new_hmac);
+ *
+ * DESCRIPTION
+ *
+ * Allocates a new SilcHmac object of name of `name'. The `hash' may
+ * be provided as argument. If provided it is used as the hash function
+ * of the HMAC. If it is NULL then the hash function is allocated and
+ * the name of the hash algorithm is derived from the `name'. Returns
+ * FALSE if such HMAC does not exist.
+ *
+ ***/
bool silc_hmac_alloc(char *name, SilcHash hash, SilcHmac *new_hmac);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_free
+ *
+ * SYNOPSIS
+ *
+ * void silc_hmac_free(SilcHmac hmac);
+ *
+ * DESCRIPTION
+ *
+ * Frees the allocated HMAC context. The key that may have been set
+ * with the silc_hmac_set_key is also destroyed.
+ *
+ ***/
void silc_hmac_free(SilcHmac hmac);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_is_supported
+ *
+ * SYNOPSIS
+ *
+ * bool silc_hmac_is_supported(const char *name);
+ *
+ * DESCRIPTION
+ *
+ * Returns TRUE if the HMAC indicated by the `name' exists.
+ *
+ ***/
bool silc_hmac_is_supported(const char *name);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_get_supported
+ *
+ * SYNOPSIS
+ *
+ * char *silc_hmac_get_supported(void);
+ *
+ * DESCRIPTION
+ *
+ * Returns comma (`,') separated list of registered HMACs. This is
+ * used for example when sending supported HMAC list during the SILC
+ * Key Exchange protocol (SKE). The caller must free the returned
+ * pointer.
+ *
+ ***/
char *silc_hmac_get_supported(void);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_len
+ *
+ * SYNOPSIS
+ *
+ * uint32 silc_hmac_len(SilcHmac hmac);
+ *
+ * DESCRIPTION
+ *
+ * Returns the length of the MAC that the HMAC will produce.
+ *
+ ***/
uint32 silc_hmac_len(SilcHmac hmac);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_get_hash
+ *
+ * SYNOPSIS
+ *
+ * SilcHash silc_hmac_get_hash(SilcHmac hmac);
+ *
+ * DESCRIPTION
+ *
+ * Returns the SilcHash context that has been associated with the
+ * HMAC context. The caller must not free the returned context.
+ *
+ ***/
+SilcHash silc_hmac_get_hash(SilcHmac hmac);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_get_name
+ *
+ * SYNOPSIS
+ *
+ * const char *silc_hmac_get_name(SilcHmac hmac);
+ *
+ * DESCRIPTION
+ *
+ * Returns the name of the HMAC context.
+ *
+ ***/
+const char *silc_hmac_get_name(SilcHmac hmac);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_set_key
+ *
+ * SYNOPSIS
+ *
+ * void silc_hmac_set_key(SilcHmac hmac, const unsigned char *key,
+ * uint32 key_len);
+ *
+ * DESCRIPTION
+ *
+ * Sets the key to be used in the HMAC operation. This must be set
+ * before calling silc_hmac_make or silc_hmac_final functions. If
+ * you do not want to set the key you can still produce a MAC by
+ * calling the silc_hmac_make_with_key where you give the key as
+ * argument. Usually application still wants to set the key.
+ *
+ ***/
void silc_hmac_set_key(SilcHmac hmac, const unsigned char *key,
uint32 key_len);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_make
+ *
+ * SYNOPSIS
+ *
+ * void silc_hmac_make(SilcHmac hmac, unsigned char *data,
+ * uint32 data_len, unsigned char *return_hash,
+ * uint32 *return_len);
+ *
+ * DESCRIPTION
+ *
+ * Computes a MAC from a data buffer indicated by the `data' of the
+ * length of `data_len'. The returned MAC is copied into the
+ * `return_hash' pointer which must be at least the size of the
+ * value silc_hmac_len returns. The returned length is still
+ * returned to `return_len'.
+ *
+ ***/
void silc_hmac_make(SilcHmac hmac, unsigned char *data,
uint32 data_len, unsigned char *return_hash,
uint32 *return_len);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_make_with_key
+ *
+ * SYNOPSIS
+ *
+ * void silc_hmac_make_with_key(SilcHmac hmac, unsigned char *data,
+ * uint32 data_len,
+ * unsigned char *key, uint32 key_len,
+ * unsigned char *return_hash,
+ * uint32 *return_len);
+ *
+ * DESCRIPTION
+ *
+ * Same as the silc_hmac_make but takes the key for the HMAC as
+ * argument. If this is used the key that may have been set by calling
+ * silc_hmac_set_key is ignored.
+ *
+ ***/
void silc_hmac_make_with_key(SilcHmac hmac, unsigned char *data,
uint32 data_len,
unsigned char *key, uint32 key_len,
unsigned char *return_hash,
uint32 *return_len);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_make_truncated
+ *
+ * SYNOPSIS
+ *
+ * void silc_hmac_make_truncated(SilcHmac hmac,
+ * unsigned char *data,
+ * uint32 data_len,
+ * uint32 truncated_len,
+ * unsigned char *return_hash);
+ *
+ * DESCRIPTION
+ *
+ * Same as the silc_hmac_make except that the returned MAC is
+ * truncated to the length indicated by the `truncated_len'. Some
+ * special applications may need this function. The `return_hash'
+ * must be at least the size of `truncated_len'.
+ *
+ * NOTES
+ *
+ * For security reasons, one should not truncate to less than half
+ * of the length of the true MAC lenght. However, since this routine
+ * may be used to non-critical applications this allows these dangerous
+ * truncations.
+ *
+ ***/
void silc_hmac_make_truncated(SilcHmac hmac,
unsigned char *data,
uint32 data_len,
uint32 truncated_len,
unsigned char *return_hash);
+/****f* silccrypt/SilcHMACAPI/silc_hmac_init
+ *
+ * SYNOPSIS
+ *
+ * void silc_hmac_init(SilcHmac hmac);
+ *
+ * DESCRIPTION
+ *
+ * Sometimes calling the silc_hmac_make might not be the most
+ * optimal case of doing MACs. If you have a lot of different data
+ * that you need to put together for computing a MAC you may either
+ * put them into a buffer and compute the MAC from the buffer by
+ * calling the silc_hmac_make, or you can use the silc_hmac_init,
+ * silc_hmac_update and silc_hmac_final to do the MAC. This function
+ * prepares the allocated HMAC context for this kind of MAC
+ * computation. The caller must have been called the function
+ * silc_hmac_set_key before calling this function. To add the
+ * data to be used in the MAC computation call the silc_hmac_update
+ * function.
+ *
+ ***/
+void silc_hmac_init(SilcHmac hmac);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_init_with_key
+ *
+ * SYNOPSIS
+ *
+ * void silc_hmac_init_with_key(SilcHmac hmac, const unsigned char *key,
+ * uint32 key_len);
+ *
+ * DESCRIPTION
+ *
+ * Same as silc_hmac_init but initializes with specific key. The
+ * key that may have been set with silc_hmac_set_key is ignored.
+ *
+ ***/
+void silc_hmac_init_with_key(SilcHmac hmac, const unsigned char *key,
+ uint32 key_len);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_update
+ *
+ * SYNOPSIS
+ *
+ * void silc_hmac_update(SilcHmac hmac, const unsigned char *data,
+ * uint32 data_len);
+ *
+ * DESCRIPTION
+ *
+ * This function may be called to add data to be used in the MAC
+ * computation. This can be called multiple times to add data from
+ * many sources before actually performing the HMAC. Once you've
+ * added all the data you need you can call the silc_hmac_final to
+ * actually produce the MAC.
+ *
+ * EXAMPLE
+ *
+ * unsigned char mac[20];
+ * uint32 mac_len;
+ *
+ * silc_hmac_init(hmac);
+ * silc_hmac_update(hmac, data, data_len);
+ * silc_hmac_update(hmac, more_data, more_data_len);
+ * silc_hmac_final(hmac, mac, &mac_len);
+ *
+ ***/
+void silc_hmac_update(SilcHmac hmac, const unsigned char *data,
+ uint32 data_len);
+
+/****f* silccrypt/SilcHMACAPI/silc_hmac_init
+ *
+ * SYNOPSIS
+ *
+ * void silc_hmac_final(SilcHmac hmac, unsigned char *return_hash,
+ * uint32 *return_len);
+ *
+ * DESCRIPTION
+ *
+ * This function is used to produce the final MAC from the data
+ * that has been added to the HMAC context by calling the
+ * silc_hmac_update function. The MAC is copied in to the
+ * `return_hash' pointer which must be at least the size that
+ * the silc_hmac_len returns. The length of the MAC is still
+ * returned into `return_len'.
+ *
+ ***/
+void silc_hmac_final(SilcHmac hmac, unsigned char *return_hash,
+ uint32 *return_len);
+
#endif