LCOV - code coverage report
Current view: top level - pkcs11/gkm - gkm-aes-key.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 62.9 % 105 66
Test Date: 2024-04-08 13:24:42 Functions: 86.7 % 15 13

            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 "pkcs11/pkcs11.h"
      24              : #include "pkcs11/pkcs11i.h"
      25              : 
      26              : #include "gkm-aes-mechanism.h"
      27              : #include "gkm-attributes.h"
      28              : #include "gkm-crypto.h"
      29              : #include "gkm-aes-key.h"
      30              : #include "gkm-session.h"
      31              : #include "gkm-transaction.h"
      32              : #include "gkm-util.h"
      33              : 
      34              : #include "egg/egg-secure-memory.h"
      35              : 
      36              : struct _GkmAesKey {
      37              :         GkmSecretKey parent;
      38              :         gpointer value;
      39              :         gsize n_value;
      40              : };
      41              : 
      42           17 : G_DEFINE_TYPE (GkmAesKey, gkm_aes_key, GKM_TYPE_SECRET_KEY);
      43              : 
      44              : static const CK_MECHANISM_TYPE GKM_AES_MECHANISMS[] = {
      45              :         CKM_AES_CBC_PAD,
      46              :         CKM_G_HKDF_SHA256_DERIVE
      47              : };
      48              : 
      49            1 : EGG_SECURE_DECLARE (aes_key);
      50              : 
      51              : /* -----------------------------------------------------------------------------
      52              :  * INTERNAL
      53              :  */
      54              : 
      55              : static int
      56            3 : algorithm_for_length (gsize length)
      57              : {
      58            3 :         switch (length) {
      59            3 :         case 16:
      60            3 :                 return GCRY_CIPHER_AES128;
      61            0 :         case 24:
      62            0 :                 return GCRY_CIPHER_AES192;
      63            0 :         case 32:
      64            0 :                 return GCRY_CIPHER_AES256;
      65            0 :         default:
      66            0 :                 return 0;
      67              :         }
      68              : }
      69              : 
      70              : static CK_RV
      71            0 : attribute_set_check_value (GkmAesKey *self, CK_ATTRIBUTE *attr)
      72              : {
      73              :         gcry_cipher_hd_t cih;
      74              :         gcry_error_t gcry;
      75              :         gpointer data;
      76              :         CK_RV rv;
      77              : 
      78            0 :         g_assert (GKM_IS_AES_KEY (self));
      79            0 :         g_assert (attr);
      80              : 
      81              :         /* Just asking for the length */
      82            0 :         if (!attr->pValue) {
      83            0 :                 attr->ulValueLen = 3;
      84            0 :                 return CKR_OK;
      85              :         }
      86              : 
      87            0 :         cih = gkm_aes_key_get_cipher (self, GCRY_CIPHER_MODE_ECB);
      88            0 :         if (cih == NULL)
      89            0 :                 return CKR_FUNCTION_FAILED;
      90              : 
      91              :         /* Buffer of zeros */
      92            0 :         data = g_malloc0 (self->n_value);
      93              : 
      94              :         /* Encrypt it */
      95            0 :         gcry = gcry_cipher_encrypt (cih, data, self->n_value, NULL, 0);
      96            0 :         g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
      97              : 
      98              :         /* Use the first three bytes */
      99            0 :         g_assert (self->n_value > 3);
     100            0 :         rv = gkm_attribute_set_data (attr, data, 3);
     101              : 
     102            0 :         gcry_cipher_close (cih);
     103            0 :         g_free (data);
     104              : 
     105            0 :         return rv;
     106              : }
     107              : 
     108              : static GkmObject*
     109            1 : factory_create_aes_key (GkmSession *session, GkmTransaction *transaction,
     110              :                         CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
     111              : {
     112              :         GkmAesKey *key;
     113              :         GkmManager *manager;
     114              :         CK_ATTRIBUTE_PTR value;
     115              : 
     116            1 :         value = gkm_attributes_find (attrs, n_attrs, CKA_VALUE);
     117            1 :         if (value == NULL) {
     118            0 :                 gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
     119            0 :                 return NULL;
     120              :         }
     121              : 
     122            1 :         if (algorithm_for_length (value->ulValueLen) == 0) {
     123            0 :                 gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
     124            0 :                 return NULL;
     125              :         }
     126              : 
     127            1 :         manager = gkm_manager_for_template (attrs, n_attrs, session);
     128            1 :         key = g_object_new (GKM_TYPE_AES_KEY,
     129              :                             "module", gkm_session_get_module (session),
     130              :                             "manager", manager,
     131              :                             NULL);
     132              : 
     133            1 :         key->value = egg_secure_alloc (value->ulValueLen);
     134            1 :         key->n_value = value->ulValueLen;
     135            1 :         memcpy (key->value, value->pValue, key->n_value);
     136              : 
     137            1 :         gkm_attribute_consume (value);
     138              : 
     139            1 :         gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (key),
     140              :                                               TRUE, attrs, n_attrs);
     141            1 :         return GKM_OBJECT (key);
     142              : }
     143              : 
     144              : /* -----------------------------------------------------------------------------
     145              :  * OBJECT
     146              :  */
     147              : 
     148              : static CK_RV
     149            9 : gkm_aes_key_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE *attr)
     150              : {
     151            9 :         GkmAesKey *self = GKM_AES_KEY (base);
     152              : 
     153            9 :         switch (attr->type)
     154              :         {
     155            1 :         case CKA_KEY_TYPE:
     156            1 :                 return gkm_attribute_set_ulong (attr, CKK_AES);
     157              : 
     158            0 :         case CKA_DERIVE:
     159            0 :                 return gkm_attribute_set_bool (attr, CK_TRUE);
     160              : 
     161            1 :         case CKA_UNWRAP:
     162              :         case CKA_WRAP:
     163            1 :                 return gkm_attribute_set_bool (attr, CK_TRUE);
     164              : 
     165            0 :         case CKA_VALUE:
     166            0 :                 return gkm_attribute_set_data (attr, self->value, self->n_value);
     167              : 
     168            1 :         case CKA_VALUE_LEN:
     169            1 :                 return gkm_attribute_set_ulong (attr, self->n_value);
     170              : 
     171            0 :         case CKA_CHECK_VALUE:
     172            0 :                 return attribute_set_check_value (self, attr);
     173              : 
     174            2 :         case CKA_ALLOWED_MECHANISMS:
     175            2 :                 return gkm_attribute_set_data (attr, (CK_VOID_PTR)GKM_AES_MECHANISMS,
     176              :                                                sizeof (GKM_AES_MECHANISMS));
     177              :         };
     178              : 
     179            4 :         return GKM_OBJECT_CLASS (gkm_aes_key_parent_class)->get_attribute (base, session, attr);
     180              : }
     181              : 
     182              : static gconstpointer
     183            0 : gkm_aes_key_get_key_value (GkmSecretKey *key, gsize *n_value)
     184              : {
     185            0 :         GkmAesKey *self = GKM_AES_KEY (key);
     186            0 :         *n_value = self->n_value;
     187            0 :         return self->value;
     188              : }
     189              : 
     190              : static void
     191            1 : gkm_aes_key_init (GkmAesKey *self)
     192              : {
     193              : 
     194            1 : }
     195              : 
     196              : static void
     197            1 : gkm_aes_key_finalize (GObject *obj)
     198              : {
     199            1 :         GkmAesKey *self = GKM_AES_KEY (obj);
     200              : 
     201            1 :         if (self->value) {
     202            1 :                 egg_secure_clear (self->value, self->n_value);
     203            1 :                 egg_secure_free (self->value);
     204            1 :                 self->value = NULL;
     205            1 :                 self->n_value = 0;
     206              :         }
     207              : 
     208            1 :         G_OBJECT_CLASS (gkm_aes_key_parent_class)->finalize (obj);
     209            1 : }
     210              : 
     211              : static void
     212            1 : gkm_aes_key_class_init (GkmAesKeyClass *klass)
     213              : {
     214            1 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     215            1 :         GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass);
     216            1 :         GkmSecretKeyClass *key_class = GKM_SECRET_KEY_CLASS (klass);
     217              : 
     218            1 :         gkm_aes_key_parent_class = g_type_class_peek_parent (klass);
     219              : 
     220            1 :         gobject_class->finalize = gkm_aes_key_finalize;
     221              : 
     222            1 :         gkm_class->get_attribute = gkm_aes_key_get_attribute;
     223              : 
     224            1 :         key_class->get_key_value = gkm_aes_key_get_key_value;
     225            1 : }
     226              : 
     227              : /* -----------------------------------------------------------------------------
     228              :  * PUBLIC
     229              :  */
     230              : 
     231              : GkmFactory*
     232          287 : gkm_aes_key_get_factory (void)
     233              : {
     234              :         static CK_OBJECT_CLASS klass = CKO_SECRET_KEY;
     235              :         static CK_KEY_TYPE type = CKK_AES;
     236              : 
     237              :         static CK_ATTRIBUTE attributes[] = {
     238              :                 { CKA_CLASS, &klass, sizeof (klass) },
     239              :                 { CKA_KEY_TYPE, &type, sizeof (type) }
     240              :         };
     241              : 
     242              :         static GkmFactory factory = {
     243              :                 attributes,
     244              :                 G_N_ELEMENTS (attributes),
     245              :                 factory_create_aes_key
     246              :         };
     247              : 
     248          287 :         return &factory;
     249              : }
     250              : 
     251              : gsize
     252            1 : gkm_aes_key_get_block_size (GkmAesKey *self)
     253              : {
     254              :         int algorithm;
     255              : 
     256            1 :         g_return_val_if_fail (GKM_IS_AES_KEY (self), 0);
     257              : 
     258            1 :         algorithm = algorithm_for_length (self->n_value);
     259            1 :         g_return_val_if_fail (algorithm != 0, 0);
     260              : 
     261            1 :         return self->n_value;
     262              : }
     263              : 
     264              : gcry_cipher_hd_t
     265            1 : gkm_aes_key_get_cipher (GkmAesKey *self, int mode)
     266              : {
     267              :         gcry_cipher_hd_t cih;
     268              :         gcry_error_t gcry;
     269              :         int algorithm;
     270              : 
     271            1 :         g_return_val_if_fail (GKM_IS_AES_KEY (self), NULL);
     272              : 
     273            1 :         algorithm = algorithm_for_length (self->n_value);
     274            1 :         g_return_val_if_fail (algorithm != 0, NULL);
     275              : 
     276            1 :         gcry = gcry_cipher_open (&cih, algorithm, mode, 0);
     277            1 :         if (gcry != 0) {
     278            0 :                 g_warning ("couldn't open %s cipher: %s",
     279              :                            gcry_cipher_algo_name (algorithm), gcry_strerror (gcry));
     280            0 :                 return NULL;
     281              :         }
     282              : 
     283              :         /* Setup the key */
     284            1 :         gcry = gcry_cipher_setkey (cih, self->value, self->n_value);
     285            1 :         g_return_val_if_fail (gcry == 0, NULL);
     286              : 
     287            1 :         return cih;
     288              : }
        

Generated by: LCOV version 2.0-1