Пример #1
0
SilcBool silc_client_add_private_message_key(SilcClient client,
					     SilcClientConnection conn,
					     SilcClientEntry client_entry,
					     const char *cipher,
					     const char *hmac,
					     unsigned char *key,
					     SilcUInt32 key_len)
{
  SilcSKEKeyMaterial keymat;
  SilcBool ret;

  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;

  /* Save the key */
  client_entry->internal.key = silc_memdup(key, key_len);
  client_entry->internal.key_len = key_len;

  /* Produce the key material as the protocol defines */
  keymat = silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
					      conn->internal->sha1hash);
  if (!keymat)
    return FALSE;

  /* Set the key into use */
  ret = silc_client_add_private_message_key_ske(client, conn, client_entry,
						cipher, hmac, keymat);
  client_entry->internal.generated = FALSE;

  /* Free the key material */
  silc_ske_free_key_material(keymat);

  /* If we are setting the key without a request from the remote client,
     we will send request to remote. */
  if (!client_entry->internal.prv_resp)
    silc_client_send_private_message_key_request(client, conn, client_entry);

  return ret;
}
Пример #2
0
static void
silcpurple_buddy_keyagr_cb(SilcClient client,
			 SilcClientConnection conn,
			 SilcClientEntry client_entry,
			 SilcKeyAgreementStatus status,
			 SilcSKEKeyMaterial *key,
			 void *context)
{
	PurpleConnection *gc = client->application;
	SilcPurple sg = gc->proto_data;
	SilcPurpleKeyAgr a = context;

	if (!sg->conn)
		return;

	switch (status) {
	case SILC_KEY_AGREEMENT_OK:
		{
			PurpleConversation *convo;
			char tmp[128];

			/* Set the private key for this client */
			silc_client_del_private_message_key(client, conn, client_entry);
			silc_client_add_private_message_key_ske(client, conn, client_entry,
								NULL, NULL, key, a->responder);
			silc_ske_free_key_material(key);


			/* Open IM window */
			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
									client_entry->nickname, sg->account);
			if (convo) {
				/* we don't have windows in the core anymore...but we may want to
				 * provide some method for asking the UI to show the window
				purple_conv_window_show(purple_conversation_get_window(convo));
				 */
			} else {
				convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, sg->account,
							      client_entry->nickname);
			}
			g_snprintf(tmp, sizeof(tmp), "%s [private key]", client_entry->nickname);
			purple_conversation_set_title(convo, tmp);
		}
		break;

	case SILC_KEY_AGREEMENT_ERROR:
		purple_notify_error(gc, _("Key Agreement"),
				  _("Error occurred during key agreement"), NULL);
		break;

	case SILC_KEY_AGREEMENT_FAILURE:
		purple_notify_error(gc, _("Key Agreement"), _("Key Agreement failed"), NULL);
		break;

	case SILC_KEY_AGREEMENT_TIMEOUT:
		purple_notify_error(gc, _("Key Agreement"),
				  _("Timeout during key agreement"), NULL);
		break;

	case SILC_KEY_AGREEMENT_ABORTED:
		purple_notify_error(gc, _("Key Agreement"),
				  _("Key agreement was aborted"), NULL);
		break;

	case SILC_KEY_AGREEMENT_ALREADY_STARTED:
		purple_notify_error(gc, _("Key Agreement"),
				  _("Key agreement is already started"), NULL);
		break;

	case SILC_KEY_AGREEMENT_SELF_DENIED:
		purple_notify_error(gc, _("Key Agreement"),
				  _("Key agreement cannot be started with yourself"),
				  NULL);
		break;

	default:
		break;
	}

	silc_free(a);
}
Пример #3
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;
}