From: Pekka Riikonen Date: Tue, 27 Feb 2001 14:47:41 +0000 (+0000) Subject: updates. X-Git-Tag: SILC.0.1~155 X-Git-Url: http://git.silc.fi/gitweb/?a=commitdiff_plain;h=d8d4f7918675c2dec9b5043420126439f2091c1e;p=silc.git updates. --- diff --git a/CHANGES b/CHANGES index 77481f17..3936b9d1 100644 --- a/CHANGES +++ b/CHANGES @@ -11,6 +11,9 @@ Tue Feb 27 13:30:52 EET 2001 Pekka Riikonen SILC Client Library. Other files need not be included by the application anymore. + * Added new key_agreement client callback and also defined the + Key Agreement library API for the application. + Tue Feb 27 11:28:31 EET 2001 Pekka Riikonen * Added new packet type: SILC_PACKET_KEY_AGREEMENT. This packet diff --git a/doc/draft-riikonen-silc-pp-01.nroff b/doc/draft-riikonen-silc-pp-01.nroff index 74411196..0fa63ff2 100644 --- a/doc/draft-riikonen-silc-pp-01.nroff +++ b/doc/draft-riikonen-silc-pp-01.nroff @@ -1562,6 +1562,7 @@ o Private Message Key (variable length) - The actual private .in 3 + .ti 0 2.3.13 Command Payload @@ -1967,6 +1968,16 @@ o Port (4 bytes) - The port where the SKE protocol is bound. .in 3 +After the key material has been received from the SKE protocol it is +processed as the [SILC3] describes. If the key material is used as +channel private key then the Sending Encryption Key, as defined in +[SILC3] is used as the channel private key. Other key material must +be discarded. If the key material is used as private message key then +the keys and the IV's are used as defined in the [SILC3]. The HMAC +key, however, must be discarded. Any other use for the key material +is undefined. + + .ti 0 2.4 SILC ID Types diff --git a/doc/draft-riikonen-silc-spec-01.nroff b/doc/draft-riikonen-silc-spec-01.nroff index 85f6b101..d3162194 100644 --- a/doc/draft-riikonen-silc-spec-01.nroff +++ b/doc/draft-riikonen-silc-spec-01.nroff @@ -1639,21 +1639,20 @@ may be generated and sent to the other client by sending packet SILC_PACKET_PRIVATE_MESSAGE_KEY which travels through the network and is secured by session keys. After that the private message key is used in the private message communication between those clients. -See more information about how this works technically in [SILC2]. Other choice is to entirely use keys that are not sent through the SILC network at all. This significantly adds security. This key would be pre-shared-key that is known by both of the clients. Both agree about using the key and starts sending packets that indicate -that the private message is secured using private message key. This -is the technical aspect mentioned previously that is described -in [SILC2]. - -If the private message keys are not set to be used, which is the -case by default in SILC, the private messages are secured by using -normal session keys established by SILC Key Exchange protocol. - - +that the private message is secured using private message key. + +The key material used as private message key is implementation issue. +However, SILC_PACKET_KEY_AGREEMENT packet may be used to negotiate +the key material. If the key is normal pre-shared-key or randomly +generated key, and the SILC_PACKET_KEY_AGREEMENT was not used, then +the key material should be processed as defined in the [SILC3]. After +processing the key material it is employed as defined in [SILC3], +however, the HMAC key material must be discarded. .ti 0 diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index 24406e0b..733072c5 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -75,7 +75,7 @@ SilcClientCommand silc_command_list[] = cmd, FALSE, cmd->command->cmd) /* Generic function to send any command. The arguments must be sent already - encoded into correct form in correct order. */ + encoded into correct form and in correct order. */ void silc_client_send_command(SilcClient client, SilcClientConnection conn, SilcCommand command, unsigned short ident, @@ -201,8 +201,7 @@ void silc_client_command_free(SilcClientCommandContext ctx) /* Duplicate Command Context by adding reference counter. The context won't be free'd untill it hits zero. */ -SilcClientCommandContext -silc_client_command_dup(SilcClientCommandContext ctx) +SilcClientCommandContext silc_client_command_dup(SilcClientCommandContext ctx) { ctx->users++; SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1, diff --git a/lib/silcclient/command.h b/lib/silcclient/command.h index d36ae130..1954d457 100644 --- a/lib/silcclient/command.h +++ b/lib/silcclient/command.h @@ -59,7 +59,10 @@ typedef struct { /* All client commands */ extern SilcClientCommand silc_command_list[]; -/* Context sent as argument to all commands */ +/* Context sent as argument to all commands. This is used by the library + and application should use this as well. However, application may + choose to use some own context for its own local command. All library + commands, however, must use this context. */ typedef struct { SilcClient client; SilcClientConnection conn; @@ -72,12 +75,7 @@ typedef struct { int users; /* Reference counter */ } *SilcClientCommandContext; -/* Pending Command callback destructor. This is called after calling the - pending callback or if error occurs while processing the pending command. - If error occurs then the callback won't be called at all, and only this - destructor is called. The `context' is the context given for the function - silc_client_command_pending. */ -typedef void (*SilcClientPendingDestructor)(void *context); +#include "silcapi.h" /* Structure holding pending commands. If command is pending it will be executed after command reply has been executed. */ @@ -121,21 +119,7 @@ do { \ (*ctx->destructor)(ctx->context); \ } while(0) -/* Prototypes */ -void silc_client_send_command(SilcClient client, SilcClientConnection conn, - SilcCommand command, unsigned short ident, - unsigned int argc, ...); -SilcClientCommand *silc_client_command_find(const char *name); -SilcClientCommandContext silc_client_command_alloc(); -void silc_client_command_free(SilcClientCommandContext ctx); -SilcClientCommandContext -silc_client_command_dup(SilcClientCommandContext ctx); -void silc_client_command_pending(SilcClientConnection conn, - SilcCommand reply_cmd, - unsigned short ident, - SilcClientPendingDestructor destructor, - SilcCommandCb callback, - void *context); +/* Prototypes (some prototypes are in the silcapi.h file) */ void silc_client_command_pending_del(SilcClientConnection conn, SilcCommand reply_cmd, unsigned short ident); diff --git a/lib/silcclient/silcapi.h b/lib/silcclient/silcapi.h index c67a969f..e91929c9 100644 --- a/lib/silcclient/silcapi.h +++ b/lib/silcclient/silcapi.h @@ -151,6 +151,15 @@ typedef struct { types). */ void (*failure)(SilcClient client, SilcClientConnection conn, SilcProtocol protocol, void *failure); + + /* Asks whether the user would like to perform the key agreement protocol. + This is called after we have received an key agreement packet or an + reply to our key agreement packet. This returns TRUE if the user wants + the library to perform the key agreement protocol and FALSE if it is not + desired. */ + int (*key_agreement)(SilcClient client, SilcClientConnection conn, + SilcClientEntry client_entry, char *hostname, + int port); } SilcClientOperations; @@ -233,7 +242,7 @@ void silc_client_close_connection(SilcClient client, SilcClientConnection conn); -/* Packet sending functions */ +/* Message sending functions */ /* Sends packet to the `channel'. Packet to channel is always encrypted differently from "normal" packets. SILC header of the packet is @@ -263,14 +272,108 @@ void silc_client_send_private_message(SilcClient client, int force_send); +/* Client and Channel entry retrieval */ + +/* Callback function given to the silc_client_get_client function. The + found entries are allocated into the `clients' array. The array must + not be freed by the caller, the library will free it later. If the + `clients' is NULL, no such clients exist in the SILC Network. */ +typedef void (*SilcGetClientCallback)(SilcClient client, + SilcClientConnection conn, + SilcClientEntry *clients, + unsigned int clients_count, + void *context); + +/* Finds client entry or entries by the `nickname' and `server'. The + completion callback will be called when the client entries has been found. + + Note: this function is always asynchronous and resolves the client + information from the server. Thus, if you already know the client + information then use the silc_client_get_client_by_id function to + get the client entry since this function may be very slow and should + be used only to initially get the client entries. */ +void silc_client_get_clients(SilcClient client, + SilcClientConnection conn, + char *nickname, + char *server, + SilcGetClientCallback completion, + void *context); + +/* Same as above function but does not resolve anything from the server. + This checks local cache and returns all clients from the cache. */ +SilcClientEntry *silc_client_get_clients_local(SilcClient client, + SilcClientConnection conn, + char *nickname, + char *server, + unsigned int *clients_count); + +/* Find entry for client by the client's ID. Returns the entry or NULL + if the entry was not found. */ +SilcClientEntry silc_client_get_client_by_id(SilcClient client, + SilcClientConnection conn, + SilcClientID *client_id); + +/* Finds entry for channel by the channel name. Returns the entry or NULL + if the entry was not found. It is found only if the client is joined + to the channel. */ +SilcChannelEntry silc_client_get_channel(SilcClient client, + SilcClientConnection conn, + char *channel); + + +/* Command management */ + +/* Allocate Command Context. The context is defined in `command.h' file. + The context is used by the library commands and applications should use + it as well. However, application may choose to use some own context + for its local commands. All library commands, however, must use this + context. */ +SilcClientCommandContext silc_client_command_alloc(); + +/* Free command context and its internals */ +void silc_client_command_free(SilcClientCommandContext ctx); + +/* Duplicate Command Context by adding reference counter. The context won't + be free'd untill it hits zero. */ +SilcClientCommandContext silc_client_command_dup(SilcClientCommandContext ctx); + +/* Finds and returns a pointer to the command list. Return NULL if the + command is not found. See the `command.[ch]' for the command list. */ +SilcClientCommand *silc_client_command_find(const char *name); + +/* Generic function to send any command. The arguments must be sent already + encoded into correct form and in correct order. */ +void silc_client_send_command(SilcClient client, SilcClientConnection conn, + SilcCommand command, unsigned short ident, + unsigned int argc, ...); + +/* Pending Command callback destructor. This is called after calling the + pending callback or if error occurs while processing the pending command. + If error occurs then the callback won't be called at all, and only this + destructor is called. The `context' is the context given for the function + silc_client_command_pending. */ +typedef void (*SilcClientPendingDestructor)(void *context); + +/* Add new pending command to be executed when reply to a command has been + received. The `reply_cmd' is the command that will call the `callback' + with `context' when reply has been received. If `ident is non-zero + the `callback' will be executed when received reply with command + identifier `ident'. */ +void silc_client_command_pending(SilcClientConnection conn, + SilcCommand reply_cmd, + unsigned short ident, + SilcClientPendingDestructor destructor, + SilcCommandCb callback, + void *context); + + /* Private Message key management */ /* Adds private message key to the client library. The key will be used to encrypt all private message between the client and the remote client - indicated by the `client_entry'. If `key' is NULL and the boolean value - `generate_key' is TRUE then the library will generate random key. - Otherwise the `key' provided by the application will be used. It maybe - random key or pre-shared-key. + indicated by the `client_entry'. If the `key' is NULL and the boolean + value `generate_key' is TRUE the library will generate random key. + The `key' maybe for example pre-shared-key, passphrase or similar. 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 @@ -289,6 +392,14 @@ int silc_client_add_private_message_key(SilcClient client, unsigned int key_len, int generate_key); +/* 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. */ +int silc_client_add_private_message_key_ske(SilcClient client, + SilcClientConnection conn, + SilcClientConnection client_entry, + SilcSKEKeyMaterial *key); + /* Removes the private message from the library. The key won't be used after this to protect the private messages with the remote `client_entry' client. Returns FALSE on error, TRUE otherwise. */ @@ -298,12 +409,14 @@ int silc_client_del_private_message_key(SilcClient client, /* Structure to hold the list of private message keys. The array of this structure is returned by the silc_client_list_private_message_keys - function. */ + function. */ typedef struct { SilcClientEntry client_entry; /* The remote client entry */ - unsigned char *key; /* The raw key data */ + unsigned char *key; /* The original key, If the appliation + provided it. This is NULL if the + library generated the key or if + the SKE key material was used. */ unsigned int key_len; /* The key length */ - int generated; /* TRUE if library generated the key */ } *SilcPrivateMessageKeys; /* Returns array of set private message keys associated to the connection @@ -324,7 +437,7 @@ void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys, unsigned int key_count); -/* Channel Message (private) key management */ +/* Channel private key management */ /* Adds private key for channel. This may be set only if the channel's mode mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the @@ -343,8 +456,14 @@ void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys, be tried in order to find the correct decryption key. However, setting a few keys does not have big impact to the decryption performace. - Note that this is entirely local setting. The key set using this function - is not sent to the network at any phase. */ + NOTE: that this is entirely local setting. The key set using this function + is not sent to the network at any phase. + + NOTE: If the key material was originated by the SKE protocol (using + silc_client_send_key_agreement) then the `key' MUST be the + key->send_enc_key as this is dictated by the SILC protocol. However, + currently it is not expected that the SKE key material would be used + as channel private key. However, this API allows it. */ int silc_client_add_channel_private_key(SilcClient client, SilcClientConnection conn, SilcChannelEntry channel, @@ -390,52 +509,65 @@ void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys, unsigned int key_count); -/* Client and Channel entry retrieval */ +/* Key Agreement routines */ -/* Callback function given to the silc_client_get_client function. The - found entries are allocated into the `clients' array. The array must - not be freed by the caller, the library will free it later. If the - `clients' is NULL, no such clients exist in the SILC Network. */ -typedef void (*SilcGetClientCallback)(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - unsigned int clients_count, - void *context); - -/* Finds client entry or entries by the `nickname' and `server'. The - completion callback will be called when the client entries has been found. - - Note: this function is always asynchronous and resolves the client - information from the server. Thus, if you already know the client - information then use the silc_client_get_client_by_id function to - get the client entry since this function may be very slow and should - be used only to initially get the client entries. */ -void silc_client_get_clients(SilcClient client, - SilcClientConnection conn, - char *nickname, - char *server, - SilcGetClientCallback completion, - void *context); - -/* Same as above function but does not resolve anything from the server. - This checks local cache and returns all clients from the cache. */ -SilcClientEntry *silc_client_get_clients_local(SilcClient client, - SilcClientConnection conn, - char *nickname, - char *server, - unsigned int *clients_count); - -/* Find entry for client by the client's ID. Returns the entry or NULL - if the entry was not found. */ -SilcClientEntry silc_client_get_client_by_id(SilcClient client, - SilcClientConnection conn, - SilcClientID *client_id); - -/* Finds entry for channel by the channel name. Returns the entry or NULL - if the entry was not found. It is found only if the client is joined - to the channel. */ -SilcChannelEntry silc_client_get_channel(SilcClient client, +/* Key agreement callback that is called after the key agreement protocol + has been performed. This is called also if error occured during the + key agreement protocol. The `key' is the allocated key material and + the caller is responsible of freeing it. The `key' is NULL if error + has occured. The application can freely use the `key' to whatever + purpose it needs. See lib/silcske/silcske.h for the definition of + the SilcSKEKeyMaterial structure. */ +typedef void (*SilcKeyAgreementCallback)(SilcClient client, SilcClientConnection conn, - char *channel); + SilcClientEntry client_entry, + SilcSKEKeyMaterial *key, + void *context); + +/* Sends key agreement request to the remote client indicated by the + `client_entry'. If the caller provides the `hostname' and the `port' + arguments then the library will bind the client to that hostname and + that port for the key agreement protocol. It also sends the `hostname' + and the `port' in the key agreement packet to the remote client. This + would indicate that the remote client may initiate the key agreement + protocol to the `hostname' on the `port'. + + If the `hostname' and `port' is not provided then empty key agreement + packet is sent to the remote client. The remote client may reply with + the same packet including its hostname and port. If the library receives + the reply from the remote client the `key_agreement' client operation + callback will be called to verify whether the user wants to perform the + key agreement or not. + + NOTE: If the application provided the `hostname' and the `port' and the + remote side initiates the key agreement protocol it is not verified + from the user anymore whether the protocol should be executed or not. + By setting the `hostname' and `port' the user gives permission to + perform the protocol. + + NOTE: If the remote side decides not to initiate the key agreement + or decides not to reply with the key agreement packet then we cannot + perform the key agreement at all. If the key agreement protocol is + performed the `completion' callback with `context' will be called. + If remote side decides to ignore the request the `completion' will never + be called and the caller is responsible of freeing the `context' memory. + The application can do this by setting, for example, timeout. */ +void silc_client_send_key_agreement(SilcClient client, + SilcClientConnection conn, + SilcClientEntry client_entry, + char *hostname, + int port, + SilcKeyAgreementCallback completion, + void *context); + +/* This function can be called to unbind the hostname and the port for + the key agreement protocol. However, this function has effect only + before the key agreement protocol has been performed. After it has + been performed the library will automatically unbind the port. The + `client_entry' is the client to which we sent the key agreement + request. */ +void silc_client_abort_key_agreement(SilcClient client, + SilcClientConnection conn, + SilcClientEntry client_entry); #endif