From ab7222201001be00e81f2bb7df98e67753eb79cb Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Sun, 5 Nov 2006 13:04:15 +0000 Subject: [PATCH] Fixed parsing mesage payload. Removed silc_message_get_iv. Added message payload tester program. --- lib/silccore/silcmessage.c | 28 +- lib/silccore/silcmessage.h | 15 - lib/silccore/tests/Makefile.am | 3 +- lib/silccore/tests/test_silcmessage.c | 387 ++++++++++++++++++++++++++ 4 files changed, 397 insertions(+), 36 deletions(-) create mode 100644 lib/silccore/tests/test_silcmessage.c diff --git a/lib/silccore/silcmessage.c b/lib/silccore/silcmessage.c index f7adbc2b..ff8a8433 100644 --- a/lib/silccore/silcmessage.c +++ b/lib/silccore/silcmessage.c @@ -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 diff --git a/lib/silccore/silcmessage.h b/lib/silccore/silcmessage.h index 1ff19512..186844f7 100644 --- a/lib/silccore/silcmessage.h +++ b/lib/silccore/silcmessage.h @@ -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 diff --git a/lib/silccore/tests/Makefile.am b/lib/silccore/tests/Makefile.am index 7adf83c4..95577501 100644 --- a/lib/silccore/tests/Makefile.am +++ b/lib/silccore/tests/Makefile.am @@ -17,9 +17,10 @@ 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 index 00000000..e6feb3ae --- /dev/null +++ b/lib/silccore/tests/test_silcmessage.c @@ -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; +} -- 2.24.0