LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib - pkcs11_privkey.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 461 694 66.4 %
Date: 2020-10-30 04:50:48 Functions: 15 20 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * GnuTLS PKCS#11 support
       3             :  * Copyright (C) 2010-2012 Free Software Foundation, Inc.
       4             :  * Copyright (C) 2017 Red Hat, Inc.
       5             :  * 
       6             :  * Authors: Nikos Mavrogiannopoulos, Stef Walter
       7             :  *
       8             :  * The GnuTLS is free software; you can redistribute it and/or
       9             :  * modify it under the terms of the GNU Lesser General Public License
      10             :  * as published by the Free Software Foundation; either version 2.1 of
      11             :  * the License, or (at your option) any later version.
      12             :  *
      13             :  * This library is distributed in the hope that it will be useful, but
      14             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public License
      19             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      20             :  */
      21             : 
      22             : #include "gnutls_int.h"
      23             : #include <gnutls/pkcs11.h>
      24             : #include <stdio.h>
      25             : #include <string.h>
      26             : #include "errors.h"
      27             : #include <datum.h>
      28             : #include <pkcs11_int.h>
      29             : #include <tls-sig.h>
      30             : #include <pk.h>
      31             : #include <fips.h>
      32             : #include "urls.h"
      33             : #include "locks.h"
      34             : #include <p11-kit/uri.h>
      35             : 
      36             : /* In case of a fork, it will invalidate the open session
      37             :  * in the privkey and start another */
      38             : #define PKCS11_CHECK_INIT_PRIVKEY(k) \
      39             :         ret = _gnutls_pkcs11_check_init(PROV_INIT_ALL, k, reopen_privkey_session); \
      40             :         if (ret < 0) \
      41             :                 return gnutls_assert_val(ret)
      42             : 
      43             : #define FIND_OBJECT(key) \
      44             :         do { \
      45             :                 int retries = 0; \
      46             :                 int rret; \
      47             :                 ret = find_object (&key->sinfo, &key->pin, &key->ref, key->uinfo, \
      48             :                                           SESSION_LOGIN); \
      49             :                 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \
      50             :                         if (_gnutls_token_func) \
      51             :                           { \
      52             :                             rret = pkcs11_call_token_func (key->uinfo, retries++); \
      53             :                             if (rret == 0) continue; \
      54             :                           } \
      55             :                         return gnutls_assert_val(ret); \
      56             :                 } else if (ret < 0) { \
      57             :                         return gnutls_assert_val(ret); \
      58             :                 } \
      59             :                 break; \
      60             :         } while (1);
      61             : 
      62             : 
      63             : /**
      64             :  * gnutls_pkcs11_privkey_init:
      65             :  * @key: A pointer to the type to be initialized
      66             :  *
      67             :  * This function will initialize an private key structure. This
      68             :  * structure can be used for accessing an underlying PKCS#11 object.
      69             :  *
      70             :  * In versions of GnuTLS later than 3.5.11 the object is protected
      71             :  * using locks and a single %gnutls_pkcs11_privkey_t can be re-used
      72             :  * by many threads. However, for performance it is recommended to utilize
      73             :  * one object per key per thread.
      74             :  *
      75             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
      76             :  *   negative error value.
      77             :  **/
      78          72 : int gnutls_pkcs11_privkey_init(gnutls_pkcs11_privkey_t * key)
      79             : {
      80          72 :         int ret;
      81          72 :         FAIL_IF_LIB_ERROR;
      82             : 
      83          72 :         *key = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_privkey_st));
      84          72 :         if (*key == NULL) {
      85           0 :                 gnutls_assert();
      86           0 :                 return GNUTLS_E_MEMORY_ERROR;
      87             :         }
      88             : 
      89          72 :         (*key)->uinfo = p11_kit_uri_new();
      90          72 :         if ((*key)->uinfo == NULL) {
      91           0 :                 free(*key);
      92           0 :                 gnutls_assert();
      93           0 :                 return GNUTLS_E_MEMORY_ERROR;
      94             :         }
      95             : 
      96          72 :         ret = gnutls_mutex_init(&(*key)->mutex);
      97          72 :         if (ret < 0) {
      98           0 :                 gnutls_assert();
      99           0 :                 p11_kit_uri_free((*key)->uinfo);
     100           0 :                 free(*key);
     101           0 :                 return GNUTLS_E_LOCKING_ERROR;
     102             :         }
     103             : 
     104             :         return 0;
     105             : }
     106             : 
     107             : /**
     108             :  * gnutls_pkcs11_privkey_cpy:
     109             :  * @dst: The destination key, which should be initialized.
     110             :  * @src: The source key
     111             :  *
     112             :  * This function will copy a private key from source to destination
     113             :  * key. Destination has to be initialized.
     114             :  *
     115             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     116             :  *   negative error value.
     117             :  *
     118             :  * Since: 3.4.0
     119             :  **/
     120             : int
     121           0 : gnutls_pkcs11_privkey_cpy(gnutls_pkcs11_privkey_t dst,
     122             :                           gnutls_pkcs11_privkey_t src)
     123             : {
     124           0 :         return gnutls_pkcs11_privkey_import_url(dst, src->url, src->flags);
     125             : }
     126             : 
     127             : /**
     128             :  * gnutls_pkcs11_privkey_deinit:
     129             :  * @key: the key to be deinitialized
     130             :  *
     131             :  * This function will deinitialize a private key structure.
     132             :  **/
     133          61 : void gnutls_pkcs11_privkey_deinit(gnutls_pkcs11_privkey_t key)
     134             : {
     135          61 :         p11_kit_uri_free(key->uinfo);
     136          61 :         gnutls_free(key->url);
     137          61 :         if (key->sinfo.init != 0)
     138          59 :                 pkcs11_close_session(&key->sinfo);
     139          61 :         gnutls_mutex_deinit(&key->mutex);
     140          61 :         gnutls_free(key);
     141          61 : }
     142             : 
     143             : /**
     144             :  * gnutls_pkcs11_privkey_get_pk_algorithm:
     145             :  * @key: should contain a #gnutls_pkcs11_privkey_t type
     146             :  * @bits: if bits is non null it will hold the size of the parameters' in bits
     147             :  *
     148             :  * This function will return the public key algorithm of a private
     149             :  * key.
     150             :  *
     151             :  * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
     152             :  *   success, or a negative error code on error.
     153             :  **/
     154             : int
     155         416 : gnutls_pkcs11_privkey_get_pk_algorithm(gnutls_pkcs11_privkey_t key,
     156             :                                        unsigned int *bits)
     157             : {
     158         416 :         if (bits)
     159         282 :                 *bits = key->bits;
     160         416 :         return key->pk_algorithm;
     161             : }
     162             : 
     163             : /**
     164             :  * gnutls_pkcs11_privkey_get_info:
     165             :  * @pkey: should contain a #gnutls_pkcs11_privkey_t type
     166             :  * @itype: Denotes the type of information requested
     167             :  * @output: where output will be stored
     168             :  * @output_size: contains the maximum size of the output and will be overwritten with actual
     169             :  *
     170             :  * This function will return information about the PKCS 11 private key such
     171             :  * as the label, id as well as token information where the key is stored. When
     172             :  * output is text it returns null terminated string although #output_size contains
     173             :  * the size of the actual data only.
     174             :  *
     175             :  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
     176             :  **/
     177             : int
     178           0 : gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t pkey,
     179             :                                gnutls_pkcs11_obj_info_t itype,
     180             :                                void *output, size_t * output_size)
     181             : {
     182           0 :         return pkcs11_get_info(pkey->uinfo, itype, output, output_size);
     183             : }
     184             : 
     185             : static int
     186          75 : find_object(struct pkcs11_session_info *sinfo,
     187             :             struct pin_info_st *pin_info,
     188             :             ck_object_handle_t * _ctx,
     189             :             struct p11_kit_uri *info, unsigned int flags)
     190             : {
     191          75 :         int ret;
     192          75 :         ck_object_handle_t ctx;
     193          75 :         struct ck_attribute *attrs;
     194          75 :         unsigned long attr_count;
     195          75 :         unsigned long count;
     196          75 :         ck_rv_t rv;
     197             : 
     198          75 :         ret =
     199          75 :             pkcs11_open_session(sinfo, pin_info, info,
     200             :                                 flags & SESSION_LOGIN);
     201          75 :         if (ret < 0) {
     202           2 :                 gnutls_assert();
     203           2 :                 return ret;
     204             :         }
     205             : 
     206          73 :         attrs = p11_kit_uri_get_attributes(info, &attr_count);
     207          73 :         rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, attrs,
     208             :                                       attr_count);
     209          73 :         if (rv != CKR_OK) {
     210           0 :                 gnutls_assert();
     211           0 :                 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
     212           0 :                 ret = pkcs11_rv_to_err(rv);
     213           0 :                 goto fail;
     214             :         }
     215             : 
     216          73 :         if (pkcs11_find_objects(sinfo->module, sinfo->pks, &ctx, 1, &count)
     217          73 :             == CKR_OK && count == 1) {
     218          73 :                 *_ctx = ctx;
     219          73 :                 pkcs11_find_objects_final(sinfo);
     220          73 :                 return 0;
     221             :         }
     222             : 
     223           0 :         ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
     224           0 :         pkcs11_find_objects_final(sinfo);
     225           0 :       fail:
     226           0 :         pkcs11_close_session(sinfo);
     227             : 
     228           0 :         return ret;
     229             : }
     230             : 
     231             : /* callback function to be passed in _gnutls_pkcs11_check_init().
     232             :  * It is run, only when a fork has been detected, and data have
     233             :  * been re-initialized. In that case we reset the session and re-open
     234             :  * the object. */
     235           3 : static int reopen_privkey_session(void * _privkey)
     236             : {
     237           3 :         int ret;
     238           3 :         gnutls_pkcs11_privkey_t privkey = _privkey;
     239             : 
     240           3 :         memset(&privkey->sinfo, 0, sizeof(privkey->sinfo));
     241           3 :         privkey->ref = 0;
     242           3 :         FIND_OBJECT(privkey);
     243             : 
     244             :         return 0;
     245             : }
     246             : 
     247             : #define REPEAT_ON_INVALID_HANDLE(expr) \
     248             :         if ((expr) == CKR_SESSION_HANDLE_INVALID) { \
     249             :                 ret = reopen_privkey_session(key); \
     250             :                 if (ret < 0) \
     251             :                         return gnutls_assert_val(ret); \
     252             :                 expr; \
     253             :         }
     254             : 
     255             : struct hash_mappings_st {
     256             :         gnutls_digest_algorithm_t id;
     257             :         unsigned long phash; /* pkcs11 hash ID */
     258             :         unsigned long mgf_id;
     259             : };
     260             : 
     261             : 
     262             : #ifndef CKG_MGF1_SHA224
     263             : # define CKG_MGF1_SHA224 0x00000005UL
     264             : # define CKG_MGF1_SHA256 0x00000002UL
     265             : # define CKG_MGF1_SHA384 0x00000003UL
     266             : # define CKG_MGF1_SHA512 0x00000004UL
     267             : 
     268             : struct ck_rsa_pkcs_pss_params {
     269             :         ck_mechanism_type_t hash_alg;
     270             :         /* ck_rsa_pkcs_mgf_type_t is not defined in old versions of p11-kit */
     271             :         unsigned long mgf;
     272             :         unsigned long s_len;
     273             : };
     274             : #endif
     275             : 
     276             : static const struct hash_mappings_st hash_mappings[] =
     277             : {
     278             :         {.id = GNUTLS_DIG_SHA224,
     279             :          .phash = CKM_SHA224,
     280             :          .mgf_id = CKG_MGF1_SHA224
     281             :         },
     282             :         {.id = GNUTLS_DIG_SHA256,
     283             :          .phash = CKM_SHA256,
     284             :          .mgf_id = CKG_MGF1_SHA256
     285             :         },
     286             :         {.id = GNUTLS_DIG_SHA384,
     287             :          .phash = CKM_SHA384,
     288             :          .mgf_id = CKG_MGF1_SHA384
     289             :         },
     290             :         {.id = GNUTLS_DIG_SHA512,
     291             :          .phash = CKM_SHA512,
     292             :          .mgf_id = CKG_MGF1_SHA512
     293             :         }
     294             : };
     295             : 
     296          43 : static const struct hash_mappings_st *hash_to_map(gnutls_digest_algorithm_t hash)
     297             : {
     298          43 :         unsigned i;
     299          86 :         for (i=0;i<sizeof(hash_mappings)/sizeof(hash_mappings[0]);i++) {
     300          86 :                 if (hash == hash_mappings[i].id)
     301          43 :                         return &hash_mappings[i];
     302             :         }
     303             :         return NULL;
     304             : }
     305             : 
     306             : /*-
     307             :  * _gnutls_pkcs11_privkey_sign:
     308             :  * @key: Holds the key
     309             :  * @hash: holds the data to be signed (should be output of a hash)
     310             :  * @signature: will contain the signature allocated with gnutls_malloc()
     311             :  *
     312             :  * This function will sign the given data using a signature algorithm
     313             :  * supported by the private key. It is assumed that the given data
     314             :  * are the output of a hash function. Input is the same as in
     315             :  * privkey_sign_raw_data().
     316             :  *
     317             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     318             :  *   negative error value.
     319             :  -*/
     320             : int
     321         249 : _gnutls_pkcs11_privkey_sign(gnutls_pkcs11_privkey_t key,
     322             :                             const gnutls_sign_entry_st *se,
     323             :                             const gnutls_datum_t * hash,
     324             :                             gnutls_datum_t * signature,
     325             :                             gnutls_x509_spki_st *spki_params)
     326             : {
     327         249 :         ck_rv_t rv;
     328         249 :         int ret;
     329         249 :         struct ck_mechanism mech;
     330         249 :         gnutls_datum_t tmp = { NULL, 0 };
     331         249 :         unsigned long siglen;
     332         249 :         struct pkcs11_session_info *sinfo;
     333         249 :         unsigned req_login = 0;
     334         249 :         unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC;
     335         249 :         struct ck_rsa_pkcs_pss_params rsa_pss_params;
     336             : 
     337         249 :         PKCS11_CHECK_INIT_PRIVKEY(key);
     338             : 
     339         249 :         sinfo = &key->sinfo;
     340             : 
     341         249 :         if (se->pk == GNUTLS_PK_RSA_PSS) {
     342          43 :                 const struct hash_mappings_st *map = hash_to_map(se->hash);
     343             : 
     344          43 :                 if (unlikely(map == NULL))
     345           0 :                         return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
     346             : 
     347          43 :                 if (unlikely(!key->rsa_pss_ok))
     348           0 :                         return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
     349             : 
     350          43 :                 rsa_pss_params.hash_alg = map->phash;
     351          43 :                 rsa_pss_params.mgf = map->mgf_id;
     352          43 :                 rsa_pss_params.s_len = spki_params->salt_size;
     353             : 
     354          43 :                 mech.mechanism = CKM_RSA_PKCS_PSS;
     355          43 :                 mech.parameter = &rsa_pss_params;
     356          43 :                 mech.parameter_len = sizeof(rsa_pss_params);
     357             :         } else {
     358         206 :                 ret = pk_to_mech(se->pk);
     359             : 
     360           0 :                 if (ret == -1)
     361           0 :                         return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
     362             : 
     363         206 :                 mech.mechanism = ret;
     364         206 :                 mech.parameter = NULL;
     365         206 :                 mech.parameter_len = 0;
     366             :         }
     367             : 
     368         249 :         ret = gnutls_mutex_lock(&key->mutex);
     369         249 :         if (ret != 0)
     370           0 :                 return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
     371             : 
     372             :         /* Initialize signing operation; using the private key discovered
     373             :          * earlier. */
     374         249 :         REPEAT_ON_INVALID_HANDLE(rv = pkcs11_sign_init(sinfo->module, sinfo->pks, &mech, key->ref));
     375         249 :         if (rv != CKR_OK) {
     376           2 :                 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
     377           2 :                 gnutls_assert();
     378           2 :                 ret = pkcs11_rv_to_err(rv);
     379           2 :                 goto cleanup;
     380             :         }
     381             : 
     382         247 :  retry_login:
     383         249 :         if (key->reauth || req_login) {
     384           4 :                 if (req_login)
     385           2 :                         login_flags = SESSION_FORCE_LOGIN|SESSION_LOGIN;
     386           4 :                 ret =
     387           4 :                     pkcs11_login(&key->sinfo, &key->pin,
     388             :                                  key->uinfo, login_flags);
     389           4 :                 if (ret < 0) {
     390           0 :                         gnutls_assert();
     391           0 :                         _gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
     392             :                         /* let's try the operation anyway */
     393             :                 }
     394             :         }
     395             : 
     396             :         /* Work out how long the signature must be: */
     397         249 :         rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
     398             :                          NULL, &siglen);
     399         249 :         if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) {
     400           2 :                 req_login = 1;
     401           2 :                 goto retry_login;
     402             :         }
     403             : 
     404         247 :         if (rv != CKR_OK) {
     405           0 :                 gnutls_assert();
     406           0 :                 ret = pkcs11_rv_to_err(rv);
     407           0 :                 goto cleanup;
     408             :         }
     409             : 
     410         247 :         tmp.data = gnutls_malloc(siglen);
     411         247 :         tmp.size = siglen;
     412             : 
     413         247 :         rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
     414             :                          tmp.data, &siglen);
     415         247 :         if (rv != CKR_OK) {
     416           0 :                 gnutls_assert();
     417           0 :                 ret = pkcs11_rv_to_err(rv);
     418           0 :                 goto cleanup;
     419             :         }
     420             : 
     421             : 
     422         247 :         if (key->pk_algorithm == GNUTLS_PK_ECDSA
     423         247 :             || key->pk_algorithm == GNUTLS_PK_DSA) {
     424         105 :                 unsigned int hlen = siglen / 2;
     425         105 :                 gnutls_datum_t r, s;
     426             : 
     427         105 :                 if (siglen % 2 != 0) {
     428           0 :                         gnutls_assert();
     429           0 :                         ret = GNUTLS_E_PK_SIGN_FAILED;
     430           0 :                         goto cleanup;
     431             :                 }
     432             : 
     433         105 :                 r.data = tmp.data;
     434         105 :                 r.size = hlen;
     435             : 
     436         105 :                 s.data = &tmp.data[hlen];
     437         105 :                 s.size = hlen;
     438             : 
     439         105 :                 ret = _gnutls_encode_ber_rs_raw(signature, &r, &s);
     440         105 :                 if (ret < 0) {
     441           0 :                         gnutls_assert();
     442           0 :                         goto cleanup;
     443             :                 }
     444             : 
     445         105 :                 gnutls_free(tmp.data);
     446             :         } else {
     447         142 :                 signature->size = siglen;
     448         142 :                 signature->data = tmp.data;
     449             :         }
     450             : 
     451             :         ret = 0;
     452             : 
     453         249 :       cleanup:
     454         249 :         gnutls_mutex_unlock(&key->mutex);
     455         249 :         if (sinfo != &key->sinfo)
     456             :                 pkcs11_close_session(sinfo);
     457         249 :         if (ret < 0)
     458           2 :                 gnutls_free(tmp.data);
     459             : 
     460             :         return ret;
     461             : }
     462             : 
     463             : /**
     464             :  * gnutls_pkcs11_privkey_status:
     465             :  * @key: Holds the key
     466             :  *
     467             :  * Checks the status of the private key token.
     468             :  *
     469             :  * Returns: this function will return non-zero if the token
     470             :  * holding the private key is still available (inserted), and zero otherwise.
     471             :  *
     472             :  * Since: 3.1.9
     473             :  *
     474             :  **/
     475           0 : unsigned gnutls_pkcs11_privkey_status(gnutls_pkcs11_privkey_t key)
     476             : {
     477           0 :         ck_rv_t rv;
     478           0 :         int ret;
     479           0 :         struct ck_session_info session_info;
     480             : 
     481           0 :         PKCS11_CHECK_INIT_PRIVKEY(key);
     482             : 
     483           0 :         REPEAT_ON_INVALID_HANDLE(rv = (key->sinfo.module)->C_GetSessionInfo(key->sinfo.pks, &session_info));
     484           0 :         if (rv != CKR_OK) {
     485           0 :                 ret = 0;
     486           0 :                 goto cleanup;
     487             :         }
     488             :         ret = 1;
     489             : 
     490           0 :       cleanup:
     491             : 
     492           0 :         return ret;
     493             : }
     494             : 
     495             : /**
     496             :  * gnutls_pkcs11_privkey_import_url:
     497             :  * @pkey: The private key
     498             :  * @url: a PKCS 11 url identifying the key
     499             :  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
     500             :  *
     501             :  * This function will "import" a PKCS 11 URL identifying a private
     502             :  * key to the #gnutls_pkcs11_privkey_t type. In reality since
     503             :  * in most cases keys cannot be exported, the private key structure
     504             :  * is being associated with the available operations on the token.
     505             :  *
     506             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     507             :  *   negative error value.
     508             :  **/
     509             : int
     510          72 : gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
     511             :                                  const char *url, unsigned int flags)
     512             : {
     513          72 :         int ret;
     514          72 :         struct ck_attribute *attr;
     515          72 :         struct ck_attribute a[4];
     516          72 :         ck_key_type_t key_type;
     517          72 :         ck_bool_t reauth = 0;
     518             : 
     519          72 :         PKCS11_CHECK_INIT;
     520             : 
     521          72 :         memset(&pkey->sinfo, 0, sizeof(pkey->sinfo));
     522             : 
     523          72 :         if (pkey->url)
     524           0 :                 gnutls_free(pkey->url);
     525             : 
     526          72 :         if (pkey->uinfo) {
     527          72 :                 p11_kit_uri_free(pkey->uinfo);
     528          72 :                 pkey->uinfo = NULL;
     529             :         }
     530             : 
     531          72 :         pkey->url = gnutls_strdup(url);
     532          72 :         if (pkey->url == NULL)
     533           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     534             : 
     535          72 :         ret = pkcs11_url_to_info(pkey->url, &pkey->uinfo, flags|GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PRIVKEY);
     536          72 :         if (ret < 0) {
     537           0 :                 gnutls_assert();
     538           0 :                 goto cleanup;
     539             :         }
     540             : 
     541          72 :         pkey->flags = flags;
     542             : 
     543          72 :         attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_CLASS);
     544          72 :         if (!attr || attr->value_len != sizeof(ck_object_class_t) ||
     545          72 :             *(ck_object_class_t *) attr->value != CKO_PRIVATE_KEY) {
     546           0 :                 gnutls_assert();
     547           0 :                 ret = GNUTLS_E_INVALID_REQUEST;
     548           0 :                 goto cleanup;
     549             :         }
     550             : 
     551          72 :         attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_ID);
     552          72 :         if (!attr) {
     553          49 :                 attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_LABEL);
     554          49 :                 if (!attr) {
     555           0 :                         gnutls_assert();
     556           0 :                         ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
     557           0 :                         goto cleanup;
     558             :                 }
     559             :         }
     560             : 
     561          72 :         FIND_OBJECT(pkey);
     562             : 
     563          70 :         pkey->pk_algorithm = GNUTLS_PK_UNKNOWN;
     564          70 :         a[0].type = CKA_KEY_TYPE;
     565          70 :         a[0].value = &key_type;
     566          70 :         a[0].value_len = sizeof(key_type);
     567          70 :         if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1)
     568             :             == CKR_OK) {
     569          79 :                 pkey->pk_algorithm = key_type_to_pk(key_type);
     570             :         }
     571             : 
     572          70 :         if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN) {
     573           0 :                 _gnutls_debug_log
     574             :                     ("Cannot determine PKCS #11 key algorithm\n");
     575           0 :                 ret = GNUTLS_E_UNKNOWN_ALGORITHM;
     576           0 :                 goto cleanup;
     577             :         }
     578             : 
     579             : 
     580          70 :         if (pkey->pk_algorithm == GNUTLS_PK_RSA) { /* determine whether it can do rsa-pss */
     581          61 :                 ck_bool_t tval = 0;
     582             : 
     583          61 :                 a[0].type = CKA_MODULUS;
     584          61 :                 a[0].value = NULL;
     585          61 :                 a[0].value_len = 0;
     586          61 :                 a[1].type = CKA_SIGN;
     587          61 :                 a[1].value = &tval;
     588          61 :                 a[1].value_len = sizeof(tval);
     589          61 :                 if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 2)
     590             :                     == CKR_OK) {
     591          52 :                         pkey->bits = a[0].value_len*8;
     592             :                 }
     593             : 
     594          61 :                 ret = gnutls_pkcs11_token_check_mechanism(url, CKM_RSA_PKCS_PSS, NULL, 0, 0);
     595          61 :                 if (ret != 0 && tval) {
     596          49 :                         pkey->rsa_pss_ok = 1;
     597             :                 } else {
     598          61 :                         _gnutls_debug_log("Detected incompatible with TLS1.3 RSA key! (%s)\n", url);
     599             :                 }
     600             :         }
     601             : 
     602          70 :         a[0].type = CKA_ALWAYS_AUTHENTICATE;
     603          70 :         a[0].value = &reauth;
     604          70 :         a[0].value_len = sizeof(reauth);
     605             : 
     606          70 :         if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1)
     607             :             == CKR_OK) {
     608          69 :                 pkey->reauth = reauth;
     609             :         }
     610             : 
     611          72 :         ret = 0;
     612             : 
     613             :         return ret;
     614             : 
     615           0 :       cleanup:
     616           0 :         if (pkey->uinfo != NULL) {
     617           0 :                 p11_kit_uri_free(pkey->uinfo);
     618           0 :                 pkey->uinfo = NULL;
     619             :         }
     620           0 :         gnutls_free(pkey->url);
     621             : 
     622           0 :         return ret;
     623             : }
     624             : 
     625             : /*-
     626             :  * _gnutls_pkcs11_privkey_decrypt_data:
     627             :  * @key: Holds the key
     628             :  * @flags: should be 0 for now
     629             :  * @ciphertext: holds the data to be signed
     630             :  * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
     631             :  *
     632             :  * This function will decrypt the given data using the public key algorithm
     633             :  * supported by the private key.
     634             :  *
     635             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     636             :  *   negative error value.
     637             :  -*/
     638             : int
     639           0 : _gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key,
     640             :                                     unsigned int flags,
     641             :                                     const gnutls_datum_t * ciphertext,
     642             :                                     gnutls_datum_t * plaintext)
     643             : {
     644           0 :         ck_rv_t rv;
     645           0 :         int ret;
     646           0 :         struct ck_mechanism mech;
     647           0 :         unsigned long siglen;
     648           0 :         unsigned req_login = 0;
     649           0 :         unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC;
     650             : 
     651           0 :         PKCS11_CHECK_INIT_PRIVKEY(key);
     652             : 
     653           0 :         if (key->pk_algorithm != GNUTLS_PK_RSA)
     654           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     655             : 
     656           0 :         mech.mechanism = CKM_RSA_PKCS;
     657           0 :         mech.parameter = NULL;
     658           0 :         mech.parameter_len = 0;
     659             : 
     660           0 :         ret = gnutls_mutex_lock(&key->mutex);
     661           0 :         if (ret != 0)
     662           0 :                 return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
     663             : 
     664             :         /* Initialize signing operation; using the private key discovered
     665             :          * earlier. */
     666           0 :         REPEAT_ON_INVALID_HANDLE(rv = pkcs11_decrypt_init(key->sinfo.module, key->sinfo.pks, &mech, key->ref));
     667           0 :         if (rv != CKR_OK) {
     668           0 :                 gnutls_assert();
     669           0 :                 ret = pkcs11_rv_to_err(rv);
     670           0 :                 goto cleanup;
     671             :         }
     672             : 
     673           0 :  retry_login:
     674           0 :         if (key->reauth || req_login) {
     675           0 :                 if (req_login)
     676           0 :                         login_flags = SESSION_FORCE_LOGIN|SESSION_LOGIN;
     677           0 :                 ret =
     678           0 :                     pkcs11_login(&key->sinfo, &key->pin,
     679             :                                  key->uinfo, login_flags);
     680           0 :                 if (ret < 0) {
     681           0 :                         gnutls_assert();
     682           0 :                         _gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
     683             :                         /* let's try the operation anyway */
     684             :                 }
     685             :         }
     686             : 
     687             :         /* Work out how long the plaintext must be: */
     688           0 :         rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks, ciphertext->data,
     689           0 :                             ciphertext->size, NULL, &siglen);
     690           0 :         if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) {
     691           0 :                 req_login = 1;
     692           0 :                 goto retry_login;
     693             :         }
     694             : 
     695           0 :         if (rv != CKR_OK) {
     696           0 :                 gnutls_assert();
     697           0 :                 ret = pkcs11_rv_to_err(rv);
     698           0 :                 goto cleanup;
     699             :         }
     700             : 
     701           0 :         plaintext->data = gnutls_malloc(siglen);
     702           0 :         plaintext->size = siglen;
     703             : 
     704           0 :         rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks, ciphertext->data,
     705           0 :                             ciphertext->size, plaintext->data, &siglen);
     706           0 :         if (rv != CKR_OK) {
     707           0 :                 gnutls_free(plaintext->data);
     708           0 :                 gnutls_assert();
     709           0 :                 ret = pkcs11_rv_to_err(rv);
     710           0 :                 goto cleanup;
     711             :         }
     712             : 
     713           0 :         plaintext->size = siglen;
     714             : 
     715           0 :         ret = 0;
     716             : 
     717           0 :       cleanup:
     718           0 :         gnutls_mutex_unlock(&key->mutex);
     719           0 :         return ret;
     720             : }
     721             : 
     722             : /*-
     723             :  * _gnutls_pkcs11_privkey_decrypt_data2:
     724             :  * @key: Holds the key
     725             :  * @flags: should be 0 for now
     726             :  * @ciphertext: holds the data to be signed
     727             :  * @plaintext: a preallocated buffer that will be filled with the plaintext
     728             :  * @plaintext_size: size of the plaintext
     729             :  *
     730             :  * This function will decrypt the given data using the public key algorithm
     731             :  * supported by the private key.
     732             :  * Unlike with _gnutls_pkcs11_privkey_decrypt_data the plaintext size is known
     733             :  * and provided by the caller, if the plaintext size differs from the requested
     734             :  * one, the operation fails and the provided buffer is left unchanged.
     735             :  * NOTE: plaintext_size must be exactly the size of the payload in the
     736             :  * ciphertext, otherwise an error is returned and the plaintext buffer is left
     737             :  * unchanged.
     738             :  *
     739             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     740             :  *   negative error value.
     741             :  -*/
     742             : int
     743           2 : _gnutls_pkcs11_privkey_decrypt_data2(gnutls_pkcs11_privkey_t key,
     744             :                                      unsigned int flags,
     745             :                                      const gnutls_datum_t * ciphertext,
     746             :                                      unsigned char * plaintext,
     747             :                                      size_t plaintext_size)
     748             : {
     749           2 :         ck_rv_t rv;
     750           2 :         int ret;
     751           2 :         struct ck_mechanism mech;
     752           2 :         unsigned long siglen = ciphertext->size;
     753           2 :         unsigned req_login = 0;
     754           2 :         unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC;
     755           2 :         unsigned char *buffer;
     756           2 :         volatile unsigned char value;
     757           2 :         unsigned char mask;
     758             : 
     759           2 :         PKCS11_CHECK_INIT_PRIVKEY(key);
     760             : 
     761           2 :         if (key->pk_algorithm != GNUTLS_PK_RSA)
     762           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     763             : 
     764           2 :         mech.mechanism = CKM_RSA_PKCS;
     765           2 :         mech.parameter = NULL;
     766           2 :         mech.parameter_len = 0;
     767             : 
     768           2 :         ret = gnutls_mutex_lock(&key->mutex);
     769           2 :         if (ret != 0)
     770           0 :                 return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
     771             : 
     772           2 :         buffer = gnutls_malloc(siglen);
     773           2 :         if (!buffer) {
     774           0 :                 gnutls_assert();
     775           0 :                 return GNUTLS_E_MEMORY_ERROR;
     776             :         }
     777             : 
     778             :         /* Initialize signing operation; using the private key discovered
     779             :          * earlier. */
     780           2 :         REPEAT_ON_INVALID_HANDLE(
     781             :                 rv = pkcs11_decrypt_init(key->sinfo.module, key->sinfo.pks,
     782             :                                          &mech, key->ref)
     783           2 :         );
     784           2 :         if (rv != CKR_OK) {
     785           0 :                 gnutls_assert();
     786           0 :                 ret = pkcs11_rv_to_err(rv);
     787           0 :                 goto cleanup;
     788             :         }
     789             : 
     790           2 :  retry_login:
     791           2 :         if (key->reauth || req_login) {
     792           0 :                 if (req_login)
     793           0 :                         login_flags = SESSION_FORCE_LOGIN|SESSION_LOGIN;
     794           0 :                 ret =
     795           0 :                     pkcs11_login(&key->sinfo, &key->pin,
     796             :                                  key->uinfo, login_flags);
     797           0 :                 if (ret < 0) {
     798           0 :                         gnutls_assert();
     799           0 :                         _gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
     800             :                         /* let's try the operation anyway */
     801             :                 }
     802             :         }
     803             : 
     804           2 :         ret = 0;
     805           2 :         siglen = ciphertext->size;
     806           2 :         rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks,
     807             :                             ciphertext->data, ciphertext->size,
     808             :                             buffer, &siglen);
     809           2 :         if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) {
     810           0 :                 req_login = 1;
     811           0 :                 goto retry_login;
     812             :         }
     813             : 
     814             :         /* NOTE: These branches are not side-channel silent */
     815           2 :         if (rv != CKR_OK) {
     816           0 :                 gnutls_assert();
     817           0 :                 ret = pkcs11_rv_to_err(rv);
     818           2 :         } else if (siglen != plaintext_size) {
     819           0 :                 gnutls_assert();
     820             :                 ret = GNUTLS_E_INVALID_REQUEST;
     821             :         }
     822             : 
     823             :         /* conditionally copy buffer in a side-channel silent way */
     824             :         /* on success mask is 0xFF, on failure it is 0 */
     825           2 :         mask = ((uint32_t)ret >> 31) - 1U;
     826          98 :         for (size_t i = 0; i < plaintext_size; i++) {
     827          96 :                 value = (buffer[i] & mask) + (plaintext[i] & ~mask);
     828          96 :                 plaintext[i] = value;
     829             :         }
     830             : 
     831           2 :       cleanup:
     832           2 :         gnutls_mutex_unlock(&key->mutex);
     833           2 :         gnutls_free(buffer);
     834           2 :         return ret;
     835             : }
     836             : 
     837             : /**
     838             :  * gnutls_pkcs11_privkey_export_url:
     839             :  * @key: Holds the PKCS 11 key
     840             :  * @detailed: non zero if a detailed URL is required
     841             :  * @url: will contain an allocated url
     842             :  *
     843             :  * This function will export a URL identifying the given key.
     844             :  *
     845             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     846             :  *   negative error value.
     847             :  **/
     848             : int
     849           0 : gnutls_pkcs11_privkey_export_url(gnutls_pkcs11_privkey_t key,
     850             :                                  gnutls_pkcs11_url_type_t detailed,
     851             :                                  char **url)
     852             : {
     853           0 :         int ret;
     854             : 
     855           0 :         ret = pkcs11_info_to_url(key->uinfo, detailed, url);
     856           0 :         if (ret < 0) {
     857           0 :                 gnutls_assert();
     858           0 :                 return ret;
     859             :         }
     860             : 
     861             :         return 0;
     862             : }
     863             : 
     864             : #if 0
     865             : /**
     866             :  * gnutls_pkcs11_privkey_generate:
     867             :  * @url: a token URL
     868             :  * @pk: the public key algorithm
     869             :  * @bits: the security bits
     870             :  * @label: a label
     871             :  * @flags: should be zero
     872             :  *
     873             :  * This function will generate a private key in the specified
     874             :  * by the @url token. The private key will be generate within
     875             :  * the token and will not be exportable.
     876             :  *
     877             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     878             :  *   negative error value.
     879             :  *
     880             :  * Since: 3.0
     881             :  **/
     882             : int
     883             : gnutls_pkcs11_privkey_generate(const char *url, gnutls_pk_algorithm_t pk,
     884             :                                unsigned int bits, const char *label,
     885             :                                unsigned int flags)
     886             : {
     887             :         int x;
     888             : }
     889             : 
     890             : /**
     891             :  * gnutls_pkcs11_privkey_generate2:
     892             :  * @url: a token URL
     893             :  * @pk: the public key algorithm
     894             :  * @bits: the security bits
     895             :  * @label: a label
     896             :  * @fmt: the format of output params. PEM or DER
     897             :  * @pubkey: will hold the public key (may be %NULL)
     898             :  * @flags: zero or an OR'ed sequence of %GNUTLS_PKCS11_OBJ_FLAGs
     899             :  *
     900             :  * This function will generate a private key in the specified
     901             :  * by the @url token. The private key will be generate within
     902             :  * the token and will not be exportable. This function will
     903             :  * store the DER-encoded public key in the SubjectPublicKeyInfo format
     904             :  * in @pubkey. The @pubkey should be deinitialized using gnutls_free().
     905             :  *
     906             :  * Note that when generating an elliptic curve key, the curve
     907             :  * can be substituted in the place of the bits parameter using the
     908             :  * GNUTLS_CURVE_TO_BITS() macro.
     909             :  *
     910             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     911             :  *   negative error value.
     912             :  *
     913             :  * Since: 3.1.5
     914             :  **/
     915             : int
     916             : gnutls_pkcs11_privkey_generate2(const char *url, gnutls_pk_algorithm_t pk,
     917             :                                 unsigned int bits, const char *label,
     918             :                                 gnutls_x509_crt_fmt_t fmt,
     919             :                                 gnutls_datum_t * pubkey,
     920             :                                 unsigned int flags)
     921             : {
     922             :         int x;
     923             : }
     924             : #endif
     925             : 
     926             : static const char def_rsa_pub_exp[3] = { 1,0,1 }; // 65537 = 0x10001
     927             : 
     928             : struct dsa_params {
     929             :         /* FIPS 186-3 maximal size for L and N length pair is (3072,256). */
     930             :         uint8_t prime[384];
     931             :         uint8_t subprime[32];
     932             :         uint8_t generator[384];
     933             : };
     934             : 
     935             : static int
     936           1 : _dsa_params_generate(struct ck_function_list *module, ck_session_handle_t session,
     937             :                      unsigned long bits, struct dsa_params *params,
     938             :                      struct ck_attribute *a, int *a_val)
     939             : {
     940           1 :         struct ck_mechanism mech = { CKM_DSA_PARAMETER_GEN };
     941           1 :         struct ck_attribute attr = { CKA_PRIME_BITS, &bits, sizeof(bits) };
     942           1 :         ck_object_handle_t key;
     943           1 :         ck_rv_t rv;
     944             : 
     945             :         /* Generate DSA parameters from prime length. */
     946             : 
     947           1 :         rv = pkcs11_generate_key(module, session, &mech, &attr, 1, &key);
     948           1 :         if (rv != CKR_OK) {
     949           0 :                 gnutls_assert();
     950           0 :                 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
     951           0 :                 return pkcs11_rv_to_err(rv);
     952             :         }
     953             : 
     954             :         /* Retrieve generated parameters to be used with the new key pair. */
     955             : 
     956           1 :         a[*a_val + 0].type = CKA_PRIME;
     957           1 :         a[*a_val + 0].value = params->prime;
     958           1 :         a[*a_val + 0].value_len = sizeof(params->prime);
     959             : 
     960           1 :         a[*a_val + 1].type = CKA_SUBPRIME;
     961           1 :         a[*a_val + 1].value = params->subprime;
     962           1 :         a[*a_val + 1].value_len = sizeof(params->subprime);
     963             : 
     964           1 :         a[*a_val + 2].type = CKA_BASE;
     965           1 :         a[*a_val + 2].value = params->generator;
     966           1 :         a[*a_val + 2].value_len = sizeof(params->generator);
     967             : 
     968           1 :         rv = pkcs11_get_attribute_value(module, session, key, &a[*a_val], 3);
     969           1 :         if (rv != CKR_OK) {
     970           0 :                 gnutls_assert();
     971           0 :                 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
     972           0 :                 return pkcs11_rv_to_err(rv);
     973             :         }
     974             : 
     975           1 :         *a_val += 3;
     976             : 
     977           1 :         return 0;
     978             : }
     979             : 
     980             : /**
     981             :  * gnutls_pkcs11_privkey_generate3:
     982             :  * @url: a token URL
     983             :  * @pk: the public key algorithm
     984             :  * @bits: the security bits
     985             :  * @label: a label
     986             :  * @cid: The CKA_ID to use for the new object
     987             :  * @fmt: the format of output params. PEM or DER
     988             :  * @pubkey: will hold the public key (may be %NULL)
     989             :  * @key_usage: One of GNUTLS_KEY_*
     990             :  * @flags: zero or an OR'ed sequence of %GNUTLS_PKCS11_OBJ_FLAGs
     991             :  *
     992             :  * This function will generate a private key in the specified
     993             :  * by the @url token. The private key will be generate within
     994             :  * the token and will not be exportable. This function will
     995             :  * store the DER-encoded public key in the SubjectPublicKeyInfo format 
     996             :  * in @pubkey. The @pubkey should be deinitialized using gnutls_free().
     997             :  *
     998             :  * Note that when generating an elliptic curve key, the curve
     999             :  * can be substituted in the place of the bits parameter using the
    1000             :  * GNUTLS_CURVE_TO_BITS() macro.
    1001             :  *
    1002             :  * Since 3.6.3 the objects are marked as sensitive by default unless
    1003             :  * %GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE is specified.
    1004             :  *
    1005             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    1006             :  *   negative error value.
    1007             :  *
    1008             :  * Since: 3.4.0
    1009             :  **/
    1010             : int
    1011           9 : gnutls_pkcs11_privkey_generate3(const char *url, gnutls_pk_algorithm_t pk,
    1012             :                                 unsigned int bits, const char *label,
    1013             :                                 const gnutls_datum_t *cid,
    1014             :                                 gnutls_x509_crt_fmt_t fmt,
    1015             :                                 gnutls_datum_t * pubkey,
    1016             :                                 unsigned int key_usage,
    1017             :                                 unsigned int flags)
    1018             : {
    1019           9 :         int ret;
    1020           9 :         const ck_bool_t tval = 1;
    1021           9 :         const ck_bool_t fval = 0;
    1022           9 :         struct pkcs11_session_info sinfo;
    1023           9 :         struct p11_kit_uri *info = NULL;
    1024           9 :         ck_rv_t rv;
    1025           9 :         struct ck_attribute a[22], p[22];
    1026           9 :         ck_object_handle_t pub_ctx, priv_ctx;
    1027           9 :         unsigned long _bits = bits;
    1028           9 :         int a_val, p_val;
    1029           9 :         struct ck_mechanism mech;
    1030           9 :         gnutls_pubkey_t pkey = NULL;
    1031           9 :         gnutls_pkcs11_obj_t obj = NULL;
    1032           9 :         gnutls_datum_t der = {NULL, 0};
    1033           9 :         ck_key_type_t key_type;
    1034           9 :         uint8_t id[20];
    1035           9 :         struct dsa_params dsa_params;
    1036             : 
    1037           9 :         PKCS11_CHECK_INIT;
    1038           9 :         FIX_KEY_USAGE(pk, key_usage);
    1039             : 
    1040           9 :         memset(&sinfo, 0, sizeof(sinfo));
    1041             : 
    1042           9 :         ret = pkcs11_url_to_info(url, &info, 0);
    1043           9 :         if (ret < 0) {
    1044           0 :                 gnutls_assert();
    1045           0 :                 return ret;
    1046             :         }
    1047             : 
    1048           9 :         ret =
    1049           9 :             pkcs11_open_session(&sinfo, NULL, info,
    1050             :                                 SESSION_WRITE |
    1051           9 :                                 pkcs11_obj_flags_to_int(flags));
    1052           9 :         p11_kit_uri_free(info);
    1053             : 
    1054           9 :         if (ret < 0) {
    1055           0 :                 gnutls_assert();
    1056           0 :                 goto cleanup;
    1057             :         }
    1058             : 
    1059             :         /* a holds the public key template
    1060             :          * and p the private key */
    1061           9 :         a_val = p_val = 0;
    1062           9 :         mech.parameter = NULL;
    1063           9 :         mech.parameter_len = 0;
    1064           9 :         mech.mechanism = pk_to_genmech(pk, &key_type);
    1065             : 
    1066           9 :         if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_NO_STORE_PUBKEY)) {
    1067           9 :                 a[a_val].type = CKA_TOKEN;
    1068           9 :                 a[a_val].value = (void *) &tval;
    1069           9 :                 a[a_val].value_len = sizeof(tval);
    1070           9 :                 a_val++;
    1071             : 
    1072           9 :                 a[a_val].type = CKA_PRIVATE;
    1073           9 :                 a[a_val].value = (void *) &fval;
    1074           9 :                 a[a_val].value_len = sizeof(fval);
    1075           9 :                 a_val++;
    1076             :         }
    1077             : 
    1078           9 :         a[a_val].type = CKA_ID;
    1079           9 :         if (cid == NULL || cid->size == 0) {
    1080           8 :                 ret = gnutls_rnd(GNUTLS_RND_NONCE, id, sizeof(id));
    1081           8 :                 if (ret < 0) {
    1082           0 :                         gnutls_assert();
    1083           0 :                         goto cleanup;
    1084             :                 }
    1085             : 
    1086           8 :                 a[a_val].value = (void *) id;
    1087           8 :                 a[a_val].value_len = sizeof(id);
    1088             :         } else {
    1089           1 :                 a[a_val].value = (void *) cid->data;
    1090           1 :                 a[a_val].value_len = cid->size;
    1091             :         }
    1092             : 
    1093           9 :         p[p_val].type = CKA_ID;
    1094           9 :         p[p_val].value = a[a_val].value;
    1095           9 :         p[p_val].value_len = a[a_val].value_len;
    1096           9 :         a_val++;
    1097           9 :         p_val++;
    1098             : 
    1099           9 :         switch (pk) {
    1100           5 :         case GNUTLS_PK_RSA:
    1101           5 :                 p[p_val].type = CKA_DECRYPT;
    1102           5 :                 if (key_usage & (GNUTLS_KEY_DECIPHER_ONLY|GNUTLS_KEY_ENCIPHER_ONLY)) {
    1103           5 :                         p[p_val].value = (void *) &tval;
    1104           5 :                         p[p_val].value_len = sizeof(tval);
    1105             :                 } else {
    1106           0 :                         p[p_val].value = (void *) &fval;
    1107           0 :                         p[p_val].value_len = sizeof(fval);
    1108             :                 }
    1109           5 :                 p_val++;
    1110             : 
    1111           5 :                 p[p_val].type = CKA_SIGN;
    1112           5 :                 if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
    1113           5 :                         p[p_val].value = (void *) &tval;
    1114           5 :                         p[p_val].value_len = sizeof(tval);
    1115             :                 } else {
    1116           0 :                         p[p_val].value = (void *) &fval;
    1117           0 :                         p[p_val].value_len = sizeof(fval);
    1118             :                 }
    1119           5 :                 p_val++;
    1120             : 
    1121           5 :                 a[a_val].type = CKA_ENCRYPT;
    1122           5 :                 a[a_val].value = (void *) &tval;
    1123           5 :                 a[a_val].value_len = sizeof(tval);
    1124           5 :                 a_val++;
    1125             : 
    1126           5 :                 a[a_val].type = CKA_VERIFY;
    1127           5 :                 a[a_val].value = (void *) &tval;
    1128           5 :                 a[a_val].value_len = sizeof(tval);
    1129           5 :                 a_val++;
    1130             : 
    1131           5 :                 a[a_val].type = CKA_MODULUS_BITS;
    1132           5 :                 a[a_val].value = &_bits;
    1133           5 :                 a[a_val].value_len = sizeof(_bits);
    1134           5 :                 a_val++;
    1135             : 
    1136           5 :                 a[a_val].type = CKA_PUBLIC_EXPONENT;
    1137           5 :                 a[a_val].value = (char*)def_rsa_pub_exp;
    1138           5 :                 a[a_val].value_len = sizeof(def_rsa_pub_exp);
    1139           5 :                 a_val++;
    1140             : 
    1141           5 :                 break;
    1142           1 :         case GNUTLS_PK_DSA:
    1143           1 :                 p[p_val].type = CKA_SIGN;
    1144           1 :                 if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
    1145           1 :                         p[p_val].value = (void *) &tval;
    1146           1 :                         p[p_val].value_len = sizeof(tval);
    1147             :                 } else {
    1148           0 :                         p[p_val].value = (void *) &fval;
    1149           0 :                         p[p_val].value_len = sizeof(fval);
    1150             :                 }
    1151           1 :                 p_val++;
    1152             : 
    1153           1 :                 a[a_val].type = CKA_VERIFY;
    1154           1 :                 a[a_val].value = (void *) &tval;
    1155           1 :                 a[a_val].value_len = sizeof(tval);
    1156           1 :                 a_val++;
    1157             : 
    1158           1 :                 ret = _dsa_params_generate(sinfo.module, sinfo.pks, _bits,
    1159             :                                            &dsa_params, a, &a_val);
    1160           1 :                 if (ret < 0) {
    1161           0 :                         goto cleanup;
    1162             :                 }
    1163             : 
    1164             :                 break;
    1165           3 :         case GNUTLS_PK_ECDSA:
    1166           3 :                 p[p_val].type = CKA_SIGN;
    1167           3 :                 if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
    1168           3 :                         p[p_val].value = (void *) &tval;
    1169           3 :                         p[p_val].value_len = sizeof(tval);
    1170             :                 } else {
    1171           0 :                         p[p_val].value = (void *) &fval;
    1172           0 :                         p[p_val].value_len = sizeof(fval);
    1173             :                 }
    1174           3 :                 p_val++;
    1175             : 
    1176           3 :                 a[a_val].type = CKA_VERIFY;
    1177           3 :                 a[a_val].value = (void *) &tval;
    1178           3 :                 a[a_val].value_len = sizeof(tval);
    1179           3 :                 a_val++;
    1180             : 
    1181           3 :                 if (GNUTLS_BITS_ARE_CURVE(bits)) {
    1182           0 :                         bits = GNUTLS_BITS_TO_CURVE(bits);
    1183             :                 } else {
    1184           3 :                         bits = _gnutls_ecc_bits_to_curve(pk, bits);
    1185             :                 }
    1186             : 
    1187           3 :                 ret = _gnutls_x509_write_ecc_params(bits, &der);
    1188           3 :                 if (ret < 0) {
    1189           0 :                         gnutls_assert();
    1190           0 :                         goto cleanup;
    1191             :                 }
    1192             : 
    1193           3 :                 a[a_val].type = CKA_EC_PARAMS;
    1194           3 :                 a[a_val].value = der.data;
    1195           3 :                 a[a_val].value_len = der.size;
    1196           3 :                 a_val++;
    1197             : 
    1198           3 :                 break;
    1199           0 :         case GNUTLS_PK_EDDSA_ED25519:
    1200           0 :                 p[p_val].type = CKA_SIGN;
    1201           0 :                 p[p_val].value = (void *) &tval;
    1202           0 :                 p[p_val].value_len = sizeof(tval);
    1203           0 :                 p_val++;
    1204             : 
    1205           0 :                 a[a_val].type = CKA_VERIFY;
    1206           0 :                 a[a_val].value = (void *) &tval;
    1207           0 :                 a[a_val].value_len = sizeof(tval);
    1208           0 :                 a_val++;
    1209             : 
    1210           0 :                 ret = _gnutls_x509_write_ecc_params(GNUTLS_ECC_CURVE_ED25519, &der);
    1211           0 :                 if (ret < 0) {
    1212           0 :                         gnutls_assert();
    1213           0 :                         goto cleanup;
    1214             :                 }
    1215             : 
    1216           0 :                 a[a_val].type = CKA_EC_PARAMS;
    1217           0 :                 a[a_val].value = der.data;
    1218           0 :                 a[a_val].value_len = der.size;
    1219           0 :                 a_val++;
    1220           0 :                 break;
    1221             :         default:
    1222           0 :                 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
    1223           0 :                 goto cleanup;
    1224             :         }
    1225             : 
    1226             :         /*
    1227             :          * on request, add the CKA_WRAP/CKA_UNWRAP key attribute
    1228             :          */
    1229           9 :         if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP) {
    1230           0 :                 p[p_val].type = CKA_UNWRAP;
    1231           0 :                 p[p_val].value = (void*)&tval;
    1232           0 :                 p[p_val].value_len = sizeof(tval);
    1233           0 :                 p_val++;
    1234           0 :                 a[a_val].type = CKA_WRAP;
    1235           0 :                 a[a_val].value = (void*)&tval;
    1236           0 :                 a[a_val].value_len = sizeof(tval);
    1237           0 :                 a_val++;
    1238             :         }
    1239             : 
    1240             :         /* a private key is set always as private unless
    1241             :          * requested otherwise
    1242             :          */
    1243           9 :         if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
    1244           0 :                 p[p_val].type = CKA_PRIVATE;
    1245           0 :                 p[p_val].value = (void *) &fval;
    1246           0 :                 p[p_val].value_len = sizeof(fval);
    1247           0 :                 p_val++;
    1248             :         } else {
    1249           9 :                 p[p_val].type = CKA_PRIVATE;
    1250           9 :                 p[p_val].value = (void *) &tval;
    1251           9 :                 p[p_val].value_len = sizeof(tval);
    1252           9 :                 p_val++;
    1253             :         }
    1254             : 
    1255           9 :         p[p_val].type = CKA_TOKEN;
    1256           9 :         p[p_val].value = (void *) &tval;
    1257           9 :         p[p_val].value_len = sizeof(tval);
    1258           9 :         p_val++;
    1259             : 
    1260           9 :         if (label) {
    1261           9 :                 p[p_val].type = CKA_LABEL;
    1262           9 :                 p[p_val].value = (void *) label;
    1263           9 :                 p[p_val].value_len = strlen(label);
    1264           9 :                 p_val++;
    1265             : 
    1266           9 :                 a[a_val].type = CKA_LABEL;
    1267           9 :                 a[a_val].value = (void *) label;
    1268           9 :                 a[a_val].value_len = strlen(label);
    1269           9 :                 a_val++;
    1270             :         }
    1271             : 
    1272           9 :         if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE)) {
    1273           8 :                 p[p_val].type = CKA_SENSITIVE;
    1274           8 :                 p[p_val].value = (void *) &tval;
    1275           8 :                 p[p_val].value_len = sizeof(tval);
    1276           8 :                 p_val++;
    1277             :         } else {
    1278           1 :                 p[p_val].type = CKA_SENSITIVE;
    1279           1 :                 p[p_val].value = (void *) &fval;
    1280           1 :                 p[p_val].value_len = sizeof(fval);
    1281           1 :                 p_val++;
    1282             :         }
    1283             : 
    1284           9 :         rv = pkcs11_generate_key_pair(sinfo.module, sinfo.pks, &mech, a,
    1285             :                                       a_val, p, p_val, &pub_ctx, &priv_ctx);
    1286           9 :         if (rv != CKR_OK) {
    1287           0 :                 gnutls_assert();
    1288           0 :                 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
    1289           0 :                 ret = pkcs11_rv_to_err(rv);
    1290           0 :                 goto cleanup;
    1291             :         }
    1292             : 
    1293             :         /* extract the public key */
    1294           9 :         if (pubkey) {
    1295             : 
    1296           9 :                 ret = gnutls_pubkey_init(&pkey);
    1297           9 :                 if (ret < 0) {
    1298           0 :                         gnutls_assert();
    1299           0 :                         goto cleanup;
    1300             :                 }
    1301             : 
    1302           9 :                 ret = gnutls_pkcs11_obj_init(&obj);
    1303           9 :                 if (ret < 0) {
    1304           0 :                         gnutls_assert();
    1305           0 :                         goto cleanup;
    1306             :                 }
    1307             : 
    1308           9 :                 obj->pk_algorithm = pk;
    1309           9 :                 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
    1310           9 :                 ret =
    1311           9 :                     pkcs11_read_pubkey(sinfo.module, sinfo.pks, pub_ctx,
    1312             :                                        key_type, obj);
    1313           9 :                 if (ret < 0) {
    1314           0 :                         gnutls_assert();
    1315           0 :                         goto cleanup;
    1316             :                 }
    1317             : 
    1318           9 :                 ret = gnutls_pubkey_import_pkcs11(pkey, obj, 0);
    1319           9 :                 if (ret < 0) {
    1320           0 :                         gnutls_assert();
    1321           0 :                         goto cleanup;
    1322             :                 }
    1323             : 
    1324           9 :                 ret = gnutls_pubkey_export2(pkey, fmt, pubkey);
    1325           9 :                 if (ret < 0) {
    1326           0 :                         gnutls_assert();
    1327           0 :                         goto cleanup;
    1328             :                 }
    1329             :         }
    1330             : 
    1331           9 :       cleanup:
    1332           9 :         if (obj != NULL)
    1333           9 :                 gnutls_pkcs11_obj_deinit(obj);
    1334           9 :         if (pkey != NULL)
    1335           9 :                 gnutls_pubkey_deinit(pkey);
    1336             : 
    1337           9 :         if (sinfo.pks != 0)
    1338           9 :                 pkcs11_close_session(&sinfo);
    1339           9 :         gnutls_free(der.data);
    1340             : 
    1341           9 :         return ret;
    1342             : }
    1343             : 
    1344             : /* loads a the corresponding to the private key public key either from 
    1345             :  * a public key object or from a certificate.
    1346             :  */
    1347           4 : static int load_pubkey_obj(gnutls_pkcs11_privkey_t pkey, gnutls_pubkey_t pub)
    1348             : {
    1349           4 :         int ret, iret;
    1350           4 :         gnutls_x509_crt_t crt;
    1351             : 
    1352           4 :         ret = gnutls_pubkey_import_url(pub, pkey->url, pkey->flags);
    1353           4 :         if (ret >= 0) {
    1354             :                 return ret;
    1355             :         }
    1356           2 :         iret = ret;
    1357             : 
    1358             :         /* else try certificate */
    1359           2 :         ret = gnutls_x509_crt_init(&crt);
    1360           2 :         if (ret < 0) {
    1361           0 :                 gnutls_assert();
    1362           0 :                 return ret;
    1363             :         }
    1364             : 
    1365           2 :         gnutls_x509_crt_set_pin_function(crt, pkey->pin.cb, pkey->pin.data);
    1366             : 
    1367           2 :         ret = gnutls_x509_crt_import_url(crt, pkey->url, pkey->flags);
    1368           2 :         if (ret < 0) {
    1369           1 :                 ret = iret;
    1370           1 :                 goto cleanup;
    1371             :         }
    1372             : 
    1373           1 :         ret = gnutls_pubkey_import_x509(pub, crt, 0);
    1374             : 
    1375           2 :  cleanup:
    1376           2 :         gnutls_x509_crt_deinit(crt);
    1377           2 :         return ret;
    1378             : }
    1379             : 
    1380             : int
    1381          27 : _pkcs11_privkey_get_pubkey (gnutls_pkcs11_privkey_t pkey, gnutls_pubkey_t *pub, unsigned flags)
    1382             : {
    1383          27 :         gnutls_pubkey_t pubkey = NULL;
    1384          27 :         gnutls_pkcs11_obj_t obj = NULL;
    1385          27 :         ck_key_type_t key_type;
    1386          27 :         int ret;
    1387             : 
    1388          27 :         PKCS11_CHECK_INIT_PRIVKEY(pkey);
    1389             : 
    1390          27 :         if (!pkey) {
    1391           0 :                 gnutls_assert();
    1392           0 :                 return GNUTLS_E_INVALID_REQUEST;
    1393             :         }
    1394             : 
    1395          27 :         ret = gnutls_pubkey_init(&pubkey);
    1396          27 :         if (ret < 0) {
    1397           0 :                 gnutls_assert();
    1398           0 :                 goto cleanup;
    1399             :         }
    1400             : 
    1401          27 :         ret = gnutls_pkcs11_obj_init(&obj);
    1402          27 :         if (ret < 0) {
    1403           0 :                 gnutls_assert();
    1404           0 :                 goto cleanup;
    1405             :         }
    1406             : 
    1407          27 :         obj->pk_algorithm = gnutls_pkcs11_privkey_get_pk_algorithm(pkey, 0);
    1408          27 :         obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
    1409          27 :         pk_to_genmech(obj->pk_algorithm, &key_type);
    1410             : 
    1411          27 :         gnutls_pubkey_set_pin_function(pubkey, pkey->pin.cb, pkey->pin.data);
    1412             : 
    1413             :         /* we can only read the public key from RSA keys */
    1414          27 :         if (key_type != CKK_RSA) {
    1415             :                 /* try opening the public key object if it exists */
    1416           4 :                 ret = load_pubkey_obj(pkey, pubkey);
    1417           4 :                 if (ret < 0) {
    1418           1 :                         gnutls_assert();
    1419           1 :                         goto cleanup;
    1420             :                 }
    1421             :         } else {
    1422          23 :                 ret = pkcs11_read_pubkey(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, key_type, obj);
    1423          23 :                 if (ret < 0) {
    1424           0 :                         gnutls_assert();
    1425           0 :                         goto cleanup;
    1426             :                 }
    1427             : 
    1428          23 :                 ret = gnutls_pubkey_import_pkcs11(pubkey, obj, 0);
    1429          23 :                 if (ret < 0) {
    1430           0 :                         gnutls_assert();
    1431           0 :                         goto cleanup;
    1432             :                 }
    1433             :         }
    1434             : 
    1435          26 :         *pub = pubkey;
    1436             : 
    1437          26 :         pubkey = NULL;
    1438          26 :         ret = 0;
    1439             : 
    1440          27 :  cleanup:
    1441          27 :         if (obj != NULL)
    1442          27 :                 gnutls_pkcs11_obj_deinit(obj);
    1443          27 :         if (pubkey != NULL)
    1444           1 :                 gnutls_pubkey_deinit(pubkey);
    1445             : 
    1446             :         return ret;
    1447             : }
    1448             : 
    1449             : /**
    1450             :  * gnutls_pkcs11_privkey_export_pubkey
    1451             :  * @pkey: The private key
    1452             :  * @fmt: the format of output params. PEM or DER.
    1453             :  * @data: will hold the public key
    1454             :  * @flags: should be zero
    1455             :  *
    1456             :  * This function will extract the public key (modulus and public
    1457             :  * exponent) from the private key specified by the @url private key.
    1458             :  * This public key will be stored in @pubkey in the format specified
    1459             :  * by @fmt. @pubkey should be deinitialized using gnutls_free().
    1460             :  *
    1461             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    1462             :  *   negative error value.
    1463             :  *
    1464             :  * Since: 3.3.7
    1465             :  **/
    1466             : int
    1467           1 : gnutls_pkcs11_privkey_export_pubkey(gnutls_pkcs11_privkey_t pkey,
    1468             :                                      gnutls_x509_crt_fmt_t fmt,
    1469             :                                      gnutls_datum_t * data,
    1470             :                                      unsigned int flags)
    1471             : {
    1472           1 :         int ret;
    1473           1 :         gnutls_pubkey_t pubkey = NULL;
    1474             : 
    1475           1 :         ret = _pkcs11_privkey_get_pubkey(pkey, &pubkey, flags);
    1476           1 :         if (ret < 0)
    1477           0 :                 return gnutls_assert_val(ret);
    1478             : 
    1479           1 :         ret = gnutls_pubkey_export2(pubkey, fmt, data);
    1480           1 :         if (ret < 0) {
    1481           0 :                 gnutls_assert();
    1482           0 :                 goto cleanup;
    1483             :         }
    1484             : 
    1485             :         ret = 0;
    1486             : 
    1487           1 :       cleanup:
    1488           1 :         if (pubkey != NULL)
    1489           1 :                 gnutls_pubkey_deinit(pubkey);
    1490             : 
    1491             :         return ret;
    1492             : }
    1493             : 
    1494             : /**
    1495             :  * gnutls_pkcs11_privkey_set_pin_function:
    1496             :  * @key: The private key
    1497             :  * @fn: the callback
    1498             :  * @userdata: data associated with the callback
    1499             :  *
    1500             :  * This function will set a callback function to be used when
    1501             :  * required to access the object. This function overrides the global
    1502             :  * set using gnutls_pkcs11_set_pin_function().
    1503             :  *
    1504             :  * Since: 3.1.0
    1505             :  *
    1506             :  **/
    1507             : void
    1508          13 : gnutls_pkcs11_privkey_set_pin_function(gnutls_pkcs11_privkey_t key,
    1509             :                                        gnutls_pin_callback_t fn,
    1510             :                                        void *userdata)
    1511             : {
    1512          13 :         key->pin.cb = fn;
    1513          13 :         key->pin.data = userdata;
    1514          13 : }

Generated by: LCOV version 1.14