Esempio n. 1
0
void silc_client_current_channel_private_key(SilcClient client,
					     SilcClientConnection conn,
					     SilcChannelEntry channel,
					     SilcChannelPrivateKey key)
{
  if (!channel)
    return;
  channel->internal.curr_key = key;
  channel->cipher = silc_cipher_get_name(key->send_key);
  channel->hmac = silc_hmac_get_name(key->hmac);
}
Esempio n. 2
0
SilcPrivateMessageKeys
silc_client_list_private_message_keys(SilcClient client,
				      SilcClientConnection conn,
				      SilcUInt32 *key_count)
{
  SilcPrivateMessageKeys keys;
  SilcUInt32 count = 0;
  SilcList list;
  SilcIDCacheEntry id_cache;
  SilcClientEntry entry;

  if (!client || !conn)
    return NULL;

  silc_mutex_lock(conn->internal->lock);
  if (!silc_idcache_get_all(conn->internal->client_cache, &list)) {
    silc_mutex_unlock(conn->internal->lock);
    return NULL;
  }

  keys = silc_calloc(silc_list_count(list), sizeof(*keys));
  if (!keys) {
    silc_mutex_unlock(conn->internal->lock);
    return NULL;
  }

  silc_list_start(list);
  while ((id_cache = silc_list_get(list))) {
    entry = id_cache->context;
    if (entry->internal.send_key) {
      keys[count].client_entry = entry;
      keys[count].cipher = (char *)silc_cipher_get_name(entry->internal.
							send_key);
      keys[count].key = (entry->internal.generated == FALSE ?
			 entry->internal.key : NULL);
      keys[count].key_len = (entry->internal.generated == FALSE ?
			     entry->internal.key_len : 0);
      count++;
    }
  }

  silc_mutex_unlock(conn->internal->lock);

  if (key_count)
    *key_count = count;

  return keys;
}
Esempio n. 3
0
SilcBool silc_client_del_channel_private_key(SilcClient client,
					     SilcClientConnection conn,
					     SilcChannelEntry channel,
					     SilcChannelPrivateKey key)
{
  SilcChannelPrivateKey entry;

  if (!client || !conn || !channel)
    return FALSE;

  if (!channel->internal.private_keys)
    return FALSE;

  silc_dlist_start(channel->internal.private_keys);
  while ((entry = silc_dlist_get(channel->internal.private_keys))) {
    if (entry != key)
      continue;

    if (channel->internal.curr_key == entry) {
      channel->internal.curr_key = NULL;
      channel->cipher = silc_cipher_get_name(channel->internal.send_key);
      channel->hmac = silc_hmac_get_name(channel->internal.hmac);
    }

    silc_dlist_del(channel->internal.private_keys, entry);
    silc_free(entry->name);
    silc_cipher_free(entry->send_key);
    silc_cipher_free(entry->receive_key);
    silc_hmac_free(entry->hmac);
    silc_free(entry);

    if (silc_dlist_count(channel->internal.private_keys) == 0) {
      silc_dlist_uninit(channel->internal.private_keys);
      channel->internal.private_keys = NULL;
    }

    return TRUE;
  }

  return FALSE;
}
Esempio n. 4
0
static SilcBool
silc_client_send_private_message_key_request(SilcClient client,
					     SilcClientConnection conn,
					     SilcClientEntry client_entry)
{
  const char *cipher, *hmac;

  SILC_LOG_DEBUG(("Sending private message key request"));

  cipher = silc_cipher_get_name(client_entry->internal.send_key);
  hmac = silc_hmac_get_name(client_entry->internal.hmac_send);

  /* Send the packet */
  return silc_packet_send_va_ext(conn->stream,
				 SILC_PACKET_PRIVATE_MESSAGE_KEY,
				 0, 0, NULL, SILC_ID_CLIENT,
				 &client_entry->id, NULL, NULL,
				 SILC_STR_UI_SHORT(strlen(cipher)),
				 SILC_STR_DATA(cipher, strlen(cipher)),
				 SILC_STR_UI_SHORT(strlen(hmac)),
				 SILC_STR_DATA(hmac, strlen(hmac)),
				 SILC_STR_END);
}
Esempio n. 5
0
static void
silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components)
{
	SilcPurple sg = gc->proto_data;
	const char *chname;
	char *buf, tmp[256], *tmp2;
	GString *s;
	SilcChannelEntry channel;
	SilcHashTableList htl;
	SilcChannelUser chu;

	if (!components)
		return;

	chname = g_hash_table_lookup(components, "channel");
	if (!chname)
		return;
	channel = silc_client_get_channel(sg->client, sg->conn,
					  (char *)chname);
	if (!channel) {
		silc_client_get_channel_resolve(sg->client, sg->conn,
						(char *)chname,
						silcpurple_chat_getinfo_res,
						components);
		return;
	}

	s = g_string_new("");
	tmp2 = g_markup_escape_text(channel->channel_name, -1);
	g_string_append_printf(s, _("<b>Channel Name:</b> %s"), tmp2);
	g_free(tmp2);
	if (channel->user_list && silc_hash_table_count(channel->user_list))
		g_string_append_printf(s, _("<br><b>User Count:</b> %d"),
				       (int)silc_hash_table_count(channel->user_list));

	silc_hash_table_list(channel->user_list, &htl);
	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
		if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) {
			tmp2 = g_markup_escape_text(chu->client->nickname, -1);
			g_string_append_printf(s, _("<br><b>Channel Founder:</b> %s"),
					       tmp2);
			g_free(tmp2);
			break;
		}
	}
	silc_hash_table_list_reset(&htl);

	if (channel->channel_key)
		g_string_append_printf(s, _("<br><b>Channel Cipher:</b> %s"),
				       silc_cipher_get_name(channel->channel_key));
	if (channel->hmac)
		/* Definition of HMAC: http://en.wikipedia.org/wiki/HMAC */
		g_string_append_printf(s, _("<br><b>Channel HMAC:</b> %s"),
				       silc_hmac_get_name(channel->hmac));

	if (channel->topic) {
		tmp2 = g_markup_escape_text(channel->topic, -1);
		g_string_append_printf(s, _("<br><b>Channel Topic:</b><br>%s"), tmp2);
		g_free(tmp2);
	}

	if (channel->mode) {
		g_string_append_printf(s, _("<br><b>Channel Modes:</b> "));
		silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp));
		g_string_append(s, tmp);
	}

	if (channel->founder_key) {
		char *fingerprint, *babbleprint;
		unsigned char *pk;
		SilcUInt32 pk_len;
		pk = silc_pkcs_public_key_encode(channel->founder_key, &pk_len);
		fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
		babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);

		g_string_append_printf(s, _("<br><b>Founder Key Fingerprint:</b><br>%s"), fingerprint);
		g_string_append_printf(s, _("<br><b>Founder Key Babbleprint:</b><br>%s"), babbleprint);

		silc_free(fingerprint);
		silc_free(babbleprint);
		silc_free(pk);
	}

	buf = g_string_free(s, FALSE);
	purple_notify_formatted(gc, NULL, _("Channel Information"), NULL, buf, NULL, NULL);
	g_free(buf);
}
Esempio n. 6
0
int main(int argc, char **argv)
{
  SilcBool success = FALSE;
  SilcCipher cipher, cipher2;
  unsigned char dst[256], pdst[256];
  int i;

  if (argc > 1 && !strcmp(argv[1], "-d")) {
    silc_log_debug(TRUE);
    silc_log_debug_hexdump(TRUE);
    silc_log_set_debug_string("*crypt*,*cast*,*cipher*");
  }

  SILC_LOG_DEBUG(("Registering builtin hash functions"));
  silc_cipher_register_default();

  SILC_LOG_DEBUG(("Allocating cast5-CBC cipher"));
  if (!silc_cipher_alloc("cast5-128-cbc", &cipher)) {
    SILC_LOG_DEBUG(("Allocating cas5-CBC cipher failed"));
    goto err;
  }
  if (!silc_cipher_alloc("cast5-128-cbc", &cipher2)) {
    SILC_LOG_DEBUG(("Allocating cast5-CBC cipher failed"));
    goto err;
  }

  /* First test vector */
  SILC_LOG_DEBUG(("First test vector"));
  memset(dst, 0, sizeof(dst));
  memset(pdst, 0, sizeof(pdst));
  silc_cipher_set_iv(cipher, iv1);
  assert(silc_cipher_set_key(cipher, key1, key1_len, TRUE));
  assert(silc_cipher_set_key(cipher2, key1, key1_len, FALSE));
  assert(silc_cipher_encrypt(cipher, p1, dst, p1_len, NULL));
  SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
		 silc_cipher_get_block_len(cipher),
		 silc_cipher_get_key_len(cipher),
		 silc_cipher_get_name(cipher)));
  SILC_LOG_HEXDUMP(("Plaintext"), (unsigned char *)p1, p1_len);
  SILC_LOG_HEXDUMP(("Ciphertext"), (unsigned char *)dst, p1_len);
  SILC_LOG_HEXDUMP(("Expected ciphertext"), (unsigned char *)c1, p1_len);
  if (memcmp(dst, c1, p1_len)) {
    SILC_LOG_DEBUG(("Encrypt failed"));
    goto err;
  }
  SILC_LOG_DEBUG(("Encrypt is successful"));
  silc_cipher_set_iv(cipher2, iv1);
  assert(silc_cipher_decrypt(cipher2, dst, pdst, p1_len, NULL));
  SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p1_len);
  SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p1, p1_len);
  if (memcmp(pdst, p1, p1_len)) {
    SILC_LOG_DEBUG(("Decrypt failed"));
    goto err;
  }
  SILC_LOG_DEBUG(("Decrypt is successful"));


  /* Second test vector */
  SILC_LOG_DEBUG(("Second test vector"));
  memset(dst, 0, sizeof(dst));
  memset(pdst, 0, sizeof(pdst));
  silc_cipher_set_iv(cipher, iv2);
  assert(silc_cipher_set_key(cipher, key2, key2_len, TRUE));
  assert(silc_cipher_set_key(cipher2, key2, key2_len, FALSE));
  assert(silc_cipher_encrypt(cipher, p2, dst, p2_len, NULL));
  SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
		 silc_cipher_get_block_len(cipher),
		 silc_cipher_get_key_len(cipher),
		 silc_cipher_get_name(cipher)));
  SILC_LOG_HEXDUMP(("Plaintext"), (unsigned char *)p2, p2_len);
  SILC_LOG_HEXDUMP(("Ciphertext"), (unsigned char *)dst, p2_len);
  SILC_LOG_HEXDUMP(("Expected ciphertext"), (unsigned char *)c2, p2_len);
  if (memcmp(dst, c2, p2_len)) {
    SILC_LOG_DEBUG(("Encrypt failed"));
    goto err;
  }
  SILC_LOG_DEBUG(("Encrypt is successful"));
  silc_cipher_set_iv(cipher2, iv2);
  assert(silc_cipher_decrypt(cipher2, dst, pdst, p2_len, NULL));
  SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p2_len);
  SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p2, p2_len);
  if (memcmp(pdst, p2, p2_len)) {
    SILC_LOG_DEBUG(("Decrypt failed"));
    goto err;
  }
  SILC_LOG_DEBUG(("Decrypt is successful"));
  silc_cipher_free(cipher);
  silc_cipher_free(cipher2);

  SILC_LOG_DEBUG(("Allocating cast5-128-ctr cipher"));
  if (!silc_cipher_alloc("cast5-128-ctr", &cipher)) {
    SILC_LOG_DEBUG(("Allocating cast5-128-ctr cipher failed"));
    goto err;
  }

  /* Fourth test vector */
  SILC_LOG_DEBUG(("Fourth test vector"));
  memset(dst, 0, sizeof(dst));
  memset(pdst, 0, sizeof(pdst));
  silc_cipher_set_iv(cipher, iv4);
  assert(silc_cipher_set_key(cipher, key4, key4_len, TRUE));
  assert(silc_cipher_encrypt(cipher, p4, dst, p4_len, NULL));
  SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
		 silc_cipher_get_block_len(cipher),
		 silc_cipher_get_key_len(cipher),
		 silc_cipher_get_name(cipher)));
  SILC_LOG_HEXDUMP(("Plaintext"), (unsigned char *)p4, p4_len);
  SILC_LOG_HEXDUMP(("Ciphertext"), (unsigned char *)dst, p4_len);
  SILC_LOG_HEXDUMP(("Expected ciphertext"), (unsigned char *)c4, p4_len);
  if (memcmp(dst, c4, p4_len)) {
    SILC_LOG_DEBUG(("Encrypt failed"));
    goto err;
  }
  SILC_LOG_DEBUG(("Encrypt is successful"));
  silc_cipher_set_iv(cipher, iv4);
  assert(silc_cipher_decrypt(cipher, dst, pdst, p4_len, NULL));
  SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p4_len);
  SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p4, p4_len);
  if (memcmp(pdst, p4, p4_len)) {
    SILC_LOG_DEBUG(("Decrypt failed"));
    goto err;
  }
  SILC_LOG_DEBUG(("Decrypt is successful"));
  silc_cipher_free(cipher);


  SILC_LOG_DEBUG(("Allocating cast5-128-cfb cipher"));
  if (!silc_cipher_alloc("cast5-128-cfb", &cipher)) {
    SILC_LOG_DEBUG(("Allocating cast5-128-cfb cipher failed"));
    goto err;
  }
  if (!silc_cipher_alloc("cast5-128-cfb", &cipher2)) {
    SILC_LOG_DEBUG(("Allocating cast5-128-cfb cipher failed"));
    goto err;
  }

  SILC_LOG_DEBUG(("CFB test vector"));
  memset(dst, 0, sizeof(dst));
  memset(pdst, 0, sizeof(pdst));
  silc_cipher_set_iv(cipher, iv6);
  assert(silc_cipher_set_key(cipher, key6, key6_len, TRUE));
  assert(silc_cipher_set_key(cipher2, key6, key6_len, FALSE));
  assert(silc_cipher_encrypt(cipher, p6, dst, p6_len, NULL));
  SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
		 silc_cipher_get_block_len(cipher),
		 silc_cipher_get_key_len(cipher),
		 silc_cipher_get_name(cipher)));
  SILC_LOG_HEXDUMP(("Plaintext"), (unsigned char *)p6, p6_len);
  SILC_LOG_HEXDUMP(("Ciphertext"), (unsigned char *)dst, p6_len);
  SILC_LOG_HEXDUMP(("Expected ciphertext"), (unsigned char *)c6, p6_len);
  if (memcmp(dst, c6, p6_len)) {
    SILC_LOG_DEBUG(("Encrypt failed"));
    goto err;
  }
  SILC_LOG_DEBUG(("Encrypt is successful"));
  silc_cipher_set_iv(cipher2, iv6);
  assert(silc_cipher_decrypt(cipher2, dst, pdst, p6_len, NULL));
  SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p6_len);
  SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p6, p6_len);
  if (memcmp(pdst, p6, p6_len)) {
    SILC_LOG_DEBUG(("Decrypt failed"));
    goto err;
  }
  SILC_LOG_DEBUG(("Decrypt is successful"));
  silc_cipher_free(cipher2);

  success = TRUE;

 err:
  SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
  fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");

  silc_cipher_unregister_all();
  return success;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}