static void
realize_and_take_data (GkmSshPrivateKey *self,
                       gcry_sexp_t sexp,
                       gchar *comment,
                       GBytes *private_data)
{
	GkmSexp *wrapper;

	g_assert (GKM_IS_SSH_PRIVATE_KEY (self));

	/* The base public key gets setup. */
	wrapper = gkm_sexp_new (sexp);
	gkm_sexp_key_set_base (GKM_SEXP_KEY (self), wrapper);
	gkm_sexp_key_set_base (GKM_SEXP_KEY (self->pubkey), wrapper);
	gkm_sexp_unref (wrapper);

	/* Own the comment */
	gkm_ssh_public_key_set_label (self->pubkey, comment);
	gkm_ssh_private_key_set_label (self, comment);
	g_free (comment);

	/* Own the data */
	if (self->private_bytes)
		g_bytes_unref (self->private_bytes);
	self->private_bytes = private_data;

	/* Try to parse the private data, and note if it's not actually encrypted */
	self->is_encrypted = TRUE;
	if (unlock_private_key (self, "", 0, &wrapper) == CKR_OK) {
		self->is_encrypted = FALSE;
		gkm_private_xsa_key_set_unlocked_private (GKM_PRIVATE_XSA_KEY (self), wrapper);
		gkm_sexp_unref (wrapper);
	}
}
static gboolean
gkm_mate2_public_key_real_load (GkmSerializable *base, GkmSecret *login, gconstpointer data, gsize n_data)
{
	GkmMate2PublicKey *self = GKM_MATE2_PUBLIC_KEY (base);
	GkmDataResult res;
	GkmSexp *wrapper;
	gcry_sexp_t sexp;

	g_return_val_if_fail (GKM_IS_MATE2_PUBLIC_KEY (self), FALSE);
	g_return_val_if_fail (data, FALSE);

	res = gkm_data_der_read_public_key (data, n_data, &sexp);

	switch (res) {
	case GKM_DATA_LOCKED:
		g_message ("public key is locked");
		return FALSE;
	case GKM_DATA_FAILURE:
		g_message ("couldn't parse public key");
		return FALSE;
	case GKM_DATA_UNRECOGNIZED:
		g_message ("invalid or unrecognized public key");
		return FALSE;
	case GKM_DATA_SUCCESS:
		break;
	default:
		g_assert_not_reached();
	}

	wrapper = gkm_sexp_new (sexp);
	gkm_sexp_key_set_base (GKM_SEXP_KEY (self), wrapper);
	gkm_sexp_unref (wrapper);

	return TRUE;
}
static gboolean
gkm_gnome2_private_key_real_load (GkmSerializable *base,
                                  GkmSecret *login,
                                  GBytes *data)
{
	GkmGnome2PrivateKey *self = GKM_GNOME2_PRIVATE_KEY (base);
	GkmDataResult res;
	gcry_sexp_t sexp, pub;
	GkmSexp *wrapper;
	const gchar *password;
	gsize n_password;

	if (g_bytes_get_size (data) == 0)
		return FALSE;

	res = gkm_data_der_read_private_pkcs8 (data, NULL, 0, &sexp);

	/* An unencrypted pkcs8 file */
	if (res == GKM_DATA_SUCCESS) {
		self->is_encrypted = FALSE;

	/* If it's locked, then use our token password */
	} else if (res == GKM_DATA_LOCKED) {
		self->is_encrypted = TRUE;

		if (!login) {
			g_message ("encountered private key but no private key present");
			return FALSE;
		}

		password = gkm_secret_get_password (login, &n_password);
		res = gkm_data_der_read_private_pkcs8 (data, password, n_password, &sexp);
	}

	switch (res) {
	case GKM_DATA_LOCKED:
		g_message ("private key is encrypted with wrong password");
		return FALSE;
	case GKM_DATA_FAILURE:
		g_message ("couldn't parse private key");
		return FALSE;
	case GKM_DATA_UNRECOGNIZED:
		g_message ("invalid or unrecognized private key");
		return FALSE;
	case GKM_DATA_SUCCESS:
		break;
	default:
		g_assert_not_reached();
	}

	/* Calculate a public key as our 'base' */
	if (!gkm_sexp_key_to_public (sexp, &pub))
		g_return_val_if_reached (FALSE);

	/* Keep the public part of the key around for answering queries */
	wrapper = gkm_sexp_new (pub);
	gkm_sexp_key_set_base (GKM_SEXP_KEY (self), wrapper);
	gkm_sexp_unref (wrapper);

	/* Encrypted private key, keep login and data */
	if (self->is_encrypted) {
		if (self->private_bytes)
			g_bytes_unref (self->private_bytes);
		self->private_bytes = g_bytes_ref (data);

		g_object_ref (login);
		if (self->login)
			g_object_unref (self->login);
		self->login = login;

		/* Don't need the private key any more */
		gcry_sexp_release (sexp);

	/* Not encrypted, just keep the parsed key */
	} else {
		wrapper = gkm_sexp_new (sexp);
		if (self->private_sexp)
			gkm_sexp_unref (self->private_sexp);
		self->private_sexp = wrapper;

		if (self->login)
			g_object_unref (login);
		self->login = NULL;
	}

	return TRUE;
}
Example #4
0
static gboolean
gkm_certificate_real_load (GkmSerializable *base, GkmSecret *login, gconstpointer data, gsize n_data)
{
	GkmCertificate *self = GKM_CERTIFICATE (base);
	GNode *asn1 = NULL;
	GkmDataResult res;
	guchar *copy, *keydata;
	gsize n_keydata;
	gcry_sexp_t sexp;
	GkmSexp *wrapper;

	g_return_val_if_fail (GKM_IS_CERTIFICATE (self), FALSE);

	if (!data || !n_data) {
		g_message ("cannot load empty certificate file");
		return FALSE;
	}

	copy = g_memdup (data, n_data);

	/* Parse the ASN1 data */
	res = gkm_data_der_read_certificate (copy, n_data, &asn1);
	if (res != GKM_DATA_SUCCESS) {
		g_message ("couldn't parse certificate data");
		g_free (copy);
		return FALSE;
	}

	/* Generate a raw public key from our certificate */
	keydata = egg_asn1x_encode (egg_asn1x_node (asn1, "tbsCertificate", "subjectPublicKeyInfo", NULL), NULL, &n_keydata);
	g_return_val_if_fail (keydata, FALSE);

	/* Now create us a nice public key with that identifier */
	res = gkm_data_der_read_public_key_info (keydata, n_keydata, &sexp);
	g_free (keydata);

	switch (res) {

	/* Create ourselves a public key with that */
	case GKM_DATA_SUCCESS:
		wrapper = gkm_sexp_new (sexp);
		if (!self->pv->key)
			self->pv->key = gkm_certificate_key_new (gkm_object_get_module (GKM_OBJECT (self)),
			                                         gkm_object_get_manager (GKM_OBJECT (self)),
			                                         self);
		gkm_sexp_key_set_base (GKM_SEXP_KEY (self->pv->key), wrapper);
		gkm_sexp_unref (wrapper);
		break;

	/* Unknown type of public key for this certificate, just ignore */
	case GKM_DATA_UNRECOGNIZED:
		if (self->pv->key)
			g_object_unref (self->pv->key);
		self->pv->key = NULL;
		break;

	/* Bad key, drop certificate */
	case GKM_DATA_FAILURE:
	case GKM_DATA_LOCKED:
		g_warning ("couldn't parse certificate key data");
		g_free (copy);
		egg_asn1x_destroy (asn1);
		return FALSE;

	default:
		g_assert_not_reached ();
		break;
	}

	g_free (self->pv->data);
	self->pv->data = copy;
	self->pv->n_data = n_data;

	egg_asn1x_destroy (self->pv->asn1);
	self->pv->asn1 = asn1;

	return TRUE;
}