static void
apartment_free (gpointer data)
{
	Apartment *apt;
	GList *l;

	g_assert (data != NULL);
	apt = (Apartment*)data;

	g_return_if_fail (GKM_IS_MANAGER (apt->session_manager));

	/* Unreference all the sessions */
	for (l = apt->sessions; l; l = g_list_next (l)) {

		/* Some sanity checks to make sure things have remained as expected */
		g_return_if_fail (GKM_IS_SESSION (l->data));
		g_return_if_fail (gkm_session_get_apartment (l->data) == apt->apt_id);
		g_return_if_fail (gkm_session_get_manager (l->data) == apt->session_manager);
		g_return_if_fail (gkm_session_get_logged_in (l->data) == apt->logged_in);

		g_object_unref (l->data);
	}

	g_list_free (apt->sessions);
	g_object_unref (apt->session_manager);

	g_slice_free (Apartment, apt);
}
Ejemplo n.º 2
0
CK_RV
gkm_crypto_derive_key (GkmSession *session, CK_MECHANISM_PTR mech, GkmObject *base,
                       CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, GkmObject **derived)
{
	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
	g_return_val_if_fail (GKM_IS_OBJECT (base), CKR_GENERAL_ERROR);
	g_return_val_if_fail (derived, CKR_GENERAL_ERROR);

	if (!gkm_object_has_attribute_ulong (base, session, CKA_ALLOWED_MECHANISMS, mech->mechanism))
		return CKR_KEY_TYPE_INCONSISTENT;

	if (!gkm_object_has_attribute_boolean (base, session, CKA_DERIVE, TRUE))
		return CKR_KEY_FUNCTION_NOT_PERMITTED;

	switch (mech->mechanism) {
	case CKM_DH_PKCS_DERIVE:
		return gkm_dh_mechanism_derive (session, mech, base, attrs,
		                                n_attrs, derived);
	case CKM_G_HKDF_SHA256_DERIVE:
		return gkm_hkdf_mechanism_derive (session, "sha256", mech, base,
		                                  attrs, n_attrs, derived);
	default:
		return CKR_MECHANISM_INVALID;
	}
}
CK_RV
gkm_crypto_unwrap_key (GkmSession *session, CK_MECHANISM_PTR mech, GkmObject *wrapper,
                       CK_VOID_PTR input, CK_ULONG n_input, CK_ATTRIBUTE_PTR attrs,
                       CK_ULONG n_attrs, GkmObject **unwrapped)
{
	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
	g_return_val_if_fail (GKM_IS_OBJECT (wrapper), CKR_GENERAL_ERROR);
	g_return_val_if_fail (mech, CKR_GENERAL_ERROR);
	g_return_val_if_fail (unwrapped, CKR_GENERAL_ERROR);

	if (!gkm_object_has_attribute_ulong (wrapper, session, CKA_ALLOWED_MECHANISMS, mech->mechanism))
		return CKR_KEY_TYPE_INCONSISTENT;

	if (!gkm_object_has_attribute_boolean (wrapper, session, CKA_UNWRAP, TRUE))
		return CKR_KEY_FUNCTION_NOT_PERMITTED;

	switch (mech->mechanism) {
	case CKM_AES_CBC_PAD:
		return gkm_aes_mechanism_unwrap (session, mech, wrapper, input,
		                                 n_input, attrs, n_attrs, unwrapped);
	case CKM_G_NULL:
		return gkm_null_mechanism_unwrap (session, mech, wrapper, input,
		                                  n_input, attrs, n_attrs, unwrapped);
	default:
		return CKR_MECHANISM_INVALID;
	}
}
gboolean
gkm_object_has_attribute_ulong (GkmObject *self, GkmSession *session,
                                CK_ATTRIBUTE_TYPE type, gulong value)
{
	gulong *data;
	gsize n_data, i;

	g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE);
	g_return_val_if_fail (GKM_IS_SESSION (session), FALSE);

	data = gkm_object_get_attribute_data (self, session, type, &n_data);
	if (data == NULL)
		return FALSE;

	g_return_val_if_fail (n_data % sizeof (gulong) == 0, FALSE);
	for (i = 0; i < n_data / sizeof (gulong); ++i) {
		if (data[i] == value) {
			g_free (data);
			return TRUE;
		}
	}

	g_free (data);
	return FALSE;
}
gboolean
gkm_object_has_attribute_boolean (GkmObject *self, GkmSession *session,
                                  CK_ATTRIBUTE_TYPE type, gboolean value)
{
	gboolean data;

	g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE);
	g_return_val_if_fail (GKM_IS_SESSION (session), FALSE);

	if (!gkm_object_get_attribute_boolean (self, session, type, &data))
		return FALSE;
	return data == value;
}
GkmSession*
gkm_module_lookup_session (GkmModule *self, CK_SESSION_HANDLE handle)
{
	GkmSession *session;

	g_return_val_if_fail (GKM_IS_MODULE (self), NULL);

	session = g_hash_table_lookup (self->pv->sessions_by_handle, &handle);
	if (!session)
		return NULL;

	g_return_val_if_fail (GKM_IS_SESSION (session), NULL);
	return session;
}
CK_RV
gkm_crypto_prepare (GkmSession *session, CK_MECHANISM_TYPE mech, GkmObject *key)
{
	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);

	switch (mech) {
	case CKM_RSA_PKCS:
	case CKM_RSA_X_509:
	case CKM_DSA:
		return gkm_crypto_prepare_xsa (session, mech, key);
	default:
		g_return_val_if_reached (CKR_GENERAL_ERROR);
	}
}
void
gkm_object_create_attributes (GkmObject *self, GkmSession *session, GkmTransaction *transaction,
                              CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
{
	g_return_if_fail (GKM_IS_OBJECT (self));
	g_return_if_fail (GKM_IS_TRANSACTION (transaction));
	g_return_if_fail (!gkm_transaction_get_failed (transaction));
	g_return_if_fail (GKM_IS_SESSION (session));
	g_return_if_fail (attrs);

	g_assert (GKM_OBJECT_GET_CLASS (self)->create_attributes);

	/* Check that the value will actually change */
	GKM_OBJECT_GET_CLASS (self)->create_attributes (self, session, transaction, attrs, n_attrs);
}
CK_RV
gkm_crypto_prepare_xsa (GkmSession *session, CK_MECHANISM_TYPE mech, GkmObject *key)
{
	GkmSexp *sexp;

	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
	g_return_val_if_fail (GKM_IS_SEXP_KEY (key), CKR_GENERAL_ERROR);

	/* Load up the actual sexp we're going to use */
	sexp = gkm_sexp_key_acquire_crypto_sexp (GKM_SEXP_KEY (key), session);
	if (sexp == NULL)
		return CKR_USER_NOT_LOGGED_IN;

	gkm_session_set_crypto_state (session, sexp, gkm_sexp_unref);
	return CKR_OK;
}
CK_RV
gkm_crypto_generate_key_pair (GkmSession *session, CK_MECHANISM_TYPE mech,
                              CK_ATTRIBUTE_PTR pub_atts, CK_ULONG n_pub_atts,
                              CK_ATTRIBUTE_PTR priv_atts, CK_ULONG n_priv_atts,
                              GkmObject **pub_key, GkmObject **priv_key)
{
	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
	g_return_val_if_fail (pub_key, CKR_GENERAL_ERROR);
	g_return_val_if_fail (priv_key, CKR_GENERAL_ERROR);

	switch (mech) {
	case CKM_DH_PKCS_KEY_PAIR_GEN:
		return gkm_dh_mechanism_generate (session, pub_atts, n_pub_atts,
		                                  priv_atts, n_priv_atts,
		                                  pub_key, priv_key);
	default:
		return CKR_MECHANISM_INVALID;
	}
}
CK_RV
gkm_crypto_perform (GkmSession *session, CK_MECHANISM_TYPE mech, CK_ATTRIBUTE_TYPE method,
                    CK_BYTE_PTR bufone, CK_ULONG n_bufone, CK_BYTE_PTR buftwo, CK_ULONG_PTR n_buftwo)
{
	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
	g_return_val_if_fail (method, CKR_GENERAL_ERROR);
	g_return_val_if_fail (n_buftwo, CKR_GENERAL_ERROR);

	switch (method) {
	case CKA_ENCRYPT:
		return gkm_crypto_encrypt (session, mech, bufone, n_bufone, buftwo, n_buftwo);
	case CKA_DECRYPT:
		return gkm_crypto_decrypt (session, mech, bufone, n_bufone, buftwo, n_buftwo);
	case CKA_SIGN:
		return gkm_crypto_sign (session, mech, bufone, n_bufone, buftwo, n_buftwo);
	case CKA_VERIFY:
		return gkm_crypto_verify (session, mech, bufone, n_bufone, buftwo, *n_buftwo);
	default:
		g_return_val_if_reached (CKR_GENERAL_ERROR);
	}
}
Ejemplo n.º 12
0
gboolean
gkm_credential_for_each (GkmSession *session, GkmObject *object,
                         GkmCredentialFunc func, gpointer user_data)
{
	CK_OBJECT_HANDLE handle;
	CK_OBJECT_CLASS klass;
	CK_ATTRIBUTE attrs[2];
	GList *results, *l;
	GkmCredential *cred;
	gboolean ret;

	g_return_val_if_fail (GKM_IS_SESSION (session), FALSE);
	g_return_val_if_fail (GKM_IS_OBJECT (object), FALSE);
	g_return_val_if_fail (func, FALSE);

	/* Do we have one right on the session */
	cred = gkm_session_get_credential (session);
	if (cred && gkm_credential_get_object (cred) == object) {
		g_object_ref (cred);
		ret = (func) (cred, object, user_data);
		g_object_unref (cred);
		if (ret)
			return TRUE;
	}

	klass = CKO_G_CREDENTIAL;
	attrs[0].type = CKA_CLASS;
	attrs[0].pValue = &klass;
	attrs[0].ulValueLen = sizeof (klass);

	handle = gkm_object_get_handle (object);
	attrs[1].type = CKA_G_OBJECT;
	attrs[1].pValue = &handle;
	attrs[1].ulValueLen = sizeof (handle);

	/* Find any on the session */
	results = gkm_manager_find_by_attributes (gkm_session_get_manager (session),
	                                          session, attrs, G_N_ELEMENTS (attrs));

	for (l = results; l; l = g_list_next (l)) {
		g_object_ref (l->data);
		ret = (func) (l->data, object, user_data);
		g_object_unref (l->data);
		if (ret)
			break;
	}

	g_list_free (results);

	if (l != NULL)
		return TRUE;

	/* Find any in the token */
	results = gkm_manager_find_by_attributes (gkm_module_get_manager (gkm_session_get_module (session)),
	                                          session, attrs, G_N_ELEMENTS (attrs));

	for (l = results; l; l = g_list_next (l)) {
		g_object_ref (l->data);
		ret = (func) (l->data, object, user_data);
		g_object_unref (l->data);
		if (ret)
			break;
	}

	g_list_free (results);

	return (l != NULL);
}
Ejemplo n.º 13
0
CK_RV
gkm_aes_mechanism_wrap (GkmSession *session, CK_MECHANISM_PTR mech,
                        GkmObject *wrapper, GkmObject *wrapped,
                        CK_BYTE_PTR output, CK_ULONG_PTR n_output)
{
	gcry_cipher_hd_t cih;
	gcry_error_t gcry;
	GkmAesKey *key;
	gpointer value, padded;
	gsize n_value, n_padded;
	gsize block, pos;
	gboolean ret;
	CK_RV rv;

	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
	g_return_val_if_fail (mech, CKR_GENERAL_ERROR);
	g_return_val_if_fail (mech->mechanism == CKM_AES_CBC_PAD, CKR_GENERAL_ERROR);
	g_return_val_if_fail (GKM_IS_OBJECT (wrapped), CKR_GENERAL_ERROR);
	g_return_val_if_fail (n_output, CKR_GENERAL_ERROR);

	if (!GKM_IS_AES_KEY (wrapper))
		return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
	key = GKM_AES_KEY (wrapper);

	block = gkm_aes_key_get_block_size (key);
	g_return_val_if_fail (block != 0, CKR_GENERAL_ERROR);

	/* They just want the length */
	if (!output) {
		rv = retrieve_length (session, wrapped, &n_value);
		if (rv != CKR_OK)
			return rv;
		if (!egg_padding_pkcs7_pad (NULL, block, NULL, n_value, NULL, &n_padded))
			return CKR_KEY_SIZE_RANGE;
		*n_output = n_padded;
		return CKR_OK;
	}

	cih = gkm_aes_key_get_cipher (key, GCRY_CIPHER_MODE_CBC);
	if (cih == NULL)
		return CKR_FUNCTION_FAILED;

	if (!mech->pParameter || gcry_cipher_setiv (cih, mech->pParameter, mech->ulParameterLen) != 0) {
		gcry_cipher_close (cih);
		return CKR_MECHANISM_PARAM_INVALID;
	}

	rv = retrieve_value (session, wrapped, &value, &n_value);
	if (rv != CKR_OK) {
		gcry_cipher_close (cih);
		return rv;
	}

	ret = egg_padding_pkcs7_pad (egg_secure_realloc, block, value, n_value, &padded, &n_padded);
	egg_secure_free (value);

	if (ret == FALSE) {
		gcry_cipher_close (cih);
		return CKR_KEY_SIZE_RANGE;
	}

	/* In place encryption */
	for (pos = 0; pos < n_padded; pos += block) {
		gcry = gcry_cipher_encrypt (cih, (guchar*)padded + pos, block, NULL, 0);
		g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
	}

	gcry_cipher_close (cih);

	rv = gkm_util_return_data (output, n_output, padded, n_padded);
	egg_secure_free (padded);
	return rv;
}
Ejemplo n.º 14
0
CK_RV
gkm_aes_mechanism_unwrap (GkmSession *session, CK_MECHANISM_PTR mech,
                          GkmObject *wrapper, CK_VOID_PTR input, CK_ULONG n_input,
                          CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs,
                          GkmObject **unwrapped)
{
	gcry_cipher_hd_t cih;
	gcry_error_t gcry;
	CK_ATTRIBUTE attr;
	GArray *array;
	GkmAesKey *key;
	gpointer padded, value;
	gsize n_padded, n_value;
	GkmTransaction *transaction;
	gsize block, pos;
	gboolean ret;

	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
	g_return_val_if_fail (mech, CKR_GENERAL_ERROR);
	g_return_val_if_fail (mech->mechanism == CKM_AES_CBC_PAD, CKR_GENERAL_ERROR);
	g_return_val_if_fail (GKM_IS_OBJECT (wrapper), CKR_GENERAL_ERROR);

	if (!GKM_IS_AES_KEY (wrapper))
		return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
	key = GKM_AES_KEY (wrapper);

	block = gkm_aes_key_get_block_size (key);
	g_return_val_if_fail (block != 0, CKR_GENERAL_ERROR);

	if (n_input == 0 || n_input % block != 0)
		return CKR_WRAPPED_KEY_LEN_RANGE;

	cih = gkm_aes_key_get_cipher (key, GCRY_CIPHER_MODE_CBC);
	if (cih == NULL)
		return CKR_FUNCTION_FAILED;

	if (!mech->pParameter || gcry_cipher_setiv (cih, mech->pParameter, mech->ulParameterLen) != 0) {
		gcry_cipher_close (cih);
		return CKR_MECHANISM_PARAM_INVALID;
	}

	padded = egg_secure_alloc (n_input);
	memcpy (padded, input, n_input);
	n_padded = n_input;

	/* In place decryption */
	for (pos = 0; pos < n_padded; pos += block) {
		gcry = gcry_cipher_decrypt (cih, (guchar*)padded + pos, block, NULL, 0);
		g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
	}

	gcry_cipher_close (cih);

	/* Unpad the resulting value */
	ret = egg_padding_pkcs7_unpad (egg_secure_realloc, block, padded, n_padded, &value, &n_value);
	egg_secure_free (padded);

	/* TODO: This is dubious, there doesn't seem to be an rv for 'bad decrypt' */
	if (ret == FALSE)
		return CKR_WRAPPED_KEY_INVALID;

	/* Now setup the attributes with our new value */
	array = g_array_new (FALSE, FALSE, sizeof (CK_ATTRIBUTE));

	/* Prepend the value */
	attr.type = CKA_VALUE;
	attr.pValue = value;
	attr.ulValueLen = n_value;
	g_array_append_val (array, attr);

	/* Add the remainder of the attributes */
	g_array_append_vals (array, attrs, n_attrs);

	transaction = gkm_transaction_new ();

	/* Now create an object with these attributes */
	*unwrapped = gkm_session_create_object_for_attributes (session, transaction,
	                                                       (CK_ATTRIBUTE_PTR)array->data, array->len);

	egg_secure_free (value);
	g_array_free (array, TRUE);

	return gkm_transaction_complete_and_unref (transaction);
}