SilcChannelEntry silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode, SilcChannelID *id, SilcServerEntry router, SilcCipher send_key, SilcCipher receive_key, SilcHmac hmac) { SilcChannelEntry channel; char *channel_namec = NULL; SILC_LOG_DEBUG(("Adding new channel %s", channel_name)); /* Normalize name. This is cached, original is in client context. */ if (channel_name) { channel_namec = silc_channel_name_check(channel_name, strlen(channel_name), SILC_STRING_UTF8, 256, NULL); if (!channel_namec) return NULL; } channel = silc_calloc(1, sizeof(*channel)); channel->channel_name = channel_name; channel->mode = mode; channel->id = id; channel->router = router; channel->send_key = send_key; channel->receive_key = receive_key; channel->hmac = hmac; channel->created = channel->updated = time(0); if (!channel->hmac) if (!silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac)) { silc_free(channel); return NULL; } channel->user_list = silc_hash_table_alloc(3, silc_hash_ptr, NULL, NULL, NULL, NULL, NULL, TRUE); if (!silc_idcache_add(id_list->channels, channel_namec, (void *)channel->id, (void *)channel)) { silc_hmac_free(channel->hmac); silc_hash_table_free(channel->user_list); silc_free(channel); silc_free(channel_namec); return NULL; } return channel; }
int main(int argc, char **argv) { SilcBool success = FALSE; unsigned char digest[20]; SilcUInt32 len; SilcHmac hmac; if (argc > 1 && !strcmp(argv[1], "-d")) { silc_log_debug(TRUE); silc_log_debug_hexdump(TRUE); silc_log_set_debug_string("*crypt*,*hash*,*sha1*,*hmac*"); } SILC_LOG_DEBUG(("Registering builtin hash functions")); silc_hash_register_default(); silc_hmac_register_default(); SILC_LOG_DEBUG(("Allocating sha1 HMAC")); if (!silc_hmac_alloc("hmac-sha1", NULL, &hmac)) { SILC_LOG_DEBUG(("Allocating sha1 HMAC failed")); goto err; } /* First test vector */ SILC_LOG_DEBUG(("First test vector")); silc_hmac_init_with_key(hmac, key1, key1_len); silc_hmac_update(hmac, data1, strlen(data1)); silc_hmac_final(hmac, digest, &len); SILC_LOG_HEXDUMP(("Key"), (unsigned char *)key1, key1_len); SILC_LOG_HEXDUMP(("Message"), (unsigned char *)data1, strlen(data1)); SILC_LOG_HEXDUMP(("Digest"), digest, len); SILC_LOG_HEXDUMP(("Expected digest"), (unsigned char *)data1_digest, len); if (memcmp(digest, data1_digest, len)) { SILC_LOG_DEBUG(("HMAC failed")); goto err; } SILC_LOG_DEBUG(("HMAC is successful")); /* Second test vector */ SILC_LOG_DEBUG(("Second test vector")); silc_hmac_init_with_key(hmac, key2, key2_len); silc_hmac_update(hmac, data2, strlen(data2)); silc_hmac_final(hmac, digest, &len); SILC_LOG_HEXDUMP(("Key"), (unsigned char *)key2, key2_len); SILC_LOG_HEXDUMP(("Message"), (unsigned char *)data2, strlen(data2)); SILC_LOG_HEXDUMP(("Digest"), digest, len); SILC_LOG_HEXDUMP(("Expected digest"), (unsigned char *)data2_digest, len); if (memcmp(digest, data2_digest, len)) { SILC_LOG_DEBUG(("HMAC failed")); goto err; } SILC_LOG_DEBUG(("HMAC is successful")); /* Third test vector */ SILC_LOG_DEBUG(("Third test vector")); silc_hmac_init_with_key(hmac, key3, key3_len); memset(data3, '\xdd', sizeof(data3)); silc_hmac_update(hmac, data3, sizeof(data3)); silc_hmac_final(hmac, digest, &len); SILC_LOG_HEXDUMP(("Key"), (unsigned char *)key3, key3_len); SILC_LOG_HEXDUMP(("Message"), (unsigned char *)data3, sizeof(data3)); SILC_LOG_HEXDUMP(("Digest"), digest, len); SILC_LOG_HEXDUMP(("Expected digest"), (unsigned char *)data3_digest, len); if (memcmp(digest, data3_digest, len)) { SILC_LOG_DEBUG(("HMAC failed")); goto err; } SILC_LOG_DEBUG(("HMAC is successful")); /* Fourth test vector */ SILC_LOG_DEBUG(("Fourth test vector")); memset(key4, '\xaa', key4_len); silc_hmac_init_with_key(hmac, key4, key4_len); silc_hmac_update(hmac, data4, strlen(data4)); silc_hmac_final(hmac, digest, &len); SILC_LOG_HEXDUMP(("Key"), (unsigned char *)key4, key4_len); SILC_LOG_HEXDUMP(("Message"), (unsigned char *)data4, sizeof(data4)); SILC_LOG_HEXDUMP(("Digest"), digest, len); SILC_LOG_HEXDUMP(("Expected digest"), (unsigned char *)data4_digest, len); if (memcmp(digest, data4_digest, len)) { SILC_LOG_DEBUG(("HMAC failed")); goto err; } SILC_LOG_DEBUG(("HMAC is successful")); success = TRUE; err: SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE")); fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE"); silc_hmac_free(hmac); silc_hash_unregister_all(); silc_hmac_unregister_all(); return success; }
SilcBool silc_client_add_private_message_key_ske(SilcClient client, SilcClientConnection conn, SilcClientEntry client_entry, const char *cipher, const char *hmac, SilcSKEKeyMaterial keymat) { if (!client || !client_entry) return FALSE; /* Return FALSE if key already set */ if (client_entry->internal.send_key && client_entry->internal.receive_key) return FALSE; if (!cipher) cipher = SILC_DEFAULT_CIPHER; if (!hmac) hmac = SILC_DEFAULT_HMAC; /* Check the requested cipher and HMAC */ if (!silc_cipher_is_supported(cipher)) return FALSE; if (!silc_hmac_is_supported(hmac)) return FALSE; client_entry->internal.generated = TRUE; /* Allocate the cipher and HMAC */ if (!silc_cipher_alloc(cipher, &client_entry->internal.send_key)) return FALSE; if (!silc_cipher_alloc(cipher, &client_entry->internal.receive_key)) return FALSE; if (!silc_hmac_alloc(hmac, NULL, &client_entry->internal.hmac_send)) return FALSE; if (!silc_hmac_alloc(hmac, NULL, &client_entry->internal.hmac_receive)) return FALSE; /* Set the keys */ if (client_entry->internal.prv_resp) { silc_cipher_set_key(client_entry->internal.send_key, keymat->receive_enc_key, keymat->enc_key_len, TRUE); silc_cipher_set_iv(client_entry->internal.send_key, keymat->receive_iv); silc_cipher_set_key(client_entry->internal.receive_key, keymat->send_enc_key, keymat->enc_key_len, FALSE); silc_cipher_set_iv(client_entry->internal.receive_key, keymat->send_iv); silc_hmac_set_key(client_entry->internal.hmac_send, keymat->receive_hmac_key, keymat->hmac_key_len); silc_hmac_set_key(client_entry->internal.hmac_receive, keymat->send_hmac_key, keymat->hmac_key_len); } else { silc_cipher_set_key(client_entry->internal.send_key, keymat->send_enc_key, keymat->enc_key_len, TRUE); silc_cipher_set_iv(client_entry->internal.send_key, keymat->send_iv); silc_cipher_set_key(client_entry->internal.receive_key, keymat->receive_enc_key, keymat->enc_key_len, FALSE); silc_cipher_set_iv(client_entry->internal.receive_key, keymat->receive_iv); silc_hmac_set_key(client_entry->internal.hmac_send, keymat->send_hmac_key, keymat->hmac_key_len); silc_hmac_set_key(client_entry->internal.hmac_receive, keymat->receive_hmac_key, keymat->hmac_key_len); } return TRUE; }
int main(int argc, char **argv) { SilcBool success = FALSE; SilcMessagePayload message; SilcBuffer buf; const char *msg = "FOOBAR MESSAGE"; unsigned char *data, tmp[1023], *tmp2; SilcUInt32 data_len; SilcUInt16 flags; int i, n; 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, NULL, FALSE, 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; 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 */ n = 10; SILC_LOG_DEBUG(("Encoding private message len %d (static key)", n)); buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION | SILC_MESSAGE_FLAG_UTF8 | SILC_MESSAGE_FLAG_ACK, msg, n, 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, NULL, FALSE, 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; data = silc_message_get_data(message, &data_len); SILC_LOG_HEXDUMP(("Data"), data, data_len); if (data_len != n || memcmp(data, msg, n)) goto err; SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message), silc_hmac_len(hmac)); silc_message_payload_free(message); /* Simple private message */ n = 1; SILC_LOG_DEBUG(("Encoding private message len %d (static key)", n)); buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION | SILC_MESSAGE_FLAG_UTF8 | SILC_MESSAGE_FLAG_ACK, msg, n, 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, NULL, FALSE, 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; data = silc_message_get_data(message, &data_len); SILC_LOG_HEXDUMP(("Data"), data, data_len); if (data_len != n || memcmp(data, msg, n)) 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, NULL, FALSE, 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; 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, NULL, FALSE, 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) || memcmp(data, tmp, sizeof(tmp))) goto err; SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message), silc_hmac_len(hmac)); SILC_LOG_DEBUG(("Verifying signature")); if (silc_message_signed_verify(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(message, 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, NULL, FALSE, 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_HEXDUMP(("MAC"), silc_message_get_mac(message), silc_hmac_len(hmac)); SILC_LOG_DEBUG(("Verifying signature")); if (silc_message_signed_verify(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(message, 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, NULL, FALSE, 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(("Verifying signature")); if (silc_message_signed_verify(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(message, 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 (LARGE) */ n = 65550; tmp2 = silc_malloc(n); if (!tmp2) goto err; SILC_LOG_DEBUG(("Encoding channel message len %d (static key) SIGNED LARGE", n)); buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION | SILC_MESSAGE_FLAG_UTF8 | SILC_MESSAGE_FLAG_ACK | SILC_MESSAGE_FLAG_SIGNED, tmp2, n, TRUE, FALSE, key, hmac, rng, public_key, private_key, hash, buf); if (!buf) goto err; SILC_LOG_DEBUG(("Message length: %d", silc_buffer_len(buf))); if (silc_buffer_len(buf) > SILC_PACKET_MAX_LEN) goto err; 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, NULL, FALSE, 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_DEBUG(("Data len: %d", data_len)); if (silc_buffer_len(buf) > SILC_PACKET_MAX_LEN) goto err; SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message), silc_hmac_len(hmac)); SILC_LOG_DEBUG(("Verifying signature")); if (silc_message_signed_verify(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(message, 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); silc_free(tmp2); 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; }
SilcBool silc_client_add_channel_private_key(SilcClient client, SilcClientConnection conn, SilcChannelEntry channel, const char *name, char *cipher, char *hmac, unsigned char *key, SilcUInt32 key_len, SilcChannelPrivateKey *ret_key) { SilcChannelPrivateKey entry; unsigned char hash[SILC_HASH_MAXLEN]; SilcSKEKeyMaterial keymat; if (!client || !conn || !channel) return FALSE; if (!cipher) cipher = SILC_DEFAULT_CIPHER; if (!hmac) hmac = SILC_DEFAULT_HMAC; if (!silc_cipher_is_supported(cipher)) return FALSE; if (!silc_hmac_is_supported(hmac)) return FALSE; if (!channel->internal.private_keys) { channel->internal.private_keys = silc_dlist_init(); if (!channel->internal.private_keys) return FALSE; } /* Produce the key material */ keymat = silc_ske_process_key_material_data(key, key_len, 16, 256, 16, conn->internal->sha1hash); if (!keymat) return FALSE; /* Save the key */ entry = silc_calloc(1, sizeof(*entry)); if (!entry) { silc_ske_free_key_material(keymat); return FALSE; } entry->name = name ? strdup(name) : NULL; /* Allocate the cipher and set the key */ if (!silc_cipher_alloc(cipher, &entry->send_key)) { silc_free(entry); silc_free(entry->name); silc_ske_free_key_material(keymat); return FALSE; } if (!silc_cipher_alloc(cipher, &entry->receive_key)) { silc_free(entry); silc_free(entry->name); silc_cipher_free(entry->send_key); silc_ske_free_key_material(keymat); return FALSE; } silc_cipher_set_key(entry->send_key, keymat->send_enc_key, keymat->enc_key_len, TRUE); silc_cipher_set_key(entry->receive_key, keymat->send_enc_key, keymat->enc_key_len, FALSE); /* Generate HMAC key from the channel key data and set it */ if (!silc_hmac_alloc(hmac, NULL, &entry->hmac)) { silc_free(entry); silc_free(entry->name); silc_cipher_free(entry->send_key); silc_cipher_free(entry->receive_key); silc_ske_free_key_material(keymat); return FALSE; } silc_hash_make(silc_hmac_get_hash(entry->hmac), keymat->send_enc_key, keymat->enc_key_len / 8, hash); silc_hmac_set_key(entry->hmac, hash, silc_hash_len(silc_hmac_get_hash(entry->hmac))); memset(hash, 0, sizeof(hash)); /* Add to the private keys list */ silc_dlist_add(channel->internal.private_keys, entry); if (!channel->internal.curr_key) { channel->internal.curr_key = entry; channel->cipher = silc_cipher_get_name(entry->send_key); channel->hmac = silc_cipher_get_name(entry->send_key); } /* Free the key material */ silc_ske_free_key_material(keymat); if (ret_key) *ret_key = entry; return TRUE; }
SilcBool silc_client_save_channel_key(SilcClient client, SilcClientConnection conn, SilcBuffer key_payload, SilcChannelEntry channel) { unsigned char *id_string, *key, *cipher, *hmac, hash[SILC_HASH_MAXLEN]; SilcUInt32 tmp_len; SilcChannelID id; SilcChannelKeyPayload payload; SILC_LOG_DEBUG(("New channel key")); payload = silc_channel_key_payload_parse(silc_buffer_data(key_payload), silc_buffer_len(key_payload)); if (!payload) return FALSE; id_string = silc_channel_key_get_id(payload, &tmp_len); if (!id_string) { silc_channel_key_payload_free(payload); return FALSE; } if (!silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL, &id, sizeof(id))) { silc_channel_key_payload_free(payload); return FALSE; } /* Find channel. */ if (!channel) { channel = silc_client_get_channel_by_id(client, conn, &id); if (!channel) { SILC_LOG_DEBUG(("Key for unknown channel")); silc_channel_key_payload_free(payload); return FALSE; } } else { silc_client_ref_channel(client, conn, channel); } /* Save the old key for a short period of time so that we can decrypt channel message even after the rekey if some client would be sending messages with the old key after the rekey. */ if (!channel->internal.old_channel_keys) channel->internal.old_channel_keys = silc_dlist_init(); if (!channel->internal.old_hmacs) channel->internal.old_hmacs = silc_dlist_init(); if (channel->internal.old_channel_keys && channel->internal.old_hmacs) { silc_dlist_add(channel->internal.old_channel_keys, channel->internal.receive_key); silc_dlist_add(channel->internal.old_hmacs, channel->internal.hmac); silc_schedule_task_add_timeout(client->schedule, silc_client_save_channel_key_rekey, channel, 15, 0); } /* Get channel cipher */ cipher = silc_channel_key_get_cipher(payload, NULL); if (!silc_cipher_alloc(cipher, &channel->internal.send_key)) { client->internal->ops->say( conn->client, conn, SILC_CLIENT_MESSAGE_AUDIT, "Cannot talk to channel: unsupported cipher %s", cipher); silc_client_unref_channel(client, conn, channel); silc_channel_key_payload_free(payload); return FALSE; } if (!silc_cipher_alloc(cipher, &channel->internal.receive_key)) { client->internal->ops->say( conn->client, conn, SILC_CLIENT_MESSAGE_AUDIT, "Cannot talk to channel: unsupported cipher %s", cipher); silc_client_unref_channel(client, conn, channel); silc_channel_key_payload_free(payload); return FALSE; } /* Set the cipher key. Both sending and receiving keys are same */ key = silc_channel_key_get_key(payload, &tmp_len); silc_cipher_set_key(channel->internal.send_key, key, tmp_len * 8, TRUE); silc_cipher_set_key(channel->internal.receive_key, key, tmp_len * 8, FALSE); /* Get channel HMAC */ hmac = (channel->internal.hmac ? (char *)silc_hmac_get_name(channel->internal.hmac) : SILC_DEFAULT_HMAC); if (!silc_hmac_alloc(hmac, NULL, &channel->internal.hmac)) { client->internal->ops->say( conn->client, conn, SILC_CLIENT_MESSAGE_AUDIT, "Cannot talk to channel: unsupported HMAC %s", hmac); silc_client_unref_channel(client, conn, channel); silc_channel_key_payload_free(payload); return FALSE; } channel->cipher = silc_cipher_get_name(channel->internal.send_key); channel->hmac = silc_hmac_get_name(channel->internal.hmac); /* Set HMAC key */ silc_hash_make(silc_hmac_get_hash(channel->internal.hmac), key, tmp_len, hash); silc_hmac_set_key(channel->internal.hmac, hash, silc_hash_len(silc_hmac_get_hash(channel->internal.hmac))); memset(hash, 0, sizeof(hash)); silc_channel_key_payload_free(payload); silc_client_unref_channel(client, conn, channel); return TRUE; }