Added SILC_SKE_STATUS_SIGNATURE_ERROR and OUT_OF_MEMORY and
authorPekka Riikonen <priikone@silcnet.org>
Fri, 11 Oct 2002 21:02:48 +0000 (21:02 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Fri, 11 Oct 2002 21:02:48 +0000 (21:02 +0000)
added better error printing to SKE library.
Fixed the usage of silc_pkcs_get_key_len as it returns the length
in bits not in bytes.

lib/silccore/silcauth.c
lib/silccrypt/silcpkcs.c
lib/silcske/payload.c
lib/silcske/silcske.c
lib/silcske/silcske_status.h

index 63ad694021ee67dffcc767783479f109b95bab5c..aea21a993f34f62a777a06815a3f78e2e1d4ad1b 100644 (file)
@@ -274,7 +274,7 @@ SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key,
   silc_pkcs_private_key_set(pkcs, private_key);
 
   /* Compute the hash and the signature. */
-  if (silc_pkcs_get_key_len(pkcs) > sizeof(auth_data) - 1 ||
+  if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
       !silc_pkcs_sign_with_hash(pkcs, hash, tmp, tmp_len, auth_data,
                                &auth_len)) {
     memset(randomdata, 0, 256);
index 2e8ca92e9c492461ba4600f670771b645d3534ba..cbc8c762416cf51937fc2f590e35d0f38ec79799 100644 (file)
@@ -25,9 +25,9 @@
 
 /* The main SILC PKCS structure. */
 struct SilcPKCSStruct {
-  void *context;
-  SilcPKCSObject *pkcs;
-  SilcUInt32 key_len;
+  void *context;               /* Algorithm internal context */
+  SilcPKCSObject *pkcs;                /* Algorithm implementation */
+  SilcUInt32 key_len;          /* Key length in bits */
 };
 
 #ifndef SILC_EPOC
index eafbd873330404b36fe711a529c9476671b556db..eeb22f011ad591a73cf6e1dfe2ca9d320391bdaa 100644 (file)
@@ -37,6 +37,8 @@ SilcSKEStatus silc_ske_payload_start_encode(SilcSKE ske,
     return SILC_SKE_STATUS_ERROR;
 
   buf = silc_buffer_alloc(payload->len);
+  if (!buf)
+    return SILC_SKE_STATUS_OUT_OF_MEMORY;
   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
 
   /* Encode the payload */
@@ -99,6 +101,8 @@ silc_ske_payload_start_decode(SilcSKE ske,
   SILC_LOG_HEXDUMP(("KE Start Payload"), buffer->data, buffer->len);
 
   payload = silc_calloc(1, sizeof(*payload));
+  if (!payload)
+    return SILC_SKE_STATUS_OUT_OF_MEMORY;
   payload->cookie_len = SILC_SKE_COOKIE_LEN;
 
   /* Parse start of the payload */
@@ -125,18 +129,20 @@ silc_ske_payload_start_decode(SilcSKE ske,
                                                     &payload->comp_alg_len),
                         SILC_STR_END);
   if (ret == -1) {
-    status = SILC_SKE_STATUS_ERROR;
+    SILC_LOG_ERROR(("Malformed KE Start Payload"));
+    status = SILC_SKE_STATUS_BAD_PAYLOAD;
     goto err;
   }
 
   if (tmp != 0) {
     SILC_LOG_DEBUG(("Bad reserved field"));
+    SILC_LOG_ERROR(("Bad RESERVED field in KE Start Payload"));
     status = SILC_SKE_STATUS_BAD_RESERVED_FIELD;
     goto err;
   }
 
   if (payload->len != buffer->len) {
-    SILC_LOG_DEBUG(("Bad payload length"));
+    SILC_LOG_ERROR(("Garbage after KE Start Payload"));
     status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
     goto err;
   }
@@ -201,6 +207,8 @@ SilcSKEStatus silc_ske_payload_ke_encode(SilcSKE ske,
      is 4 + public key + 2 + x + 2 + signature. */
   buf = silc_buffer_alloc(4 + payload->pk_len + 2 + x_len + 
                          2 + payload->sign_len);
+  if (!buf)
+    return SILC_SKE_STATUS_OUT_OF_MEMORY;
   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
 
   /* Encode the payload */
@@ -252,6 +260,8 @@ SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske,
   SILC_LOG_HEXDUMP(("KE Payload"), buffer->data, buffer->len);
 
   payload = silc_calloc(1, sizeof(*payload));
+  if (!payload)
+    return SILC_SKE_STATUS_OUT_OF_MEMORY;
 
   len2 = buffer->len;
 
@@ -261,13 +271,15 @@ SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske,
                             SILC_STR_UI_SHORT(&payload->pk_type),
                             SILC_STR_END);
   if (ret == -1) {
-    status = SILC_SKE_STATUS_ERROR;
+    SILC_LOG_ERROR(("Cannot decode public key from KE payload"));
+    status = SILC_SKE_STATUS_BAD_PAYLOAD;
     goto err;
   }
 
   if (ske->start_payload && 
       (payload->pk_type < SILC_SKE_PK_TYPE_SILC || 
        payload->pk_type > SILC_SKE_PK_TYPE_SPKI)) {
+    SILC_LOG_ERROR(("Malformed public key in KE payload"));
     status = SILC_SKE_STATUS_BAD_PAYLOAD;
     goto err;
   }
@@ -284,7 +296,8 @@ SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske,
                                                         &payload->sign_len),
                             SILC_STR_END);
   if (ret == -1) {
-    status = SILC_SKE_STATUS_ERROR;
+    SILC_LOG_ERROR(("Malformed KE Payload"));
+    status = SILC_SKE_STATUS_BAD_PAYLOAD;
     goto err;
   }
 
@@ -292,6 +305,7 @@ SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske,
   tot_len += payload->sign_len + 2;
 
   if (x_len < 3) {
+    SILC_LOG_ERROR(("Too short signature in KE Payload"));
     status = SILC_SKE_STATUS_BAD_PAYLOAD;
     goto err;
   }
@@ -299,13 +313,14 @@ SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske,
   if (ske->start_payload && 
       (ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) &&
       (payload->sign_len < 3 || !payload->sign_data)) {
-    SILC_LOG_DEBUG(("The signature data is missing - both parties are "
+    SILC_LOG_ERROR(("The signature data is missing - both parties are "
                    "required to do authentication"));
     status = SILC_SKE_STATUS_BAD_PAYLOAD;
     goto err;
   }
 
   if (tot_len != len2) {
+    SILC_LOG_ERROR(("Garbage after KE payload"));
     status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
     goto err;
   }
index 6535f55d4d9d1c54d12701b357edcc3895c56ef6..625e41105d4845b71f43f12e4afbc58e8c969a69 100644 (file)
@@ -50,6 +50,8 @@ SilcSKE silc_ske_alloc(SilcRng rng, void *context)
   SILC_LOG_DEBUG(("Allocating new Key Exchange object"));
 
   ske = silc_calloc(1, sizeof(*ske));
+  if (!ske)
+    return NULL;
   ske->status = SILC_SKE_STATUS_OK;
   ske->rng = rng;
   ske->user_data = context;
@@ -157,6 +159,8 @@ void silc_ske_set_callbacks(SilcSKE ske,
   if (ske->callbacks)
     silc_free(ske->callbacks);
   ske->callbacks = silc_calloc(1, sizeof(*ske->callbacks));
+  if (!ske->callbacks)
+    return;
   ske->callbacks->send_packet = send_packet;
   ske->callbacks->payload_receive = payload_receive;
   ske->callbacks->verify_key = verify_key;
@@ -236,7 +240,7 @@ SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
   /* Check that the cookie is returned unmodified */
   if (memcmp(ske->start_payload->cookie, payload->cookie,
             ske->start_payload->cookie_len)) {
-    SILC_LOG_DEBUG(("Responder modified our cookie and it must not do it"));
+    SILC_LOG_ERROR(("Responder modified our cookie and it must not do it"));
     ske->status = SILC_SKE_STATUS_INVALID_COOKIE;
     silc_ske_payload_start_free(ske->start_payload);
     return status;
@@ -262,6 +266,8 @@ SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
      exchange. The same data is returned to upper levels by calling
      the callback function. */
   ske->prop = prop = silc_calloc(1, sizeof(*prop));
+  if (!ske->prop)
+    goto err;
   prop->flags = payload->flags;
   status = silc_ske_group_get_by_name(payload->ke_grp_list, &group);
   if (status != SILC_SKE_STATUS_OK)
@@ -341,6 +347,10 @@ SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
 
   /* Create the random number x, 1 < x < q. */
   x = silc_calloc(1, sizeof(*x));
+  if (!x){
+    ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
+    return ske->status;
+  }
   silc_mp_init(x);
   status = 
     silc_ske_create_rnd(ske, &ske->prop->group->group_order,
@@ -356,6 +366,12 @@ SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
   /* Encode the result to Key Exchange Payload. */
 
   payload = silc_calloc(1, sizeof(*payload));
+  if (!payload) {
+    silc_mp_uninit(x);
+    silc_free(x);
+    ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
+    return ske->status;
+  }
   ske->ke1_payload = payload;
 
   SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
@@ -397,15 +413,15 @@ SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
     /* Sign the hash value */
     silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv, 
                                   private_key->prv_len);
-    if (silc_pkcs_get_key_len(ske->prop->pkcs) > sizeof(sign) - 1 ||
+    if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
        !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
       silc_mp_uninit(x);
       silc_free(x);
       silc_mp_uninit(&payload->x);
       silc_free(payload->pk_data);
       silc_free(payload);
-      ske->status = status;
-      return status;
+      ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
+      return ske->status;
     }
     payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
     memcpy(payload->sign_data, sign, sign_len);
@@ -503,7 +519,6 @@ static void silc_ske_initiator_finish_final(SilcSKE ske,
                         payload->sign_len, hash, hash_len) == FALSE) {
       
       SILC_LOG_DEBUG(("Signature don't match"));
-      
       status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
       goto err;
     }
@@ -1015,7 +1030,7 @@ SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
     /* Get the public key */
     pk = silc_pkcs_public_key_encode(public_key, &pk_len);
     if (!pk) {
-      status = SILC_SKE_STATUS_ERROR;
+      status = SILC_SKE_STATUS_OUT_OF_MEMORY;
       goto err;
     }
     ske->ke2_payload->pk_data = pk;
@@ -1038,9 +1053,11 @@ SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
     /* Sign the hash value */
     silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv, 
                                   private_key->prv_len);
-    if (silc_pkcs_get_key_len(ske->prop->pkcs) > sizeof(sign) - 1 ||
-       !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len))
+    if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
+       !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
+      status = SILC_SKE_STATUS_SIGNATURE_ERROR;
       goto err;
+    }
     ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
     memcpy(ske->ke2_payload->sign_data, sign, sign_len);
     memset(sign, 0, sizeof(sign));
@@ -1087,8 +1104,9 @@ SilcSKEStatus silc_ske_end(SilcSKE ske)
 
   SILC_LOG_DEBUG(("Start"));
 
-  packet = silc_buffer_alloc(4);
-  silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
+  packet = silc_buffer_alloc_size(4);
+  if (!packet)
+    return SILC_SKE_STATUS_OUT_OF_MEMORY;
   silc_buffer_format(packet,
                     SILC_STR_UI_INT((SilcUInt32)SILC_SKE_STATUS_OK),
                     SILC_STR_END);
@@ -1115,8 +1133,9 @@ SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
   if (status > SILC_SKE_STATUS_INVALID_COOKIE)
     status = SILC_SKE_STATUS_BAD_PAYLOAD;
 
-  packet = silc_buffer_alloc(4);
-  silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
+  packet = silc_buffer_alloc_size(4);
+  if (!packet)
+    return SILC_SKE_STATUS_OUT_OF_MEMORY;
   silc_buffer_format(packet,
                     SILC_STR_UI_INT((SilcUInt32)status),
                     SILC_STR_END);
@@ -1581,7 +1600,7 @@ static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
   /* Get the random number as string */
   string = silc_rng_get_rn_data(ske->rng, (len / 8));
   if (!string)
-    return SILC_SKE_STATUS_ERROR;
+    return SILC_SKE_STATUS_OUT_OF_MEMORY;
 
   /* Decode the string into a MP integer */
   silc_mp_bin2mp(string, (len / 8), rnd);
@@ -1624,11 +1643,12 @@ static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
     KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
     
     /* Format the buffer used to compute the hash value */
-    buf = silc_buffer_alloc(ske->start_payload_copy->len + 
-                           ske->ke2_payload->pk_len + 
-                           ske->ke1_payload->pk_len + 
-                           e_len + f_len + KEY_len);
-    silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+    buf = silc_buffer_alloc_size(ske->start_payload_copy->len + 
+                                ske->ke2_payload->pk_len + 
+                                ske->ke1_payload->pk_len + 
+                                e_len + f_len + KEY_len);
+    if (!buf)
+      return SILC_SKE_STATUS_OUT_OF_MEMORY;
 
     /* Initiator is not required to send its public key */
     if (!ske->ke1_payload->pk_data) {
@@ -1680,9 +1700,10 @@ static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
   } else {
     e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
 
-    buf = silc_buffer_alloc(ske->start_payload_copy->len + 
-                           ske->ke1_payload->pk_len + e_len);
-    silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+    buf = silc_buffer_alloc_size(ske->start_payload_copy->len + 
+                                 ske->ke1_payload->pk_len + e_len);
+    if (!buf)
+      return SILC_SKE_STATUS_OUT_OF_MEMORY;
     
     /* Format the buffer used to compute the hash value */
     ret = 
@@ -1741,8 +1762,9 @@ silc_ske_process_key_material_data(unsigned char *data,
   if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
     return SILC_SKE_STATUS_ERROR;
 
-  buf = silc_buffer_alloc(1 + data_len);
-  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+  buf = silc_buffer_alloc_size(1 + data_len);
+  if (!buf)
+    return SILC_SKE_STATUS_OUT_OF_MEMORY;
   silc_buffer_format(buf,
                     SILC_STR_UI_CHAR(0),
                     SILC_STR_UI_XNSTRING(data, data_len),
@@ -1779,8 +1801,9 @@ silc_ske_process_key_material_data(unsigned char *data,
     silc_hash_make(hash, buf->data, buf->len, k1);
     
     /* Take second round */
-    dist = silc_buffer_alloc(data_len + hash_len);
-    silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
+    dist = silc_buffer_alloc_size(data_len + hash_len);
+    if (!dist)
+      return SILC_SKE_STATUS_OUT_OF_MEMORY;
     silc_buffer_format(dist,
                       SILC_STR_UI_XNSTRING(data, data_len),
                       SILC_STR_UI_XNSTRING(k1, hash_len),
@@ -1839,8 +1862,9 @@ silc_ske_process_key_material_data(unsigned char *data,
     silc_hash_make(hash, buf->data, buf->len, k1);
     
     /* Take second round */
-    dist = silc_buffer_alloc(data_len + hash_len);
-    silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
+    dist = silc_buffer_alloc_size(data_len + hash_len);
+    if (!dist)
+      return SILC_SKE_STATUS_OUT_OF_MEMORY;
     silc_buffer_format(dist,
                       SILC_STR_UI_XNSTRING(data, data_len),
                       SILC_STR_UI_XNSTRING(k1, hash_len),
@@ -1920,8 +1944,9 @@ SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
   /* Encode KEY to binary data */
   tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
 
-  buf = silc_buffer_alloc(klen + ske->hash_len);
-  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+  buf = silc_buffer_alloc_size(klen + ske->hash_len);
+  if (!buf)
+    return SILC_SKE_STATUS_OUT_OF_MEMORY;
   silc_buffer_format(buf,
                     SILC_STR_UI_XNSTRING(tmpbuf, klen),
                     SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
@@ -1992,7 +2017,8 @@ const char *silc_ske_status_string[] =
   "Key exchange protocol is not active",
   "Bad reserved field in packet",
   "Bad payload length in packet",
-  "Incorrect hash",
+  "Error computing signature",
+  "System out of memory",
 
   NULL
 };
index 908a807dd1cf122307af6af2a35d4bd9baf9782b..4eb3371998c81f7aadbc974cd97ca7c84ddde8dd 100644 (file)
@@ -63,6 +63,8 @@ typedef enum {
   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 */
+  SILC_SKE_STATUS_SIGNATURE_ERROR,            /* Error computing signature */
+  SILC_SKE_STATUS_OUT_OF_MEMORY,              /* System out of memory */
 
   /* Other internal status types */
   SILC_SKE_STATUS_FREED,                      /* Internal library status */