LCOV - code coverage report
Current view: top level - daemon/dbus - gkd-secret-session.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 60.5 % 324 196
Test Date: 2024-04-08 13:24:42 Functions: 84.6 % 26 22

            Line data    Source code
       1              : /*
       2              :  * gnome-keyring
       3              :  *
       4              :  * Copyright (C) 2008 Stefan Walter
       5              :  *
       6              :  * This program is free software; you can redistribute it and/or modify
       7              :  * it under the terms of the GNU Lesser General Public License as
       8              :  * published by the Free Software Foundation; either version 2.1 of
       9              :  * the License, or (at your option) any later version.
      10              :  *
      11              :  * This program is distributed in the hope that it will be useful, but
      12              :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :  * Lesser General Public License for more details.
      15              :  *
      16              :  * You should have received a copy of the GNU Lesser General Public
      17              :  * License along with this program; if not, see
      18              :  * <http://www.gnu.org/licenses/>.
      19              :  */
      20              : 
      21              : #include "config.h"
      22              : 
      23              : #include "gkd-dbus.h"
      24              : #include "gkd-secret-dispatch.h"
      25              : #include "gkd-secret-error.h"
      26              : #include "gkd-secret-secret.h"
      27              : #include "gkd-secret-service.h"
      28              : #include "gkd-secret-session.h"
      29              : #include "gkd-secret-types.h"
      30              : #include "gkd-secret-util.h"
      31              : #include "gkd-secrets-generated.h"
      32              : 
      33              : #include "egg/egg-dh.h"
      34              : #include "egg/egg-error.h"
      35              : 
      36              : #include "pkcs11/pkcs11i.h"
      37              : 
      38              : #include <string.h>
      39              : 
      40              : enum {
      41              :         PROP_0,
      42              :         PROP_CALLER,
      43              :         PROP_OBJECT_PATH,
      44              :         PROP_SERVICE
      45              : };
      46              : 
      47              : struct _GkdSecretSession {
      48              :         GObject parent;
      49              : 
      50              :         /* Information about this object */
      51              :         gchar *object_path;
      52              :         GkdSecretService *service;
      53              :         GkdExportedSession *skeleton;
      54              :         gchar *caller;
      55              : 
      56              :         /* While negotiating with a prompt, set to private key */
      57              :         GckObject *private;
      58              : 
      59              :         /* Once negotiated set to key and mechanism */
      60              :         GckObject *key;
      61              :         CK_MECHANISM_TYPE mech_type;
      62              : };
      63              : 
      64              : static void gkd_secret_dispatch_iface (GkdSecretDispatchIface *iface);
      65          209 : G_DEFINE_TYPE_WITH_CODE (GkdSecretSession, gkd_secret_session, G_TYPE_OBJECT,
      66              :                          G_IMPLEMENT_INTERFACE (GKD_SECRET_TYPE_DISPATCH, gkd_secret_dispatch_iface));
      67              : 
      68              : static guint unique_session_number = 0;
      69              : 
      70              : /* -----------------------------------------------------------------------------
      71              :  * INTERNAL
      72              :  */
      73              : 
      74              : static void
      75           16 : take_session_key (GkdSecretSession *self, GckObject *key, CK_MECHANISM_TYPE mech)
      76              : {
      77           16 :         g_return_if_fail (!self->key);
      78           16 :         self->key = key;
      79           16 :         self->mech_type = mech;
      80              : }
      81              : 
      82              : static gboolean
      83            1 : aes_create_dh_keys (GckSession *session, const gchar *group,
      84              :                     GckObject **pub_key, GckObject **priv_key)
      85              : {
      86            1 :         GckBuilder builder = GCK_BUILDER_INIT;
      87              :         GckAttributes *attrs;
      88              :         gconstpointer prime, base;
      89              :         gsize n_prime, n_base;
      90            1 :         GError *error = NULL;
      91              :         gboolean ret;
      92              : 
      93            1 :         if (!egg_dh_default_params_raw (group, &prime, &n_prime, &base, &n_base)) {
      94            0 :                 g_warning ("couldn't load dh parameter group: %s", group);
      95            0 :                 return FALSE;
      96              :         }
      97              : 
      98            1 :         gck_builder_add_data (&builder, CKA_PRIME, prime, n_prime);
      99            1 :         gck_builder_add_data (&builder, CKA_BASE, base, n_base);
     100            1 :         attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
     101              : 
     102              :         /* Perform the DH key generation */
     103            1 :         ret = gck_session_generate_key_pair (session, CKM_DH_PKCS_KEY_PAIR_GEN, attrs, attrs,
     104              :                                              pub_key, priv_key, NULL, &error);
     105              : 
     106            1 :         gck_attributes_unref (attrs);
     107              : 
     108            1 :         if (ret == FALSE) {
     109            0 :                 g_warning ("couldn't generate dh key pair: %s", egg_error_message (error));
     110            0 :                 g_clear_error (&error);
     111            0 :                 return FALSE;
     112              :         }
     113              : 
     114            1 :         return TRUE;
     115              : }
     116              : 
     117              : static gboolean
     118            1 : aes_derive_key (GckSession *session, GckObject *priv_key,
     119              :                 gconstpointer input, gsize n_input, GckObject **aes_key)
     120              : {
     121            1 :         GckBuilder builder = GCK_BUILDER_INIT;
     122            1 :         GError *error = NULL;
     123              :         GckMechanism mech;
     124              :         GckObject *dh_key;
     125              : 
     126              :         /*
     127              :          * First we have to generate a secret key from the DH key. The
     128              :          * length of this key depends on the size of our DH prime
     129              :          */
     130              : 
     131            1 :         mech.type = CKM_DH_PKCS_DERIVE;
     132            1 :         mech.parameter = input;
     133            1 :         mech.n_parameter = n_input;
     134              : 
     135            1 :         gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
     136            1 :         gck_builder_add_ulong (&builder, CKA_KEY_TYPE, CKK_GENERIC_SECRET);
     137            1 :         dh_key = gck_session_derive_key_full (session, priv_key, &mech, gck_builder_end (&builder), NULL, &error);
     138              : 
     139            1 :         if (!dh_key) {
     140            0 :                 g_warning ("couldn't derive key from dh key pair: %s", egg_error_message (error));
     141            0 :                 g_clear_error (&error);
     142            0 :                 return FALSE;
     143              :         }
     144              : 
     145              :         /*
     146              :          * Now use HKDF to generate our AES key.
     147              :          */
     148              : 
     149            1 :         mech.type = CKM_G_HKDF_SHA256_DERIVE;
     150            1 :         mech.parameter = NULL;
     151            1 :         mech.n_parameter = 0;
     152              : 
     153            1 :         gck_builder_add_ulong (&builder, CKA_VALUE_LEN, 16UL);
     154            1 :         gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
     155            1 :         gck_builder_add_ulong (&builder, CKA_KEY_TYPE, CKK_AES);
     156              : 
     157            1 :         *aes_key = gck_session_derive_key_full (session, dh_key, &mech, gck_builder_end (&builder), NULL, &error);
     158            1 :         g_object_unref (dh_key);
     159              : 
     160            1 :         if (!*aes_key) {
     161            0 :                 g_warning ("couldn't derive aes key from dh key: %s", egg_error_message (error));
     162            0 :                 g_clear_error (&error);
     163            0 :                 return FALSE;
     164              :         }
     165              : 
     166            1 :         return TRUE;
     167              : }
     168              : 
     169              : static gboolean
     170            0 : aes_negotiate (GkdSecretSession *self,
     171              :                GVariant *input_variant,
     172              :                GVariant **output_variant,
     173              :                gchar **result,
     174              :                GError **error_out)
     175              : {
     176              :         GckSession *session;
     177              :         GckObject *pub, *priv, *key;
     178            0 :         GError *error = NULL;
     179              :         gpointer output;
     180              :         gsize n_output;
     181              :         const gchar *input;
     182              :         gsize n_input;
     183              :         gboolean ret;
     184              : 
     185            0 :         session = gkd_secret_service_get_pkcs11_session (self->service, self->caller);
     186            0 :         g_return_val_if_fail (session, FALSE);
     187              : 
     188            0 :         if (!aes_create_dh_keys (session, "ietf-ike-grp-modp-1024", &pub, &priv)) {
     189            0 :                 g_set_error_literal (error_out, G_DBUS_ERROR,
     190              :                                      G_DBUS_ERROR_FAILED,
     191              :                                      "Failed to create necessary crypto keys.");
     192            0 :                 return FALSE;
     193              :         }
     194              : 
     195              :         /* Get the output data */
     196            0 :         output = gck_object_get_data (pub, CKA_VALUE, NULL, &n_output, &error);
     197            0 :         gck_object_destroy (pub, NULL, NULL);
     198            0 :         g_object_unref (pub);
     199              : 
     200            0 :         if (output == NULL) {
     201            0 :                 g_warning ("couldn't get public key DH value: %s", egg_error_message (error));
     202            0 :                 g_clear_error (&error);
     203            0 :                 g_object_unref (priv);
     204            0 :                 g_set_error_literal (error_out, G_DBUS_ERROR,
     205              :                                      G_DBUS_ERROR_FAILED,
     206              :                                      "Failed to retrieve necessary crypto keys.");
     207            0 :                 return FALSE;
     208              :         }
     209              : 
     210            0 :         input = g_variant_get_fixed_array (input_variant, &n_input, sizeof (guchar));
     211            0 :         ret = aes_derive_key (session, priv, input, n_input, &key);
     212              : 
     213            0 :         gck_object_destroy (priv, NULL, NULL);
     214            0 :         g_object_unref (priv);
     215              : 
     216            0 :         if (ret == FALSE) {
     217            0 :                 g_free (output);
     218            0 :                 g_set_error_literal (error_out, G_DBUS_ERROR,
     219              :                                      G_DBUS_ERROR_FAILED,
     220              :                                      "Failed to create necessary crypto key.");
     221            0 :                 return FALSE;
     222              :         }
     223              : 
     224            0 :         take_session_key (self, key, CKM_AES_CBC_PAD);
     225              : 
     226            0 :         if (output_variant != NULL) {
     227            0 :                 *output_variant = g_variant_new_variant (g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
     228              :                                                                                     output, n_output,
     229              :                                                                                     sizeof (guchar)));
     230              :         }
     231              : 
     232            0 :         if (result != NULL) {
     233            0 :                 *result = g_strdup (self->object_path);
     234              :         }
     235              : 
     236            0 :         g_free (output);
     237              : 
     238            0 :         return TRUE;
     239              : }
     240              : 
     241              : static gboolean
     242           16 : plain_negotiate (GkdSecretSession *self,
     243              :                  GVariant **output,
     244              :                  gchar **result,
     245              :                  GError **error_out)
     246              : {
     247           16 :         GckBuilder builder = GCK_BUILDER_INIT;
     248           16 :         GError *error = NULL;
     249              :         GckObject *key;
     250              :         GckSession *session;
     251              : 
     252           16 :         session = gkd_secret_service_get_pkcs11_session (self->service, self->caller);
     253           16 :         g_return_val_if_fail (session, FALSE);
     254              : 
     255           16 :         gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
     256           16 :         gck_builder_add_ulong (&builder, CKA_KEY_TYPE, CKK_G_NULL);
     257              : 
     258           16 :         key = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error);
     259              : 
     260           16 :         if (key == NULL) {
     261            0 :                 g_warning ("couldn't create null key: %s", egg_error_message (error));
     262            0 :                 g_clear_error (&error);
     263            0 :                 g_set_error_literal (error_out, G_DBUS_ERROR,
     264              :                                      G_DBUS_ERROR_FAILED,
     265              :                                      "Failed to create necessary plain keys.");
     266            0 :                 return FALSE;
     267              :         }
     268              : 
     269           16 :         take_session_key (self, key, CKM_G_NULL);
     270              : 
     271           16 :         if (output != NULL) {
     272           16 :                 *output = g_variant_new_variant (g_variant_new_string (""));
     273              :         }
     274              : 
     275           16 :         if (result != NULL) {
     276           32 :                 *result = g_strdup (self->object_path);
     277              :         }
     278              : 
     279           16 :         return TRUE;
     280              : }
     281              : 
     282              : /* -----------------------------------------------------------------------------
     283              :  * DBUS
     284              :  */
     285              : static gboolean
     286            0 : session_method_close (GkdExportedSession *skeleton,
     287              :                       GDBusMethodInvocation *invocation,
     288              :                       GkdSecretSession *self)
     289              : {
     290            0 :         if (!gkd_dbus_invocation_matches_caller (invocation, self->caller))
     291            0 :                 return FALSE;
     292              : 
     293            0 :         gkd_secret_service_close_session (self->service, self);
     294            0 :         gkd_exported_session_complete_close (skeleton, invocation);
     295              : 
     296            0 :         return TRUE;
     297              : }
     298              : 
     299              : /* -----------------------------------------------------------------------------
     300              :  * OBJECT
     301              :  */
     302              : static GObject*
     303           17 : gkd_secret_session_constructor (GType type, guint n_props, GObjectConstructParam *props)
     304              : {
     305           17 :         GkdSecretSession *self = GKD_SECRET_SESSION (G_OBJECT_CLASS (gkd_secret_session_parent_class)->constructor(type, n_props, props));
     306           17 :         GError *error = NULL;
     307              : 
     308           17 :         g_return_val_if_fail (self, NULL);
     309           17 :         g_return_val_if_fail (self->caller, NULL);
     310           17 :         g_return_val_if_fail (self->service, NULL);
     311              : 
     312              :         /* Setup the path for the object */
     313           17 :         self->object_path = g_strdup_printf (SECRET_SESSION_PREFIX "/s%d", ++unique_session_number);
     314              : 
     315           17 :         self->skeleton = gkd_exported_session_skeleton_new ();
     316           17 :         g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self->skeleton),
     317              :                                           gkd_secret_service_get_connection (self->service),
     318           17 :                                           self->object_path, &error);
     319              : 
     320           17 :         if (error != NULL) {
     321            0 :                 g_warning ("could not register secret session on session bus: %s", error->message);
     322            0 :                 g_error_free (error);
     323              :         }
     324              : 
     325           17 :         g_signal_connect (self->skeleton, "handle-close",
     326              :                           G_CALLBACK (session_method_close), self);
     327              : 
     328           17 :         return G_OBJECT (self);
     329              : }
     330              : 
     331              : static void
     332           17 : gkd_secret_session_init (GkdSecretSession *self)
     333              : {
     334              : 
     335           17 : }
     336              : 
     337              : static void
     338           32 : gkd_secret_session_dispose (GObject *obj)
     339              : {
     340           32 :         GkdSecretSession *self = GKD_SECRET_SESSION (obj);
     341              : 
     342           32 :         g_free (self->object_path);
     343           32 :         self->object_path = NULL;
     344              : 
     345           32 :         if (self->skeleton) {
     346           16 :                 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (self->skeleton));
     347           16 :                 g_clear_object (&self->skeleton);
     348              :         }
     349              : 
     350           32 :         if (self->service) {
     351           16 :                 g_object_remove_weak_pointer (G_OBJECT (self->service),
     352           16 :                                               (gpointer*)&(self->service));
     353           16 :                 self->service = NULL;
     354              :         }
     355              : 
     356           32 :         if (self->key) {
     357           16 :                 g_object_unref (self->key);
     358           16 :                 self->key = NULL;
     359              :         }
     360              : 
     361           32 :         G_OBJECT_CLASS (gkd_secret_session_parent_class)->dispose (obj);
     362           32 : }
     363              : 
     364              : static void
     365           16 : gkd_secret_session_finalize (GObject *obj)
     366              : {
     367           16 :         GkdSecretSession *self = GKD_SECRET_SESSION (obj);
     368              : 
     369           16 :         g_assert (!self->object_path);
     370           16 :         g_assert (!self->service);
     371           16 :         g_assert (!self->key);
     372              : 
     373           16 :         g_free (self->caller);
     374           16 :         self->caller = NULL;
     375              : 
     376           16 :         G_OBJECT_CLASS (gkd_secret_session_parent_class)->finalize (obj);
     377           16 : }
     378              : 
     379              : static void
     380           34 : gkd_secret_session_set_property (GObject *obj, guint prop_id, const GValue *value,
     381              :                                  GParamSpec *pspec)
     382              : {
     383           34 :         GkdSecretSession *self = GKD_SECRET_SESSION (obj);
     384              : 
     385           34 :         switch (prop_id) {
     386           17 :         case PROP_CALLER:
     387           17 :                 g_return_if_fail (!self->caller);
     388           17 :                 self->caller = g_value_dup_string (value);
     389           17 :                 break;
     390           17 :         case PROP_SERVICE:
     391           17 :                 g_return_if_fail (!self->service);
     392           17 :                 self->service = g_value_get_object (value);
     393           17 :                 g_return_if_fail (self->service);
     394           17 :                 g_object_add_weak_pointer (G_OBJECT (self->service),
     395           17 :                                            (gpointer*)&(self->service));
     396           17 :                 break;
     397            0 :         default:
     398            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     399            0 :                 break;
     400              :         }
     401              : }
     402              : 
     403              : static void
     404           16 : gkd_secret_session_get_property (GObject *obj, guint prop_id, GValue *value,
     405              :                                  GParamSpec *pspec)
     406              : {
     407           16 :         GkdSecretSession *self = GKD_SECRET_SESSION (obj);
     408              : 
     409           16 :         switch (prop_id) {
     410            0 :         case PROP_CALLER:
     411            0 :                 g_value_set_string (value, gkd_secret_session_get_caller (self));
     412            0 :                 break;
     413           16 :         case PROP_OBJECT_PATH:
     414           16 :                 g_value_set_pointer (value, self->object_path);
     415           16 :                 break;
     416            0 :         case PROP_SERVICE:
     417            0 :                 g_value_set_object (value, self->service);
     418            0 :                 break;
     419            0 :         default:
     420            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     421            0 :                 break;
     422              :         }
     423           16 : }
     424              : 
     425              : static void
     426           16 : gkd_secret_session_class_init (GkdSecretSessionClass *klass)
     427              : {
     428           16 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     429              : 
     430           16 :         gobject_class->constructor = gkd_secret_session_constructor;
     431           16 :         gobject_class->dispose = gkd_secret_session_dispose;
     432           16 :         gobject_class->finalize = gkd_secret_session_finalize;
     433           16 :         gobject_class->set_property = gkd_secret_session_set_property;
     434           16 :         gobject_class->get_property = gkd_secret_session_get_property;
     435              : 
     436           16 :         g_object_class_install_property (gobject_class, PROP_CALLER,
     437              :                 g_param_spec_string ("caller", "Caller", "DBus caller name",
     438              :                                      NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ));
     439              : 
     440           16 :         g_object_class_install_property (gobject_class, PROP_OBJECT_PATH,
     441              :                 g_param_spec_pointer ("object-path", "Object Path", "DBus Object Path",
     442              :                                       G_PARAM_READABLE));
     443              : 
     444           16 :         g_object_class_install_property (gobject_class, PROP_SERVICE,
     445              :                 g_param_spec_object ("service", "Service", "Service which owns this session",
     446              :                                      GKD_SECRET_TYPE_SERVICE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
     447           16 : }
     448              : 
     449              : static void
     450           16 : gkd_secret_dispatch_iface (GkdSecretDispatchIface *iface)
     451              : {
     452           16 : }
     453              : 
     454              : /* -----------------------------------------------------------------------------
     455              :  * PUBLIC
     456              :  */
     457              : 
     458              : GkdSecretSession*
     459           17 : gkd_secret_session_new (GkdSecretService *service, const gchar *caller)
     460              : {
     461           17 :         g_return_val_if_fail (GKD_SECRET_IS_SERVICE (service), NULL);
     462           17 :         g_return_val_if_fail (caller, NULL);
     463           17 :         return g_object_new (GKD_SECRET_TYPE_SESSION,
     464              :                              "caller", caller, "service", service, NULL);
     465              : }
     466              : 
     467              : gpointer
     468            1 : gkd_secret_session_begin (GkdSecretSession *self, const gchar *group,
     469              :                           gsize *n_output)
     470              : {
     471            1 :         GError *error = NULL;
     472              :         GckSession *session;
     473              :         GckObject *public;
     474              :         gpointer output;
     475              : 
     476            1 :         g_return_val_if_fail (GKD_SECRET_IS_SESSION (self), NULL);
     477            1 :         g_return_val_if_fail (group, NULL);
     478            1 :         g_return_val_if_fail (n_output, NULL);
     479            1 :         g_return_val_if_fail (self->private == NULL, NULL);
     480              : 
     481            1 :         session = gkd_secret_session_get_pkcs11_session (self);
     482            1 :         g_return_val_if_fail (session, NULL);
     483              : 
     484            1 :         if (!aes_create_dh_keys (session, group, &public, &self->private))
     485            0 :                 return NULL;
     486              : 
     487              :         /* Get the output data */
     488            1 :         output = gck_object_get_data (public, CKA_VALUE, NULL, n_output, &error);
     489            1 :         gck_object_destroy (public, NULL, NULL);
     490            1 :         g_object_unref (public);
     491              : 
     492            1 :         if (output == NULL) {
     493            0 :                 g_warning ("couldn't get public key DH value: %s", egg_error_message (error));
     494            0 :                 g_clear_error (&error);
     495            0 :                 return NULL;
     496              :         }
     497              : 
     498            1 :         return output;
     499              : }
     500              : 
     501              : gboolean
     502            1 : gkd_secret_session_complete (GkdSecretSession *self, gconstpointer peer,
     503              :                              gsize n_peer)
     504              : {
     505              :         GckSession *session;
     506              : 
     507            1 :         g_return_val_if_fail (GKD_SECRET_IS_SESSION (self), FALSE);
     508            1 :         g_return_val_if_fail (self->key == NULL, FALSE);
     509              : 
     510            1 :         session = gkd_secret_session_get_pkcs11_session (self);
     511            1 :         g_return_val_if_fail (session, FALSE);
     512              : 
     513            1 :         if (!aes_derive_key (session, self->private, peer, n_peer, &self->key))
     514            0 :                 return FALSE;
     515              : 
     516            1 :         self->mech_type = CKM_AES_CBC_PAD;
     517            1 :         return TRUE;
     518              : }
     519              : 
     520              : gboolean
     521           16 : gkd_secret_session_handle_open (GkdSecretSession *self,
     522              :                                 const gchar *algorithm,
     523              :                                 GVariant *input,
     524              :                                 GVariant **output,
     525              :                                 gchar **result,
     526              :                                 GError **error)
     527              : {
     528              :         const GVariantType *variant_type;
     529              : 
     530           16 :         variant_type = g_variant_get_type (input);
     531              : 
     532              :         /* Plain transfers? just remove our session key */
     533           16 :         if (g_str_equal (algorithm, "plain")) {
     534           16 :                 if (!g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING)) {
     535            0 :                         g_set_error (error, G_DBUS_ERROR,
     536              :                                      G_DBUS_ERROR_INVALID_ARGS,
     537              :                                      "The session algorithm input argument (%s) was invalid",
     538              :                                      algorithm);
     539            0 :                         return FALSE;
     540              :                 }
     541              : 
     542           16 :                 return plain_negotiate (self, output, result, error);
     543              : 
     544            0 :         } else if (g_str_equal (algorithm, "dh-ietf1024-sha256-aes128-cbc-pkcs7")) {
     545            0 :                 if (!g_variant_type_equal (variant_type, G_VARIANT_TYPE_BYTESTRING)) {
     546            0 :                         g_set_error (error, G_DBUS_ERROR,
     547              :                                      G_DBUS_ERROR_INVALID_ARGS,
     548              :                                      "The session algorithm input argument (%s) was invalid",
     549              :                                      algorithm);
     550            0 :                         return FALSE;
     551              :                 }
     552              : 
     553            0 :                 return aes_negotiate (self, input, output, result, error);
     554              : 
     555              :         } else {
     556            0 :                 g_set_error (error, G_DBUS_ERROR,
     557              :                              G_DBUS_ERROR_NOT_SUPPORTED,
     558              :                              "The algorithm '%s' is not supported", algorithm);
     559            0 :                 return FALSE;
     560              :         }
     561              : 
     562              :         g_assert_not_reached ();
     563              : }
     564              : 
     565              : 
     566              : const gchar*
     567            0 : gkd_secret_session_get_caller (GkdSecretSession *self)
     568              : {
     569            0 :         g_return_val_if_fail (GKD_SECRET_IS_SESSION (self), NULL);
     570            0 :         return self->caller;
     571              : }
     572              : 
     573              : GckSession*
     574            4 : gkd_secret_session_get_pkcs11_session (GkdSecretSession *self)
     575              : {
     576            4 :         g_return_val_if_fail (GKD_SECRET_IS_SESSION (self), NULL);
     577            4 :         return gkd_secret_service_get_pkcs11_session (self->service, self->caller);
     578              : }
     579              : 
     580              : GkdSecretSecret*
     581            0 : gkd_secret_session_get_item_secret (GkdSecretSession *self, GckObject *item,
     582              :                                     GError **error_out)
     583              : {
     584            0 :         GckMechanism mech = { 0UL, NULL, 0 };
     585              :         GckSession *session;
     586              :         gpointer value, iv;
     587              :         gsize n_value, n_iv;
     588            0 :         GError *error = NULL;
     589              : 
     590            0 :         g_assert (GCK_IS_OBJECT (self->key));
     591              : 
     592            0 :         session = gck_object_get_session (item);
     593            0 :         g_return_val_if_fail (session, NULL);
     594              : 
     595            0 :         if (self->mech_type == CKM_AES_CBC_PAD) {
     596            0 :                 n_iv = 16;
     597            0 :                 iv = g_malloc (n_iv);
     598            0 :                 gcry_create_nonce (iv, n_iv);
     599              :         } else {
     600            0 :                 n_iv = 0;
     601            0 :                 iv = NULL;
     602              :         }
     603              : 
     604            0 :         mech.type = self->mech_type;
     605            0 :         mech.parameter = iv;
     606            0 :         mech.n_parameter = n_iv;
     607              : 
     608            0 :         value = gck_session_wrap_key_full (session, self->key, &mech, item, &n_value,
     609              :                                            NULL, &error);
     610              : 
     611            0 :         if (error != NULL) {
     612            0 :                 if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN)) {
     613            0 :                         g_set_error_literal (error_out, GKD_SECRET_ERROR,
     614              :                                              GKD_SECRET_ERROR_IS_LOCKED,
     615              :                                              "Cannot get secret of a locked object");
     616              :                 } else {
     617            0 :                         g_message ("couldn't wrap item secret: %s", egg_error_message (error));
     618            0 :                         g_set_error_literal (error_out, G_DBUS_ERROR,
     619              :                                              G_DBUS_ERROR_FAILED,
     620              :                                              "Couldn't get item secret");
     621              :                 }
     622            0 :                 g_clear_error (&error);
     623            0 :                 g_free (iv);
     624            0 :                 return NULL;
     625              :         }
     626              : 
     627            0 :         return gkd_secret_secret_new_take_memory (self, iv, n_iv, value, n_value);
     628              : }
     629              : 
     630              : gboolean
     631            2 : gkd_secret_session_set_item_secret (GkdSecretSession *self, GckObject *item,
     632              :                                     GkdSecretSecret *secret, GError **error_out)
     633              : {
     634            2 :         GckBuilder builder = GCK_BUILDER_INIT;
     635              :         GckMechanism mech;
     636              :         GckObject *object;
     637              :         GckSession *session;
     638            2 :         GError *error = NULL;
     639              :         GckAttributes *attrs;
     640              : 
     641            2 :         g_return_val_if_fail (GKD_SECRET_IS_SESSION (self), FALSE);
     642            2 :         g_return_val_if_fail (GCK_IS_OBJECT (item), FALSE);
     643            2 :         g_return_val_if_fail (secret, FALSE);
     644              : 
     645            2 :         g_assert (GCK_IS_OBJECT (self->key));
     646              : 
     647              :         /*
     648              :          * By getting these attributes, and then using them in the unwrap,
     649              :          * the unwrap won't generate a new object, but merely set the secret.
     650              :          */
     651              : 
     652            2 :         attrs = gck_object_get (item, NULL, &error, CKA_ID, CKA_G_COLLECTION, GCK_INVALID);
     653            2 :         if (attrs == NULL) {
     654            0 :                 g_set_error_literal (error_out, G_DBUS_ERROR,
     655              :                                      G_DBUS_ERROR_FAILED,
     656              :                                      "Couldn't set item secret");
     657            0 :                 g_clear_error (&error);
     658            0 :                 return FALSE;
     659              :         }
     660            2 :         gck_builder_add_all (&builder, attrs);
     661            2 :         gck_attributes_unref (attrs);
     662            2 :         gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
     663              : 
     664            2 :         session = gkd_secret_service_get_pkcs11_session (self->service, self->caller);
     665            2 :         g_return_val_if_fail (session, FALSE);
     666              : 
     667            2 :         mech.type = self->mech_type;
     668            2 :         mech.parameter = secret->parameter;
     669            2 :         mech.n_parameter = secret->n_parameter;
     670              : 
     671            2 :         object = gck_session_unwrap_key_full (session, self->key, &mech, secret->value,
     672              :                                               secret->n_value, gck_builder_end (&builder), NULL, &error);
     673              : 
     674            2 :         if (object == NULL) {
     675            0 :                 if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN)) {
     676            0 :                         g_set_error_literal (error_out, GKD_SECRET_ERROR,
     677              :                                              GKD_SECRET_ERROR_IS_LOCKED,
     678              :                                              "Cannot set secret of a locked item");
     679            0 :                 } else if (g_error_matches (error, GCK_ERROR, CKR_WRAPPED_KEY_INVALID) ||
     680            0 :                            g_error_matches (error, GCK_ERROR, CKR_WRAPPED_KEY_LEN_RANGE) ||
     681            0 :                            g_error_matches (error, GCK_ERROR, CKR_MECHANISM_PARAM_INVALID)) {
     682            0 :                         g_set_error_literal (error_out, G_DBUS_ERROR,
     683              :                                              G_DBUS_ERROR_INVALID_ARGS,
     684              :                                              "The secret was transferred or encrypted in an invalid way.");
     685              :                 } else {
     686            0 :                         g_message ("couldn't unwrap item secret: %s", egg_error_message (error));
     687            0 :                         g_set_error_literal (error_out, G_DBUS_ERROR,
     688              :                                              G_DBUS_ERROR_FAILED,
     689              :                                              "Couldn't set item secret");
     690              :                 }
     691            0 :                 g_clear_error (&error);
     692            0 :                 return FALSE;
     693              :         }
     694              : 
     695            2 :         if (!gck_object_equal (object, item)) {
     696            0 :                 g_warning ("unwrapped secret went to new object, instead of item");
     697            0 :                 g_set_error_literal (error_out, G_DBUS_ERROR,
     698              :                                      G_DBUS_ERROR_FAILED,
     699              :                                      "Couldn't set item secret");
     700            0 :                 g_object_unref (object);
     701            0 :                 return FALSE;
     702              :         }
     703              : 
     704            2 :         g_object_unref (object);
     705            2 :         return TRUE;
     706              : }
     707              : 
     708              : GckObject*
     709           17 : gkd_secret_session_create_credential (GkdSecretSession *self,
     710              :                                       GckSession *session,
     711              :                                       GckAttributes *attrs,
     712              :                                       GkdSecretSecret *secret,
     713              :                                       GError **error)
     714              : {
     715           17 :         GckBuilder builder = GCK_BUILDER_INIT;
     716           17 :         GckAttributes *alloc = NULL;
     717              :         GckMechanism mech;
     718              :         GckObject *object;
     719              : 
     720           17 :         g_assert (GCK_IS_OBJECT (self->key));
     721           17 :         g_assert (attrs != NULL);
     722              : 
     723           17 :         if (session == NULL)
     724           15 :                 session = gkd_secret_service_get_pkcs11_session (self->service, self->caller);
     725           17 :         g_return_val_if_fail (session, NULL);
     726              : 
     727           17 :         if (attrs == NULL) {
     728            0 :                 gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_CREDENTIAL);
     729            0 :                 gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE);
     730            0 :                 alloc = attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
     731              :         }
     732              : 
     733           17 :         mech.type = self->mech_type;
     734           17 :         mech.parameter = secret->parameter;
     735           17 :         mech.n_parameter = secret->n_parameter;
     736              : 
     737           17 :         object = gck_session_unwrap_key_full (session, self->key, &mech, secret->value,
     738              :                                               secret->n_value, attrs, NULL, error);
     739              : 
     740           17 :         gck_attributes_unref (alloc);
     741              : 
     742           17 :         return object;
     743              : }
        

Generated by: LCOV version 2.0-1