Example #1
0
SilcBuffer silc_public_key_payload_encode(SilcPublicKey public_key)
{
  SilcBuffer buffer;
  unsigned char *pk;
  SilcUInt32 pk_len;
  SilcPKCSType type;

  if (!public_key)
    return NULL;

  type = silc_pkcs_get_type(public_key);
  pk = silc_pkcs_public_key_encode(public_key, &pk_len);
  if (!pk)
    return NULL;

  buffer = silc_buffer_alloc_size(4 + pk_len);
  if (!buffer) {
    silc_free(pk);
    return NULL;
  }

  if (silc_buffer_format(buffer,
			 SILC_STR_UI_SHORT(pk_len),
			 SILC_STR_UI_SHORT(type),
			 SILC_STR_DATA(pk, pk_len),
			 SILC_STR_END) < 0) {
    silc_buffer_free(buffer);
    silc_free(pk);
    return NULL;
  }

  silc_free(pk);
  return buffer;
}
Example #2
0
SilcPrivateKey silc_acc_private_key(SilcAccelerator acc,
				    SilcPrivateKey private_key)
{
  SilcPrivateKey privkey;
  SilcAcceleratorPrivateKey acc_privkey;
  const SilcPKCSAlgorithm *alg;
  int i;

  if (!acc || !private_key)
    return NULL;

  SILC_LOG_DEBUG(("Accelerate private key %p with accelerator %s",
		  private_key, acc->name));

  if (!acc->pkcs) {
    SILC_LOG_ERROR(("Accelerator '%s' does not support private key "
		    "acceleration", acc->name));
    return NULL;
  }

  if (silc_acc_get_private_key(NULL, private_key)) {
    SILC_LOG_DEBUG(("Private key %p is already accelerated", private_key));
    return NULL;
  }

  /* Check that accelerator supports this private key algorithm */
  alg = silc_pkcs_get_algorithm(private_key);
  if (!alg)
    return NULL;
  for (i = 0; acc->pkcs[i].name; i++) {
    if ((!strcmp(acc->pkcs[i].name, alg->name) &&
	 !strcmp(acc->pkcs[i].scheme, alg->scheme)) ||
	!strcmp(acc->pkcs[i].name, "any")) {
      alg = NULL;
      break;
    }
  }
  if (alg) {
    SILC_LOG_DEBUG(("Accelerator %s does not support %s/%s acceleration",
		    acc->name, alg->name, alg->scheme));
    return NULL;
  }

  privkey = silc_calloc(1, sizeof(*privkey));
  if (!privkey)
    return NULL;

  /* Allocate PKCS operations */
  privkey->pkcs = silc_calloc(1, sizeof(*privkey->pkcs));
  if (!privkey->pkcs) {
    silc_free(privkey);
    return NULL;
  }
  *privkey->pkcs = silc_acc_pkcs;
  privkey->pkcs->type = silc_pkcs_get_type(private_key);
  privkey->alg = silc_pkcs_get_algorithm(private_key);

  /* Allocate accelerator public key */
  acc_privkey = silc_calloc(1, sizeof(*acc_privkey));
  if (!acc_privkey) {
    silc_free(privkey->pkcs);
    silc_free(privkey);
    return NULL;
  }
  acc_privkey->magic = SILC_ACC_KEY_MAGIC;
  acc_privkey->accelerated = private_key;
  acc_privkey->acc = acc;
  acc_privkey->pkcs_index = i;

  /* Accelerate the public key.  Returns accelerator context.  The
     import_public_key operation is used to accelerate the key. */
  if (!acc->pkcs[i].import_private_key(&acc->pkcs[i], private_key, 0,
				       &acc_privkey->context)) {
    SILC_LOG_ERROR(("Error accelerating private key with accelerator '%s'",
		    acc->name));
    silc_free(acc_privkey);
    silc_free(privkey->pkcs);
    silc_free(privkey);
    return NULL;
  }
  privkey->private_key = acc_privkey;

  SILC_LOG_DEBUG(("New accelerated private key %p", privkey));

  return privkey;
}
Example #3
0
void silcpurple_show_public_key(SilcPurple sg,
				const char *name, SilcPublicKey public_key,
				GCallback callback, void *context)
{
	SilcPublicKeyIdentifier ident;
	SilcSILCPublicKey silc_pubkey;
	char *fingerprint, *babbleprint;
	unsigned char *pk;
	SilcUInt32 pk_len, key_len = 0;
	GString *s;

	/* We support showing only SILC public keys for now */
	if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC)
	  return;

	silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
	ident = &silc_pubkey->identifier;
	key_len = silc_pkcs_public_key_get_len(public_key);

	pk = silc_pkcs_public_key_encode(public_key, &pk_len);
	if (!pk)
	  return;
	fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
	babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
	if (!fingerprint || !babbleprint)
	  return;

	s = g_string_new("");
	if (ident->realname)
		/* Hint for translators: Please check the tabulator width here and in
		   the next strings (short strings: 2 tabs, longer strings 1 tab,
		   sum: 3 tabs or 24 characters) */
		g_string_append_printf(s, _("Real Name: \t%s\n"), ident->realname);
	if (ident->username)
		g_string_append_printf(s, _("User Name: \t%s\n"), ident->username);
	if (ident->email)
		g_string_append_printf(s, _("Email: \t\t%s\n"), ident->email);
	if (ident->host)
		g_string_append_printf(s, _("Host Name: \t%s\n"), ident->host);
	if (ident->org)
		g_string_append_printf(s, _("Organization: \t%s\n"), ident->org);
	if (ident->country)
		g_string_append_printf(s, _("Country: \t%s\n"), ident->country);
	g_string_append_printf(s, _("Algorithm: \t%s\n"), silc_pubkey->pkcs->name);
	g_string_append_printf(s, _("Key Length: \t%d bits\n"), (int)key_len);
	if (ident->version)
	  g_string_append_printf(s, _("Version: \t%s\n"), ident->version);
	g_string_append_printf(s, "\n");
	g_string_append_printf(s, _("Public Key Fingerprint:\n%s\n\n"), fingerprint);
	g_string_append_printf(s, _("Public Key Babbleprint:\n%s"), babbleprint);

	purple_request_action(sg->gc, _("Public Key Information"),
			      _("Public Key Information"),
			      s->str, 0, purple_connection_get_account(sg->gc),
			      NULL, NULL, context, 1, _("Close"), callback);

	g_string_free(s, TRUE);
	silc_free(fingerprint);
	silc_free(babbleprint);
	silc_free(pk);
}
Example #4
0
File: pk.c Project: Lilitana/Pidgin
void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn,
				  const char *name, SilcConnectionType conn_type,
				  SilcPublicKey public_key,
				  SilcVerifyPublicKey completion, void *context)
{
	PurpleConnection *gc = client->application;
	int i;
	char file[256], filename[256], filename2[256], *ipf, *hostf = NULL;
	char *fingerprint, *babbleprint;
	struct passwd *pw;
	struct stat st;
	char *entity = ((conn_type == SILC_CONN_SERVER ||
			 conn_type == SILC_CONN_ROUTER) ?
			"server" : "client");
	PublicKeyVerify verify;
	const char *ip, *hostname;
	SilcUInt16 port;
	unsigned char *pk;
	SilcUInt32 pk_len;

	if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC) {
		purple_notify_error(gc, _("Verify Public Key"),
				    _("Unsupported public key type"), NULL);
		if (completion)
			completion(FALSE, context);
		return;
	}

	pw = getpwuid(getuid());
	if (!pw) {
		if (completion)
			completion(FALSE, context);
		return;
	}

	memset(filename, 0, sizeof(filename));
	memset(filename2, 0, sizeof(filename2));
	memset(file, 0, sizeof(file));

	silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->stream),
				    NULL, &hostname, &ip, &port);

	pk = silc_pkcs_public_key_encode(public_key, &pk_len);
	if (!pk) {
		if (completion)
			completion(FALSE, context);
		return;
	}

	if (conn_type == SILC_CONN_SERVER ||
	    conn_type == SILC_CONN_ROUTER) {
		if (!name) {
			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
				   ip, port);
			g_snprintf(filename, sizeof(filename) - 1,
				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
				   silcpurple_silcdir(), entity, file);

			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
				   hostname, port);
			g_snprintf(filename2, sizeof(filename2) - 1,
				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
				   silcpurple_silcdir(), entity, file);

			ipf = filename;
			hostf = filename2;
		} else {
			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
				   name, port);
			g_snprintf(filename, sizeof(filename) - 1,
				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
				   silcpurple_silcdir(), entity, file);

			ipf = filename;
		}
	} else {
		/* Replace all whitespaces with `_'. */
		fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
		for (i = 0; i < strlen(fingerprint); i++)
			if (fingerprint[i] == ' ')
				fingerprint[i] = '_';

		g_snprintf(file, sizeof(file) - 1, "%skey_%s.pub", entity, fingerprint);
		g_snprintf(filename, sizeof(filename) - 1,
			   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
			   silcpurple_silcdir(), entity, file);
		silc_free(fingerprint);

		ipf = filename;
	}

	verify = silc_calloc(1, sizeof(*verify));
	if (!verify)
		return;
	verify->client = client;
	verify->conn = conn;
	verify->filename = g_strdup(ipf);
	verify->entity = g_strdup(entity);
	verify->entity_name = (conn_type != SILC_CONN_CLIENT ?
			       (name ? g_strdup(name) : g_strdup(hostname))
			       : NULL);
	verify->public_key = silc_pkcs_public_key_copy(public_key);
	verify->completion = completion;
	verify->context = context;
	fingerprint = verify->fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
	babbleprint = verify->babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);

	/* Check whether this key already exists */
	if (g_stat(ipf, &st) < 0 && (!hostf || g_stat(hostf, &st) < 0)) {
		/* Key does not exist, ask user to verify the key and save it */
		silcpurple_verify_ask(name ? name : entity,
				      fingerprint, babbleprint, verify);
		return;
	} else {
		/* The key already exists, verify it. */
		SilcPublicKey public_key;
		unsigned char *encpk;
		SilcUInt32 encpk_len;

		/* Load the key file, try for both IP filename and hostname filename */
		if (!silc_pkcs_load_public_key(ipf, &public_key) &&
		    (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key)))) {
			silcpurple_verify_ask(name ? name : entity,
					    fingerprint, babbleprint, verify);
			return;
		}

		/* Encode the key data */
		encpk = silc_pkcs_public_key_encode(public_key, &encpk_len);
		if (!encpk) {
			silcpurple_verify_ask(name ? name : entity,
					    fingerprint, babbleprint, verify);
			return;
		}

		/* Compare the keys */
		if (memcmp(encpk, pk, encpk_len)) {
			/* Ask user to verify the key and save it */
			verify->changed = TRUE;
			silcpurple_verify_ask(name ? name : entity,
					    fingerprint, babbleprint, verify);
			return;
		}

		/* Local copy matched */
		if (completion)
			completion(TRUE, context);
		g_free(verify->filename);
		g_free(verify->entity);
		g_free(verify->entity_name);
		silc_free(verify->fingerprint);
		silc_free(verify->babbleprint);
		silc_pkcs_public_key_free(verify->public_key);
		silc_free(verify);
	}
}