updates.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 17 Feb 2002 09:28:17 +0000 (09:28 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 17 Feb 2002 09:28:17 +0000 (09:28 +0000)
14 files changed:
CHANGES
TODO
apps/silcd/protocol.c
includes/silcincludes.h
lib/silcclient/protocol.c
lib/silccrypt/pkcs1.c
lib/silcske/DIRECTORY
lib/silcske/Makefile.am
lib/silcske/payload.h [deleted file]
lib/silcske/silcske.c
lib/silcske/silcske.h
lib/silcske/silcske_groups.h [moved from lib/silcske/groups.h with 92% similarity]
lib/silcske/silcske_payload.h [new file with mode: 0644]
lib/silcske/silcske_status.h

diff --git a/CHANGES b/CHANGES
index c653e32e6acaefece9808ebbc0103059cd1b0382..21c698be99a5b130713d4c25bae1647dcfff53f8 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,14 @@
+Sun Feb 17 10:10:14 EET 2002  Pekka Riikonen <priikone@silcnet.org>
+
+       * ROBOdoc documented the lib/silcske/silcsftp.h, and improved
+         the SKE interface a bit.
+
+       * Fixed padding problem in PKCS#1. The padding was not actually
+         random since the random number generator was used incorrectly.
+         This security bug affects only when encrypting with PKCS#1, and
+         it is not currently used at all in SILC. SILC only use signing
+         with PKCS#1. Affected file lib/silccrypt/pkcs1.c.
+
 Sat Feb 16 13:44:24 EET 2002  Pekka Riikonen <priikone@silcnet.org>
 
        * Rewrote the notify handling in Irssi SILC client to not call
diff --git a/TODO b/TODO
index c8d44d4e1b356ebcff699e6aab9ea153d77b210a..c2c96454a661ecd68868f6fbf47f404d493b2f9b 100644 (file)
--- a/TODO
+++ b/TODO
@@ -45,10 +45,6 @@ TODO/bugs In SILC Server
 
        o Add rehashing support.
 
- o Assure that server is allowed to connect only once to router.  Meaning
-   if server connection is established already, same connection cannot be
-   established again.
-
  o If server send CUMODE_CHANGE notify (like setting founder) to router
    and router does not have founder on channel (founder is left or there's
    no founder on channel at all), the router will accept the server's
@@ -102,8 +98,8 @@ TODO in Toolkit Documentation
 Stuff that needs to be done in order to complete the Tooolkit Reference
 Manual.
 
- o Lots of ROBOdoc header formatting is undone in lib/silcske, 
-   lib/silcutil, and lib/silccrypt.
+ o Lots of ROBOdoc header formatting is undone in lib/silcutil, and 
+   lib/silccrypt.
 
  o Write "Programming with Toolkit" document, describing how to build
    Toolkit, how the build system works, where is everything, how
index 7e6b1631e3f96593e726a8b9e33c6bdb216013e7..d92b2c3e87d5050a5fc8d1d4e47780d626e42193 100644 (file)
@@ -457,9 +457,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
       SilcSKE ske;
 
       /* Allocate Key Exchange object */
-      ske = silc_ske_alloc();
-      ctx->ske = ske;
-      ske->rng = server->rng;
+      ctx->ske = ske = silc_ske_alloc(server->rng, server);
       
       silc_ske_set_callbacks(ske, silc_server_protocol_ke_send_packet, NULL,
                             silc_server_protocol_ke_verify_key,
@@ -514,8 +512,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
        */
       if (ctx->responder == TRUE) {
        /* Sends the selected security properties to the initiator. */
-       status = silc_ske_responder_phase_1(ctx->ske, 
-                                           ctx->ske->start_payload);
+       status = silc_ske_responder_phase_1(ctx->ske);
       } else {
        /* Call Phase-1 function. This processes the Key Exchange Start
           paylaod reply we just got from the responder. The callback
@@ -562,7 +559,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
           Key Exhange 1 Payload to the responder. */
        status = silc_ske_initiator_phase_2(ctx->ske,
                                            server->public_key,
-                                           server->private_key);
+                                           server->private_key,
+                                           SILC_SKE_PK_TYPE_SILC);
        protocol->state++;
       }
 
@@ -1382,8 +1380,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
            return;
          }
 
-         ctx->ske = silc_ske_alloc();
-         ctx->ske->rng = server->rng;
+         ctx->ske = silc_ske_alloc(server->rng, server);
          ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
          silc_ske_group_get_by_number(idata->rekey->ske_group,
                                       &ctx->ske->prop->group);
@@ -1438,8 +1435,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
           * Use Perfect Forward Secrecy, ie. negotiate the key material
           * using the SKE protocol.
           */
-         ctx->ske = silc_ske_alloc();
-         ctx->ske->rng = server->rng;
+         ctx->ske = silc_ske_alloc(server->rng, server);
          ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
          silc_ske_group_get_by_number(idata->rekey->ske_group,
                                       &ctx->ske->prop->group);
@@ -1449,7 +1445,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
                                 NULL, NULL, NULL, silc_ske_check_version,
                                 context);
       
-         status = silc_ske_initiator_phase_2(ctx->ske, NULL, NULL);
+         status = silc_ske_initiator_phase_2(ctx->ske, NULL, NULL, 0);
          if (status != SILC_SKE_STATUS_OK) {
            SILC_LOG_WARNING(("Error (%s) during Re-key (PFS)",
                              silc_ske_map_status(status)));
index fb68ce56c02f9bec916b242bcb876c5ae771fa53..4569bafef5b6a06dcea744b3720c8349c61180a1 100644 (file)
@@ -291,8 +291,8 @@ typedef uint32 * void *;
 
 /* SILC Key Exchange library includes */
 #include "silcske.h"
-#include "payload.h"
-#include "groups.h"
+#include "silcske_payload.h"
+#include "silcske_groups.h"
 
 /* SILC SFTP library */
 #include "silcsftp.h"
index 41daced5cab0a1e734df60b23af793ab2fad3e9c..3354f1d0b53f04cc98696b0734caf8d5a253b07a 100644 (file)
@@ -299,10 +299,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
       SilcSKE ske;
 
       /* Allocate Key Exchange object */
-      ske = silc_ske_alloc();
-      ctx->ske = ske;
-      ske->rng = client->rng;
-      ske->user_data = (void *)client;
+      ctx->ske = ske = silc_ske_alloc(client->rng, client);
 
       silc_ske_set_callbacks(ske, ctx->send_packet, NULL,
                             ctx->verify,
@@ -360,9 +357,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
        */
       if (ctx->responder == TRUE) {
        /* Sends the selected security properties to the initiator. */
-       status = 
-         silc_ske_responder_phase_1(ctx->ske, 
-                                    ctx->ske->start_payload);
+       status = silc_ske_responder_phase_1(ctx->ske);
       } else {
        /* Call Phase-1 function. This processes the Key Exchange Start
           paylaod reply we just got from the responder. The callback
@@ -405,7 +400,8 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
           Key Exhange 1 Payload to the responder. */
        status = silc_ske_initiator_phase_2(ctx->ske,
                                            client->public_key,
-                                           client->private_key);
+                                           client->private_key,
+                                           SILC_SKE_PK_TYPE_SILC);
        protocol->state++;
       }
 
@@ -922,8 +918,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
            silc_protocol_execute(protocol, client->schedule, 0, 300000);
          }
 
-         ctx->ske = silc_ske_alloc();
-         ctx->ske->rng = client->rng;
+         ctx->ske = silc_ske_alloc(client->rng, client);
          ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
          silc_ske_group_get_by_number(conn->rekey->ske_group,
                                       &ctx->ske->prop->group);
@@ -979,8 +974,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
           * Use Perfect Forward Secrecy, ie. negotiate the key material
           * using the SKE protocol.
           */
-         ctx->ske = silc_ske_alloc();
-         ctx->ske->rng = client->rng;
+         ctx->ske = silc_ske_alloc(client->rng, client);
          ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
          silc_ske_group_get_by_number(conn->rekey->ske_group,
                                       &ctx->ske->prop->group);
@@ -990,7 +984,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
                                 NULL,  NULL, NULL, silc_ske_check_version,
                                 context);
       
-         status =  silc_ske_initiator_phase_2(ctx->ske, NULL, NULL);
+         status =  silc_ske_initiator_phase_2(ctx->ske, NULL, NULL, 0);
          if (status != SILC_SKE_STATUS_OK) {
            SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
                              status));
index 970324a556dc604155f2ca2879ba76362c494ff3..b6a982ddad5527490fb58460ad93ee9063f9d6a0 100644 (file)
@@ -164,7 +164,7 @@ RSA_FormatOneBlock(uint32 modulusLen, RSA_BlockType blockType,
        for (i = 0; i < padLen; i++) {
            /* Pad with non-zero random data. */
            do {
-               silc_rng_global_get_byte(bp + i);
+             bp[i] = silc_rng_global_get_byte();
            } while (bp[i] == RSA_BLOCK_AFTER_PAD_OCTET);
        }
        bp += padLen;
index 9c65583e362ba8308eee9c59e25343bbd15adfb9..0fbae5476204b2afc868786f28b4523c8a43588a 100644 (file)
@@ -1,8 +1,10 @@
 <!--
 @LIBRARY=SILC Key Exchange Library
 @FILENAME=silcskelib.html
-@LINK=silcske.html:SILC SKE API
-@LINK=silcske_status.html:SILC SKE Status
+@LINK=silcske.html:SILC SKE Interface
+@LINK=silcske_status.html:SKE Status Types
+@LINK=silcske_groups.html:SKE Diffie Hellman Groups
+@LINK=silcske_payload.html:SKE Payloads
 -->
 
 <BIG><B>SILC Key Exchange Library</B></BIG>
index b233c42da5ccf4c94b80589315d98524e1f49462..f5d53f6d2dadb8d75e601afa5ac9e2c0a9840d6c 100644 (file)
@@ -26,11 +26,11 @@ libsilcske_a_SOURCES = \
         groups.c
 
 if SILC_DIST_TOOLKIT
-include_HEADERS =      \
-       groups.h        \
-       payload.h       \
-       silcske.h       \
-       silcske_status.h
+include_HEADERS =              \
+       silcske_groups.h        \
+       silcske_payload.h       \
+       silcske_status.h        \
+       silcske.h
 endif
 
 EXTRA_DIST = *.h
diff --git a/lib/silcske/payload.h b/lib/silcske/payload.h
deleted file mode 100644 (file)
index ba90004..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-
-  payload.h
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2000 - 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.
-  
-  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
-  GNU General Public License for more details.
-
-*/
-
-#ifndef PAYLOAD_H
-#define PAYLOAD_H
-
-#include "silcske_status.h"
-
-/* Forward declarations */
-typedef struct SilcSKEStartPayloadStruct SilcSKEStartPayload;
-typedef struct SilcSKEKEPayloadStruct SilcSKEKEPayload;
-
-/* SILC Key Exchange Start Payload */
-struct SilcSKEStartPayloadStruct {
-  unsigned char flags;
-  uint16 len;
-
-  unsigned char *cookie;
-  uint16 cookie_len;
-
-  unsigned char *version;
-  uint16 version_len;
-
-  uint16 ke_grp_len;
-  unsigned char *ke_grp_list;
-
-  uint16 pkcs_alg_len;
-  unsigned char *pkcs_alg_list;
-
-  uint16 enc_alg_len;
-  unsigned char *enc_alg_list;
-  
-  uint16 hash_alg_len;
-  unsigned char *hash_alg_list;
-
-  uint16 hmac_alg_len;
-  unsigned char *hmac_alg_list;
-
-  uint16 comp_alg_len;
-  unsigned char *comp_alg_list;
-};
-
-/* SILC Key Exchange Payload */
-struct SilcSKEKEPayloadStruct {
-  uint16 pk_len;
-  unsigned char *pk_data;
-  uint16 pk_type;
-
-  SilcMPInt x;
-
-  uint16 sign_len;
-  unsigned char *sign_data;
-};
-
-/* Prototypes */
-SilcSKEStatus silc_ske_payload_start_encode(SilcSKE ske,
-                                           SilcSKEStartPayload *payload,
-                                           SilcBuffer *return_buffer);
-SilcSKEStatus 
-silc_ske_payload_start_decode(SilcSKE ske,
-                             SilcBuffer buffer,
-                             SilcSKEStartPayload **return_payload);
-void silc_ske_payload_start_free(SilcSKEStartPayload *payload);
-SilcSKEStatus silc_ske_payload_ke_encode(SilcSKE ske,
-                                        SilcSKEKEPayload *payload,
-                                        SilcBuffer *return_buffer);
-SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske,
-                                        SilcBuffer buffer,
-                                        SilcSKEKEPayload **return_payload);
-void silc_ske_payload_ke_free(SilcSKEKEPayload *payload);
-
-#endif
index a5f7a6452043962de5d0861050a7e6e55223214f..cf26d0ee136b1034661f793f260474f87b27381f 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
-  silcske.c
+  silcske.c 
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2000 - 2001 Pekka Riikonen
+  Copyright (C) 2002 - 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
-  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 "silcske.h"
 #include "groups_internal.h"
 
+/* Static functions */
+static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n, 
+                                        uint32 len, 
+                                        SilcMPInt *rnd);
+static SilcSKEStatus silc_ske_make_hash(SilcSKE ske, 
+                                       unsigned char *return_hash,
+                                       uint32 *return_hash_len,
+                                       int initiator);
+
 /* Structure to hold all SKE callbacks. */
 struct SilcSKECallbacksStruct {
   SilcSKESendPacketCb send_packet;
@@ -35,7 +43,7 @@ struct SilcSKECallbacksStruct {
 
 /* Allocates new SKE object. */
 
-SilcSKE silc_ske_alloc()
+SilcSKE silc_ske_alloc(SilcRng rng, void *context)
 {
   SilcSKE ske;
 
@@ -43,6 +51,8 @@ SilcSKE silc_ske_alloc()
 
   ske = silc_calloc(1, sizeof(*ske));
   ske->status = SILC_SKE_STATUS_OK;
+  ske->rng = rng;
+  ske->user_data = context;
   ske->users = 1;
 
   return ske;
@@ -317,7 +327,8 @@ SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
 
 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
                                         SilcPublicKey public_key,
-                                        SilcPrivateKey private_key)
+                                        SilcPrivateKey private_key,
+                                        SilcSKEPKType pk_type)
 {
   SilcSKEStatus status = SILC_SKE_STATUS_OK;
   SilcBuffer payload_buf;
@@ -366,7 +377,7 @@ SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
     }
     payload->pk_len = pk_len;
   }
-  payload->pk_type = SILC_SKE_PK_TYPE_SILC;
+  payload->pk_type = pk_type;
 
   /* Compute signature data if we are doing mutual authentication */
   if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
@@ -533,7 +544,7 @@ static void silc_ske_initiator_finish_final(SilcSKE ske,
    public key, f, and signature. This function verifies the public key,
    computes the secret shared key and verifies the signature. 
 
-   The `callback' will be called to indicate that the caller may
+   The `proto_continue' will be called to indicate that the caller may
    continue with the SKE protocol.  The caller must not continue
    before the SKE libary has called that callback.  If this function
    returns an error the callback will not be called.  It is called
@@ -622,7 +633,7 @@ SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
 
 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
                                       SilcSocketConnection sock,
-                                      char *version,
+                                      const char *version,
                                       SilcBuffer start_payload,
                                       SilcSKESecurityPropertyFlag flags)
 {
@@ -690,8 +701,7 @@ SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
 /* The selected security properties from the initiator payload is now 
    encoded into Key Exchange Start Payload and sent to the initiator. */
 
-SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske, 
-                                        SilcSKEStartPayload *start_payload)
+SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske)
 {
   SilcSKEStatus status = SILC_SKE_STATUS_OK;
   SilcBuffer payload_buf;
@@ -703,39 +713,40 @@ SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske,
   /* Allocate security properties from the payload. These are allocated
      only for this negotiation and will be free'd after KE is over. */
   ske->prop = prop = silc_calloc(1, sizeof(*prop));
-  prop->flags = start_payload->flags;
-  status = silc_ske_group_get_by_name(start_payload->ke_grp_list, &group);
+  prop->flags = ske->start_payload->flags;
+  status = silc_ske_group_get_by_name(ske->start_payload->ke_grp_list, &group);
   if (status != SILC_SKE_STATUS_OK)
     goto err;
 
   prop->group = group;
 
-  if (silc_pkcs_alloc(start_payload->pkcs_alg_list, 
+  if (silc_pkcs_alloc(ske->start_payload->pkcs_alg_list, 
                      &prop->pkcs) == FALSE) {
     status = SILC_SKE_STATUS_UNKNOWN_PKCS;
     goto err;
   }
 
-  if (silc_cipher_alloc(start_payload->enc_alg_list, 
+  if (silc_cipher_alloc(ske->start_payload->enc_alg_list, 
                        &prop->cipher) == FALSE) {
     status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
     goto err;
   }
 
-  if (silc_hash_alloc(start_payload->hash_alg_list,
+  if (silc_hash_alloc(ske->start_payload->hash_alg_list,
                      &prop->hash) == FALSE) {
     status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
     goto err;
   }
 
-  if (silc_hmac_alloc(start_payload->hmac_alg_list, NULL,
+  if (silc_hmac_alloc(ske->start_payload->hmac_alg_list, NULL,
                      &prop->hmac) == FALSE) {
     status = SILC_SKE_STATUS_UNKNOWN_HMAC;
     goto err;
   }
 
   /* Encode the payload */
-  status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
+  status = silc_ske_payload_start_encode(ske, ske->start_payload, 
+                                        &payload_buf);
   if (status != SILC_SKE_STATUS_OK)
     goto err;
 
@@ -895,7 +906,7 @@ static void silc_ske_responder_phase2_final(SilcSKE ske,
    and computes f = g ^ x mod p. This then puts the result f to a Key
    Exchange Payload. 
 
-   The `callback' will be called to indicate that the caller may
+   The `proto_continue' will be called to indicate that the caller may
    continue with the SKE protocol.  The caller must not continue
    before the SKE libary has called that callback.  If this function
    returns an error the callback will not be called.  It is called
@@ -1114,7 +1125,7 @@ SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
 SilcSKEStatus 
 silc_ske_assemble_security_properties(SilcSKE ske,
                                      SilcSKESecurityPropertyFlag flags,
-                                     char *version,
+                                     const char *version,
                                      SilcSKEStartPayload **return_payload)
 {
   SilcSKEStartPayload *rp;
@@ -1125,7 +1136,7 @@ silc_ske_assemble_security_properties(SilcSKE ske,
   rp = silc_calloc(1, sizeof(*rp));
 
   /* Set flags */
-  rp->flags = flags;
+  rp->flags = (unsigned char)flags;
 
   /* Set random cookie */
   rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
@@ -1178,7 +1189,7 @@ silc_ske_assemble_security_properties(SilcSKE ske,
 
 SilcSKEStatus 
 silc_ske_select_security_properties(SilcSKE ske,
-                                   char *version,
+                                   const char *version,
                                    SilcSKEStartPayload *payload,
                                    SilcSKEStartPayload *remote_payload)
 {
@@ -1541,9 +1552,9 @@ silc_ske_select_security_properties(SilcSKE ske,
 /* Creates random number such that 1 < rnd < n and at most length
    of len bits. The rnd sent as argument must be initialized. */
 
-SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n, 
-                                 uint32 len, 
-                                 SilcMPInt *rnd)
+static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n, 
+                                        uint32 len, 
+                                        SilcMPInt *rnd)
 {
   SilcSKEStatus status = SILC_SKE_STATUS_OK;
   unsigned char *string;
@@ -1577,10 +1588,10 @@ SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
    hash value defined in the protocol. If it is FALSE then this is used
    to create the HASH value defined by the protocol. */
 
-SilcSKEStatus silc_ske_make_hash(SilcSKE ske, 
-                                unsigned char *return_hash,
-                                uint32 *return_hash_len,
-                                int initiator)
+static SilcSKEStatus silc_ske_make_hash(SilcSKE ske, 
+                                       unsigned char *return_hash,
+                                       uint32 *return_hash_len,
+                                       int initiator)
 {
   SilcSKEStatus status = SILC_SKE_STATUS_OK;
   SilcBuffer buf;
index 60de4114bab73684df6a3db17d98d8130650753b..2690405c2d1b95c448a0561c71608ae551b0756c 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
-  silcske.h
+  silcske.h 
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2000 - 2001 Pekka Riikonen
+  Copyright (C) 2000 - 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
-  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 SILCSKE_H
 #define SILCSKE_H
 
+/****h* silcske/SilcSKEAPI
+ *
+ * DESCRIPTION
+ *
+ * Implementation of the SILC Key Exchange Protocol (SKE). The SKE protocol
+ * is used to negotiate secret key material between two parties, to be used
+ * as session key or some other key. For example, when client connects to
+ * server SKE is performed to exchange public keys, and to generate the key
+ * that is then used as session key. Two clients can execute SKE as well
+ * two create secret key material for securing for example file transfer
+ * stream.
+ *
+ * SKE is based on Diffie-Hellman, and it derives its functionality from
+ * SSH2 Key Exchange protocol, OAKLEY Key Determination protocol and
+ * Station-To-Station (STS) protocols.
+ *
+ * This SKE implementation provides easy interface for application
+ * that wants to use SKE. In fact, the interface is designed to be 
+ * application independent, and does not expect that the application using
+ * SKE would actually relate in any way to SILC. Hence, the interface
+ * can be used in any kind of application needing to perform key exchange
+ * protocol with two parties. The network connection is also handled
+ * outside the SKE interface. For the interface application must provide
+ * a packet sending function which SKE library can call when it wants
+ * to send packet to the remote host. The actual network connection
+ * therefore is handled in the application and not by the SKE library.
+ *
+ * The protocol has initiator and responder. The initiator is the one
+ * that starts the protocol, and the responder is the one that receives
+ * negotiation request. The protocol has phases, and the interface is
+ * split into several phases that the application may call when
+ * needed. Heavy operations has been splitted so that application may
+ * call next phase with a timeout to give processing times to other
+ * things in the application. On the other hand, if application does
+ * not care about this it may call the phases immediately without any
+ * timeout.
+ *
+ ***/
+
 #include "silcske_status.h"
 
-/* Forward declaration for SKE object. */
+/****s* silcske/SilcSKEAPI/SilcSKE
+ *
+ * NAME
+ * 
+ *    typedef struct SilcSKEStruct *SilcSKE;
+ *
+ * DESCRIPTION
+ *
+ *    This context is forward declaration for the SilcSKEStruct.
+ *    This is allocated by the silc_ske_alloc and freed by the
+ *    silc_ske_free function. This context represents the SKE session.
+ *
+ ***/
 typedef struct SilcSKEStruct *SilcSKE;
 
-/* Forward declaration for security properties. */
+/****s* silcske/SilcSKEAPI/SilcSKESecurityProperties
+ *
+ * NAME
+ * 
+ *    typedef struct SilcSKESecurityPropertiesStruct 
+ *                                 *SilcSKESecurityProperties;
+ *
+ * DESCRIPTION
+ *
+ *    This context is forward declaration for the 
+ *    SilcSKESecurityPropertiesStruct structure. It is allocated by the
+ *    library, and it represents the security properties selected during
+ *    the SKE negotiation.
+ *
+ ***/
 typedef struct SilcSKESecurityPropertiesStruct *SilcSKESecurityProperties;
 
-/* Forward declaration for SKE callbacks structure. */
+/* Forward declaration for SKE callbacks structure, which is internal. */
 typedef struct SilcSKECallbacksStruct *SilcSKECallbacks;
 
-/* Supported Public Key Types, defined by the protocol */
+/****d* silcske/SilcSKEAPI/SilcSKEPKType
+ *
+ * NAME
+ * 
+ *    typedef enum { ... } SilcSKEPKType;
+ *
+ * DESCRIPTION
+ *
+ *    Public key and certificate types defined by the SKE protocol.
+ *
+ * SOURCE
+ */
 typedef enum {
   SILC_SKE_PK_TYPE_SILC    = 1,        /* Mandatory type */
   /* Optional types. These are not implemented currently */
@@ -41,40 +116,90 @@ typedef enum {
   SILC_SKE_PK_TYPE_OPENPGP = 4,
   SILC_SKE_PK_TYPE_SPKI    = 5
 } SilcSKEPKType;
-
-/* Packet sending callback. Caller of the SKE routines must provide
-   a routine to send packets to negotiation parties. See the
-   silc_ske_set_callbacks for more information. */
+/***/
+
+/****f* silcske/SilcSKEAPI/SilcSKESendPacketCb
+ *
+ * SYNOPSIS
+ *
+ *    typedef void (*SilcSKESendPacketCb)(SilcSKE ske, SilcBuffer packet, 
+ *                                        SilcPacketType type, void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Packet sending callback. Caller of the SKE routines must provide
+ *    a routine to send packets to negotiation parties. See the
+ *    silc_ske_set_callbacks for more information.
+ *
+ ***/
 typedef void (*SilcSKESendPacketCb)(SilcSKE ske, SilcBuffer packet, 
                                    SilcPacketType type, void *context);
 
-/* Generic SKE callback function. This is called in various SKE
-   routines. The SilcSKE object sent as argument provides all the data
-   callers routine might need (payloads etc). This is usually called
-   to indicate that the application may continue the execution of the
-   SKE protocol. The application should check the ske->status in this
-   callback function. This callback is also called when Start Payload
-   is processed. See silc_ske_set_callbacks function for more information. */
+/****f* silcske/SilcSKEAPI/SilcSKECb
+ *
+ * SYNOPSIS
+ *
+ *    typedef void (*SilcSKECb)(SilcSKE ske, void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Generic SKE callback function. This is called in various SKE
+ *    routines. The SilcSKE object sent as argument provides all the data
+ *    callers routine might need (payloads etc). This is usually called
+ *    to indicate that the application may continue the execution of the
+ *    SKE protocol. The application should check the ske->status in this
+ *    callback function. This callback is also called when Start Payload
+ *    is processed. See silc_ske_set_callbacks function for more information.
+ *
+ ***/
 typedef void (*SilcSKECb)(SilcSKE ske, void *context);
 
-/* Completion callback that will be called when the public key
-   has been verified.  The `status' will indicate whether the public
-   key were trusted or not. If the `status' is PENDING then the status
-   is not considered to be available at this moment. In this case the
-   SKE libary will assume that the caller will call this callback again
-   when the status is available. See silc_ske_set_callbacks for more
-   information. */
+/****f* silcske/SilcSKEAPI/SilcSKEVerifyCbCompletion
+ *
+ * SYNOPSIS
+ *
+ *    typedef void (*SilcSKEVerifyCbCompletion)(SilcSKE ske,
+ *                                              SilcSKEStatus status,
+ *                                              void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Completion callback that will be called when the public key
+ *    has been verified.  The `status' will indicate whether the public
+ *    key were trusted or not. If the `status' is PENDING then the status
+ *    is not considered to be available at this moment. In this case the
+ *    SKE libary will assume that the caller will call this callback again
+ *    when the status is available. See silc_ske_set_callbacks for more
+ *    information.
+ *
+ ***/
 typedef void (*SilcSKEVerifyCbCompletion)(SilcSKE ske,
                                          SilcSKEStatus status,
                                          void *context);
 
-/* Callback function used to verify the received public key or certificate. 
-   The verification process is most likely asynchronous. That's why the
-   application must call the `completion' callback when the verification
-   process has been completed. The library then calls the user callback
-   (SilcSKECb), if it was provided for the function that takes this callback
-   function as argument, to indicate that the SKE protocol may continue. 
-   See silc_ske_set_callbacks for more information. */
+/****f* silcske/SilcSKEAPI/SilcSKEVerifyCb
+ *
+ * SYNOPSIS
+ *
+ *    typedef void (*SilcSKEVerifyCb)(SilcSKE ske, 
+ *                                    unsigned char *pk_data,
+ *                                    uint32 pk_len,
+ *                                    SilcSKEPKType pk_type,
+ *                                    void *context,
+ *                                    SilcSKEVerifyCbCompletion completion,
+ *                                    void *completion_context);
+ *
+ * DESCRIPTION
+ *
+ *    Callback function used to verify the received public key or certificate. 
+ *    The verification process is most likely asynchronous. That's why the
+ *    application must call the `completion' callback when the verification
+ *    process has been completed. The library then calls the user callback
+ *    (SilcSKECb), if it was provided for the function that takes this callback
+ *    function as argument, to indicate that the SKE protocol may continue. 
+ *    See silc_ske_set_callbacks for more information.
+ *
+ ***/
 typedef void (*SilcSKEVerifyCb)(SilcSKE ske, 
                                unsigned char *pk_data,
                                uint32 pk_len,
@@ -83,17 +208,40 @@ typedef void (*SilcSKEVerifyCb)(SilcSKE ske,
                                SilcSKEVerifyCbCompletion completion,
                                void *completion_context);
 
-/* Callback function used to check the version of the remote SKE server.
-   The SKE library will call this function so that the appliation may
-   check its version against the remote host's version. This returns
-   SILC_SKE_STATUS_OK if the version string is Ok, and returns
-   SILC_SKE_STATUS_BAD_VERSION if the version was not acceptable. */
+/****f* silcske/SilcSKEAPI/SilcSKECheckVersion
+ *
+ * SYNOPSIS
+ *
+ *    typedef SilcSKEStatus (*SilcSKECheckVersion)(SilcSKE ske, 
+ *                                                 unsigned char *version, 
+ *                                                 uint32 len, void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Callback function used to check the version of the remote SKE server.
+ *    The SKE library will call this function so that the appliation may
+ *    check its version against the remote host's version. This returns
+ *    SILC_SKE_STATUS_OK if the version string is Ok, and returns
+ *    SILC_SKE_STATUS_BAD_VERSION if the version was not acceptable.
+ *
+ ***/
 typedef SilcSKEStatus (*SilcSKECheckVersion)(SilcSKE ske, 
                                             unsigned char *version, 
                                             uint32 len, void *context);
 
-/* Context passed to key material processing function. The function
-   returns the processed key material into this structure. */
+/****s* silcske/SilcSKEAPI/SilcSKEKeyMaterial
+ *
+ * NAME
+ * 
+ *    typedef struct { ... } SilcSKEKeyMaterial;
+ *
+ * DESCRIPTION
+ *
+ *    This is the key material structure, and is passed as argument by the
+ *    application to silc_ske_process_key_material* functions. It includes
+ *    the processed key material which can be used as SILC session keys.
+ *
+ ***/
 typedef struct {
   unsigned char *send_iv;
   unsigned char *receive_iv;
@@ -109,31 +257,72 @@ typedef struct {
 /* Length of cookie in Start Payload */
 #define SILC_SKE_COOKIE_LEN 16
 
-#include "groups.h"
-#include "payload.h"
-
-/* Security Property Flags. */
+#include "silcske_groups.h"
+#include "silcske_payload.h"
+
+/****d* silcske/SilcSKEAPI/SilcSKESecurityPropertyFlag
+ *
+ * NAME
+ * 
+ *    typedef enum { ... } SilcSKESecurityPropertyFlag
+ *
+ * DESCRIPTION
+ *
+ *    SKE security property flags as defined by the SK protocol.
+ *
+ * SOURCE
+ */
 typedef enum {
-  SILC_SKE_SP_FLAG_NONE      = 0x00,
-  SILC_SKE_SP_FLAG_NO_REPLY  = 0x01,
-  SILC_SKE_SP_FLAG_PFS       = 0x02,
-  SILC_SKE_SP_FLAG_MUTUAL    = 0x04,
+  SILC_SKE_SP_FLAG_NONE      = 0x00,     /* No flags */
+  SILC_SKE_SP_FLAG_NO_REPLY  = 0x01,    /* No reply required to payload */
+  SILC_SKE_SP_FLAG_PFS       = 0x02,    /* Perfect Forward Secrecy */
+  SILC_SKE_SP_FLAG_MUTUAL    = 0x04,    /* Mutual authentication */
 } SilcSKESecurityPropertyFlag;
-
-/* Security Properties negotiated between key exchange parties. This
-   structure is filled from the Key Exchange Start Payload which is used
-   to negotiate what security properties should be used in the
-   communication. */
+/***/
+
+/****s* silcske/SilcSKEAPI/SilcSKESecurityPropertiesStruct
+ *
+ * NAME
+ * 
+ *    struct SilcSKESecurityPropertiesStruct { ... };
+ *
+ * DESCRIPTION
+ *
+ *    Security Properties negotiated between key exchange parties. This
+ *    structure is filled from the Key Exchange Start Payload which is used
+ *    to negotiate what security properties should be used in the
+ *    communication.
+ *
+ * SOURCE
+ */
 struct SilcSKESecurityPropertiesStruct {
-  SilcSKESecurityPropertyFlag flags;
-  SilcSKEDiffieHellmanGroup group;
-  SilcPKCS pkcs;
-  SilcCipher cipher;
-  SilcHash hash;
-  SilcHmac hmac;
-  /* XXX SilcZip comp; */
+  SilcSKESecurityPropertyFlag flags;    /* Flags */
+  SilcSKEDiffieHellmanGroup group;      /* Selected Diffie Hellman group */
+  SilcPKCS pkcs;                        /* Selected PKCS algorithm */
+  SilcCipher cipher;                    /* Selected cipher */
+  SilcHash hash;                        /* Selected hash algorithm */
+  SilcHmac hmac;                        /* Selected HMAC */
 };
-
+/***/
+
+/****s* silcske/SilcSKEAPI/SilcSKEStruct
+ *
+ * NAME
+ * 
+ *    struct SilcSKEStruct { ... };
+ *
+ * DESCRIPTION
+ *
+ *    This structure is the SKE session context, and has a type definition
+ *    to SilcSKE. The structure includes the network connection socket,
+ *    securit properties collected during the SKE negotiation, payloads
+ *    sent and received during the negotiation, and the actual raw key
+ *    material too. The application usually does not need to reference
+ *    to the inside of this structure.  However, checking the current
+ *    status of the session can easily be checked with ske->status.
+ *
+ * SOURCE
+ */
 struct SilcSKEStruct {
   /* The connection object. This is initialized by the caller. */
   SilcSocketConnection sock;
@@ -183,10 +372,96 @@ struct SilcSKEStruct {
   /* Backwards support version indicator */
   uint32 backward_version;
 };
+/***/
 
 /* Prototypes */
-SilcSKE silc_ske_alloc();
+
+/****f* silcske/SilcSKEAPI/silc_ske_alloc
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKE silc_ske_alloc(SilcRng rng, void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Allocates the SKE session context and returns it.  The `rng' is
+ *    the random number generator the SKE is going to use when it needs
+ *    random number generation during the SKE session.  The `context' is
+ *    user context that the libary will not touch.  The application can
+ *    access that context with the ske->user_context if needed.  The
+ *    application is responsible of freeing the `context'.  After the
+ *    SKE session context is allocated application must call the
+ *    silc_ske_set_callbacks.
+ *
+ ***/
+SilcSKE silc_ske_alloc(SilcRng rng, void *context);
+
+/****f* silcske/SilcSKEAPI/silc_ske_free
+ *
+ * SYNOPSIS
+ *
+ *    void silc_ske_free(SilcSKE ske);
+ *
+ * DESCRIPTION
+ *
+ *    Frees the SKE session context and all allocated resources.
+ *
+ ***/
 void silc_ske_free(SilcSKE ske);
+
+/****f* silcske/SilcSKEAPI/silc_ske_set_callbacks
+ *
+ * SYNOPSIS
+ *
+ *    void silc_ske_set_callbacks(SilcSKE ske,
+ *                                SilcSKESendPacketCb send_packet,
+ *                                SilcSKECb payload_receive,
+ *                                SilcSKEVerifyCb verify_key,
+ *                                SilcSKECb proto_continue,
+ *                                SilcSKECheckVersion check_version,
+ *                                void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Sets the callback functions for the SKE session. 
+ *
+ *    The `send_packet' callback is a function that sends the packet to
+ *    network. The SKE library will call it at any time packet needs to
+ *    be sent to the remote host. 
+ *
+ *    The `payload_receive' callback is called when the remote host's Key
+ *    Exchange Start Payload has been processed.  The payload is saved
+ *    to ske->start_payload if the application would need it.  The application
+ *    must also provide the payload to the next state of the SKE.
+ *
+ *    The `verify_key' callback is called to verify the received public key
+ *    or certificate.  The verification process is most likely asynchronous.
+ *    That is why the application must call the completion callback when the
+ *    verification process has been completed. The library then calls the user
+ *    callback (`proto_continue'), if it is provided to indicate that the SKE
+ *    protocol may continue. If this SKE session context is used to perform
+ *    rekey, this callback usually is not provided as argument since sending
+ *    public key in rekey is not mandatory. Setting this callback implies
+ *    that remote end MUST send its public key, and this could cause
+ *    problems when performing rekey. When doing normal SKE session this
+ *    callback should be set.
+ *  
+ *    The `proto_continue' callback is called to indicate that it is
+ *    safe to continue the execution of the SKE protocol after executing
+ *    an asynchronous operation, such as calling the `verify_key' callback
+ *    function, which is asynchronous. The application should check the
+ *    ske->status in this function to check whether it is Ok to continue
+ *    the execution of the protocol.
+ *
+ *    The `check_version' callback is called to verify the remote host's
+ *    version. The application may check its own version against the remote
+ *    host's version and determine whether supporting the remote host
+ *    is possible. 
+ *
+ *    The `context' is passed as argument to all of the above callback
+ *    functions.
+ *
+ ***/
 void silc_ske_set_callbacks(SilcSKE ske,
                            SilcSKESendPacketCb send_packet,
                            SilcSKECb payload_receive,
@@ -194,48 +469,407 @@ void silc_ske_set_callbacks(SilcSKE ske,
                            SilcSKECb proto_continue,
                            SilcSKECheckVersion check_version,
                            void *context);
+
+/****f* silcske/SilcSKEAPI/silc_ske_initiator_start
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
+ *                                           SilcSocketConnection sock,
+ *                                           SilcSKEStartPayload 
+ *                                              *start_payload);
+ *
+ * DESCRIPTION
+ *
+ *    Starts the SILC Key Exchange protocol for initiator. The connection
+ *    to the responder end must be established before calling this function
+ *    and the connecting socket must be sent as argument. This function
+ *    creates the Key Exchange Start Payload which includes all our
+ *    configured security properties. This payload is then sent to the
+ *    responder end for further processing. This payload must be sent as
+ *    argument to the function, however, it must not be encoded
+ *    already, it is done by this function. The caller must not free
+ *    the `start_payload' since the SKE library will save it.
+ *
+ *    Before calling this function application calls the
+ *    silc_ske_assemble_security_properties which returns the `start_payload'
+ *    which application must provide for this function.
+ *
+ *    After calling this function the application must wait for reply
+ *    from the responder.
+ *
+ ***/
 SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
                                       SilcSocketConnection sock,
                                       SilcSKEStartPayload *start_payload);
+
+/****f* silcske/SilcSKEAPI/silc_ske_initiator_phase_1
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske, 
+ *                                             SilcBuffer start_payload);
+ *
+ * DESCRIPTION
+ *
+ *    Function called after ske_initiator_start fuction. This receives
+ *    the responder's Key Exchange Start payload which includes the
+ *    security properties selected by the responder from our payload
+ *    sent in the silc_ske_initiator_start function. The `start_payload'
+ *    is the received payload and the application must send it as argument.
+ *
+ *    After calling this function the application must call immediately,
+ *    or with short timeout, the silc_ske_initiator_phase_2 function.
+ *
+ ***/
 SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske, 
                                         SilcBuffer start_payload);
+
+/****f* silcske/SilcSKEAPI/silc_ske_initiator_phase_1
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
+ *                                             SilcPublicKey public_key,
+ *                                             SilcPrivateKey private_key,
+ *                                             SilcSKEPKType pk_type)
+ *
+ * DESCRIPTION
+ *
+ *    This function continues the SKE session after the initiator has
+ *    called the silc_ske_initiator_phase_1.  After that function returns
+ *    the application should call immediately, or with short timeout, this
+ *    function which will continue with the session, and sends next phase
+ *    packet to the responder.  The caller must provide the caller's
+ *    public key and private key as argument, since the public key is
+ *    sent to the responder, and the private key is be used to generate
+ *    digital signature.
+ *
+ *    After this function the application must wait for reply from the
+ *    responder.
+ *
+ ***/
 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
                                         SilcPublicKey public_key,
-                                        SilcPrivateKey private_key);
+                                        SilcPrivateKey private_key,
+                                        SilcSKEPKType pk_type);
+
+/****f* silcske/SilcSKEAPI/silc_ske_initiator_finish
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
+ *                                            SilcBuffer ke_payload);
+ *
+ * DESCRIPTION
+ *
+ *    Receives the reply from the responder and processes it.  The
+ *    `ke_payload' is the reply and application must provide it as argument.
+ *    This function will verify the responder's public key, by calling
+ *    the `verify_key' callback that was set with silc_ske_set_callbacks
+ *    function.
+ *
+ *    If this function returns error, no callbacks will be called. If
+ *    this function needs to verify remote end's public key, this will
+ *    return SILC_SKE_STATUS_PENDING, which indicates application that
+ *    SKE is performing asynchronous operation and is in pending status.
+ *    When in this status application must not continue with calling
+ *    any other SKE routine. The asynchronous operation is the `verify_key'
+ *    callback, which application completes by calling its completion
+ *    callback. After completion the SKE libary will call the 
+ *    `proto_continue' callback, to indicate application that pending
+ *    status is over and it is safe to continue the execution of SKE,
+ *    which application does by calling the silc_ske_end function.
+ *
+ *    If this function returns SILC_SKE_STATUS_OK, it will not call the
+ *    `verify_key' callback, however, it will or has already called the
+ *    `proto_continue' callback.
+ *
+ *    Application must not continue execution of the SKE before library
+ *    has called the `proto_continue' callback.  After it is called
+ *    the application finishes SKE session by calling silc_ske_end
+ *    function.
+ *
+ ***/
 SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
                                        SilcBuffer ke_payload);
+
+/****f* silcske/SilcSKEAPI/silc_ske_responder_start
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
+ *                                           SilcSocketConnection sock,
+ *                                           const char *version,
+ *                                           SilcBuffer start_payload,
+ *                                           SilcSKESecurityPropertyFlag 
+ *                                                               flags);
+ *
+ * DESCRIPTION
+ *
+ *    Starts Key Exchange protocol for responder. The application has
+ *    received initiator's first packet from network and it must provide
+ *    it as `start_payload' argument to this function. The function 
+ *    processes the packet and makes security property selection from
+ *    the initiator's proposal. The `version' is the responder's version
+ *    that will be sent in reply to the initiator. The `flags' indicates
+ *    SilcSKESecurityPropertyFlag flags that responder enforces for the
+ *    initiator. Responder may, for example, enforce that the PFS
+ *    will be performed in rekey. This example can be done by providing
+ *    SILC_SKE_SP_FLAG_PFS as `flags'. The `flags' is a bit mask of
+ *    enforced flags.
+ *
+ *    After this function the responder calls immediately, or with short
+ *    timeout the silc_ske_responder_phase_1 function.
+ *
+ ***/
 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
                                       SilcSocketConnection sock,
-                                      char *version,
+                                      const char *version,
                                       SilcBuffer start_payload,
                                       SilcSKESecurityPropertyFlag flags);
-SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske, 
-                                        SilcSKEStartPayload *start_payload);
+
+/****f* silcske/SilcSKEAPI/silc_ske_responder_phase_1
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske);
+ *
+ * DESCRIPTION
+ *
+ *    This function is called after the silc_ske_responder_start, and
+ *    is used to send our reply to the initiator.  This function is
+ *    called either immediately, or with short timeout, after the
+ *    silc_ske_responder_start function returned.
+ *
+ *    After this function the responder must wait for reply from the
+ *    initiator.
+ *
+ ***/
+SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske);
+
+/****f* silcske/SilcSKEAPI/silc_ske_responder_phase_2
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
+ *                                             SilcBuffer ke_payload);
+ *
+ * DESCRIPTION
+ *
+ *    Receives the reply from the initiator and procedses it.  The
+ *    `ke_payload' is the reply and application must provide it as argument.
+ *    This function will verify the remote host's public key, by calling
+ *    the `verify_key' callback that was set with silc_ske_set_callbacks
+ *    function.
+ *
+ *    If this function returns error, no callbacks will be called. If
+ *    this function needs to verify remote end's public key, this will
+ *    return SILC_SKE_STATUS_PENDING, which indicates application that
+ *    SKE is performing asynchronous operation and is in pending status.
+ *    When in this status application must not continue with calling
+ *    any other SKE routine. The asynchronous operation is the `verify_key'
+ *    callback, which application completes by calling its completion
+ *    callback. After completion the SKE libary will call the 
+ *    `proto_continue' callback, to indicate application that pending
+ *    status is over and it is safe to continue the execution of SKE,
+ *    which application does by calling the silc_ske_responder_finish
+ *    function.
+ *
+ *    If this function returns SILC_SKE_STATUS_OK, it will not call the
+ *    `verify_key' callback, however, it will or has already called the
+ *    `proto_continue' callback.
+ *
+ *    Application must not continue execution of the SKE before library
+ *    has called the `proto_continue' callback.  After it is called
+ *    the application calls the silc_ske_responder_finish function.
+ *
+ ***/
 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
                                         SilcBuffer ke_payload);
+
+/****f* silcske/SilcSKEAPI/silc_ske_responder_finish
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
+ *                                            SilcPublicKey public_key,
+ *                                            SilcPrivateKey private_key,
+ *                                            SilcSKEPKType pk_type);
+ *
+ * DESCRIPTION
+ *
+ *    This function finishes the responder's SKE session, and this function
+ *    is called either immediately, or with short timeout, after the
+ *    silc_ske_responder_phase_2 returned. This will send our reply to
+ *    the initiator.  The caller must provide the caller's public key and
+ *    private key as argument, since the public key is sent to the responder,
+ *    and the private key is be used to generate digital signature.
+ *
+ *    After this function the application must wait for the end indication
+ *    from the intiator, and when it is received the silc_ske_end is called.
+ *
+ ***/
 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
                                        SilcPublicKey public_key,
                                        SilcPrivateKey private_key,
                                        SilcSKEPKType pk_type);
+
+/****f* silcske/SilcSKEAPI/silc_ske_end
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus silc_ske_end(SilcSKE ske);
+ *
+ * DESCRIPTION
+ *
+ *    The Key Exchange protocol is ended by calling this function. This
+ *    must not be called until the keys are processed by calling the
+ *    silc_ske_process_key_material function. The protocol prohibits
+ *    calling this function before key material is processed properly.
+ *
+ *    This function is for both initiator and responder. After calling
+ *    this function initiator must wait for end indication from the
+ *    responder. After that the silc_ske_free may be called. The responder
+ *    calls this function after it has received the intiator's end
+ *    indication.
+ *
+ * NOTES
+ *
+ *    Initiator must not start using the negotiated key material before
+ *    calling this function or before remote end has sent its end
+ *    indication. Only after that the key material may be taken in use.
+ *
+ ***/
 SilcSKEStatus silc_ske_end(SilcSKE ske);
+
+/****f* silcske/SilcSKEAPI/silc_ske_abort
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status);
+ *
+ * DESCRIPTION
+ *
+ *    Aborts the Key Exchange protocol. This is called if error occurs
+ *    while performing the protocol. The status argument is the error
+ *    status and it is sent to the remote end.
+ *
+ ***/
 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status);
+
+/****f* silcske/SilcSKEAPI/silc_ske_assemble_security_properties
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus 
+ *    silc_ske_assemble_security_properties(SilcSKE ske,
+ *                                          SilcSKESecurityPropertyFlag flags,
+ *                                          const char *version,
+ *                                          SilcSKEStartPayload 
+ *                                            **return_payload);
+ *
+ * DESCRIPTION
+ *
+ *    Assembles security properties to Key Exchange Start Payload to be
+ *    sent to the remote end. This checks system wide (SILC system, that is)
+ *    settings and chooses from those. However, if other properties
+ *    should be used this function is easy to replace by another function,
+ *    as, this function is called by the caller of the library and not
+ *    by the SKE library itself. The assembled payload is returned into
+ *    the `return_payload' pointer.
+ *
+ ***/
 SilcSKEStatus 
 silc_ske_assemble_security_properties(SilcSKE ske,
                                      SilcSKESecurityPropertyFlag flags,
-                                     char *version,
+                                     const char *version,
                                      SilcSKEStartPayload **return_payload);
+
+/****f* silcske/SilcSKEAPI/silc_ske_select_security_properties
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus 
+ *    silc_ske_select_security_properties(SilcSKE ske,
+ *                                        const char *version,
+ *                                        SilcSKEStartPayload *payload,
+ *                                        SilcSKEStartPayload *remote_payload);
+ *
+ * DESCRIPTION
+ *
+ *    Parses the Key Exchange Start Payload indicated by `remote_payload',
+ *    and selects the security properties properties from it, and puts the
+ *    selection into the `payload'. This always attempts to select the
+ *    best security properties from the payload, and it always selects
+ *    one of each kind of security property, as this is dictated by the
+ *    protocol. The `version' is our version, that we will put to the
+ *    `payload', since the `payload' is usually sent to the remote end.
+ *    the `check_version' callback will be called in this function so
+ *    that application can do version check with the remote end.
+ *
+ ***/
 SilcSKEStatus 
 silc_ske_select_security_properties(SilcSKE ske,
-                                   char *version,
+                                   const char *version,
                                    SilcSKEStartPayload *payload,
                                    SilcSKEStartPayload *remote_payload);
-SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n, 
-                                 uint32 len, 
-                                 SilcMPInt *rnd);
-SilcSKEStatus silc_ske_make_hash(SilcSKE ske, 
-                                unsigned char *return_hash,
-                                uint32 *return_hash_len,
-                                int initiator);
+
+/****f* silcske/SilcSKEAPI/silc_ske_process_key_material
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus silc_ske_process_key_material(SilcSKE ske, 
+ *                                                uint32 req_iv_len,
+ *                                                uint32 req_enc_key_len,
+ *                                                uint32 req_hmac_key_len,
+ *                                                SilcSKEKeyMaterial *key);
+ *
+ * DESCRIPTION
+ *
+ *    This function is used by the application to process the key material
+ *    negotiated with the SKE session, to actually produce the keys that
+ *    is to be used in SILC protocol. The key processing is defined by the
+ *    protocol. The `req_iv_len', `req_enc_key_len' and `req_hmac_key_len'
+ *    are the request IV length, requested encryption/decrypt key length,
+ *    and requested HMAC key length, respectively, and  they cannot be
+ *    zero (0). They tell the function how long the keys should be, and
+ *    it will produce the requested length keys for the application.
+ *    The key material is returned in to the `key', which the caller must
+ *    free.
+ *
+ ***/
+SilcSKEStatus silc_ske_process_key_material(SilcSKE ske, 
+                                           uint32 req_iv_len,
+                                           uint32 req_enc_key_len,
+                                           uint32 req_hmac_key_len,
+                                           SilcSKEKeyMaterial *key);
+
+/****f* silcske/SilcSKEAPI/silc_ske_process_key_material_data
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus 
+ *    silc_ske_process_key_material_data(unsigned char *data,
+ *                                       uint32 data_len,
+ *                                       uint32 req_iv_len,
+ *                                       uint32 req_enc_key_len,
+ *                                       uint32 req_hmac_key_len,
+ *                                       SilcHash hash,
+ *                                       SilcSKEKeyMaterial *key);
+ *
+ * DESCRIPTION
+ *
+ *    This function is equivalent to silc_ske_process_key_material, except
+ *    that the caller provides the raw key material as argument, the `data'
+ *    and `data_len'. This is special utility function provided for the
+ *    application, if it needs to generate key material as the protocol
+ *    defines for some other purpose than strictly SILC session key usage.
+ *    Hence, this function can be used outside SKE protocol to just produce
+ *    key material from some raw data. The `hash' is a hash algorithm that
+ *    is used as part of key processing, and caller must provide it.
+ *
+ ***/
 SilcSKEStatus 
 silc_ske_process_key_material_data(unsigned char *data,
                                   uint32 data_len,
@@ -244,12 +878,18 @@ silc_ske_process_key_material_data(unsigned char *data,
                                   uint32 req_hmac_key_len,
                                   SilcHash hash,
                                   SilcSKEKeyMaterial *key);
-SilcSKEStatus silc_ske_process_key_material(SilcSKE ske, 
-                                           uint32 req_iv_len,
-                                           uint32 req_enc_key_len,
-                                           uint32 req_hmac_key_len,
-                                           SilcSKEKeyMaterial *key);
+
+/****f* silcske/SilcSKEAPI/silc_ske_free_key_material
+ *
+ * SYNOPSIS
+ *
+ *    void silc_ske_free_key_material(SilcSKEKeyMaterial *key);
+ *
+ * DESCRIPTION
+ *
+ *    Frees the key material indicated by `key', and all data in it.
+ *
+ ***/
 void silc_ske_free_key_material(SilcSKEKeyMaterial *key);
-const char *silc_ske_map_status(SilcSKEStatus status);
 
-#endif
+#endif /* SILCSKE_H */
similarity index 92%
rename from lib/silcske/groups.h
rename to lib/silcske/silcske_groups.h
index 724bc3d5f86f1dec73ab9c022f485e6024a78e44..acbdb58ababcd127b8f143a43d552fc6bee42b73 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
-  groups.h
+  silcske_groups.h 
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2000 - 2001 Pekka Riikonen
+  Copyright (C) 2000 - 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
-  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
  *
  * This interface defines the Diffie Hellman group management and utility
  * functions for the SKE.  They can be used find DH groups by group number,
- * and group name.  These routines are used during the SKE session.
+ * and group name.  These routines are used during the SKE session by the
+ * SKE library. However, application may use these as well if needed.
  *
  ***/
 
-#ifndef GROUPS_H
-#define GROUPS_H
+#ifndef SILCSKE_GROUPS_H
+#define SILCSKE_GROUPS_H
 
 #include "silcske_status.h"
 
@@ -141,4 +141,4 @@ int silc_ske_group_get_number(SilcSKEDiffieHellmanGroup group);
  ***/
 const char *silc_ske_group_get_name(SilcSKEDiffieHellmanGroup group);
 
-#endif
+#endif /* SILCSKE_GROUPS_H */
diff --git a/lib/silcske/silcske_payload.h b/lib/silcske/silcske_payload.h
new file mode 100644 (file)
index 0000000..4acfa06
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+
+  silcske_payload.h 
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2000 - 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
+  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
+  GNU General Public License for more details.
+
+*/
+
+/****h* silcske/SilcSKEPayloads
+ *
+ * DESCRIPTION
+ *
+ * This interface defines the implementation of the SKE Payloads, as
+ * defined by the SKE protocol. This interface is mainly used by the SKE
+ * library, however all structures are public and the interface can be used
+ * by the application if needed. Usually application does not need use this
+ * interface.
+ *
+ ***/
+
+#ifndef SILCSKE_PAYLOAD_H
+#define SILCSKE_PAYLOAD_H
+
+/****s* silcske/SilcSKEPayloads/SilcSKEStartPayload
+ *
+ * NAME
+ * 
+ *    typedef struct SilcSKEStartPayloadStruct SilcSKEStartPayload;
+ *
+ * DESCRIPTION
+ *
+ *    This context is the actual Key Exchange Start Payload and is allocated
+ *    by silc_ske_payload_start_decode. It is freed by calling the
+ *    silc_ske_payload_start_free function.
+ *
+ ***/
+typedef struct SilcSKEStartPayloadStruct SilcSKEStartPayload;
+
+/****s* silcske/SilcSKEPayloads/SilcSKEKEPayload
+ *
+ * NAME
+ * 
+ *    typedef struct SilcSKEKEPayloadStruct SilcSKEKEPayload;
+ *
+ * DESCRIPTION
+ *
+ *    This context is the actual Key Exchange Payload and is allocated
+ *    by silc_ske_payload_ke_decode. It is freed by calling the
+ *    silc_ske_payload_ke_free function. 
+ *
+ ***/
+typedef struct SilcSKEKEPayloadStruct SilcSKEKEPayload;
+
+/* SILC Key Exchange Start Payload */
+struct SilcSKEStartPayloadStruct {
+  unsigned char flags;
+  uint16 len;
+
+  unsigned char *cookie;
+  uint16 cookie_len;
+
+  unsigned char *version;
+  uint16 version_len;
+
+  uint16 ke_grp_len;
+  unsigned char *ke_grp_list;
+
+  uint16 pkcs_alg_len;
+  unsigned char *pkcs_alg_list;
+
+  uint16 enc_alg_len;
+  unsigned char *enc_alg_list;
+  
+  uint16 hash_alg_len;
+  unsigned char *hash_alg_list;
+
+  uint16 hmac_alg_len;
+  unsigned char *hmac_alg_list;
+
+  uint16 comp_alg_len;
+  unsigned char *comp_alg_list;
+};
+
+/* SILC Key Exchange Payload */
+struct SilcSKEKEPayloadStruct {
+  uint16 pk_len;
+  unsigned char *pk_data;
+  uint16 pk_type;
+
+  SilcMPInt x;
+
+  uint16 sign_len;
+  unsigned char *sign_data;
+};
+
+/* Prototypes */
+
+/****f* silcske/SilcSKEPayloads/silc_ske_payload_start_encode
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus silc_ske_payload_start_encode(SilcSKE ske,
+ *                                                SilcSKEStartPayload *payload,
+ *                                                SilcBuffer *return_buffer);
+ *
+ * DESCRIPTION
+ *
+ *    Utility function used to encode Key Exchange Start Payload from the
+ *    `payload' structure. The encoded buffer is returned into the
+ *    `return_buffer' and the caller must free it.
+ *
+ ***/
+SilcSKEStatus silc_ske_payload_start_encode(SilcSKE ske,
+                                           SilcSKEStartPayload *payload,
+                                           SilcBuffer *return_buffer);
+
+/****f* silcske/SilcSKEPayloads/silc_ske_payload_start_decode
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus 
+ *    silc_ske_payload_start_decode(SilcSKE ske,
+ *                                  SilcBuffer buffer,
+ *                                  SilcSKEStartPayload **return_payload);
+ *
+ * DESCRIPTION
+ *
+ *    Utility function used to decode Key Exchange Start Payload from the
+ *    `buffer' data buffer. The decoded payload is returned into the
+ *    `return_payload' and the caller must free it.
+ *
+ ***/
+SilcSKEStatus 
+silc_ske_payload_start_decode(SilcSKE ske,
+                             SilcBuffer buffer,
+                             SilcSKEStartPayload **return_payload);
+
+/****f* silcske/SilcSKEPayloads/silc_ske_payload_start_free
+ *
+ * SYNOPSIS
+ *
+ *    void silc_ske_payload_start_free(SilcSKEStartPayload *payload);
+ *
+ * DESCRIPTION
+ *
+ *    Frees the Key Exchange Start Payload indicated by `payload'.
+ *
+ ***/
+void silc_ske_payload_start_free(SilcSKEStartPayload *payload);
+
+/****f* silcske/SilcSKEPayloads/silc_ske_payload_ke_encode
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus silc_ske_payload_ke_encode(SilcSKE ske,
+ *                                             SilcSKEKEPayload *payload,
+ *                                             SilcBuffer *return_buffer);
+ *
+ * DESCRIPTION
+ *
+ *    Utility function used to encode Key Exchange Payload from the
+ *    `payload' structure. The encoded buffer is returned into the
+ *    `return_buffer' and the caller must free it.
+ *
+ ***/
+SilcSKEStatus silc_ske_payload_ke_encode(SilcSKE ske,
+                                        SilcSKEKEPayload *payload,
+                                        SilcBuffer *return_buffer);
+
+/****f* silcske/SilcSKEPayloads/silc_ske_payload_ke_decode
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske,
+ *                                             SilcBuffer buffer,
+ *                                             SilcSKEKEPayload 
+ *                                               **return_payload);
+ *
+ * DESCRIPTION
+ *
+ *    Utility function used to decode Key Exchange Payload from the
+ *    `buffer' data buffer. The decoded payload is returned into the
+ *    `return_payload' and the caller must free it.
+ *
+ ***/
+SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske,
+                                        SilcBuffer buffer,
+                                        SilcSKEKEPayload **return_payload);
+
+/****f* silcske/SilcSKEPayloads/silc_ske_payload_ke_free
+ *
+ * SYNOPSIS
+ *
+ *    void silc_ske_payload_ke_free(SilcSKEKEPayload *payload);
+ *
+ * DESCRIPTION
+ *
+ *    Frees the Key Exchange Payload indicated by `payload'.
+ *
+ ***/
+void silc_ske_payload_ke_free(SilcSKEKEPayload *payload);
+
+#endif /* SILCSKE_PAYLOAD_H */
index f223354bc50f7ef87cac7d3d6c9d3ce28f71b0bc..4ca238de02a1750797c763b3fad56cac6b0cac68 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
-  silcske_status.h
+  silcske_status.h 
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2000 - 2001 Pekka Riikonen
+  Copyright (C) 2000 - 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
-  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
 
 */
 
+/****h* silcske/SilcSKEStatuses
+ *
+ * DESCRIPTION
+ *
+ * Defines the SilcSKEStatus type, that is returned by all SKE routines,
+ * and a utility interface for handling the status.
+ *
+ ***/
+
 #ifndef SILCSKE_STATUS_H
 #define SILCSKE_STATUS_H
 
-/* Status flags returned by all SKE routines */
+/****d* silcske/SilcSKEStatuses/SilcSKEStatus
+ *
+ * NAME
+ * 
+ *    typedef enum { ... } SilcSKEStatus;
+ *
+ * DESCRIPTION
+ *
+ *    Status types returned by all SKE routines. This tell the status of
+ *    the SKE session, and if an error occurred. 
+ *
+ * SOURCE
+ */
 typedef enum {
   /* These are defined by the protocol */
-  SILC_SKE_STATUS_OK                     = 0,
-  SILC_SKE_STATUS_ERROR                  = 1,
-  SILC_SKE_STATUS_BAD_PAYLOAD            = 2,
-  SILC_SKE_STATUS_UNKNOWN_GROUP          = 3,
-  SILC_SKE_STATUS_UNKNOWN_CIPHER         = 4,
-  SILC_SKE_STATUS_UNKNOWN_PKCS           = 5,
-  SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION  = 6,
-  SILC_SKE_STATUS_UNKNOWN_HMAC           = 7,
-  SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY = 8,
-  SILC_SKE_STATUS_INCORRECT_SIGNATURE    = 9,
-  SILC_SKE_STATUS_BAD_VERSION            = 10,
-  SILC_SKE_STATUS_INVALID_COOKIE         = 11,
-
-  SILC_SKE_STATUS_PENDING,
-  SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED,
-  SILC_SKE_STATUS_KEY_EXCHANGE_NOT_ACTIVE,
-  SILC_SKE_STATUS_BAD_RESERVED_FIELD,
-  SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH,
-  SILC_SKE_STATUS_INCORRECT_HASH,
-  SILC_SKE_STATUS_FREED,
+  SILC_SKE_STATUS_OK                     = 0,  /* No error */
+  SILC_SKE_STATUS_ERROR                  = 1,  /* Unknown error */
+  SILC_SKE_STATUS_BAD_PAYLOAD            = 2,  /* Malformed payload */
+  SILC_SKE_STATUS_UNKNOWN_GROUP          = 3,  /* Unsupported DH group */
+  SILC_SKE_STATUS_UNKNOWN_CIPHER         = 4,  /* Unsupported cipher */
+  SILC_SKE_STATUS_UNKNOWN_PKCS           = 5,  /* Unsupported PKCS algorithm */
+  SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION  = 6,  /* Unsupported hash function */
+  SILC_SKE_STATUS_UNKNOWN_HMAC           = 7,  /* Unsupported HMAC */
+  SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY = 8,  /* Unsupported/not trusted PK */
+  SILC_SKE_STATUS_INCORRECT_SIGNATURE    = 9,  /* Incorrect signature */
+  SILC_SKE_STATUS_BAD_VERSION            = 10, /* Unsupported version */
+  SILC_SKE_STATUS_INVALID_COOKIE         = 11, /* Cookie was modified */
+
+  /* Implementation specific status types */
+  SILC_SKE_STATUS_PENDING,                    /* SKE library is pending */
+  SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED,     /* Remote did not send PK */
+  SILC_SKE_STATUS_KEY_EXCHANGE_NOT_ACTIVE,     /* SKE is not started */
+  SILC_SKE_STATUS_BAD_RESERVED_FIELD,         /* Reserved field was not 0 */
+  SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH,         /* Payload includes garbage */
+
+  /* Other internal status types */
+  SILC_SKE_STATUS_FREED,                      /* Internal libary status */
 } SilcSKEStatus;
+/***/
 
-extern const char *silc_ske_status_string[];
+/****f* silcske/SilcSKEStatuses/silc_ske_map_status
+ *
+ * SYNOPSIS
+ *
+ *    const char *silc_ske_map_status(SilcSKEStatus status);
+ *
+ * DESCRIPTION
+ *
+ *    Utility function to map the `status' into human readable message.
+ *
+ ***/
+const char *silc_ske_map_status(SilcSKEStatus status);
 
-#endif
+#endif /* SILCSKE_STATUS_H */