LCOV - code coverage report
Current view: top level - pkcs11/gkm - gkm-public-xsa-key.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 34.7 % 167 58
Test Date: 2024-04-08 13:24:42 Functions: 71.4 % 14 10

            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              : 
      25              : #include "gkm-attributes.h"
      26              : #define DEBUG_FLAG GKM_DEBUG_OBJECT
      27              : #include "gkm-debug.h"
      28              : #include "gkm-factory.h"
      29              : #include "gkm-public-xsa-key.h"
      30              : #include "gkm-data-der.h"
      31              : #include "gkm-session.h"
      32              : #include "gkm-sexp.h"
      33              : #include "gkm-transaction.h"
      34              : #include "gkm-util.h"
      35              : 
      36           75 : G_DEFINE_TYPE (GkmPublicXsaKey, gkm_public_xsa_key, GKM_TYPE_SEXP_KEY);
      37              : 
      38              : /* -----------------------------------------------------------------------------
      39              :  * INTERNAL
      40              :  */
      41              : 
      42              : static CK_RV
      43            0 : return_modulus_bits (GkmPublicXsaKey *self, CK_ATTRIBUTE_PTR attr)
      44              : {
      45              :         gcry_sexp_t numbers;
      46              :         gcry_mpi_t mpi;
      47              :         int algorithm;
      48              :         CK_RV rv;
      49              : 
      50            0 :         if (!gkm_sexp_parse_key (gkm_sexp_get (gkm_sexp_key_get_base (GKM_SEXP_KEY (self))),
      51              :                                  &algorithm, NULL, &numbers))
      52            0 :                 g_return_val_if_reached (CKR_GENERAL_ERROR);
      53              : 
      54            0 :         if (algorithm != GCRY_PK_RSA) {
      55            0 :                 gcry_sexp_release (numbers);
      56            0 :                 gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: CKA_MODULUS_BITS not valid for non-RSA keys");
      57            0 :                 return CKR_ATTRIBUTE_TYPE_INVALID;
      58              :         }
      59              : 
      60            0 :         g_assert (numbers);
      61            0 :         if (!gkm_sexp_extract_mpi (numbers, &mpi, "n", NULL))
      62            0 :                 g_return_val_if_reached (CKR_GENERAL_ERROR);
      63              : 
      64            0 :         gcry_sexp_release (numbers);
      65            0 :         rv = gkm_attribute_set_ulong (attr, gcry_mpi_get_nbits (mpi));
      66            0 :         gcry_mpi_release (mpi);
      67              : 
      68            0 :         return rv;
      69              : }
      70              : 
      71              : static CK_RV
      72            1 : create_rsa_public (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, gcry_sexp_t *skey)
      73              : {
      74              :         gcry_error_t gcry;
      75            1 :         gcry_mpi_t n = NULL;
      76            1 :         gcry_mpi_t e = NULL;
      77              :         CK_RV ret;
      78              : 
      79            2 :         if (!gkm_attributes_find_mpi (attrs, n_attrs, CKA_MODULUS, &n) ||
      80            1 :             !gkm_attributes_find_mpi (attrs, n_attrs, CKA_PUBLIC_EXPONENT, &e)) {
      81            0 :                 ret = CKR_TEMPLATE_INCOMPLETE;
      82            0 :                 goto done;
      83              :         }
      84              : 
      85            1 :         gcry = gcry_sexp_build (skey, NULL,
      86              :                                 "(public-key (rsa (n %m) (e %m)))",
      87              :                                 n, e);
      88              : 
      89            1 :         if (gcry != 0) {
      90            0 :                 g_message ("couldn't create RSA key from passed attributes: %s", gcry_strerror (gcry));
      91            0 :                 ret = CKR_FUNCTION_FAILED;
      92            0 :                 goto done;
      93              :         }
      94              : 
      95            1 :         gkm_attributes_consume (attrs, n_attrs, CKA_MODULUS, CKA_PUBLIC_EXPONENT, CKA_MODULUS_BITS, G_MAXULONG);
      96            1 :         ret = CKR_OK;
      97              : 
      98            1 : done:
      99            1 :         gcry_mpi_release (n);
     100            1 :         gcry_mpi_release (e);
     101            1 :         return ret;
     102              : }
     103              : 
     104              : static CK_RV
     105            0 : create_dsa_public (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, gcry_sexp_t *skey)
     106              : {
     107              :         gcry_error_t gcry;
     108            0 :         gcry_mpi_t p = NULL;
     109            0 :         gcry_mpi_t q = NULL;
     110            0 :         gcry_mpi_t g = NULL;
     111            0 :         gcry_mpi_t y = NULL;
     112              :         CK_RV ret;
     113              : 
     114            0 :         if (!gkm_attributes_find_mpi (attrs, n_attrs, CKA_PRIME, &p) ||
     115            0 :             !gkm_attributes_find_mpi (attrs, n_attrs, CKA_SUBPRIME, &q) ||
     116            0 :             !gkm_attributes_find_mpi (attrs, n_attrs, CKA_BASE, &g) ||
     117            0 :             !gkm_attributes_find_mpi (attrs, n_attrs, CKA_VALUE, &y)) {
     118            0 :                 ret = CKR_TEMPLATE_INCOMPLETE;
     119            0 :                 goto done;
     120              :         }
     121              : 
     122            0 :         gcry = gcry_sexp_build (skey, NULL,
     123              :                                 "(public-key (dsa (p %m) (q %m) (g %m) (y %m)))",
     124              :                                 p, q, g, y);
     125              : 
     126            0 :         if (gcry != 0) {
     127            0 :                 g_message ("couldn't create DSA key from passed attributes: %s", gcry_strerror (gcry));
     128            0 :                 ret = CKR_FUNCTION_FAILED;
     129            0 :                 goto done;
     130              :         }
     131              : 
     132            0 :         gkm_attributes_consume (attrs, n_attrs, CKA_PRIME, CKA_SUBPRIME,
     133              :                                 CKA_BASE, CKA_VALUE, G_MAXULONG);
     134            0 :         ret = CKR_OK;
     135              : 
     136            0 : done:
     137            0 :         gcry_mpi_release (p);
     138            0 :         gcry_mpi_release (q);
     139            0 :         gcry_mpi_release (g);
     140            0 :         gcry_mpi_release (y);
     141            0 :         return ret;
     142              : }
     143              : 
     144              : static CK_RV
     145            1 : create_ecdsa_public (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, gcry_sexp_t *skey)
     146              : {
     147              :         gcry_error_t gcry;
     148              :         const gchar *curve_name, *q_data;
     149            1 :         GBytes *q = NULL;
     150              :         gsize q_size;
     151              :         GQuark oid;
     152              :         CK_RV ret;
     153              : 
     154            2 :         if (!gkm_attributes_find_ecc_oid (attrs, n_attrs, &oid) ||
     155            1 :             !gkm_attributes_find_ecc_q (attrs, n_attrs, CKA_EC_POINT, &q)) {
     156            0 :                 ret = CKR_TEMPLATE_INCOMPLETE;
     157            0 :                 goto done;
     158              :         }
     159              : 
     160            1 :         curve_name = gkm_data_der_oid_to_curve (oid);
     161            1 :         if (curve_name == NULL) {
     162            0 :                 ret = CKR_FUNCTION_FAILED;
     163            0 :                 goto done;
     164              :         }
     165              : 
     166            1 :         q_data = g_bytes_get_data (q, &q_size);
     167              : 
     168            1 :         gcry = gcry_sexp_build (skey, NULL,
     169              :                                 "(public-key (ecdsa (curve %s) (q %b)))",
     170              :                                 curve_name, q_size, q_data);
     171              : 
     172            1 :         if (gcry != 0) {
     173            0 :                 g_message ("couldn't create ECDSA key from passed attributes: %s", gcry_strerror (gcry));
     174            0 :                 ret = CKR_FUNCTION_FAILED;
     175            0 :                 goto done;
     176              :         }
     177              : 
     178            1 :         gkm_attributes_consume (attrs, n_attrs, CKA_EC_POINT, CKA_EC_PARAMS,
     179              :                                 G_MAXULONG);
     180            1 :         ret = CKR_OK;
     181              : 
     182            1 : done:
     183            1 :         g_bytes_unref (q);
     184            1 :         return ret;
     185              : }
     186              : 
     187              : static GkmObject*
     188            0 : factory_create_public_xsa_key (GkmSession *session, GkmTransaction *transaction,
     189              :                                CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
     190              : {
     191            0 :         GkmObject *object = NULL;
     192              :         GkmSexp *sexp;
     193              : 
     194            0 :         g_return_val_if_fail (GKM_IS_TRANSACTION (transaction), NULL);
     195            0 :         g_return_val_if_fail (attrs || !n_attrs, NULL);
     196              : 
     197            0 :         sexp = gkm_public_xsa_key_create_sexp (session, transaction, attrs, n_attrs);
     198            0 :         if (sexp != NULL) {
     199            0 :                 object = g_object_new (GKM_TYPE_PUBLIC_XSA_KEY, "base-sexp", sexp,
     200              :                                        "module", gkm_session_get_module (session),
     201              :                                        "manager", gkm_manager_for_template (attrs, n_attrs, session),
     202              :                                        NULL);
     203            0 :                 gkm_sexp_unref (sexp);
     204            0 :                 gkm_session_complete_object_creation (session, transaction, object,
     205              :                                                       TRUE, attrs, n_attrs);
     206              :         }
     207              : 
     208            0 :         return object;
     209              : }
     210              : 
     211              : /* -----------------------------------------------------------------------------
     212              :  * PUBLIC_XSA_KEY
     213              :  */
     214              : 
     215              : static CK_RV
     216           54 : gkm_public_xsa_key_real_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE* attr)
     217              : {
     218           54 :         GkmPublicXsaKey *self = GKM_PUBLIC_XSA_KEY (base);
     219              :         gint algorithm;
     220              : 
     221           54 :         switch (attr->type)
     222              :         {
     223              : 
     224            0 :         case CKA_CLASS:
     225            0 :                 return gkm_attribute_set_ulong (attr, CKO_PUBLIC_KEY);
     226              : 
     227            0 :         case CKA_ENCRYPT:
     228            0 :                 algorithm = gkm_sexp_key_get_algorithm (GKM_SEXP_KEY (self));
     229            0 :                 return gkm_attribute_set_bool (attr, algorithm == GCRY_PK_RSA);
     230              : 
     231            0 :         case CKA_VERIFY:
     232            0 :                 return gkm_attribute_set_bool (attr, TRUE);
     233              : 
     234            0 :         case CKA_VERIFY_RECOVER:
     235            0 :                 return gkm_attribute_set_bool (attr, FALSE);
     236              : 
     237            0 :         case CKA_WRAP:
     238            0 :                 return gkm_attribute_set_bool (attr, FALSE);
     239              : 
     240            0 :         case CKA_TRUSTED:
     241            0 :                 return gkm_attribute_set_bool (attr, FALSE);
     242              : 
     243            0 :         case CKA_WRAP_TEMPLATE:
     244            0 :                 gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: no CKA_WRAP_TEMPLATE on key");
     245            0 :                 return CKR_ATTRIBUTE_TYPE_INVALID;
     246              : 
     247            0 :         case CKA_MODULUS_BITS:
     248            0 :                 return return_modulus_bits (self, attr);
     249              : 
     250            0 :         case CKA_MODULUS:
     251            0 :                 return gkm_sexp_key_set_part (GKM_SEXP_KEY (self), GCRY_PK_RSA, "n", attr);
     252              : 
     253            0 :         case CKA_PUBLIC_EXPONENT:
     254            0 :                 return gkm_sexp_key_set_part (GKM_SEXP_KEY (self), GCRY_PK_RSA, "e", attr);
     255              : 
     256            0 :         case CKA_PRIME:
     257            0 :                 return gkm_sexp_key_set_part (GKM_SEXP_KEY (self), GCRY_PK_DSA, "p", attr);
     258              : 
     259            0 :         case CKA_SUBPRIME:
     260            0 :                 return gkm_sexp_key_set_part (GKM_SEXP_KEY (self), GCRY_PK_DSA, "q", attr);
     261              : 
     262            0 :         case CKA_BASE:
     263            0 :                 return gkm_sexp_key_set_part (GKM_SEXP_KEY (self), GCRY_PK_DSA, "g", attr);
     264              : 
     265              :         /* DSA public value */
     266            0 :         case CKA_VALUE:
     267            0 :                 return gkm_sexp_key_set_part (GKM_SEXP_KEY (self), GCRY_PK_DSA, "y", attr);
     268              : 
     269            0 :         case CKA_EC_POINT:
     270            0 :                 return gkm_sexp_key_set_ec_q (GKM_SEXP_KEY (self), GCRY_PK_ECC, attr);
     271              : 
     272            0 :         case CKA_EC_PARAMS:
     273            0 :                 return gkm_sexp_key_set_ec_params (GKM_SEXP_KEY (self), GCRY_PK_ECC, attr);
     274              :         };
     275              : 
     276           54 :         return GKM_OBJECT_CLASS (gkm_public_xsa_key_parent_class)->get_attribute (base, session, attr);
     277              : }
     278              : 
     279              : static GkmSexp*
     280            0 : gkm_public_xsa_key_acquire_crypto_sexp (GkmSexpKey *self, GkmSession *session)
     281              : {
     282              :         GkmSexp* sexp;
     283              : 
     284            0 :         sexp = gkm_sexp_key_get_base (self);
     285            0 :         if (sexp != NULL)
     286            0 :                 gkm_sexp_ref (sexp);
     287              : 
     288            0 :         return sexp;
     289              : }
     290              : 
     291              : static void
     292           45 : gkm_public_xsa_key_init (GkmPublicXsaKey *self)
     293              : {
     294              : 
     295           45 : }
     296              : 
     297              : static void
     298            7 : gkm_public_xsa_key_class_init (GkmPublicXsaKeyClass *klass)
     299              : {
     300            7 :         GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass);
     301            7 :         GkmSexpKeyClass *key_class = GKM_SEXP_KEY_CLASS (klass);
     302              : 
     303            7 :         gkm_public_xsa_key_parent_class = g_type_class_peek_parent (klass);
     304              : 
     305            7 :         gkm_class->get_attribute = gkm_public_xsa_key_real_get_attribute;
     306              : 
     307            7 :         key_class->acquire_crypto_sexp = gkm_public_xsa_key_acquire_crypto_sexp;
     308            7 : }
     309              : 
     310              : /* -----------------------------------------------------------------------------
     311              :  * PUBLIC
     312              :  */
     313              : 
     314              : GkmSexp*
     315            2 : gkm_public_xsa_key_create_sexp (GkmSession *session, GkmTransaction *transaction,
     316              :                                 CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
     317              : {
     318              :         CK_KEY_TYPE type;
     319              :         gcry_sexp_t sexp;
     320              :         CK_RV ret;
     321              : 
     322            2 :         g_return_val_if_fail (GKM_IS_TRANSACTION (transaction), NULL);
     323            2 :         g_return_val_if_fail (attrs || !n_attrs, NULL);
     324              : 
     325            2 :         if (!gkm_attributes_find_ulong (attrs, n_attrs, CKA_KEY_TYPE, &type)) {
     326            0 :                 gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
     327            0 :                 return NULL;
     328              :         }
     329              : 
     330            2 :         gkm_attributes_consume (attrs, n_attrs, CKA_KEY_TYPE, CKA_CLASS, G_MAXULONG);
     331              : 
     332            2 :         switch (type) {
     333            1 :         case CKK_RSA:
     334            1 :                 ret = create_rsa_public (attrs, n_attrs, &sexp);
     335            1 :                 break;
     336            0 :         case CKK_DSA:
     337            0 :                 ret = create_dsa_public (attrs, n_attrs, &sexp);
     338            0 :                 break;
     339            1 :         case CKK_EC:
     340            1 :                 ret = create_ecdsa_public (attrs, n_attrs, &sexp);
     341            1 :                 break;
     342            0 :         default:
     343            0 :                 ret = CKR_ATTRIBUTE_VALUE_INVALID;
     344            0 :                 break;
     345              :         };
     346              : 
     347            2 :         if (ret != CKR_OK) {
     348            0 :                 gkm_transaction_fail (transaction, ret);
     349            0 :                 return NULL;
     350              :         }
     351              : 
     352            2 :         g_return_val_if_fail (sexp, NULL);
     353            2 :         return gkm_sexp_new (sexp);
     354              : }
     355              : 
     356              : GkmFactory*
     357          287 : gkm_public_xsa_key_get_factory (void)
     358              : {
     359              :         static CK_OBJECT_CLASS klass = CKO_PUBLIC_KEY;
     360              : 
     361              :         static CK_ATTRIBUTE attributes[] = {
     362              :                 { CKA_CLASS, &klass, sizeof (klass) }
     363              :         };
     364              : 
     365              :         static GkmFactory factory = {
     366              :                 attributes,
     367              :                 G_N_ELEMENTS (attributes),
     368              :                 factory_create_public_xsa_key
     369              :         };
     370              : 
     371          287 :         return &factory;
     372              : }
        

Generated by: LCOV version 2.0-1