From 128d31659892cce4b9538295712c871b6df8f9df Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Fri, 20 Nov 2009 17:29:53 +0000 Subject: [PATCH] [gp11] Implement support for generate, wrap, unwrap, derive. Implement gp11_session_generate_key_pair...(), gp11_session_wrap_key...(), gp11_session_unwrap_key...(), and gp11_session_derive_key...(). --- gp11/gp11-misc.c | 83 ++++ gp11/gp11-session.c | 840 ++++++++++++++++++++++++++++++++++--- gp11/gp11.h | 158 +++---- gp11/tests/Makefile.am | 1 + gp11/tests/gp11-test-module.c | 251 ++++++++++- gp11/tests/gp11-test.h | 13 + gp11/tests/test-gp11-mechanism.c | 60 +++ gp11/tests/unit-test-gp11-crypto.c | 349 +++++++++++++-- 8 files changed, 1564 insertions(+), 191 deletions(-) create mode 100644 gp11/tests/test-gp11-mechanism.c diff --git a/gp11/gp11-misc.c b/gp11/gp11-misc.c index 090246e..9b6293a 100644 --- a/gp11/gp11-misc.c +++ b/gp11/gp11-misc.c @@ -352,3 +352,86 @@ _gp11_ulong_equal (gconstpointer v1, gconstpointer v2) { return *((const gulong*)v1) == *((const gulong*)v2); } + +static GQuark mechanism_quark = 0; + +static void +free_refs (gpointer data) +{ + gint *refs = data; + g_assert (refs); + g_assert (*refs == 0); + g_slice_free (gint, data); +} + +GP11Mechanism* +gp11_mechanism_new (gulong type) +{ + return gp11_mechanism_new_with_param (type, NULL, 0); +} + +GP11Mechanism* +gp11_mechanism_new_with_param (gulong type, gconstpointer parameter, + gulong n_parameter) +{ + static volatile gsize inited_quark = 0; + GP11Mechanism *mech; + gint *refs; + + /* Initialize first time around */ + if (g_once_init_enter (&inited_quark)) { + mechanism_quark = g_quark_from_static_string ("GP11Mechanism::refs"); + g_once_init_leave (&inited_quark, 1); + } + + mech = g_slice_new (GP11Mechanism); + mech->type = type; + mech->parameter = g_memdup (parameter, n_parameter); + mech->n_parameter = n_parameter; + + refs = g_slice_new (gint); + *refs = 1; + g_dataset_id_set_data_full (mech, mechanism_quark, refs, free_refs); + + return mech; +} + +GP11Mechanism* +gp11_mechanism_ref (GP11Mechanism* mech) +{ + gint *refs; + + g_return_val_if_fail (mech, NULL); + + refs = g_dataset_id_get_data (mech, mechanism_quark); + if (refs == NULL) { + g_warning ("Encountered invalid GP11Mechanism struct. Either it was unreffed or " + "possibly allocated on the stack. Always use gp11_mechanism_new () and friends."); + return NULL; + } + + g_atomic_int_add (refs, 1); + return mech; +} + +void +gp11_mechanism_unref (GP11Mechanism* mech) +{ + gint *refs; + + if (!mech) + return; + + refs = g_dataset_id_get_data (mech, mechanism_quark); + if (refs == NULL) { + g_warning ("Encountered invalid GP11Mechanism struct. Either it was unreffed or " + "possibly allocated on the stack. Always use gp11_mechanism_new () and friends."); + return; + } + + if (g_atomic_int_dec_and_test (refs)) { + g_free (mech->parameter); + g_dataset_id_remove_data (mech, mechanism_quark); + g_slice_free (GP11Mechanism, mech); + } +} diff --git a/gp11/gp11-session.c b/gp11/gp11-session.c index 2698eb8..06a49f5 100644 --- a/gp11/gp11-session.c +++ b/gp11/gp11-session.c @@ -1039,6 +1039,736 @@ gp11_session_find_objects_finish (GP11Session *self, GAsyncResult *result, GErro return objlist_from_handles (self, args->objects, args->n_objects); } +/* ----------------------------------------------------------------------------- + * KEY PAIR GENERATION + */ + +typedef struct _GenerateKeyPair { + GP11Arguments base; + GP11Mechanism *mechanism; + GP11Attributes *public_attrs; + GP11Attributes *private_attrs; + CK_OBJECT_HANDLE public_key; + CK_OBJECT_HANDLE private_key; +} GenerateKeyPair; + +static void +free_generate_key_pair (GenerateKeyPair *args) +{ + gp11_mechanism_unref (args->mechanism); + gp11_attributes_unref (args->public_attrs); + gp11_attributes_unref (args->private_attrs); + g_free (args); +} + +static CK_RV +perform_generate_key_pair (GenerateKeyPair *args) +{ + CK_ATTRIBUTE_PTR pub_attrs, priv_attrs; + CK_ULONG n_pub_attrs, n_priv_attrs; + + g_assert (sizeof (CK_MECHANISM) == sizeof (GP11Mechanism)); + + pub_attrs = _gp11_attributes_commit_out (args->public_attrs, &n_pub_attrs); + priv_attrs = _gp11_attributes_commit_out (args->private_attrs, &n_priv_attrs); + + return (args->base.pkcs11->C_GenerateKeyPair) (args->base.handle, + (CK_MECHANISM_PTR)args->mechanism, + pub_attrs, n_pub_attrs, + priv_attrs, n_priv_attrs, + &args->public_key, + &args->private_key); +} + +/** + * gp11_session_generate_key_pair_full: + * @self: The session to use. + * @mechanism: The mechanism to use for key generation. + * @public_attrs: Additional attributes for the generated public key. + * @private_attrs: Additional attributes for the generated private key. + * @public_key: A location to return the resulting public key. + * @private_key: A location to return the resulting private key. + * @cancellable: Optional cancellation object, or NULL. + * @err: A location to return an error, or NULL. + * + * Generate a new key pair of public and private keys. This call may block for an + * indefinite period. + * + * Return value: TRUE if the operation succeeded. + **/ +gboolean +gp11_session_generate_key_pair_full (GP11Session *self, GP11Mechanism *mechanism, + GP11Attributes *public_attrs, GP11Attributes *private_attrs, + GP11Object **public_key, GP11Object **private_key, + GCancellable *cancellable, GError **err) +{ + GP11SessionData *data = GP11_SESSION_GET_DATA (self); + GenerateKeyPair args = { GP11_ARGUMENTS_INIT, mechanism, public_attrs, private_attrs, 0, 0 }; + gboolean ret; + + g_return_val_if_fail (GP11_IS_SESSION (self), FALSE); + g_return_val_if_fail (mechanism, FALSE); + g_return_val_if_fail (public_attrs, FALSE); + g_return_val_if_fail (private_attrs, FALSE); + g_return_val_if_fail (public_key, FALSE); + g_return_val_if_fail (private_key, FALSE); + + _gp11_attributes_lock (public_attrs); + _gp11_attributes_lock (private_attrs); + ret = _gp11_call_sync (self, perform_generate_key_pair, NULL, &args, cancellable, err); + _gp11_attributes_unlock (private_attrs); + _gp11_attributes_unlock (public_attrs); + + if (!ret) + return FALSE; + + *public_key = gp11_object_from_handle (data->slot, args.public_key); + *private_key = gp11_object_from_handle (data->slot, args.private_key); + return TRUE; +} + +/** + * gp11_session_generate_key_pair_async: + * @self: The session to use. + * @mechanism: The mechanism to use for key generation. + * @public_attrs: Additional attributes for the generated public key. + * @private_attrs: Additional attributes for the generated private key. + * @cancellable: Optional cancellation object or NULL. + * @callback: Called when the operation completes. + * @user_data: Data to pass to the callback. + * + * Generate a new key pair of public and private keys. This call will + * return immediately and complete asynchronously. + **/ +void +gp11_session_generate_key_pair_async (GP11Session *self, GP11Mechanism *mechanism, + GP11Attributes *public_attrs, GP11Attributes *private_attrs, + GCancellable *cancellable, GAsyncReadyCallback callback, + gpointer user_data) +{ + GenerateKeyPair *args = _gp11_call_async_prep (self, self, perform_generate_key_pair, + NULL, sizeof (*args), free_generate_key_pair); + + g_return_if_fail (GP11_IS_SESSION (self)); + g_return_if_fail (mechanism); + g_return_if_fail (public_attrs); + g_return_if_fail (private_attrs); + + args->public_attrs = gp11_attributes_ref (public_attrs); + _gp11_attributes_lock (public_attrs); + args->private_attrs = gp11_attributes_ref (private_attrs); + _gp11_attributes_lock (private_attrs); + args->mechanism = gp11_mechanism_ref (mechanism); + + _gp11_call_async_ready_go (args, cancellable, callback, user_data); +} + +/** + * gp11_session_generate_key_pair_finish: + * @self: The session to use. + * @result: The async result passed to the callback. + * @public_key: A location to return the resulting public key. + * @private_key: A location to return the resulting private key. + * @err: A location to return an error. + * + * Get the result of a generate key pair operation. + * + * Return value: TRUE if the operation succeeded. + **/ +gboolean +gp11_session_generate_key_pair_finish (GP11Session *self, GAsyncResult *result, + GP11Object **public_key, GP11Object **private_key, + GError **err) +{ + GP11SessionData *data = GP11_SESSION_GET_DATA (self); + GenerateKeyPair *args; + + g_return_val_if_fail (GP11_IS_SESSION (self), FALSE); + g_return_val_if_fail (public_key, FALSE); + g_return_val_if_fail (private_key, FALSE); + + args = _gp11_call_arguments (result, GenerateKeyPair); + _gp11_attributes_unlock (args->public_attrs); + _gp11_attributes_unlock (args->private_attrs); + + if (!_gp11_call_basic_finish (result, err)) + return FALSE; + + *public_key = gp11_object_from_handle (data->slot, args->public_key); + *private_key = gp11_object_from_handle (data->slot, args->private_key); + return TRUE; +} + +/* ----------------------------------------------------------------------------- + * KEY WRAPPING + */ + +typedef struct _WrapKey { + GP11Arguments base; + GP11Mechanism *mechanism; + CK_OBJECT_HANDLE wrapper; + CK_OBJECT_HANDLE wrapped; + gpointer result; + gulong n_result; +} WrapKey; + +static void +free_wrap_key (WrapKey *args) +{ + gp11_mechanism_unref (args->mechanism); + g_free (args->result); + g_free (args); +} + +static CK_RV +perform_wrap_key (WrapKey *args) +{ + CK_RV rv; + + g_assert (sizeof (CK_MECHANISM) == sizeof (GP11Mechanism)); + + /* Get the length of the result */ + rv = (args->base.pkcs11->C_WrapKey) (args->base.handle, + (CK_MECHANISM_PTR)args->mechanism, + args->wrapper, args->wrapped, + NULL, &args->n_result); + if (rv != CKR_OK) + return rv; + + /* And try again with a real buffer */ + args->result = g_malloc0 (args->n_result); + return (args->base.pkcs11->C_WrapKey) (args->base.handle, + (CK_MECHANISM_PTR)args->mechanism, + args->wrapper, args->wrapped, + args->result, &args->n_result); +} + +/** + * gp11_session_wrap_key: + * @self: The session to use. + * @wrapper: The key to use for wrapping. + * @mechanism: The mechanism type to use for wrapping. + * @wrapped: The key to wrap. + * @n_result: A location in which to return the length of the wrapped data. + * @err: A location to return an error, or NULL. + * + * Wrap a key into a byte stream. This call may block for an + * indefinite period. + * + * Return value: The wrapped data or NULL if the operation failed. + **/ +gpointer +gp11_session_wrap_key (GP11Session *self, GP11Object *key, gulong mech_type, + GP11Object *wrapped, gsize *n_result, GError **err) +{ + GP11Mechanism mech = { mech_type, NULL, 0 }; + return gp11_session_wrap_key_full (self, key, &mech, wrapped, n_result, NULL, err); +} + +/** + * gp11_session_wrap_key_full: + * @self: The session to use. + * @wrapper: The key to use for wrapping. + * @mechanism: The mechanism to use for wrapping. + * @wrapped: The key to wrap. + * @n_result: A location in which to return the length of the wrapped data. + * @cancellable: Optional cancellation object, or NULL. + * @err: A location to return an error, or NULL. + * + * Wrap a key into a byte stream. This call may block for an + * indefinite period. + * + * Return value: The wrapped data or NULL if the operation failed. + **/ +gpointer +gp11_session_wrap_key_full (GP11Session *self, GP11Object *wrapper, GP11Mechanism *mechanism, + GP11Object *wrapped, gsize *n_result, GCancellable *cancellable, + GError **err) +{ + WrapKey args = { GP11_ARGUMENTS_INIT, mechanism, 0, 0, NULL, 0 }; + gboolean ret; + + g_return_val_if_fail (GP11_IS_SESSION (self), FALSE); + g_return_val_if_fail (mechanism, FALSE); + g_return_val_if_fail (GP11_IS_OBJECT (wrapped), FALSE); + g_return_val_if_fail (GP11_IS_OBJECT (wrapper), FALSE); + g_return_val_if_fail (n_result, FALSE); + + g_object_get (wrapper, "handle", &args.wrapper, NULL); + g_return_val_if_fail (args.wrapper != 0, NULL); + g_object_get (wrapped, "handle", &args.wrapped, NULL); + g_return_val_if_fail (args.wrapped != 0, NULL); + + ret = _gp11_call_sync (self, perform_wrap_key, NULL, &args, cancellable, err); + + if (!ret) + return FALSE; + + *n_result = args.n_result; + return args.result; +} + +/** + * gp11_session_wrap_key_async: + * @self: The session to use. + * @wrapper: The key to use for wrapping. + * @mechanism: The mechanism to use for wrapping. + * @wrapped: The key to wrap. + * @cancellable: Optional cancellation object or NULL. + * @callback: Called when the operation completes. + * @user_data: Data to pass to the callback. + * + * Wrap a key into a byte stream. This call will + * return immediately and complete asynchronously. + **/ +void +gp11_session_wrap_key_async (GP11Session *self, GP11Object *key, GP11Mechanism *mechanism, + GP11Object *wrapped, GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer user_data) +{ + WrapKey *args = _gp11_call_async_prep (self, self, perform_wrap_key, + NULL, sizeof (*args), free_wrap_key); + + g_return_if_fail (GP11_IS_SESSION (self)); + g_return_if_fail (mechanism); + g_return_if_fail (GP11_IS_OBJECT (wrapped)); + g_return_if_fail (GP11_IS_OBJECT (key)); + + args->mechanism = gp11_mechanism_ref (mechanism); + g_object_get (key, "handle", &args->wrapper, NULL); + g_return_if_fail (args->wrapper != 0); + g_object_get (wrapped, "handle", &args->wrapped, NULL); + g_return_if_fail (args->wrapped != 0); + + _gp11_call_async_ready_go (args, cancellable, callback, user_data); +} + +/** + * gp11_session_wrap_key_finish: + * @self: The session to use. + * @result: The async result passed to the callback. + * @n_result: A location in which to return the length of the wrapped data. + * @err: A location to return an error. + * + * Get the result of a wrap key operation. + * + * Return value: The wrapped data or NULL if the operation failed. + **/ +gpointer +gp11_session_wrap_key_finish (GP11Session *self, GAsyncResult *result, + gsize *n_result, GError **err) +{ + WrapKey *args; + gpointer ret; + + g_return_val_if_fail (GP11_IS_SESSION (self), NULL); + g_return_val_if_fail (n_result, NULL); + + args = _gp11_call_arguments (result, WrapKey); + + if (!_gp11_call_basic_finish (result, err)) + return NULL; + + *n_result = args->n_result; + args->n_result = 0; + ret = args->result; + args->result = NULL; + + return ret; +} + +/* ----------------------------------------------------------------------------- + * KEY UNWRAPPING + */ + +typedef struct _UnwrapKey { + GP11Arguments base; + GP11Mechanism *mechanism; + GP11Attributes *attrs; + CK_OBJECT_HANDLE wrapper; + gconstpointer input; + gulong n_input; + CK_OBJECT_HANDLE unwrapped; +} UnwrapKey; + +static void +free_unwrap_key (UnwrapKey *args) +{ + gp11_mechanism_unref (args->mechanism); + gp11_attributes_unref (args->attrs); + g_free (args); +} + +static CK_RV +perform_unwrap_key (UnwrapKey *args) +{ + CK_ATTRIBUTE_PTR attrs; + CK_ULONG n_attrs; + + g_assert (sizeof (CK_MECHANISM) == sizeof (GP11Mechanism)); + + attrs = _gp11_attributes_commit_out (args->attrs, &n_attrs); + + return (args->base.pkcs11->C_UnwrapKey) (args->base.handle, + (CK_MECHANISM_PTR)args->mechanism, + args->wrapper, (CK_BYTE_PTR)args->input, + args->n_input, attrs, n_attrs, + &args->unwrapped); +} + +/** + * gp11_session_unwrap_key: + * @self: The session to use. + * @wrapper: The key to use for unwrapping. + * @mech_type: The mechanism type to use for derivation. + * @input: The wrapped data as a byte stream. + * @n_input: The length of the wrapped data. + * @err: A location to return an error, or NULL. + * @...: Additional attributes for the unwrapped key. + * + * Unwrap a key from a byte stream. This call may block for an + * indefinite period. + * + * The arguments must be triples of: attribute type, data type, value + * + * The variable argument list should contain: + * + * + * a) + * The gulong attribute type (ie: CKA_LABEL). + * + * + * b) + * The attribute data type (one of GP11_BOOLEAN, GP11_ULONG, + * GP11_STRING, GP11_DATE) orthe raw attribute value length. + * + * + * c) + * The attribute value, either a gboolean, gulong, gchar*, GDate* or + * a pointer to a raw attribute value. + * + * + * The variable argument list should be terminated with GP11_INVALID. + * + * Return value: The new unwrapped key or NULL if the operation failed. + **/ +GP11Object* +gp11_session_unwrap_key (GP11Session *self, GP11Object *key, gulong mech_type, + gconstpointer input, gsize n_input, GError **err, ...) +{ + GP11Mechanism mech = { mech_type, NULL, 0 }; + GP11Attributes *attrs; + GP11Object *object; + va_list va; + + va_start (va, err); + attrs = gp11_attributes_new_valist (g_realloc, va); + va_end (va); + + object = gp11_session_unwrap_key_full (self, key, &mech, input, n_input, attrs, NULL, err); + gp11_attributes_unref (attrs); + return object; +} + +/** + * gp11_session_unwrap_key_full: + * @self: The session to use. + * @wrapper: The key to use for unwrapping. + * @mechanism: The mechanism to use for unwrapping. + * @input: The wrapped data as a byte stream. + * @n_input: The length of the wrapped data. + * @attrs: Additional attributes for the unwrapped key. + * @cancellable: Optional cancellation object, or NULL. + * @err: A location to return an error, or NULL. + * + * Unwrap a key from a byte stream. This call may block for an + * indefinite period. + * + * Return value: The new unwrapped key or NULL if the operation failed. + **/ +GP11Object* +gp11_session_unwrap_key_full (GP11Session *self, GP11Object *wrapper, GP11Mechanism *mechanism, + gconstpointer input, gsize n_input, GP11Attributes *attrs, + GCancellable *cancellable, GError **err) +{ + GP11SessionData *data = GP11_SESSION_GET_DATA (self); + UnwrapKey args = { GP11_ARGUMENTS_INIT, mechanism, attrs, 0, input, n_input, 0 }; + gboolean ret; + + g_return_val_if_fail (GP11_IS_SESSION (self), FALSE); + g_return_val_if_fail (GP11_IS_OBJECT (wrapper), FALSE); + g_return_val_if_fail (mechanism, FALSE); + g_return_val_if_fail (attrs, FALSE); + + g_object_get (wrapper, "handle", &args.wrapper, NULL); + g_return_val_if_fail (args.wrapper != 0, NULL); + + _gp11_attributes_lock (attrs); + ret = _gp11_call_sync (self, perform_unwrap_key, NULL, &args, cancellable, err); + _gp11_attributes_unlock (attrs); + + if (!ret) + return NULL; + + return gp11_object_from_handle (data->slot, args.unwrapped); +} + +/** + * gp11_session_unwrap_key_async: + * @self: The session to use. + * @wrapper: The key to use for unwrapping. + * @mechanism: The mechanism to use for unwrapping. + * @input: The wrapped data as a byte stream. + * @n_input: The length of the wrapped data. + * @attrs: Additional attributes for the unwrapped key. + * @cancellable: Optional cancellation object or NULL. + * @callback: Called when the operation completes. + * @user_data: Data to pass to the callback. + * + * Unwrap a key from a byte stream. This call will + * return immediately and complete asynchronously. + **/ +void +gp11_session_unwrap_key_async (GP11Session *self, GP11Object *wrapper, GP11Mechanism *mechanism, + gconstpointer input, gsize n_input, GP11Attributes *attrs, + GCancellable *cancellable, GAsyncReadyCallback callback, + gpointer user_data) +{ + UnwrapKey *args = _gp11_call_async_prep (self, self, perform_unwrap_key, + NULL, sizeof (*args), free_unwrap_key); + + g_return_if_fail (GP11_IS_SESSION (self)); + g_return_if_fail (GP11_IS_OBJECT (wrapper)); + g_return_if_fail (attrs); + + g_object_get (wrapper, "handle", &args->wrapper, NULL); + g_return_if_fail (args->wrapper != 0); + + args->mechanism = gp11_mechanism_ref (mechanism); + args->attrs = gp11_attributes_ref (attrs); + args->input = input; + args->n_input = n_input; + _gp11_attributes_lock (attrs); + + _gp11_call_async_ready_go (args, cancellable, callback, user_data); +} + +/** + * gp11_session_wrap_key_finish: + * @self: The session to use. + * @result: The async result passed to the callback. + * @err: A location to return an error. + * + * Get the result of a unwrap key operation. + * + * Return value: The new unwrapped key or NULL if the operation failed. + **/ +GP11Object* +gp11_session_unwrap_key_finish (GP11Session *self, GAsyncResult *result, GError **err) +{ + GP11SessionData *data = GP11_SESSION_GET_DATA (self); + UnwrapKey *args; + + g_return_val_if_fail (GP11_IS_SESSION (self), NULL); + + args = _gp11_call_arguments (result, UnwrapKey); + _gp11_attributes_unlock (args->attrs); + + if (!_gp11_call_basic_finish (result, err)) + return NULL; + return gp11_object_from_handle (data->slot, args->unwrapped); +} + +/* ----------------------------------------------------------------------------- + * KEY DERIVATION + */ + +typedef struct _DeriveKey { + GP11Arguments base; + GP11Mechanism *mechanism; + GP11Attributes *attrs; + CK_OBJECT_HANDLE key; + CK_OBJECT_HANDLE derived; +} DeriveKey; + +static void +free_derive_key (DeriveKey *args) +{ + gp11_mechanism_unref (args->mechanism); + gp11_attributes_unref (args->attrs); + g_free (args); +} + +static CK_RV +perform_derive_key (DeriveKey *args) +{ + CK_ATTRIBUTE_PTR attrs; + CK_ULONG n_attrs; + + g_assert (sizeof (CK_MECHANISM) == sizeof (GP11Mechanism)); + + attrs = _gp11_attributes_commit_out (args->attrs, &n_attrs); + + return (args->base.pkcs11->C_DeriveKey) (args->base.handle, + (CK_MECHANISM_PTR)args->mechanism, + args->key, attrs, n_attrs, + &args->derived); +} + +/** + * gp11_session_derive_key_full: + * @self: The session to use. + * @base: The key to derive from. + * @mech_type: The mechanism type to use for derivation. + * @err: A location to return an error, or NULL. + * @...: Additional attributes for the derived key. + * + * Derive a key from another key. This call may block for an + * indefinite period. + * + * The arguments must be triples of: attribute type, data type, value + * + * The variable argument list should contain: + * + * + * a) + * The gulong attribute type (ie: CKA_LABEL). + * + * + * b) + * The attribute data type (one of GP11_BOOLEAN, GP11_ULONG, + * GP11_STRING, GP11_DATE) orthe raw attribute value length. + * + * + * c) + * The attribute value, either a gboolean, gulong, gchar*, GDate* or + * a pointer to a raw attribute value. + * + * + * The variable argument list should be terminated with GP11_INVALID. + * + * Return value: The new derived key or NULL if the operation failed. + **/ +GP11Object* +gp11_session_derive_key (GP11Session *self, GP11Object *key, gulong mech_type, + GError **err, ...) +{ + GP11Mechanism mech = { mech_type, NULL, 0 }; + GP11Attributes *attrs; + GP11Object *object; + va_list va; + + va_start (va, err); + attrs = gp11_attributes_new_valist (g_realloc, va); + va_end (va); + + object = gp11_session_derive_key_full (self, key, &mech, attrs, NULL, err); + gp11_attributes_unref (attrs); + return object; +} + +/** + * gp11_session_derive_key_full: + * @self: The session to use. + * @base: The key to derive from. + * @mechanism: The mechanism to use for derivation. + * @attrs: Additional attributes for the derived key. + * @cancellable: Optional cancellation object, or NULL. + * @err: A location to return an error, or NULL. + * + * Derive a key from another key. This call may block for an + * indefinite period. + * + * Return value: The new derived key or NULL if the operation failed. + **/ +GP11Object* +gp11_session_derive_key_full (GP11Session *self, GP11Object *base, GP11Mechanism *mechanism, + GP11Attributes *attrs, GCancellable *cancellable, GError **err) +{ + GP11SessionData *data = GP11_SESSION_GET_DATA (self); + DeriveKey args = { GP11_ARGUMENTS_INIT, mechanism, attrs, 0, 0 }; + gboolean ret; + + g_return_val_if_fail (GP11_IS_SESSION (self), FALSE); + g_return_val_if_fail (GP11_IS_OBJECT (base), FALSE); + g_return_val_if_fail (mechanism, FALSE); + g_return_val_if_fail (attrs, FALSE); + + g_object_get (base, "handle", &args.key, NULL); + g_return_val_if_fail (args.key != 0, NULL); + + _gp11_attributes_lock (attrs); + ret = _gp11_call_sync (self, perform_derive_key, NULL, &args, cancellable, err); + _gp11_attributes_unlock (attrs); + + if (!ret) + return NULL; + + return gp11_object_from_handle (data->slot, args.derived); +} + +/** + * gp11_session_derive_key_async: + * @self: The session to use. + * @base: The key to derive from. + * @mechanism: The mechanism to use for derivation. + * @attrs: Additional attributes for the derived key. + * @cancellable: Optional cancellation object or NULL. + * @callback: Called when the operation completes. + * @user_data: Data to pass to the callback. + * + * Derive a key from another key. This call will + * return immediately and complete asynchronously. + **/ +void +gp11_session_derive_key_async (GP11Session *self, GP11Object *base, GP11Mechanism *mechanism, + GP11Attributes *attrs, GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer user_data) +{ + DeriveKey *args = _gp11_call_async_prep (self, self, perform_derive_key, + NULL, sizeof (*args), free_derive_key); + + g_return_if_fail (GP11_IS_SESSION (self)); + g_return_if_fail (GP11_IS_OBJECT (base)); + g_return_if_fail (attrs); + + g_object_get (base, "handle", &args->key, NULL); + g_return_if_fail (args->key != 0); + + args->mechanism = gp11_mechanism_ref (mechanism); + args->attrs = gp11_attributes_ref (attrs); + _gp11_attributes_lock (attrs); + + _gp11_call_async_ready_go (args, cancellable, callback, user_data); +} + +/** + * gp11_session_wrap_key_finish: + * @self: The session to use. + * @result: The async result passed to the callback. + * @err: A location to return an error. + * + * Get the result of a derive key operation. + * + * Return value: The new derived key or NULL if the operation failed. + **/ +GP11Object* +gp11_session_derive_key_finish (GP11Session *self, GAsyncResult *result, GError **err) +{ + GP11SessionData *data = GP11_SESSION_GET_DATA (self); + DeriveKey *args; + + g_return_val_if_fail (GP11_IS_SESSION (self), NULL); + + args = _gp11_call_arguments (result, DeriveKey); + _gp11_attributes_unlock (args->attrs); + + if (!_gp11_call_basic_finish (result, err)) + return NULL; + + return gp11_object_from_handle (data->slot, args->derived); +} + /* -------------------------------------------------------------------------------------------------- * AUTHENTICATE */ @@ -1227,7 +1957,7 @@ typedef struct _Crypt { /* Input */ CK_OBJECT_HANDLE key; - CK_MECHANISM mech; + GP11Mechanism *mech; guchar *input; CK_ULONG n_input; @@ -1249,7 +1979,7 @@ perform_crypt (Crypt *args) g_assert (!args->n_result); /* Initialize the crypt operation */ - rv = (args->init_func) (args->base.handle, &args->mech, args->key); + rv = (args->init_func) (args->base.handle, (CK_MECHANISM_PTR)args->mech, args->key); if (rv != CKR_OK) return rv; @@ -1281,13 +2011,13 @@ static void free_crypt (Crypt *args) { g_free (args->input); - g_free (args->mech.pParameter); + gp11_mechanism_unref (args->mech); g_free (args->result); g_free (args); } static guchar* -crypt_sync (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, +crypt_sync (GP11Session *self, GP11Object *key, GP11Mechanism *mechanism, const guchar *input, gsize n_input, gsize *n_result, GCancellable *cancellable, GError **err, CK_C_EncryptInit init_func, CK_C_Encrypt complete_func) { @@ -1295,7 +2025,7 @@ crypt_sync (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const GP11Slot *slot; g_return_val_if_fail (GP11_IS_OBJECT (key), NULL); - g_return_val_if_fail (mech_args, NULL); + g_return_val_if_fail (mechanism, NULL); g_return_val_if_fail (init_func, NULL); g_return_val_if_fail (complete_func, NULL); @@ -1303,9 +2033,7 @@ crypt_sync (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const g_object_get (key, "handle", &args.key, NULL); g_return_val_if_fail (args.key != 0, NULL); - args.mech.mechanism = mech_args->type; - args.mech.pParameter = mech_args->parameter; - args.mech.ulParameterLen = mech_args->n_parameter; + args.mech = mechanism; /* No need to copy in this case */ args.input = (guchar*)input; @@ -1328,7 +2056,7 @@ crypt_sync (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const } static void -crypt_async (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, +crypt_async (GP11Session *self, GP11Object *key, GP11Mechanism *mechanism, const guchar *input, gsize n_input, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, CK_C_EncryptInit init_func, CK_C_Encrypt complete_func) { @@ -1336,17 +2064,14 @@ crypt_async (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const GP11Slot *slot; g_return_if_fail (GP11_IS_OBJECT (key)); - g_return_if_fail (mech_args); + g_return_if_fail (mechanism); g_return_if_fail (init_func); g_return_if_fail (complete_func); g_object_get (key, "handle", &args->key, NULL); g_return_if_fail (args->key != 0); - args->mech.mechanism = mech_args->type; - args->mech.pParameter = mech_args->parameter && mech_args->n_parameter ? - g_memdup (mech_args->parameter, mech_args->n_parameter) : NULL; - args->mech.ulParameterLen = mech_args->n_parameter; + args->mech = gp11_mechanism_ref (mechanism); args->input = input && n_input ? g_memdup (input, n_input) : NULL; args->n_input = n_input; @@ -1403,15 +2128,15 @@ guchar* gp11_session_encrypt (GP11Session *self, GP11Object *key, gulong mech_type, const guchar *input, gsize n_input, gsize *n_result, GError **err) { - GP11Mechanism mech_args = { mech_type, NULL, 0 }; - return gp11_session_encrypt_full (self, key, &mech_args, input, n_input, n_result, NULL, err); + GP11Mechanism mechanism = { mech_type, NULL, 0 }; + return gp11_session_encrypt_full (self, key, &mechanism, input, n_input, n_result, NULL, err); } /** * gp11_session_encrypt_full: * @self: The session. * @key: The key to encrypt with. - * @mech_args: The mechanism type and parameters to use for encryption. + * @mechanism: The mechanism type and parameters to use for encryption. * @input: The data to encrypt. * @n_input: The length of the data to encrypt. * @n_result: A location to store the length of the result data. @@ -1424,7 +2149,7 @@ gp11_session_encrypt (GP11Session *self, GP11Object *key, gulong mech_type, cons * Returns: The data that was encrypted, or NULL if an error occured. */ guchar* -gp11_session_encrypt_full (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_encrypt_full (GP11Session *self, GP11Object *key, GP11Mechanism *mechanism, const guchar *input, gsize n_input, gsize *n_result, GCancellable *cancellable, GError **err) { @@ -1438,7 +2163,7 @@ gp11_session_encrypt_full (GP11Session *self, GP11Object *key, GP11Mechanism *me funcs = gp11_module_get_functions (module); g_return_val_if_fail (module != NULL, NULL); - ret = crypt_sync (self, key, mech_args, input, n_input, n_result, cancellable, err, + ret = crypt_sync (self, key, mechanism, input, n_input, n_result, cancellable, err, funcs->C_EncryptInit, funcs->C_Encrypt); g_object_unref (module); @@ -1449,7 +2174,7 @@ gp11_session_encrypt_full (GP11Session *self, GP11Object *key, GP11Mechanism *me * gp11_session_encrypt_async: * @self: The session. * @key: The key to encrypt with. - * @mech_args: The mechanism type and parameters to use for encryption. + * @mechanism: The mechanism type and parameters to use for encryption. * @input: The data to encrypt. * @n_input: The length of the data to encrypt. * @cancellable: A GCancellable which can be used to cancel the operation. @@ -1458,11 +2183,9 @@ gp11_session_encrypt_full (GP11Session *self, GP11Object *key, GP11Mechanism *me * * Encrypt data in a mechanism specific manner. This call will * return immediately and complete asynchronously. - * - * Returns: The data that was encrypted. - */ + **/ void -gp11_session_encrypt_async (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_encrypt_async (GP11Session *self, GP11Object *key, GP11Mechanism *mechanism, const guchar *input, gsize n_input, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { @@ -1475,7 +2198,7 @@ gp11_session_encrypt_async (GP11Session *self, GP11Object *key, GP11Mechanism *m funcs = gp11_module_get_functions (module); g_return_if_fail (module != NULL); - crypt_async (self, key, mech_args, input, n_input, cancellable, callback, user_data, + crypt_async (self, key, mechanism, input, n_input, cancellable, callback, user_data, funcs->C_EncryptInit, funcs->C_Encrypt); g_object_unref (module); @@ -1522,15 +2245,15 @@ guchar* gp11_session_decrypt (GP11Session *self, GP11Object *key, gulong mech_type, const guchar *input, gsize n_input, gsize *n_result, GError **err) { - GP11Mechanism mech_args = { mech_type, NULL, 0 }; - return gp11_session_decrypt_full (self, key, &mech_args, input, n_input, n_result, NULL, err); + GP11Mechanism mechanism = { mech_type, NULL, 0 }; + return gp11_session_decrypt_full (self, key, &mechanism, input, n_input, n_result, NULL, err); } /** * gp11_session_decrypt_full: * @self: The session. * @key: The key to decrypt with. - * @mech_args: The mechanism type and parameters to use for decryption. + * @mechanism: The mechanism type and parameters to use for decryption. * @input: The data to decrypt. * @n_input: The length of the data to decrypt. * @n_result: A location to store the length of the result data. @@ -1543,7 +2266,7 @@ gp11_session_decrypt (GP11Session *self, GP11Object *key, gulong mech_type, cons * Returns: The data that was decrypted, or NULL if an error occured. */ guchar* -gp11_session_decrypt_full (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_decrypt_full (GP11Session *self, GP11Object *key, GP11Mechanism *mechanism, const guchar *input, gsize n_input, gsize *n_result, GCancellable *cancellable, GError **err) { @@ -1557,7 +2280,7 @@ gp11_session_decrypt_full (GP11Session *self, GP11Object *key, GP11Mechanism *me funcs = gp11_module_get_functions (module); g_return_val_if_fail (module != NULL, NULL); - ret = crypt_sync (self, key, mech_args, input, n_input, n_result, cancellable, err, + ret = crypt_sync (self, key, mechanism, input, n_input, n_result, cancellable, err, funcs->C_DecryptInit, funcs->C_Decrypt); g_object_unref (module); return ret; @@ -1567,7 +2290,7 @@ gp11_session_decrypt_full (GP11Session *self, GP11Object *key, GP11Mechanism *me * gp11_session_decrypt_async: * @self: The session. * @key: The key to decrypt with. - * @mech_args: The mechanism type and parameters to use for decryption. + * @mechanism: The mechanism type and parameters to use for decryption. * @input: The data to decrypt. * @n_input: The length of the data to decrypt. * @cancellable: A GCancellable which can be used to cancel the operation. @@ -1576,11 +2299,9 @@ gp11_session_decrypt_full (GP11Session *self, GP11Object *key, GP11Mechanism *me * * Decrypt data in a mechanism specific manner. This call will * return immediately and complete asynchronously. - * - * Returns: The data that was decrypted. */ void -gp11_session_decrypt_async (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_decrypt_async (GP11Session *self, GP11Object *key, GP11Mechanism *mechanism, const guchar *input, gsize n_input, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { @@ -1593,7 +2314,7 @@ gp11_session_decrypt_async (GP11Session *self, GP11Object *key, GP11Mechanism *m funcs = gp11_module_get_functions (module); g_return_if_fail (module != NULL); - crypt_async (self, key, mech_args, input, n_input, cancellable, callback, user_data, + crypt_async (self, key, mechanism, input, n_input, cancellable, callback, user_data, funcs->C_DecryptInit, funcs->C_Decrypt); g_object_unref (module); } @@ -1639,15 +2360,15 @@ guchar* gp11_session_sign (GP11Session *self, GP11Object *key, gulong mech_type, const guchar *input, gsize n_input, gsize *n_result, GError **err) { - GP11Mechanism mech_args = { mech_type, NULL, 0 }; - return gp11_session_sign_full (self, key, &mech_args, input, n_input, n_result, NULL, err); + GP11Mechanism mechanism = { mech_type, NULL, 0 }; + return gp11_session_sign_full (self, key, &mechanism, input, n_input, n_result, NULL, err); } /** * gp11_session_sign_full: * @self: The session. * @key: The key to sign with. - * @mech_args: The mechanism type and parameters to use for signing. + * @mechanism: The mechanism type and parameters to use for signing. * @input: The data to sign. * @n_input: The length of the data to sign. * @n_result: A location to store the length of the result data. @@ -1660,7 +2381,7 @@ gp11_session_sign (GP11Session *self, GP11Object *key, gulong mech_type, const g * Returns: The data that was signed, or NULL if an error occured. */ guchar* -gp11_session_sign_full (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_sign_full (GP11Session *self, GP11Object *key, GP11Mechanism *mechanism, const guchar *input, gsize n_input, gsize *n_result, GCancellable *cancellable, GError **err) { @@ -1674,7 +2395,7 @@ gp11_session_sign_full (GP11Session *self, GP11Object *key, GP11Mechanism *mech_ funcs = gp11_module_get_functions (module); g_return_val_if_fail (module != NULL, NULL); - ret = crypt_sync (self, key, mech_args, input, n_input, n_result, cancellable, err, + ret = crypt_sync (self, key, mechanism, input, n_input, n_result, cancellable, err, funcs->C_SignInit, funcs->C_Sign); g_object_unref (module); return ret; @@ -1684,7 +2405,7 @@ gp11_session_sign_full (GP11Session *self, GP11Object *key, GP11Mechanism *mech_ * gp11_session_sign_async: * @self: The session. * @key: The key to sign with. - * @mech_args: The mechanism type and parameters to use for signing. + * @mechanism: The mechanism type and parameters to use for signing. * @input: The data to sign. * @n_input: The length of the data to sign. * @cancellable: A GCancellable which can be used to cancel the operation. @@ -1693,11 +2414,9 @@ gp11_session_sign_full (GP11Session *self, GP11Object *key, GP11Mechanism *mech_ * * Sign data in a mechanism specific manner. This call will * return immediately and complete asynchronously. - * - * Returns: The data that was signed. */ void -gp11_session_sign_async (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_sign_async (GP11Session *self, GP11Object *key, GP11Mechanism *mechanism, const guchar *input, gsize n_input, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { @@ -1710,7 +2429,7 @@ gp11_session_sign_async (GP11Session *self, GP11Object *key, GP11Mechanism *mech funcs = gp11_module_get_functions (module); g_return_if_fail (module != NULL); - crypt_async (self, key, mech_args, input, n_input, cancellable, callback, user_data, + crypt_async (self, key, mechanism, input, n_input, cancellable, callback, user_data, funcs->C_SignInit, funcs->C_Sign); g_object_unref (module); } @@ -1745,7 +2464,7 @@ typedef struct _Verify { /* Input */ CK_OBJECT_HANDLE key; - CK_MECHANISM mech; + GP11Mechanism *mech; guchar *input; CK_ULONG n_input; guchar *signature; @@ -1759,7 +2478,7 @@ perform_verify (Verify *args) CK_RV rv; /* Initialize the crypt operation */ - rv = (args->base.pkcs11->C_VerifyInit) (args->base.handle, &args->mech, args->key); + rv = (args->base.pkcs11->C_VerifyInit) (args->base.handle, (CK_MECHANISM_PTR)args->mech, args->key); if (rv != CKR_OK) return rv; @@ -1787,7 +2506,7 @@ free_verify (Verify *args) { g_free (args->input); g_free (args->signature); - g_free (args->mech.pParameter); + gp11_mechanism_unref (args->mech); g_free (args); } @@ -1811,8 +2530,8 @@ gboolean gp11_session_verify (GP11Session *self, GP11Object *key, gulong mech_type, const guchar *input, gsize n_input, const guchar *signature, gsize n_signature, GError **err) { - GP11Mechanism mech_args = { mech_type, NULL, 0 }; - return gp11_session_verify_full (self, key, &mech_args, input, n_input, + GP11Mechanism mechanism = { mech_type, NULL, 0 }; + return gp11_session_verify_full (self, key, &mechanism, input, n_input, signature, n_signature, NULL, err); } @@ -1820,7 +2539,7 @@ gp11_session_verify (GP11Session *self, GP11Object *key, gulong mech_type, const * gp11_session_verify_full: * @self: The session. * @key: The key to verify with. - * @mech_args: The mechanism type and parameters to use for signing. + * @mechanism: The mechanism type and parameters to use for signing. * @input: The data to verify. * @n_input: The length of the data to verify. * @signature: The signature. @@ -1834,7 +2553,7 @@ gp11_session_verify (GP11Session *self, GP11Object *key, gulong mech_type, const * Returns: TRUE if the data verified correctly, otherwise a failure or error occurred. */ gboolean -gp11_session_verify_full (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_verify_full (GP11Session *self, GP11Object *key, GP11Mechanism *mechanism, const guchar *input, gsize n_input, const guchar *signature, gsize n_signature, GCancellable *cancellable, GError **err) { @@ -1842,15 +2561,13 @@ gp11_session_verify_full (GP11Session *self, GP11Object *key, GP11Mechanism *mec GP11Slot *slot; g_return_val_if_fail (GP11_IS_OBJECT (key), FALSE); - g_return_val_if_fail (mech_args, FALSE); + g_return_val_if_fail (mechanism, FALSE); memset (&args, 0, sizeof (args)); g_object_get (key, "handle", &args.key, NULL); g_return_val_if_fail (args.key != 0, FALSE); - args.mech.mechanism = mech_args->type; - args.mech.pParameter = mech_args->parameter; - args.mech.ulParameterLen = mech_args->n_parameter; + args.mech = mechanism; /* No need to copy in this case */ args.input = (guchar*)input; @@ -1869,7 +2586,7 @@ gp11_session_verify_full (GP11Session *self, GP11Object *key, GP11Mechanism *mec * gp11_session_verify_async: * @self: The session. * @key: The key to verify with. - * @mech_args: The mechanism type and parameters to use for signing. + * @mechanism: The mechanism type and parameters to use for signing. * @input: The data to verify. * @n_input: The length of the data to verify. * @signature: The signature. @@ -1882,7 +2599,7 @@ gp11_session_verify_full (GP11Session *self, GP11Object *key, GP11Mechanism *mec * immediately and completes asynchronously. */ void -gp11_session_verify_async (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, +gp11_session_verify_async (GP11Session *self, GP11Object *key, GP11Mechanism *mechanism, const guchar *input, gsize n_input, const guchar *signature, gsize n_signature, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) @@ -1891,15 +2608,12 @@ gp11_session_verify_async (GP11Session *self, GP11Object *key, GP11Mechanism *me GP11Slot *slot; g_return_if_fail (GP11_IS_OBJECT (key)); - g_return_if_fail (mech_args); + g_return_if_fail (mechanism); g_object_get (key, "handle", &args->key, NULL); g_return_if_fail (args->key != 0); - args->mech.mechanism = mech_args->type; - args->mech.pParameter = mech_args->parameter && mech_args->n_parameter ? - g_memdup (mech_args->parameter, mech_args->n_parameter) : NULL; - args->mech.ulParameterLen = mech_args->n_parameter; + args->mech = gp11_mechanism_ref (mechanism); args->input = input && n_input ? g_memdup (input, n_input) : NULL; args->n_input = n_input; diff --git a/gp11/gp11.h b/gp11/gp11.h index 29dd565..87eaaa6 100644 --- a/gp11/gp11.h +++ b/gp11/gp11.h @@ -57,6 +57,16 @@ typedef struct GP11Mechanism { gulong n_parameter; } GP11Mechanism; +GP11Mechanism* gp11_mechanism_new (gulong type); + +GP11Mechanism* gp11_mechanism_new_with_param (gulong type, + gconstpointer parameter, + gulong n_parameter); + +GP11Mechanism* gp11_mechanism_ref (GP11Mechanism* mech); + +void gp11_mechanism_unref (GP11Mechanism* mech); + typedef struct GP11Attribute { gulong type; guchar *value; @@ -714,25 +724,32 @@ GP11Object* gp11_session_generate_key_finish (GP11Session *self, GError **err, ...) GP11_INVALID_TERMINATED; -gboolean gp11_session_generate_key_pair (GP11Session *self, +#endif /* UNIMPLEMENTED */ + +gboolean gp11_session_generate_key_pair_full (GP11Session *self, GP11Mechanism *mechanism, + GP11Attributes *public_attrs, + GP11Attributes *private_attrs, GP11Object **public_key, GP11Object **private_key, - GError **err, - ...) GP11_INVALID_TERMINATED; + GCancellable *cancellable, + GError **err); void gp11_session_generate_key_pair_async (GP11Session *self, GP11Mechanism *mechanism, + GP11Attributes *public_attrs, + GP11Attributes *private_attrs, + GCancellable *cancellable, GAsyncReadyCallback callback, - gpointer user_data, - ...) GP11_INVALID_TERMINATED; + gpointer user_data); gboolean gp11_session_generate_key_pair_finish (GP11Session *self, GAsyncResult *result, GP11Object **public_key, GP11Object **private_key, - GError **err, - ...) GP11_INVALID_TERMINATED; + GError **err); + +#ifdef UNIMPLEMENTED gboolean gp11_session_seed_random (GP11Session *self, const guchar *seed, @@ -774,7 +791,7 @@ guchar* gp11_session_encrypt (GP11Session *self, guchar* gp11_session_encrypt_full (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, const guchar *input, gsize n_input, gsize *n_result, @@ -783,7 +800,7 @@ guchar* gp11_session_encrypt_full (GP11Session *self, void gp11_session_encrypt_async (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, const guchar *input, gsize n_input, GCancellable *cancellable, @@ -799,13 +816,13 @@ guchar* gp11_session_encrypt_finish (GP11Session *self, GP11Processor* gp11_session_batch_encrypt (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, GCancellable *cancellable, GError **err); void gp11_session_batch_encrypt_async (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); @@ -827,7 +844,7 @@ guchar* gp11_session_decrypt (GP11Session *self, guchar* gp11_session_decrypt_full (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, const guchar *input, gsize n_input, gsize *n_result, @@ -836,7 +853,7 @@ guchar* gp11_session_decrypt_full (GP11Session *self, void gp11_session_decrypt_async (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, const guchar *input, gsize n_input, GCancellable *cancellable, @@ -852,13 +869,13 @@ guchar* gp11_session_decrypt_finish (GP11Session *self, GP11Processor* gp11_session_batch_decrypt (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, GCancellable *cancellable, GError **err); void gp11_session_batch_decrypt_async (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); @@ -875,7 +892,7 @@ guchar* gp11_session_digest (GP11Session *self, GError **err); guchar* gp11_session_digest_full (GP11Session *self, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, const guchar *input, gsize n_input, gsize *n_result, @@ -883,7 +900,7 @@ guchar* gp11_session_digest_full (GP11Session *self, GError **err); void gp11_session_digest_async (GP11Session *self, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, const guchar *input, gsize n_input, GCancellable *cancellable, @@ -896,12 +913,12 @@ guchar* gp11_session_digest_finish (GP11Session *self, GError **err); GP11Processor* gp11_session_batch_digest (GP11Session *self, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, GCancellable *cancellable, GError **err); void gp11_session_batch_digest_async (GP11Session *self, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); @@ -979,7 +996,7 @@ guchar* gp11_session_sign (GP11Session *self, guchar* gp11_session_sign_full (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, const guchar *input, gsize n_input, gsize *n_result, @@ -988,7 +1005,7 @@ guchar* gp11_session_sign_full (GP11Session *self, void gp11_session_sign_async (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, const guchar *input, gsize n_input, GCancellable *cancellable, @@ -1004,13 +1021,13 @@ guchar* gp11_session_sign_finish (GP11Session *self, GP11Processor* gp11_session_batch_sign (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, GCancellable *cancellable, GError **err); void gp11_session_batch_sign_async (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); @@ -1048,7 +1065,7 @@ guchar* gp11_session_sign_recover (GP11Session *self, guchar* gp11_session_sign_recover_full (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, const guchar *input, gsize n_input, gsize *n_result, @@ -1057,7 +1074,7 @@ guchar* gp11_session_sign_recover_full (GP11Session *self, void gp11_session_sign_recover_async (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, const guchar *input, gsize n_input, GCancellable *cancellable, @@ -1082,7 +1099,7 @@ gboolean gp11_session_verify (GP11Session *self, gboolean gp11_session_verify_full (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, const guchar *input, gsize n_input, const guchar *signature, @@ -1118,7 +1135,7 @@ GkrProcessor* gp11_session_batch_verify (GP11Session *self, void gp11_session_batch_verify_async (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, const guchar *input, gsize n_input, GCancellable *cancellable, @@ -1139,7 +1156,7 @@ guchar* gp11_session_verify_recover (GP11Session *self, guchar* gp11_session_verify_recover_full (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, const guchar *input, gsize n_input, gsize *n_result, @@ -1148,7 +1165,7 @@ guchar* gp11_session_verify_recover_full (GP11Session *self, void gp11_session_verify_recover_async (GP11Session *self, GP11Object *key, - GP11Mechanism *mech_args, + GP11Mechanism *mechanism, const guchar *input, gsize n_input, GCancellable *cancellable, @@ -1160,93 +1177,92 @@ guchar* gp11_session_verify_recover_finish (GP11Session *self, gsize *n_result, GError **err); -guchar* gp11_session_wrap (GP11Session *self, - GP11Object *key, +#endif /* UNIMPLEMENTED */ + +gpointer gp11_session_wrap_key (GP11Session *self, + GP11Object *wrapper, gulong mech_type, - GP11Object *wrapped_key, + GP11Object *wrapped, gsize *n_result, GError **err); -guchar* gp11_session_wrap (GP11Session *self, - GP11Object *key, - GP11Mechanism *mech_args, - GP11Object *wrapped_key, +gpointer gp11_session_wrap_key_full (GP11Session *self, + GP11Object *wrapper, + GP11Mechanism *mechanism, + GP11Object *wrapped, gsize *n_result, GCancellable *cancellable, GError **err); -void gp11_session_wrap_async (GP11Session *self, - GP11Object *key, - GP11Mechanism *mech_args, - GP11Object *wrapped_key, +void gp11_session_wrap_key_async (GP11Session *self, + GP11Object *wrapper, + GP11Mechanism *mechanism, + GP11Object *wrapped, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); -guchar* gp11_session_wrap_finish (GP11Session *self, +gpointer gp11_session_wrap_key_finish (GP11Session *self, GAsyncResult *result, gsize *n_result, GError **err); -GP11Object* gp11_session_unwrap (GP11Session *self, - GP11Object *key, +GP11Object* gp11_session_unwrap_key (GP11Session *self, + GP11Object *wrapper, gulong mech_type, - const guchar *input, + gconstpointer input, gsize n_input, GError **err, ...) GP11_INVALID_TERMINATED; -GP11Object* gp11_session_unwrap (GP11Session *self, - GP11Object *key, - GP11Mechanism *mech_args, - const guchar *input, +GP11Object* gp11_session_unwrap_key_full (GP11Session *self, + GP11Object *wrapper, + GP11Mechanism *mechanism, + gconstpointer input, gsize n_input, + GP11Attributes *attrs, GCancellable *cancellable, - GError **err, - ...) GP11_INVALID_TERMINATED; + GError **err); -void gp11_session_unwrap_async (GP11Session *self, - GP11Object *key, - GP11Mechanism *mech_args, - const guchar *input, +void gp11_session_unwrap_key_async (GP11Session *self, + GP11Object *wrapper, + GP11Mechanism *mechanism, + gconstpointer input, gsize n_input, + GP11Attributes *attrs, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); - ...) GP11_INVALID_TERMINATED; -GP11Object* gp11_session_unwrap_finish (GP11Session *self, +GP11Object* gp11_session_unwrap_key_finish (GP11Session *self, GAsyncResult *result, GError **err); -GP11Object* gp11_session_derive (GP11Session *self, - GP11Object *key, +GP11Object* gp11_session_derive_key (GP11Session *self, + GP11Object *base, gulong mech_type, GError **err, ...) GP11_INVALID_TERMINATED; -GP11Object* gp11_session_derive_full (GP11Session *self, - GP11Object *key, - GP11Mechanism *mech_args, +GP11Object* gp11_session_derive_key_full (GP11Session *self, + GP11Object *base, + GP11Mechanism *mechanism, + GP11Attributes *attrs, GCancellable *cancellable, - GError **err, - ...) GP11_INVALID_TERMINATED; + GError **err); -void gp11_session_derive_async (GP11Session *self, - GP11Object *key, - GP11Mechanism *mech_args, +void gp11_session_derive_key_async (GP11Session *self, + GP11Object *base, + GP11Mechanism *mechanism, + GP11Attributes *attrs, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); - ...) GP11_INVALID_TERMINATED; -GP11Object* gp11_session_derive_finish (GP11Session *self, +GP11Object* gp11_session_derive_key_finish (GP11Session *self, GAsyncResult *result, GError **err); -#endif /* UNIMPLEMENTED */ - - /* ------------------------------------------------------------------------ * OBJECT */ diff --git a/gp11/tests/Makefile.am b/gp11/tests/Makefile.am index 3175ecb..532bfd5 100644 --- a/gp11/tests/Makefile.am +++ b/gp11/tests/Makefile.am @@ -2,6 +2,7 @@ # Keep these in the order they should be tested UNIT_AUTO = \ unit-test-gp11-attributes.c \ + test-gp11-mechanism.c \ unit-test-gp11-module.c \ unit-test-gp11-slot.c \ unit-test-gp11-session.c \ diff --git a/gp11/tests/gp11-test-module.c b/gp11/tests/gp11-test-module.c index 5dfc987..f2713f2 100644 --- a/gp11/tests/gp11-test-module.c +++ b/gp11/tests/gp11-test-module.c @@ -75,6 +75,16 @@ free_session (gpointer data) g_free (sess); } +static GP11Attributes* +lookup_object (Session *session, CK_OBJECT_HANDLE hObject) +{ + GP11Attributes *attrs; + attrs = g_hash_table_lookup (the_objects, GUINT_TO_POINTER (hObject)); + if (!attrs) + attrs = g_hash_table_lookup (session->objects, GUINT_TO_POINTER (hObject)); + return attrs; +} + static CK_RV test_C_Initialize (CK_VOID_PTR pInitArgs) { @@ -136,6 +146,10 @@ test_C_Initialize (CK_VOID_PTR pInitArgs) CKA_ALLOWED_MECHANISMS, sizeof (value), &value, CKA_DECRYPT, GP11_BOOLEAN, TRUE, CKA_PRIVATE, GP11_BOOLEAN, TRUE, + CKA_WRAP, GP11_BOOLEAN, TRUE, + CKA_UNWRAP, GP11_BOOLEAN, TRUE, + CKA_DERIVE, GP11_BOOLEAN, TRUE, + CKA_VALUE, GP11_STRING, "value", GP11_INVALID); g_hash_table_insert (the_objects, GUINT_TO_POINTER (PRIVATE_KEY_CAPITALIZE), attrs); @@ -146,6 +160,7 @@ test_C_Initialize (CK_VOID_PTR pInitArgs) CKA_ALLOWED_MECHANISMS, sizeof (value), &value, CKA_ENCRYPT, GP11_BOOLEAN, TRUE, CKA_PRIVATE, GP11_BOOLEAN, FALSE, + CKA_VALUE, GP11_STRING, "value", GP11_INVALID); g_hash_table_insert (the_objects, GUINT_TO_POINTER (PUBLIC_KEY_CAPITALIZE), attrs); @@ -157,6 +172,7 @@ test_C_Initialize (CK_VOID_PTR pInitArgs) CKA_SIGN, GP11_BOOLEAN, TRUE, CKA_PRIVATE, GP11_BOOLEAN, TRUE, CKA_ALWAYS_AUTHENTICATE, GP11_BOOLEAN, TRUE, + CKA_VALUE, GP11_STRING, "value", GP11_INVALID); g_hash_table_insert (the_objects, GUINT_TO_POINTER (PRIVATE_KEY_PREFIX), attrs); @@ -167,6 +183,7 @@ test_C_Initialize (CK_VOID_PTR pInitArgs) CKA_ALLOWED_MECHANISMS, sizeof (value), &value, CKA_VERIFY, GP11_BOOLEAN, TRUE, CKA_PRIVATE, GP11_BOOLEAN, FALSE, + CKA_VALUE, GP11_STRING, "value", GP11_INVALID); g_hash_table_insert (the_objects, GUINT_TO_POINTER (PUBLIC_KEY_PREFIX), attrs); @@ -614,9 +631,7 @@ test_C_DestroyObject (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) if (!session) return CKR_SESSION_HANDLE_INVALID; - attrs = g_hash_table_lookup (the_objects, GUINT_TO_POINTER (hObject)); - if (!attrs) - attrs = g_hash_table_lookup (session->objects, GUINT_TO_POINTER (hObject)); + attrs = lookup_object (session, hObject); if (!attrs) { g_assert_not_reached (); /* "no such object found" */ return CKR_OBJECT_HANDLE_INVALID; @@ -654,9 +669,7 @@ test_C_GetAttributeValue (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, if (!session) return CKR_SESSION_HANDLE_INVALID; - attrs = g_hash_table_lookup (the_objects, GUINT_TO_POINTER (hObject)); - if (!attrs) - attrs = g_hash_table_lookup (session->objects, GUINT_TO_POINTER (hObject)); + attrs = lookup_object (session, hObject); if (!attrs) { g_assert_not_reached (); /* "invalid object handle passed" */ return CKR_OBJECT_HANDLE_INVALID; @@ -703,9 +716,7 @@ test_C_SetAttributeValue (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, if (!session) return CKR_SESSION_HANDLE_INVALID; - attrs = g_hash_table_lookup (the_objects, GUINT_TO_POINTER (hObject)); - if (!attrs) - attrs = g_hash_table_lookup (session->objects, GUINT_TO_POINTER (hObject)); + attrs = lookup_object (session, hObject); if (!attrs) { g_assert_not_reached (); /* "invalid object handle passed" */ return CKR_OBJECT_HANDLE_INVALID; @@ -1340,21 +1351,123 @@ test_C_GenerateKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, static CK_RV test_C_GenerateKeyPair (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, - CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, - CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, - CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey) + CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, + CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey) { - g_assert_not_reached (); /* Not yet used by library */ - return CKR_FUNCTION_NOT_SUPPORTED; + GP11Attributes *attrs; + Session *session; + gboolean token; + CK_ULONG i; + + session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession)); + g_assert (session != NULL && "No such session found"); + if (!session) + return CKR_SESSION_HANDLE_INVALID; + + g_assert (pMechanism); + g_assert (pPublicKeyTemplate); + g_assert (ulPublicKeyAttributeCount); + g_assert (pPrivateKeyTemplate); + g_assert (phPublicKey); + g_assert (phPrivateKey); + + if (pMechanism->mechanism != CKM_GENERATE) + return CKR_MECHANISM_INVALID; + + if (!pMechanism->pParameter || pMechanism->ulParameterLen != 9 || + memcmp (pMechanism->pParameter, "generate", 9) != 0) { + g_assert_not_reached (); + return CKR_MECHANISM_PARAM_INVALID; + } + + attrs = gp11_attributes_new (); + gp11_attributes_add_string (attrs, CKA_VALUE, "generated"); + for (i = 0; i < ulPublicKeyAttributeCount; ++i) + gp11_attributes_add_data (attrs, pPublicKeyTemplate[i].type, + pPublicKeyTemplate[i].pValue, + pPublicKeyTemplate[i].ulValueLen); + *phPublicKey = ++unique_identifier; + if (gp11_attributes_find_boolean (attrs, CKA_TOKEN, &token) && token) + g_hash_table_insert (the_objects, GUINT_TO_POINTER (*phPublicKey), attrs); + else + g_hash_table_insert (session->objects, GUINT_TO_POINTER (*phPublicKey), attrs); + + attrs = gp11_attributes_new (); + gp11_attributes_add_string (attrs, CKA_VALUE, "generated"); + for (i = 0; i < ulPrivateKeyAttributeCount; ++i) + gp11_attributes_add_data (attrs, pPrivateKeyTemplate[i].type, + pPrivateKeyTemplate[i].pValue, + pPrivateKeyTemplate[i].ulValueLen); + *phPrivateKey = ++unique_identifier; + if (gp11_attributes_find_boolean (attrs, CKA_TOKEN, &token) && token) + g_hash_table_insert (the_objects, GUINT_TO_POINTER (*phPrivateKey), attrs); + else + g_hash_table_insert (session->objects, GUINT_TO_POINTER (*phPrivateKey), attrs); + return CKR_OK; } static CK_RV test_C_WrapKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, - CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) + CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, + CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) { - g_assert_not_reached (); /* Not yet used by library */ - return CKR_FUNCTION_NOT_SUPPORTED; + GP11Attributes *attrs; + GP11Attribute *attr; + Session *session; + + session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession)); + if (!session) { + g_assert_not_reached (); + return CKR_SESSION_HANDLE_INVALID; + } + + g_assert (pMechanism); + g_assert (hWrappingKey); + g_assert (hKey); + g_assert (pulWrappedKeyLen); + + attrs = lookup_object (session, hWrappingKey); + if (!attrs) { + g_assert_not_reached (); + return CKR_WRAPPING_KEY_HANDLE_INVALID; + } + + attrs = lookup_object (session, hKey); + if (!attrs) { + g_assert_not_reached (); + return CKR_WRAPPED_KEY_INVALID; + } + + if (pMechanism->mechanism != CKM_WRAP) + return CKR_MECHANISM_INVALID; + + if (pMechanism->pParameter) { + if (pMechanism->ulParameterLen != 4 || + memcmp (pMechanism->pParameter, "wrap", 4) != 0) { + g_assert_not_reached (); + return CKR_MECHANISM_PARAM_INVALID; + } + } + + attr = gp11_attributes_find (attrs, CKA_VALUE); + if (attr == NULL) + return CKR_WRAPPED_KEY_INVALID; + + if (!pWrappedKey) { + *pulWrappedKeyLen = attr->length; + return CKR_OK; + } + + if (*pulWrappedKeyLen < attr->length) { + *pulWrappedKeyLen = attr->length; + return CKR_BUFFER_TOO_SMALL; + } + + memcpy (pWrappedKey, attr->value, attr->length); + *pulWrappedKeyLen = attr->length; + + return CKR_OK; } static CK_RV @@ -1363,8 +1476,56 @@ test_C_UnwrapKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ULONG pulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { - g_assert_not_reached (); /* Not yet used by library */ - return CKR_FUNCTION_NOT_SUPPORTED; + GP11Attributes *attrs; + Session *session; + gboolean token; + CK_ULONG i; + + session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession)); + if (!session) { + g_assert_not_reached (); + return CKR_SESSION_HANDLE_INVALID; + } + + g_assert (pMechanism); + g_assert (pUnwrappingKey); + g_assert (pWrappedKey); + g_assert (pulWrappedKeyLen); + g_assert (phKey); + g_assert (ulCount); + g_assert (pTemplate); + g_assert (phKey); + + attrs = lookup_object (session, pUnwrappingKey); + if (!attrs) { + g_assert_not_reached (); + return CKR_WRAPPING_KEY_HANDLE_INVALID; + } + + if (pMechanism->mechanism != CKM_WRAP) + return CKR_MECHANISM_INVALID; + + if (pMechanism->pParameter) { + if (pMechanism->ulParameterLen != 4 || + memcmp (pMechanism->pParameter, "wrap", 4) != 0) { + g_assert_not_reached (); + return CKR_MECHANISM_PARAM_INVALID; + } + } + + attrs = gp11_attributes_new (); + gp11_attributes_add_data (attrs, CKA_VALUE, pWrappedKey, pulWrappedKeyLen); + for (i = 0; i < ulCount; ++i) + gp11_attributes_add_data (attrs, pTemplate[i].type, + pTemplate[i].pValue, + pTemplate[i].ulValueLen); + *phKey = ++unique_identifier; + if (gp11_attributes_find_boolean (attrs, CKA_TOKEN, &token) && token) + g_hash_table_insert (the_objects, GUINT_TO_POINTER (*phKey), attrs); + else + g_hash_table_insert (session->objects, GUINT_TO_POINTER (*phKey), attrs); + + return CKR_OK; } static CK_RV @@ -1372,8 +1533,54 @@ test_C_DeriveKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { - g_assert_not_reached (); /* Not yet used by library */ - return CKR_FUNCTION_NOT_SUPPORTED; + GP11Attributes *attrs, *copy; + Session *session; + gboolean token; + CK_ULONG i; + + session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession)); + if (!session) { + g_assert_not_reached (); + return CKR_SESSION_HANDLE_INVALID; + } + + g_assert (pMechanism); + g_assert (ulCount); + g_assert (pTemplate); + g_assert (phKey); + + attrs = lookup_object (session, hBaseKey); + if (!attrs) { + g_assert_not_reached (); + return CKR_WRAPPING_KEY_HANDLE_INVALID; + } + + if (pMechanism->mechanism != CKM_DERIVE) + return CKR_MECHANISM_INVALID; + + if (pMechanism->pParameter) { + if (pMechanism->ulParameterLen != 6 || + memcmp (pMechanism->pParameter, "derive", 6) != 0) { + g_assert_not_reached (); + return CKR_MECHANISM_PARAM_INVALID; + } + } + + copy = gp11_attributes_new (); + gp11_attributes_add_string (copy, CKA_VALUE, "derived"); + for (i = 0; i < ulCount; ++i) + gp11_attributes_add_data (copy, pTemplate[i].type, + pTemplate[i].pValue, + pTemplate[i].ulValueLen); + for (i = 0; i < gp11_attributes_count (attrs); ++i) + gp11_attributes_add (copy, gp11_attributes_at (attrs, i)); + *phKey = ++unique_identifier; + if (gp11_attributes_find_boolean (copy, CKA_TOKEN, &token) && token) + g_hash_table_insert (the_objects, GUINT_TO_POINTER (*phKey), copy); + else + g_hash_table_insert (session->objects, GUINT_TO_POINTER (*phKey), copy); + + return CKR_OK; } static CK_RV diff --git a/gp11/tests/gp11-test.h b/gp11/tests/gp11-test.h index 4a12877..428060d 100644 --- a/gp11/tests/gp11-test.h +++ b/gp11/tests/gp11-test.h @@ -29,9 +29,22 @@ * CKM_PREFIX (sign/verify) * sign prefixes data with key label * verify unprefixes data with key label. + * + * CKM_GENERATE (generate-pair) + * generates a pair of keys, mechanism param should be 'generate' + * + * CKM_WRAP (wrap key) + * wraps key by returning value, mechanism param should be 'wrap' + * + * CKM_DERIVE (derive-key) + * derives key by setting value to 'derived'. + * mechanism param should be 'derive' */ #define CKM_CAPITALIZE (CKM_VENDOR_DEFINED | 1) #define CKM_PREFIX (CKM_VENDOR_DEFINED | 2) +#define CKM_GENERATE (CKM_VENDOR_DEFINED | 3) +#define CKM_WRAP (CKM_VENDOR_DEFINED | 4) +#define CKM_DERIVE (CKM_VENDOR_DEFINED | 5) #endif /*TESTGP11HELPERS_H_*/ diff --git a/gp11/tests/test-gp11-mechanism.c b/gp11/tests/test-gp11-mechanism.c new file mode 100644 index 0000000..68543a2 --- /dev/null +++ b/gp11/tests/test-gp11-mechanism.c @@ -0,0 +1,60 @@ + +#include +#include + +#include "run-auto-test.h" +#include "gp11-test.h" + +#define MECH_TYPE 55 +#define MECH_DATA "TEST DATA" +#define N_MECH_DATA ((gsize)9) + +DEFINE_TEST(mech_new) +{ + GP11Mechanism *mech; + + mech = gp11_mechanism_new (MECH_TYPE); + + g_assert (mech); + g_assert (mech->type == MECH_TYPE); + g_assert (mech->parameter == NULL); + g_assert (mech->n_parameter == 0); + + gp11_mechanism_unref (mech); +} + +DEFINE_TEST(mech_new_with_param) +{ + GP11Mechanism *mech; + gpointer parameter = MECH_DATA; + + mech = gp11_mechanism_new_with_param (MECH_TYPE, parameter, N_MECH_DATA); + + g_assert (mech); + g_assert (mech->type == MECH_TYPE); + g_assert (mech->parameter != NULL); + g_assert (mech->parameter != parameter); /* Copied */ + g_assert (mech->n_parameter == N_MECH_DATA); + g_assert (memcmp (mech->parameter, MECH_DATA, N_MECH_DATA) == 0); + + gp11_mechanism_unref (mech); +} + +DEFINE_TEST(mech_ref_unref) +{ + GP11Mechanism *mech, *check; + + mech = gp11_mechanism_new (MECH_TYPE); + g_assert (mech); + + check = gp11_mechanism_ref (mech); + g_assert (check == mech); + + gp11_mechanism_unref (check); + gp11_mechanism_unref (mech); +} + +DEFINE_TEST(mech_unref_null) +{ + gp11_mechanism_unref (NULL); +} diff --git a/gp11/tests/unit-test-gp11-crypto.c b/gp11/tests/unit-test-gp11-crypto.c index fefd548..6a1df15 100644 --- a/gp11/tests/unit-test-gp11-crypto.c +++ b/gp11/tests/unit-test-gp11-crypto.c @@ -59,22 +59,61 @@ find_key (GP11Session *session, CK_ATTRIBUTE_TYPE method, CK_MECHANISM_TYPE mech for (l = objects; l; l = g_list_next (l)) { gp11_object_set_session (l->data, session); - mechs = gp11_object_get_data (l->data, CKA_ALLOWED_MECHANISMS, &n_mechs, NULL); - g_assert (mechs); - g_assert (n_mechs == sizeof (CK_MECHANISM_TYPE)); - - /* We know all of them only have one allowed mech */ - if (*mechs == mech) { - object = l->data; - g_object_ref (object); - break; + if (mech) { + mechs = gp11_object_get_data (l->data, CKA_ALLOWED_MECHANISMS, &n_mechs, NULL); + g_assert (mechs); + g_assert (n_mechs == sizeof (CK_MECHANISM_TYPE)); + /* We know all of them only have one allowed mech */ + if (*mechs != mech) + continue; } + object = l->data; + g_object_ref (object); + break; } gp11_list_unref_free (objects); return object; } +static GP11Object* +find_key_with_value (GP11Session *session, const gchar *value) +{ + GList *objects; + GP11Object *object; + + objects = gp11_session_find_objects (session, NULL, CKA_VALUE, GP11_STRING, value, GP11_INVALID); + g_assert (objects); + + object = g_object_ref (objects->data); + gp11_list_unref_free (objects); + return object; +} + +static void +check_key_with_value (GP11Session *session, GP11Object *key, CK_OBJECT_CLASS klass, const gchar *value) +{ + GP11Attributes *attrs; + GP11Attribute *attr; + gulong check; + + gp11_object_set_session (key, session); + attrs = gp11_object_get (key, NULL, CKA_CLASS, CKA_VALUE, GP11_INVALID); + g_assert (attrs); + + if (!gp11_attributes_find_ulong (attrs, CKA_CLASS, &check)) + g_assert_not_reached (); + g_assert (check == klass); + + attr = gp11_attributes_find (attrs, CKA_VALUE); + g_assert (attr); + g_assert (!gp11_attribute_is_invalid (attr)); + g_assert_cmpsize (attr->length, ==, strlen (value)); + g_assert (memcmp (attr->value, value, attr->length) == 0); + + gp11_attributes_unref (attrs); +} + static gboolean authenticate_object (GP11Slot *module, GP11Object *object, gchar *label, gchar **password) { @@ -89,16 +128,14 @@ authenticate_object (GP11Slot *module, GP11Object *object, gchar *label, gchar * DEFINE_TEST(encrypt) { - GP11Mechanism mech; + GP11Mechanism *mech; GError *error = NULL; GAsyncResult *result = NULL; GP11Object *key; guchar *output; gsize n_output; - mech.type = CKM_CAPITALIZE; - mech.n_parameter = 0; - mech.parameter = NULL; + mech = gp11_mechanism_new (CKM_CAPITALIZE); /* Find the right key */ key = find_key (session, CKA_ENCRYPT, CKM_CAPITALIZE); @@ -112,14 +149,14 @@ DEFINE_TEST(encrypt) g_free (output); /* Full one */ - output = gp11_session_encrypt_full (session, key, &mech, (const guchar*)"blah blah", 10, &n_output, NULL, &error); + output = gp11_session_encrypt_full (session, key, mech, (const guchar*)"blah blah", 10, &n_output, NULL, &error); SUCCESS_RES (output, error); g_assert (n_output == 10); g_assert_cmpstr ((gchar*)output, ==, "BLAH BLAH"); g_free (output); /* Asynchronous one */ - gp11_session_encrypt_async (session, key, &mech, (const guchar*)"second chance", 14, NULL, fetch_async_result, &result); + gp11_session_encrypt_async (session, key, mech, (const guchar*)"second chance", 14, NULL, fetch_async_result, &result); WAIT_UNTIL (result); g_assert (result != NULL); @@ -131,22 +168,21 @@ DEFINE_TEST(encrypt) g_assert_cmpstr ((gchar*)output, ==, "SECOND CHANCE"); g_free (output); + gp11_mechanism_unref (mech); g_object_unref (result); g_object_unref (key); } DEFINE_TEST(decrypt) { - GP11Mechanism mech; + GP11Mechanism *mech; GError *error = NULL; GAsyncResult *result = NULL; GP11Object *key; guchar *output; gsize n_output; - mech.type = CKM_CAPITALIZE; - mech.n_parameter = 0; - mech.parameter = NULL; + mech = gp11_mechanism_new (CKM_CAPITALIZE); /* Find the right key */ key = find_key (session, CKA_DECRYPT, CKM_CAPITALIZE); @@ -160,14 +196,14 @@ DEFINE_TEST(decrypt) g_free (output); /* Full one */ - output = gp11_session_decrypt_full (session, key, &mech, (const guchar*)"TENNIS instructor", 18, &n_output, NULL, &error); + output = gp11_session_decrypt_full (session, key, mech, (const guchar*)"TENNIS instructor", 18, &n_output, NULL, &error); SUCCESS_RES (output, error); g_assert (n_output == 18); g_assert_cmpstr ((gchar*)output, ==, "tennis instructor"); g_free (output); /* Asynchronous one */ - gp11_session_decrypt_async (session, key, &mech, (const guchar*)"FAT CHANCE", 11, NULL, fetch_async_result, &result); + gp11_session_decrypt_async (session, key, mech, (const guchar*)"FAT CHANCE", 11, NULL, fetch_async_result, &result); WAIT_UNTIL (result); g_assert (result != NULL); @@ -179,6 +215,7 @@ DEFINE_TEST(decrypt) g_assert_cmpstr ((gchar*)output, ==, "fat chance"); g_free (output); + gp11_mechanism_unref (mech); g_object_unref (result); g_object_unref (key); } @@ -207,16 +244,14 @@ DEFINE_TEST(login_context_specific) DEFINE_TEST(sign) { - GP11Mechanism mech; + GP11Mechanism *mech; GError *error = NULL; GAsyncResult *result = NULL; GP11Object *key; guchar *output; gsize n_output; - mech.type = CKM_PREFIX; - mech.n_parameter = 10; - mech.parameter = "my-prefix:"; + mech = gp11_mechanism_new_with_param (CKM_PREFIX, "my-prefix:", 10); /* Enable auto-login on this session, see previous test */ gp11_module_set_auto_authenticate (module, TRUE); @@ -234,14 +269,14 @@ DEFINE_TEST(sign) g_free (output); /* Full one */ - output = gp11_session_sign_full (session, key, &mech, (const guchar*)"Labarbara", 10, &n_output, NULL, &error); + output = gp11_session_sign_full (session, key, mech, (const guchar*)"Labarbara", 10, &n_output, NULL, &error); SUCCESS_RES (output, error); g_assert_cmpuint (n_output, ==, 20); g_assert_cmpstr ((gchar*)output, ==, "my-prefix:Labarbara"); g_free (output); /* Asynchronous one */ - gp11_session_sign_async (session, key, &mech, (const guchar*)"Conrad", 7, NULL, fetch_async_result, &result); + gp11_session_sign_async (session, key, mech, (const guchar*)"Conrad", 7, NULL, fetch_async_result, &result); WAIT_UNTIL (result); g_assert (result != NULL); @@ -253,21 +288,20 @@ DEFINE_TEST(sign) g_assert_cmpstr ((gchar*)output, ==, "my-prefix:Conrad"); g_free (output); + gp11_mechanism_unref (mech); g_object_unref (result); g_object_unref (key); } DEFINE_TEST(verify) { - GP11Mechanism mech; + GP11Mechanism *mech; GError *error = NULL; GAsyncResult *result = NULL; GP11Object *key; gboolean ret; - mech.type = CKM_PREFIX; - mech.n_parameter = 10; - mech.parameter = "my-prefix:"; + mech = gp11_mechanism_new_with_param (CKM_PREFIX, "my-prefix:", 10); /* Enable auto-login on this session, shouldn't be needed */ gp11_module_set_auto_authenticate (module, TRUE); @@ -283,17 +317,17 @@ DEFINE_TEST(verify) SUCCESS_RES (ret, error); /* Full one */ - ret = gp11_session_verify_full (session, key, &mech, (const guchar*)"Labarbara", 10, + ret = gp11_session_verify_full (session, key, mech, (const guchar*)"Labarbara", 10, (const guchar*)"my-prefix:Labarbara", 20, NULL, &error); SUCCESS_RES (ret, error); /* Failure one */ - ret = gp11_session_verify_full (session, key, &mech, (const guchar*)"Labarbara", 10, + ret = gp11_session_verify_full (session, key, mech, (const guchar*)"Labarbara", 10, (const guchar*)"my-prefix:Loborboro", 20, NULL, &error); FAIL_RES (ret, error); /* Asynchronous one */ - gp11_session_verify_async (session, key, &mech, (const guchar*)"Labarbara", 10, + gp11_session_verify_async (session, key, mech, (const guchar*)"Labarbara", 10, (const guchar*)"my-prefix:Labarbara", 20, NULL, fetch_async_result, &result); WAIT_UNTIL (result); g_assert (result != NULL); @@ -303,7 +337,7 @@ DEFINE_TEST(verify) /* Asynchronous failure */ result = NULL; - gp11_session_verify_async (session, key, &mech, (const guchar*)"Labarbara", 10, + gp11_session_verify_async (session, key, mech, (const guchar*)"Labarbara", 10, (const guchar*)"my-prefix:Labarxoro", 20, NULL, fetch_async_result, &result); WAIT_UNTIL (result); g_assert (result != NULL); @@ -311,5 +345,250 @@ DEFINE_TEST(verify) FAIL_RES (ret, error); g_object_unref (result); + gp11_mechanism_unref (mech); g_object_unref (key); } + +DEFINE_TEST(generate_key_pair) +{ + GP11Attributes *pub_attrs, *prv_attrs; + GP11Mechanism *mech; + GError *error = NULL; + GAsyncResult *result = NULL; + GP11Object *pub_key, *prv_key; + gboolean ret; + + mech = gp11_mechanism_new_with_param (CKM_GENERATE, "generate", 9); + + pub_attrs = gp11_attributes_new (); + gp11_attributes_add_ulong (pub_attrs, CKA_CLASS, CKO_PUBLIC_KEY); + prv_attrs = gp11_attributes_new (); + gp11_attributes_add_ulong (prv_attrs, CKA_CLASS, CKO_PRIVATE_KEY); + + /* Full One*/ + ret = gp11_session_generate_key_pair_full (session, mech, pub_attrs, prv_attrs, + &pub_key, &prv_key, NULL, &error); + SUCCESS_RES (ret, error); + g_object_unref (pub_key); + g_object_unref (prv_key); + + /* Failure one */ + mech->type = 0; + pub_key = prv_key = NULL; + ret = gp11_session_generate_key_pair_full (session, mech, pub_attrs, prv_attrs, + &pub_key, &prv_key, NULL, &error); + FAIL_RES (ret, error); + g_assert (pub_key == NULL); + g_assert (prv_key == NULL); + + /* Asynchronous one */ + mech->type = CKM_GENERATE; + gp11_session_generate_key_pair_async (session, mech, pub_attrs, prv_attrs, NULL, fetch_async_result, &result); + WAIT_UNTIL (result); + g_assert (result != NULL); + ret = gp11_session_generate_key_pair_finish (session, result, &pub_key, &prv_key, &error); + SUCCESS_RES (ret, error); + g_object_unref (result); + g_object_unref (pub_key); + g_object_unref (prv_key); + + /* Asynchronous failure */ + result = NULL; + mech->type = 0; + pub_key = prv_key = NULL; + gp11_session_generate_key_pair_async (session, mech, pub_attrs, prv_attrs, NULL, fetch_async_result, &result); + WAIT_UNTIL (result); + g_assert (result != NULL); + ret = gp11_session_generate_key_pair_finish (session, result, &pub_key, &prv_key, &error); + FAIL_RES (ret, error); + g_object_unref (result); + g_assert (pub_key == NULL); + g_assert (prv_key == NULL); + + gp11_mechanism_unref (mech); + gp11_attributes_unref (pub_attrs); + gp11_attributes_unref (prv_attrs); +} + +DEFINE_TEST(wrap_key) +{ + GP11Mechanism *mech; + GError *error = NULL; + GAsyncResult *result = NULL; + GP11Object *wrapper, *wrapped; + gpointer output; + gsize n_output; + + mech = gp11_mechanism_new_with_param (CKM_WRAP, "wrap", 4); + wrapper = find_key (session, CKA_WRAP, 0); + wrapped = find_key_with_value (session, "value"); + + /* Simple One */ + output = gp11_session_wrap_key (session, wrapper, CKM_WRAP, wrapped, &n_output, &error); + SUCCESS_RES (output, error); + g_assert (output); + g_assert_cmpsize (n_output, ==, 5); + g_assert (memcmp (output, "value", 5) == 0); + g_free (output); + + /* Full One*/ + output = gp11_session_wrap_key_full (session, wrapper, mech, wrapped, &n_output, NULL, &error); + SUCCESS_RES (output, error); + g_assert_cmpsize (n_output, ==, 5); + g_assert (memcmp (output, "value", 5) == 0); + g_free (output); + + /* Failure one */ + mech->type = 0; + n_output = 0; + output = gp11_session_wrap_key_full (session, wrapper, mech, wrapped, &n_output, NULL, &error); + FAIL_RES (output, error); + g_assert_cmpsize (n_output, ==, 0); + + /* Asynchronous one */ + mech->type = CKM_WRAP; + gp11_session_wrap_key_async (session, wrapper, mech, wrapped, NULL, fetch_async_result, &result); + WAIT_UNTIL (result); + g_assert (result != NULL); + output = gp11_session_wrap_key_finish (session, result, &n_output, &error); + SUCCESS_RES (output, error); + g_assert_cmpsize (n_output, ==, 5); + g_assert (memcmp (output, "value", 5) == 0); + g_object_unref (result); + g_free (output); + + /* Asynchronous failure */ + result = NULL; + mech->type = 0; + n_output = 0; + gp11_session_wrap_key_async (session, wrapper, mech, wrapped, NULL, fetch_async_result, &result); + WAIT_UNTIL (result); + g_assert (result != NULL); + output = gp11_session_wrap_key_finish (session, result, &n_output, &error); + FAIL_RES (output, error); + g_assert_cmpsize (n_output, ==, 0); + g_object_unref (result); + + g_object_unref (wrapper); + g_object_unref (wrapped); + gp11_mechanism_unref (mech); +} + +DEFINE_TEST(unwrap_key) +{ + GP11Mechanism *mech; + GError *error = NULL; + GAsyncResult *result = NULL; + GP11Object *wrapper, *unwrapped; + GP11Attributes *attrs; + + mech = gp11_mechanism_new_with_param (CKM_WRAP, "wrap", 4); + wrapper = find_key (session, CKA_UNWRAP, 0); + attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_SECRET_KEY, GP11_INVALID); + + /* Simple One */ + unwrapped = gp11_session_unwrap_key (session, wrapper, CKM_WRAP, "special", 7, &error, + CKA_CLASS, GP11_ULONG, CKO_SECRET_KEY, GP11_INVALID); + SUCCESS_RES (unwrapped, error); + g_assert (GP11_IS_OBJECT (unwrapped)); + check_key_with_value (session, unwrapped, CKO_SECRET_KEY, "special"); + g_object_unref (unwrapped); + + /* Full One*/ + unwrapped = gp11_session_unwrap_key_full (session, wrapper, mech, "special", 7, attrs, NULL, &error); + SUCCESS_RES (unwrapped, error); + g_assert (GP11_IS_OBJECT (unwrapped)); + check_key_with_value (session, unwrapped, CKO_SECRET_KEY, "special"); + g_object_unref (unwrapped); + + /* Failure one */ + mech->type = 0; + unwrapped = gp11_session_unwrap_key_full (session, wrapper, mech, "special", 7, attrs, NULL, &error); + FAIL_RES (unwrapped, error); + + /* Asynchronous one */ + mech->type = CKM_WRAP; + gp11_session_unwrap_key_async (session, wrapper, mech, "special", 7, attrs, NULL, fetch_async_result, &result); + WAIT_UNTIL (result); + g_assert (result != NULL); + unwrapped = gp11_session_unwrap_key_finish (session, result, &error); + SUCCESS_RES (unwrapped, error); + g_assert (GP11_IS_OBJECT (unwrapped)); + check_key_with_value (session, unwrapped, CKO_SECRET_KEY, "special"); + g_object_unref (unwrapped); + g_object_unref (result); + + /* Asynchronous failure */ + result = NULL; + mech->type = 0; + gp11_session_unwrap_key_async (session, wrapper, mech, "special", 6, attrs, NULL, fetch_async_result, &result); + WAIT_UNTIL (result); + g_assert (result != NULL); + unwrapped = gp11_session_unwrap_key_finish (session, result, &error); + FAIL_RES (unwrapped, error); + g_object_unref (result); + + g_object_unref (wrapper); + gp11_attributes_unref (attrs); + gp11_mechanism_unref (mech); +} + +DEFINE_TEST(derive_key) +{ + GP11Mechanism *mech; + GError *error = NULL; + GAsyncResult *result = NULL; + GP11Object *wrapper, *derived; + GP11Attributes *attrs; + + mech = gp11_mechanism_new_with_param (CKM_DERIVE, "derive", 6); + wrapper = find_key (session, CKA_DERIVE, 0); + attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_SECRET_KEY, GP11_INVALID); + + /* Simple One */ + derived = gp11_session_derive_key (session, wrapper, CKM_DERIVE, &error, + CKA_CLASS, GP11_ULONG, CKO_SECRET_KEY, GP11_INVALID); + SUCCESS_RES (derived, error); + g_assert (GP11_IS_OBJECT (derived)); +g_printerr ("derived is: %lu", gp11_object_get_handle (derived)); + check_key_with_value (session, derived, CKO_SECRET_KEY, "derived"); + g_object_unref (derived); + + /* Full One*/ + derived = gp11_session_derive_key_full (session, wrapper, mech, attrs, NULL, &error); + SUCCESS_RES (derived, error); + g_assert (GP11_IS_OBJECT (derived)); + check_key_with_value (session, derived, CKO_SECRET_KEY, "derived"); + g_object_unref (derived); + + /* Failure one */ + mech->type = 0; + derived = gp11_session_derive_key_full (session, wrapper, mech, attrs, NULL, &error); + FAIL_RES (derived, error); + + /* Asynchronous one */ + mech->type = CKM_DERIVE; + gp11_session_derive_key_async (session, wrapper, mech, attrs, NULL, fetch_async_result, &result); + WAIT_UNTIL (result); + g_assert (result != NULL); + derived = gp11_session_derive_key_finish (session, result, &error); + SUCCESS_RES (derived, error); + g_assert (GP11_IS_OBJECT (derived)); + check_key_with_value (session, derived, CKO_SECRET_KEY, "derived"); + g_object_unref (derived); + g_object_unref (result); + + /* Asynchronous failure */ + result = NULL; + mech->type = 0; + gp11_session_derive_key_async (session, wrapper, mech, attrs, NULL, fetch_async_result, &result); + WAIT_UNTIL (result); + g_assert (result != NULL); + derived = gp11_session_derive_key_finish (session, result, &error); + FAIL_RES (derived, error); + g_object_unref (result); + + g_object_unref (wrapper); + gp11_attributes_unref (attrs); + gp11_mechanism_unref (mech); +} -- 2.7.4