Fixed parsing mesage payload.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 5 Nov 2006 13:04:15 +0000 (13:04 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 5 Nov 2006 13:04:15 +0000 (13:04 +0000)
Removed silc_message_get_iv.
Added message payload tester program.

lib/silccore/silcmessage.c
lib/silccore/silcmessage.h
lib/silccore/tests/Makefile.am
lib/silccore/tests/test_silcmessage.c [new file with mode: 0644]

index f7adbc2b51aa9ff9a5b0edbeb008ea1e70bc8d12..ff8a8433fe83a7508b11b703eed4df8a67692784 100644 (file)
@@ -48,7 +48,6 @@ struct SilcMessagePayloadStruct {
   SilcUInt16 iv_len;
   unsigned char *data;
   unsigned char *pad;
-  unsigned char *iv;
   unsigned char *mac;
   SilcMessageSignedPayload sig;
 };
@@ -124,13 +123,10 @@ SilcBool silc_message_payload_decrypt(unsigned char *data,
   totlen += 2 + len;
   if (totlen + iv_len + mac_len + 2 > data_len)
     return FALSE;
-  SILC_GET16_MSB(len, data + totlen);
-  totlen += 2 + len;
-  if (totlen + iv_len + mac_len > data_len)
-    return FALSE;
-  if (totlen - block_len)
+  if (totlen >= block_len)
     if (!silc_cipher_decrypt(cipher, data + block_len, data + block_len,
-                            totlen - block_len, ivp))
+                            (totlen - block_len) + SILC_MESSAGE_PAD(totlen),
+                            ivp))
       return FALSE;
 
   return TRUE;
@@ -203,14 +199,11 @@ silc_message_payload_parse(unsigned char *payload,
       silc_message_signed_payload_parse(buffer.data + 6 + newp->data_len +
                                        newp->pad_len,
                                        silc_buffer_len(&buffer) -
-                                       iv_len - mac_len);
+                                       iv_len - mac_len - 6 - newp->data_len -
+                                       newp->pad_len);
   }
 
-  /* Parse IV and MAC from the payload */
-  if (iv_len) {
-    newp->iv = buffer.data + (silc_buffer_len(&buffer) - iv_len - mac_len);
-    newp->iv_len = iv_len;
-  }
+  /* Parse MAC from the payload */
   if (mac_len)
     newp->mac = buffer.data + (silc_buffer_len(&buffer) - mac_len);
 
@@ -329,6 +322,8 @@ SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
 
   if (!data_len)
     return NULL;
+  if (!private_message && (!cipher || !hmac))
+    return NULL;
 
   if (!buffer) {
     buf = buffer = silc_buffer_alloc(0);
@@ -435,13 +430,6 @@ unsigned char *silc_message_get_mac(SilcMessagePayload payload)
   return payload->mac;
 }
 
-/* Return IV. The caller knows the length of the IV */
-
-unsigned char *silc_message_get_iv(SilcMessagePayload payload)
-{
-  return payload->iv;
-}
-
 /* Return signature of the message */
 
 SilcMessageSignedPayload
index 1ff19512bc8ff4f646bceb3f2ead841267f0edfa..186844f791adc3af7b8be3a4ff8191ca0703fe6e 100644 (file)
@@ -330,21 +330,6 @@ unsigned char *silc_message_get_data(SilcMessagePayload payload,
  ***/
 unsigned char *silc_message_get_mac(SilcMessagePayload payload);
 
-/****f* silccore/SilcMessageAPI/silc_message_get_iv
- *
- * SYNOPSIS
- *
- *    unsigned char *
- *    silc_message_get_iv(SilcMessagePayload payload);
- *
- * DESCRIPTION
- *
- *    Return the IV of the payload. The caller must already know the
- *    length of the IV. The caller must not free the IV.
- *
- ***/
-unsigned char *silc_message_get_iv(SilcMessagePayload payload);
-
 /****f* silccore/SilcMessageAPI/silc_message_get_signature
  *
  * SYNOPSIS
index 7adf83c4b9a9d53ce188f15fa2674d2119e71c99..9557750160fbbbe8069de4d9fad245796e3a46ee 100644 (file)
 
 AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
 
-bin_PROGRAMS =         test_silcargument
+bin_PROGRAMS =         test_silcargument test_silcmessage
 
 test_silcargument_SOURCES = test_silcargument.c
+test_silcmesssage_SOURCES = test_silcmessage.c
 
 LIBS = $(SILC_COMMON_LIBS)
 LDADD = -L.. -L../.. -lsilc
diff --git a/lib/silccore/tests/test_silcmessage.c b/lib/silccore/tests/test_silcmessage.c
new file mode 100644 (file)
index 0000000..e6feb3a
--- /dev/null
@@ -0,0 +1,387 @@
+/* SILC Message Payload tests */
+
+#include "silc.h"
+#include "silcapputil.h"
+
+SilcPublicKey public_key, pk2;
+SilcPrivateKey private_key;
+SilcCipher key;
+SilcHash hash;
+SilcHmac hmac;
+SilcRng rng;
+
+int main(int argc, char **argv)
+{
+  SilcBool success = FALSE;
+  SilcMessagePayload message;
+  SilcBuffer buf;
+  const char *msg = "FOOBAR MESSAGE";
+  unsigned char *data, tmp[1023];
+  SilcUInt32 data_len;
+  SilcUInt16 flags;
+  int i;
+  SilcMessageSignedPayload sig;
+
+  if (argc > 1 && !strcmp(argv[1], "-d")) {
+    silc_log_debug(TRUE);
+    silc_log_debug_hexdump(TRUE);
+    silc_log_set_debug_string("*message*");
+  }
+
+  silc_cipher_register_default();
+  silc_hash_register_default();
+  silc_hmac_register_default();
+  silc_pkcs_register_default();
+
+  SILC_LOG_DEBUG(("Load keypair"));
+  if (!silc_load_key_pair("pubkey.pub", "privkey.prv", "",
+                         &public_key, &private_key)) {
+    SILC_LOG_DEBUG(("Create keypair"));
+    if (!silc_create_key_pair("rsa", 2048, "pubkey.pub", "privkey.prv",
+                             NULL, "", &public_key, &private_key, FALSE))
+      goto err;
+  }
+
+  SILC_LOG_DEBUG(("Alloc RNG"));
+  rng = silc_rng_alloc();
+  silc_rng_init(rng);
+
+  SILC_LOG_DEBUG(("Alloc AES"));
+  if (!silc_cipher_alloc("aes-128-cbc", &key))
+    goto err;
+
+  SILC_LOG_DEBUG(("Alloc SHA-256"));
+  if (!silc_hash_alloc("sha256", &hash))
+    goto err;
+
+  SILC_LOG_DEBUG(("Alloc HMAC"));
+  if (!silc_hmac_alloc("hmac-sha256-96", hash, &hmac))
+    goto err;
+
+  SILC_LOG_DEBUG(("Set static key: '1234567890123456'"));
+  if (!silc_cipher_set_key(key, "1234567890123456", 16 * 8))
+    goto err;
+  SILC_LOG_DEBUG(("Set HMAC key: '1234567890123456'"));
+  silc_hmac_set_key(hmac, "1234567890123456", 16);
+
+  /* Simple private message */
+  SILC_LOG_DEBUG(("Encoding private message len %d (static key)",
+                 strlen(msg)));
+  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
+                                   SILC_MESSAGE_FLAG_UTF8 |
+                                   SILC_MESSAGE_FLAG_ACK,
+                                   msg, strlen(msg), TRUE, TRUE,
+                                   key, hmac, rng, NULL, NULL, NULL, NULL);
+  if (!buf)
+    goto err;
+  SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf));
+  SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
+  message = silc_message_payload_parse(silc_buffer_data(buf),
+                                      silc_buffer_len(buf), TRUE, TRUE,
+                                      key, hmac);
+  if (!message)
+    goto err;
+  flags = silc_message_get_flags(message);
+  SILC_LOG_DEBUG(("Flags: %x", flags));
+  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_ACK))
+    goto err;
+  data = silc_message_get_data(message, &data_len);
+  SILC_LOG_HEXDUMP(("Data"), data, data_len);
+  if (data_len != strlen(msg) || memcmp(data, msg, strlen(msg)))
+    goto err;
+  SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
+                  silc_hmac_len(hmac));
+  silc_message_payload_free(message);
+
+  /* Simple private message */
+  SILC_LOG_DEBUG(("Encoding private message len %d (static key)", 10));
+  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
+                                   SILC_MESSAGE_FLAG_UTF8 |
+                                   SILC_MESSAGE_FLAG_ACK,
+                                   msg, 10, TRUE, TRUE,
+                                   key, hmac, rng, NULL, NULL, NULL, buf);
+  if (!buf)
+    goto err;
+  SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf));
+  SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
+  message = silc_message_payload_parse(silc_buffer_data(buf),
+                                      silc_buffer_len(buf), TRUE, TRUE,
+                                      key, hmac);
+  if (!message)
+    goto err;
+  flags = silc_message_get_flags(message);
+  SILC_LOG_DEBUG(("Flags: %x", flags));
+  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_ACK))
+    goto err;
+  data = silc_message_get_data(message, &data_len);
+  SILC_LOG_HEXDUMP(("Data"), data, data_len);
+  if (data_len != 10 || memcmp(data, msg, 10))
+    goto err;
+  SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
+                  silc_hmac_len(hmac));
+  silc_message_payload_free(message);
+
+  /* Simple private message */
+  SILC_LOG_DEBUG(("Encoding private message len %d (static key)", 1));
+  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
+                                   SILC_MESSAGE_FLAG_UTF8 |
+                                   SILC_MESSAGE_FLAG_ACK,
+                                   msg, 1, TRUE, TRUE,
+                                   key, hmac, rng, NULL, NULL, NULL, buf);
+  if (!buf)
+    goto err;
+  SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf));
+  SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
+  message = silc_message_payload_parse(silc_buffer_data(buf),
+                                      silc_buffer_len(buf), TRUE, TRUE,
+                                      key, hmac);
+  if (!message)
+    goto err;
+  flags = silc_message_get_flags(message);
+  SILC_LOG_DEBUG(("Flags: %x", flags));
+  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_ACK))
+    goto err;
+  data = silc_message_get_data(message, &data_len);
+  SILC_LOG_HEXDUMP(("Data"), data, data_len);
+  if (data_len != 1 || memcmp(data, msg, 1))
+    goto err;
+  SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
+                  silc_hmac_len(hmac));
+  silc_message_payload_free(message);
+
+  /* Simple private message */
+  for (i = 0; i < sizeof(tmp); i++)
+    tmp[i] = (32 + i) & 127;
+  SILC_LOG_DEBUG(("Encoding private message len %d (static key)",
+                 sizeof(tmp)));
+  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
+                                   SILC_MESSAGE_FLAG_UTF8 |
+                                   SILC_MESSAGE_FLAG_ACK,
+                                   tmp, sizeof(tmp), TRUE, TRUE,
+                                   key, hmac, rng, NULL, NULL, NULL, buf);
+  if (!buf)
+    goto err;
+  SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf));
+  SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
+  message = silc_message_payload_parse(silc_buffer_data(buf),
+                                      silc_buffer_len(buf), TRUE, TRUE,
+                                      key, hmac);
+  if (!message)
+    goto err;
+  flags = silc_message_get_flags(message);
+  SILC_LOG_DEBUG(("Flags: %x", flags));
+  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_ACK))
+    goto err;
+  data = silc_message_get_data(message, &data_len);
+  SILC_LOG_HEXDUMP(("Data"), data, data_len);
+  if (data_len != sizeof(tmp) || memcmp(data, tmp, sizeof(tmp)))
+    goto err;
+  SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
+                  silc_hmac_len(hmac));
+  silc_message_payload_free(message);
+
+  /* Digitally signed private message */
+  for (i = 0; i < sizeof(tmp); i++)
+    tmp[i] = (32 + i) & 127;
+  SILC_LOG_DEBUG(("Encoding private message len %d (static key) SIGNED",
+                 sizeof(tmp)));
+  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
+                                   SILC_MESSAGE_FLAG_UTF8 |
+                                   SILC_MESSAGE_FLAG_ACK |
+                                   SILC_MESSAGE_FLAG_SIGNED,
+                                   tmp, sizeof(tmp), TRUE, TRUE,
+                                   key, hmac, rng,
+                                   public_key, private_key, hash, buf);
+  if (!buf)
+    goto err;
+  SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf));
+  SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
+  message = silc_message_payload_parse(silc_buffer_data(buf),
+                                      silc_buffer_len(buf), TRUE, TRUE,
+                                      key, hmac);
+  if (!message)
+    goto err;
+  flags = silc_message_get_flags(message);
+  SILC_LOG_DEBUG(("Flags: %x", flags));
+  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_ACK))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_SIGNED))
+    goto err;
+  data = silc_message_get_data(message, &data_len);
+  SILC_LOG_HEXDUMP(("Data"), data, data_len);
+  if (data_len != sizeof(tmp) || memcmp(data, tmp, sizeof(tmp)))
+    goto err;
+  SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
+                  silc_hmac_len(hmac));
+  SILC_LOG_DEBUG(("Get signature"));
+  sig = silc_message_get_signature(message);
+  if (!sig)
+    goto err;
+  SILC_LOG_DEBUG(("Verifying signature"));
+  if (silc_message_signed_verify(sig, message, public_key, hash) !=
+      SILC_AUTH_OK)
+    goto err;
+  SILC_LOG_DEBUG(("Signature Ok"));
+  SILC_LOG_DEBUG(("Get public key"));
+  pk2 = silc_message_signed_get_public_key(sig, NULL, NULL);
+  if (!pk2)
+    goto err;
+  SILC_LOG_DEBUG(("Verify public key"));
+  if (!silc_pkcs_public_key_compare(public_key, pk2))
+    goto err;
+  SILC_LOG_DEBUG(("Public key Ok"));
+  silc_pkcs_public_key_free(pk2);
+  silc_message_payload_free(message);
+
+  /* Digitally signed channel message */
+  for (i = 0; i < sizeof(tmp) / 2; i++)
+    tmp[i] = (32 + i) & 127;
+  SILC_LOG_DEBUG(("Encoding channel message len %d (static key) SIGNED",
+                 sizeof(tmp) / 2));
+  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
+                                   SILC_MESSAGE_FLAG_UTF8 |
+                                   SILC_MESSAGE_FLAG_ACK |
+                                   SILC_MESSAGE_FLAG_SIGNED,
+                                   tmp, sizeof(tmp) / 2, TRUE, FALSE,
+                                   key, hmac, rng,
+                                   public_key, private_key, hash, buf);
+  if (!buf)
+    goto err;
+  SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf));
+  SILC_LOG_DEBUG(("Parsing channel messsage (static key)"));
+  message = silc_message_payload_parse(silc_buffer_data(buf),
+                                      silc_buffer_len(buf), FALSE, TRUE,
+                                      key, hmac);
+  if (!message)
+    goto err;
+  flags = silc_message_get_flags(message);
+  SILC_LOG_DEBUG(("Flags: %x", flags));
+  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_ACK))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_SIGNED))
+    goto err;
+  data = silc_message_get_data(message, &data_len);
+  SILC_LOG_HEXDUMP(("Data"), data, data_len);
+  if (data_len != sizeof(tmp) / 2 || memcmp(data, tmp, sizeof(tmp) / 2))
+    goto err;
+  SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
+                  silc_hmac_len(hmac));
+  SILC_LOG_DEBUG(("Get signature"));
+  sig = silc_message_get_signature(message);
+  if (!sig)
+    goto err;
+  SILC_LOG_DEBUG(("Verifying signature"));
+  if (silc_message_signed_verify(sig, message, public_key, hash) !=
+      SILC_AUTH_OK)
+    goto err;
+  SILC_LOG_DEBUG(("Signature Ok"));
+  SILC_LOG_DEBUG(("Get public key"));
+  pk2 = silc_message_signed_get_public_key(sig, NULL, NULL);
+  if (!pk2)
+    goto err;
+  SILC_LOG_DEBUG(("Verify public key"));
+  if (!silc_pkcs_public_key_compare(public_key, pk2))
+    goto err;
+  SILC_LOG_DEBUG(("Public key Ok"));
+  silc_pkcs_public_key_free(pk2);
+  silc_message_payload_free(message);
+
+  /* Digitally signed private message (no encryption) */
+  for (i = 0; i < sizeof(tmp) / 2; i++)
+    tmp[i] = (32 + i) & 127;
+  SILC_LOG_DEBUG(("Encoding private message len %d SIGNED",
+                 sizeof(tmp) / 2));
+  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
+                                   SILC_MESSAGE_FLAG_UTF8 |
+                                   SILC_MESSAGE_FLAG_ACK |
+                                   SILC_MESSAGE_FLAG_SIGNED,
+                                   tmp, sizeof(tmp) / 2, FALSE, TRUE,
+                                   NULL, NULL, rng,
+                                   public_key, private_key, hash, buf);
+  if (!buf)
+    goto err;
+  SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf));
+  SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
+  message = silc_message_payload_parse(silc_buffer_data(buf),
+                                      silc_buffer_len(buf), TRUE, FALSE,
+                                      NULL, NULL);
+  if (!message)
+    goto err;
+  flags = silc_message_get_flags(message);
+  SILC_LOG_DEBUG(("Flags: %x", flags));
+  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_ACK))
+    goto err;
+  if (!(flags & SILC_MESSAGE_FLAG_SIGNED))
+    goto err;
+  data = silc_message_get_data(message, &data_len);
+  SILC_LOG_HEXDUMP(("Data"), data, data_len);
+  if (data_len != sizeof(tmp) / 2 || memcmp(data, tmp, sizeof(tmp) / 2))
+    goto err;
+  SILC_LOG_DEBUG(("Get signature"));
+  sig = silc_message_get_signature(message);
+  if (!sig)
+    goto err;
+  SILC_LOG_DEBUG(("Verifying signature"));
+  if (silc_message_signed_verify(sig, message, public_key, hash) !=
+      SILC_AUTH_OK)
+    goto err;
+  SILC_LOG_DEBUG(("Signature Ok"));
+  SILC_LOG_DEBUG(("Get public key"));
+  pk2 = silc_message_signed_get_public_key(sig, NULL, NULL);
+  if (!pk2)
+    goto err;
+  SILC_LOG_DEBUG(("Verify public key"));
+  if (!silc_pkcs_public_key_compare(public_key, pk2))
+    goto err;
+  SILC_LOG_DEBUG(("Public key Ok"));
+  silc_pkcs_public_key_free(pk2);
+  silc_message_payload_free(message);
+
+
+  success = TRUE;
+  SILC_LOG_DEBUG(("Cleanup"));
+  silc_pkcs_public_key_free(public_key);
+  silc_pkcs_private_key_free(private_key);
+  silc_cipher_free(key);
+  silc_hash_free(hash);
+  silc_rng_free(rng);
+
+ err:
+  silc_cipher_unregister_all();
+  silc_hash_unregister_all();
+  silc_hmac_unregister_all();
+  silc_pkcs_unregister_all();
+
+  SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
+  fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
+
+  return success;
+}