|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* GnuTLS PKCS#11 support
|
|
Packit Service |
4684c1 |
* Copyright (C) 2010-2012 Free Software Foundation, Inc.
|
|
Packit Service |
4684c1 |
* Copyright (C) 2017 Red Hat, Inc.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Authors: Nikos Mavrogiannopoulos, Stef Walter
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit Service |
4684c1 |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit Service |
4684c1 |
* the License, or (at your option) any later version.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This library is distributed in the hope that it will be useful, but
|
|
Packit Service |
4684c1 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
4684c1 |
* Lesser General Public License for more details.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include "gnutls_int.h"
|
|
Packit Service |
4684c1 |
#include <gnutls/pkcs11.h>
|
|
Packit Service |
4684c1 |
#include <stdio.h>
|
|
Packit Service |
4684c1 |
#include <string.h>
|
|
Packit Service |
4684c1 |
#include "errors.h"
|
|
Packit Service |
4684c1 |
#include <datum.h>
|
|
Packit Service |
4684c1 |
#include <pkcs11_int.h>
|
|
Packit Service |
4684c1 |
#include <tls-sig.h>
|
|
Packit Service |
4684c1 |
#include <pk.h>
|
|
Packit Service |
4684c1 |
#include <fips.h>
|
|
Packit Service |
4684c1 |
#include "urls.h"
|
|
Packit Service |
4684c1 |
#include "locks.h"
|
|
Packit Service |
4684c1 |
#include <p11-kit/uri.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* In case of a fork, it will invalidate the open session
|
|
Packit Service |
4684c1 |
* in the privkey and start another */
|
|
Packit Service |
4684c1 |
#define PKCS11_CHECK_INIT_PRIVKEY(k) \
|
|
Packit Service |
4684c1 |
ret = _gnutls_pkcs11_check_init(PROV_INIT_ALL, k, reopen_privkey_session); \
|
|
Packit Service |
4684c1 |
if (ret < 0) \
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret)
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define FIND_OBJECT(key) \
|
|
Packit Service |
4684c1 |
do { \
|
|
Packit Service |
4684c1 |
int retries = 0; \
|
|
Packit Service |
4684c1 |
int rret; \
|
|
Packit Service |
4684c1 |
ret = find_object (&key->sinfo, &key->pin, &key->ref, key->uinfo, \
|
|
Packit Service |
4684c1 |
SESSION_LOGIN); \
|
|
Packit Service |
4684c1 |
if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \
|
|
Packit Service |
4684c1 |
if (_gnutls_token_func) \
|
|
Packit Service |
4684c1 |
{ \
|
|
Packit Service |
4684c1 |
rret = pkcs11_call_token_func (key->uinfo, retries++); \
|
|
Packit Service |
4684c1 |
if (rret == 0) continue; \
|
|
Packit Service |
4684c1 |
} \
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret); \
|
|
Packit Service |
4684c1 |
} else if (ret < 0) { \
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret); \
|
|
Packit Service |
4684c1 |
} \
|
|
Packit Service |
4684c1 |
break; \
|
|
Packit Service |
4684c1 |
} while (1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs11_privkey_init:
|
|
Packit Service |
4684c1 |
* @key: A pointer to the type to be initialized
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will initialize an private key structure. This
|
|
Packit Service |
4684c1 |
* structure can be used for accessing an underlying PKCS#11 object.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* In versions of GnuTLS later than 3.5.11 the object is protected
|
|
Packit Service |
4684c1 |
* using locks and a single %gnutls_pkcs11_privkey_t can be re-used
|
|
Packit Service |
4684c1 |
* by many threads. However, for performance it is recommended to utilize
|
|
Packit Service |
4684c1 |
* one object per key per thread.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int gnutls_pkcs11_privkey_init(gnutls_pkcs11_privkey_t * key)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
FAIL_IF_LIB_ERROR;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*key = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_privkey_st));
|
|
Packit Service |
4684c1 |
if (*key == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
(*key)->uinfo = p11_kit_uri_new();
|
|
Packit Service |
4684c1 |
if ((*key)->uinfo == NULL) {
|
|
Packit Service |
4684c1 |
free(*key);
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_mutex_init(&(*key)->mutex);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
p11_kit_uri_free((*key)->uinfo);
|
|
Packit Service |
4684c1 |
free(*key);
|
|
Packit Service |
4684c1 |
return GNUTLS_E_LOCKING_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs11_privkey_cpy:
|
|
Packit Service |
4684c1 |
* @dst: The destination key, which should be initialized.
|
|
Packit Service |
4684c1 |
* @src: The source key
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will copy a private key from source to destination
|
|
Packit Service |
4684c1 |
* key. Destination has to be initialized.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.4.0
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_privkey_cpy(gnutls_pkcs11_privkey_t dst,
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_privkey_t src)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
return gnutls_pkcs11_privkey_import_url(dst, src->url, src->flags);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs11_privkey_deinit:
|
|
Packit Service |
4684c1 |
* @key: the key to be deinitialized
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will deinitialize a private key structure.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
void gnutls_pkcs11_privkey_deinit(gnutls_pkcs11_privkey_t key)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
p11_kit_uri_free(key->uinfo);
|
|
Packit Service |
4684c1 |
gnutls_free(key->url);
|
|
Packit Service |
4684c1 |
if (key->sinfo.init != 0)
|
|
Packit Service |
4684c1 |
pkcs11_close_session(&key->sinfo);
|
|
Packit Service |
4684c1 |
gnutls_mutex_deinit(&key->mutex);
|
|
Packit Service |
4684c1 |
gnutls_free(key);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs11_privkey_get_pk_algorithm:
|
|
Packit Service |
4684c1 |
* @key: should contain a #gnutls_pkcs11_privkey_t type
|
|
Packit Service |
4684c1 |
* @bits: if bits is non null it will hold the size of the parameters' in bits
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will return the public key algorithm of a private
|
|
Packit Service |
4684c1 |
* key.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: a member of the #gnutls_pk_algorithm_t enumeration on
|
|
Packit Service |
4684c1 |
* success, or a negative error code on error.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_privkey_get_pk_algorithm(gnutls_pkcs11_privkey_t key,
|
|
Packit Service |
4684c1 |
unsigned int *bits)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (bits)
|
|
Packit Service |
4684c1 |
*bits = key->bits;
|
|
Packit Service |
4684c1 |
return key->pk_algorithm;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs11_privkey_get_info:
|
|
Packit Service |
4684c1 |
* @pkey: should contain a #gnutls_pkcs11_privkey_t type
|
|
Packit Service |
4684c1 |
* @itype: Denotes the type of information requested
|
|
Packit Service |
4684c1 |
* @output: where output will be stored
|
|
Packit Service |
4684c1 |
* @output_size: contains the maximum size of the output and will be overwritten with actual
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will return information about the PKCS 11 private key such
|
|
Packit Service |
4684c1 |
* as the label, id as well as token information where the key is stored. When
|
|
Packit Service |
4684c1 |
* output is text it returns null terminated string although #output_size contains
|
|
Packit Service |
4684c1 |
* the size of the actual data only.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t pkey,
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_obj_info_t itype,
|
|
Packit Service |
4684c1 |
void *output, size_t * output_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
return pkcs11_get_info(pkey->uinfo, itype, output, output_size);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
find_object(struct pkcs11_session_info *sinfo,
|
|
Packit Service |
4684c1 |
struct pin_info_st *pin_info,
|
|
Packit Service |
4684c1 |
ck_object_handle_t * _ctx,
|
|
Packit Service |
4684c1 |
struct p11_kit_uri *info, unsigned int flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
ck_object_handle_t ctx;
|
|
Packit Service |
4684c1 |
struct ck_attribute *attrs;
|
|
Packit Service |
4684c1 |
unsigned long attr_count;
|
|
Packit Service |
4684c1 |
unsigned long count;
|
|
Packit Service |
4684c1 |
ck_rv_t rv;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
pkcs11_open_session(sinfo, pin_info, info,
|
|
Packit Service |
4684c1 |
flags & SESSION_LOGIN);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
attrs = p11_kit_uri_get_attributes(info, &attr_count);
|
|
Packit Service |
4684c1 |
rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, attrs,
|
|
Packit Service |
4684c1 |
attr_count);
|
|
Packit Service |
4684c1 |
if (rv != CKR_OK) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("p11: FindObjectsInit failed.\n");
|
|
Packit Service |
4684c1 |
ret = pkcs11_rv_to_err(rv);
|
|
Packit Service |
4684c1 |
goto fail;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkcs11_find_objects(sinfo->module, sinfo->pks, &ctx, 1, &count)
|
|
Packit Service |
4684c1 |
== CKR_OK && count == 1) {
|
|
Packit Service |
4684c1 |
*_ctx = ctx;
|
|
Packit Service |
4684c1 |
pkcs11_find_objects_final(sinfo);
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit Service |
4684c1 |
pkcs11_find_objects_final(sinfo);
|
|
Packit Service |
4684c1 |
fail:
|
|
Packit Service |
4684c1 |
pkcs11_close_session(sinfo);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* callback function to be passed in _gnutls_pkcs11_check_init().
|
|
Packit Service |
4684c1 |
* It is run, only when a fork has been detected, and data have
|
|
Packit Service |
4684c1 |
* been re-initialized. In that case we reset the session and re-open
|
|
Packit Service |
4684c1 |
* the object. */
|
|
Packit Service |
4684c1 |
static int reopen_privkey_session(void * _privkey)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_privkey_t privkey = _privkey;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memset(&privkey->sinfo, 0, sizeof(privkey->sinfo));
|
|
Packit Service |
4684c1 |
privkey->ref = 0;
|
|
Packit Service |
4684c1 |
FIND_OBJECT(privkey);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define REPEAT_ON_INVALID_HANDLE(expr) \
|
|
Packit Service |
4684c1 |
if ((expr) == CKR_SESSION_HANDLE_INVALID) { \
|
|
Packit Service |
4684c1 |
ret = reopen_privkey_session(key); \
|
|
Packit Service |
4684c1 |
if (ret < 0) \
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret); \
|
|
Packit Service |
4684c1 |
expr; \
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
struct hash_mappings_st {
|
|
Packit Service |
4684c1 |
gnutls_digest_algorithm_t id;
|
|
Packit Service |
4684c1 |
unsigned long phash; /* pkcs11 hash ID */
|
|
Packit Service |
4684c1 |
unsigned long mgf_id;
|
|
Packit Service |
4684c1 |
};
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#ifndef CKG_MGF1_SHA224
|
|
Packit Service |
4684c1 |
# define CKG_MGF1_SHA224 0x00000005UL
|
|
Packit Service |
4684c1 |
# define CKG_MGF1_SHA256 0x00000002UL
|
|
Packit Service |
4684c1 |
# define CKG_MGF1_SHA384 0x00000003UL
|
|
Packit Service |
4684c1 |
# define CKG_MGF1_SHA512 0x00000004UL
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
struct ck_rsa_pkcs_pss_params {
|
|
Packit Service |
4684c1 |
ck_mechanism_type_t hash_alg;
|
|
Packit Service |
4684c1 |
/* ck_rsa_pkcs_mgf_type_t is not defined in old versions of p11-kit */
|
|
Packit Service |
4684c1 |
unsigned long mgf;
|
|
Packit Service |
4684c1 |
unsigned long s_len;
|
|
Packit Service |
4684c1 |
};
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static const struct hash_mappings_st hash_mappings[] =
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
{.id = GNUTLS_DIG_SHA224,
|
|
Packit Service |
4684c1 |
.phash = CKM_SHA224,
|
|
Packit Service |
4684c1 |
.mgf_id = CKG_MGF1_SHA224
|
|
Packit Service |
4684c1 |
},
|
|
Packit Service |
4684c1 |
{.id = GNUTLS_DIG_SHA256,
|
|
Packit Service |
4684c1 |
.phash = CKM_SHA256,
|
|
Packit Service |
4684c1 |
.mgf_id = CKG_MGF1_SHA256
|
|
Packit Service |
4684c1 |
},
|
|
Packit Service |
4684c1 |
{.id = GNUTLS_DIG_SHA384,
|
|
Packit Service |
4684c1 |
.phash = CKM_SHA384,
|
|
Packit Service |
4684c1 |
.mgf_id = CKG_MGF1_SHA384
|
|
Packit Service |
4684c1 |
},
|
|
Packit Service |
4684c1 |
{.id = GNUTLS_DIG_SHA512,
|
|
Packit Service |
4684c1 |
.phash = CKM_SHA512,
|
|
Packit Service |
4684c1 |
.mgf_id = CKG_MGF1_SHA512
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
};
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static const struct hash_mappings_st *hash_to_map(gnutls_digest_algorithm_t hash)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned i;
|
|
Packit Service |
4684c1 |
for (i=0;i
|
|
Packit Service |
4684c1 |
if (hash == hash_mappings[i].id)
|
|
Packit Service |
4684c1 |
return &hash_mappings[i];
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/*-
|
|
Packit Service |
4684c1 |
* _gnutls_pkcs11_privkey_sign:
|
|
Packit Service |
4684c1 |
* @key: Holds the key
|
|
Packit Service |
4684c1 |
* @hash: holds the data to be signed (should be output of a hash)
|
|
Packit Service |
4684c1 |
* @signature: will contain the signature allocated with gnutls_malloc()
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will sign the given data using a signature algorithm
|
|
Packit Service |
4684c1 |
* supported by the private key. It is assumed that the given data
|
|
Packit Service |
4684c1 |
* are the output of a hash function. Input is the same as in
|
|
Packit Service |
4684c1 |
* privkey_sign_raw_data().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
-*/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_gnutls_pkcs11_privkey_sign(gnutls_pkcs11_privkey_t key,
|
|
Packit Service |
4684c1 |
const gnutls_sign_entry_st *se,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t * hash,
|
|
Packit Service |
4684c1 |
gnutls_datum_t * signature,
|
|
Packit Service |
4684c1 |
gnutls_x509_spki_st *spki_params)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ck_rv_t rv;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
struct ck_mechanism mech;
|
|
Packit Service |
4684c1 |
gnutls_datum_t tmp = { NULL, 0 };
|
|
Packit Service |
4684c1 |
unsigned long siglen;
|
|
Packit Service |
4684c1 |
struct pkcs11_session_info *sinfo;
|
|
Packit Service |
4684c1 |
unsigned req_login = 0;
|
|
Packit Service |
4684c1 |
unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC;
|
|
Packit Service |
4684c1 |
struct ck_rsa_pkcs_pss_params rsa_pss_params;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
PKCS11_CHECK_INIT_PRIVKEY(key);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
sinfo = &key->sinfo;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (se->pk == GNUTLS_PK_RSA_PSS) {
|
|
Packit Service |
4684c1 |
const struct hash_mappings_st *map = hash_to_map(se->hash);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely(map == NULL))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely(!key->rsa_pss_ok))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
rsa_pss_params.hash_alg = map->phash;
|
|
Packit Service |
4684c1 |
rsa_pss_params.mgf = map->mgf_id;
|
|
Packit Service |
4684c1 |
rsa_pss_params.s_len = spki_params->salt_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mech.mechanism = CKM_RSA_PKCS_PSS;
|
|
Packit Service |
4684c1 |
mech.parameter = &rsa_pss_params;
|
|
Packit Service |
4684c1 |
mech.parameter_len = sizeof(rsa_pss_params);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
ret = pk_to_mech(se->pk);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret == -1)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mech.mechanism = ret;
|
|
Packit Service |
4684c1 |
mech.parameter = NULL;
|
|
Packit Service |
4684c1 |
mech.parameter_len = 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_mutex_lock(&key->mutex);
|
|
Packit Service |
4684c1 |
if (ret != 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Initialize signing operation; using the private key discovered
|
|
Packit Service |
4684c1 |
* earlier. */
|
|
Packit Service |
4684c1 |
REPEAT_ON_INVALID_HANDLE(rv = pkcs11_sign_init(sinfo->module, sinfo->pks, &mech, key->ref));
|
|
Packit Service |
4684c1 |
if (rv != CKR_OK) {
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = pkcs11_rv_to_err(rv);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
retry_login:
|
|
Packit Service |
4684c1 |
if (key->reauth || req_login) {
|
|
Packit Service |
4684c1 |
if (req_login)
|
|
Packit Service |
4684c1 |
login_flags = SESSION_FORCE_LOGIN|SESSION_LOGIN;
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
pkcs11_login(&key->sinfo, &key->pin,
|
|
Packit Service |
4684c1 |
key->uinfo, login_flags);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
|
|
Packit Service |
4684c1 |
/* let's try the operation anyway */
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Work out how long the signature must be: */
|
|
Packit Service |
4684c1 |
rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
|
|
Packit Service |
4684c1 |
NULL, &siglen);
|
|
Packit Service |
4684c1 |
if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) {
|
|
Packit Service |
4684c1 |
req_login = 1;
|
|
Packit Service |
4684c1 |
goto retry_login;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (rv != CKR_OK) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = pkcs11_rv_to_err(rv);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
tmp.data = gnutls_malloc(siglen);
|
|
Packit Service |
4684c1 |
tmp.size = siglen;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
|
|
Packit Service |
4684c1 |
tmp.data, &siglen);
|
|
Packit Service |
4684c1 |
if (rv != CKR_OK) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = pkcs11_rv_to_err(rv);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (key->pk_algorithm == GNUTLS_PK_ECDSA
|
|
Packit Service |
4684c1 |
|| key->pk_algorithm == GNUTLS_PK_DSA) {
|
|
Packit Service |
4684c1 |
unsigned int hlen = siglen / 2;
|
|
Packit Service |
4684c1 |
gnutls_datum_t r, s;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (siglen % 2 != 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_PK_SIGN_FAILED;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
r.data = tmp.data;
|
|
Packit Service |
4684c1 |
r.size = hlen;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
s.data = &tmp.data[hlen];
|
|
Packit Service |
4684c1 |
s.size = hlen;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_encode_ber_rs_raw(signature, &r, &s);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_free(tmp.data);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
signature->size = siglen;
|
|
Packit Service |
4684c1 |
signature->data = tmp.data;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
gnutls_mutex_unlock(&key->mutex);
|
|
Packit Service |
4684c1 |
if (sinfo != &key->sinfo)
|
|
Packit Service |
4684c1 |
pkcs11_close_session(sinfo);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
gnutls_free(tmp.data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs11_privkey_status:
|
|
Packit Service |
4684c1 |
* @key: Holds the key
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Checks the status of the private key token.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: this function will return non-zero if the token
|
|
Packit Service |
4684c1 |
* holding the private key is still available (inserted), and zero otherwise.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.1.9
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
unsigned gnutls_pkcs11_privkey_status(gnutls_pkcs11_privkey_t key)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ck_rv_t rv;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
struct ck_session_info session_info;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
PKCS11_CHECK_INIT_PRIVKEY(key);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
REPEAT_ON_INVALID_HANDLE(rv = (key->sinfo.module)->C_GetSessionInfo(key->sinfo.pks, &session_info));
|
|
Packit Service |
4684c1 |
if (rv != CKR_OK) {
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
ret = 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs11_privkey_import_url:
|
|
Packit Service |
4684c1 |
* @pkey: The private key
|
|
Packit Service |
4684c1 |
* @url: a PKCS 11 url identifying the key
|
|
Packit Service |
4684c1 |
* @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will "import" a PKCS 11 URL identifying a private
|
|
Packit Service |
4684c1 |
* key to the #gnutls_pkcs11_privkey_t type. In reality since
|
|
Packit Service |
4684c1 |
* in most cases keys cannot be exported, the private key structure
|
|
Packit Service |
4684c1 |
* is being associated with the available operations on the token.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
|
|
Packit Service |
4684c1 |
const char *url, unsigned int flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
struct ck_attribute *attr;
|
|
Packit Service |
4684c1 |
struct ck_attribute a[4];
|
|
Packit Service |
4684c1 |
ck_key_type_t key_type;
|
|
Packit Service |
4684c1 |
ck_bool_t reauth = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
PKCS11_CHECK_INIT;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memset(&pkey->sinfo, 0, sizeof(pkey->sinfo));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkey->url)
|
|
Packit Service |
4684c1 |
gnutls_free(pkey->url);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkey->uinfo) {
|
|
Packit Service |
4684c1 |
p11_kit_uri_free(pkey->uinfo);
|
|
Packit Service |
4684c1 |
pkey->uinfo = NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
pkey->url = gnutls_strdup(url);
|
|
Packit Service |
4684c1 |
if (pkey->url == NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = pkcs11_url_to_info(pkey->url, &pkey->uinfo, flags|GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PRIVKEY);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
pkey->flags = flags;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_CLASS);
|
|
Packit Service |
4684c1 |
if (!attr || attr->value_len != sizeof(ck_object_class_t) ||
|
|
Packit Service |
4684c1 |
*(ck_object_class_t *) attr->value != CKO_PRIVATE_KEY) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_ID);
|
|
Packit Service |
4684c1 |
if (!attr) {
|
|
Packit Service |
4684c1 |
attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_LABEL);
|
|
Packit Service |
4684c1 |
if (!attr) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
FIND_OBJECT(pkey);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
pkey->pk_algorithm = GNUTLS_PK_UNKNOWN;
|
|
Packit Service |
4684c1 |
a[0].type = CKA_KEY_TYPE;
|
|
Packit Service |
4684c1 |
a[0].value = &key_type;
|
|
Packit Service |
4684c1 |
a[0].value_len = sizeof(key_type);
|
|
Packit Service |
4684c1 |
if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1)
|
|
Packit Service |
4684c1 |
== CKR_OK) {
|
|
Packit Service |
4684c1 |
pkey->pk_algorithm = key_type_to_pk(key_type);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN) {
|
|
Packit Service |
4684c1 |
_gnutls_debug_log
|
|
Packit Service |
4684c1 |
("Cannot determine PKCS #11 key algorithm\n");
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_UNKNOWN_ALGORITHM;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkey->pk_algorithm == GNUTLS_PK_RSA) { /* determine whether it can do rsa-pss */
|
|
Packit Service |
4684c1 |
ck_bool_t tval = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[0].type = CKA_MODULUS;
|
|
Packit Service |
4684c1 |
a[0].value = NULL;
|
|
Packit Service |
4684c1 |
a[0].value_len = 0;
|
|
Packit Service |
4684c1 |
a[1].type = CKA_SIGN;
|
|
Packit Service |
4684c1 |
a[1].value = &tval;
|
|
Packit Service |
4684c1 |
a[1].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 2)
|
|
Packit Service |
4684c1 |
== CKR_OK) {
|
|
Packit Service |
4684c1 |
pkey->bits = a[0].value_len*8;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pkcs11_token_check_mechanism(url, CKM_RSA_PKCS_PSS, NULL, 0, 0);
|
|
Packit Service |
4684c1 |
if (ret != 0 && tval) {
|
|
Packit Service |
4684c1 |
pkey->rsa_pss_ok = 1;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("Detected incompatible with TLS1.3 RSA key! (%s)\n", url);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[0].type = CKA_ALWAYS_AUTHENTICATE;
|
|
Packit Service |
4684c1 |
a[0].value = &reauth;
|
|
Packit Service |
4684c1 |
a[0].value_len = sizeof(reauth);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1)
|
|
Packit Service |
4684c1 |
== CKR_OK) {
|
|
Packit Service |
4684c1 |
pkey->reauth = reauth;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
if (pkey->uinfo != NULL) {
|
|
Packit Service |
4684c1 |
p11_kit_uri_free(pkey->uinfo);
|
|
Packit Service |
4684c1 |
pkey->uinfo = NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
gnutls_free(pkey->url);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/*-
|
|
Packit Service |
4684c1 |
* _gnutls_pkcs11_privkey_decrypt_data:
|
|
Packit Service |
4684c1 |
* @key: Holds the key
|
|
Packit Service |
4684c1 |
* @flags: should be 0 for now
|
|
Packit Service |
4684c1 |
* @ciphertext: holds the data to be signed
|
|
Packit Service |
4684c1 |
* @plaintext: will contain the plaintext, allocated with gnutls_malloc()
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will decrypt the given data using the public key algorithm
|
|
Packit Service |
4684c1 |
* supported by the private key.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
-*/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key,
|
|
Packit Service |
4684c1 |
unsigned int flags,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t * ciphertext,
|
|
Packit Service |
4684c1 |
gnutls_datum_t * plaintext)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ck_rv_t rv;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
struct ck_mechanism mech;
|
|
Packit Service |
4684c1 |
unsigned long siglen;
|
|
Packit Service |
4684c1 |
unsigned req_login = 0;
|
|
Packit Service |
4684c1 |
unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
PKCS11_CHECK_INIT_PRIVKEY(key);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (key->pk_algorithm != GNUTLS_PK_RSA)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mech.mechanism = CKM_RSA_PKCS;
|
|
Packit Service |
4684c1 |
mech.parameter = NULL;
|
|
Packit Service |
4684c1 |
mech.parameter_len = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_mutex_lock(&key->mutex);
|
|
Packit Service |
4684c1 |
if (ret != 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Initialize signing operation; using the private key discovered
|
|
Packit Service |
4684c1 |
* earlier. */
|
|
Packit Service |
4684c1 |
REPEAT_ON_INVALID_HANDLE(rv = pkcs11_decrypt_init(key->sinfo.module, key->sinfo.pks, &mech, key->ref));
|
|
Packit Service |
4684c1 |
if (rv != CKR_OK) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = pkcs11_rv_to_err(rv);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
retry_login:
|
|
Packit Service |
4684c1 |
if (key->reauth || req_login) {
|
|
Packit Service |
4684c1 |
if (req_login)
|
|
Packit Service |
4684c1 |
login_flags = SESSION_FORCE_LOGIN|SESSION_LOGIN;
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
pkcs11_login(&key->sinfo, &key->pin,
|
|
Packit Service |
4684c1 |
key->uinfo, login_flags);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
|
|
Packit Service |
4684c1 |
/* let's try the operation anyway */
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Work out how long the plaintext must be: */
|
|
Packit Service |
4684c1 |
rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks, ciphertext->data,
|
|
Packit Service |
4684c1 |
ciphertext->size, NULL, &siglen);
|
|
Packit Service |
4684c1 |
if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) {
|
|
Packit Service |
4684c1 |
req_login = 1;
|
|
Packit Service |
4684c1 |
goto retry_login;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (rv != CKR_OK) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = pkcs11_rv_to_err(rv);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
plaintext->data = gnutls_malloc(siglen);
|
|
Packit Service |
4684c1 |
plaintext->size = siglen;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks, ciphertext->data,
|
|
Packit Service |
4684c1 |
ciphertext->size, plaintext->data, &siglen);
|
|
Packit Service |
4684c1 |
if (rv != CKR_OK) {
|
|
Packit Service |
4684c1 |
gnutls_free(plaintext->data);
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = pkcs11_rv_to_err(rv);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
plaintext->size = siglen;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
gnutls_mutex_unlock(&key->mutex);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/*-
|
|
Packit Service |
4684c1 |
* _gnutls_pkcs11_privkey_decrypt_data2:
|
|
Packit Service |
4684c1 |
* @key: Holds the key
|
|
Packit Service |
4684c1 |
* @flags: should be 0 for now
|
|
Packit Service |
4684c1 |
* @ciphertext: holds the data to be signed
|
|
Packit Service |
4684c1 |
* @plaintext: a preallocated buffer that will be filled with the plaintext
|
|
Packit Service |
4684c1 |
* @plaintext_size: size of the plaintext
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will decrypt the given data using the public key algorithm
|
|
Packit Service |
4684c1 |
* supported by the private key.
|
|
Packit Service |
4684c1 |
* Unlike with _gnutls_pkcs11_privkey_decrypt_data the plaintext size is known
|
|
Packit Service |
4684c1 |
* and provided by the caller, if the plaintext size differs from the requested
|
|
Packit Service |
4684c1 |
* one, the operation fails and the provided buffer is left unchanged.
|
|
Packit Service |
4684c1 |
* NOTE: plaintext_size must be exactly the size of the payload in the
|
|
Packit Service |
4684c1 |
* ciphertext, otherwise an error is returned and the plaintext buffer is left
|
|
Packit Service |
4684c1 |
* unchanged.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
-*/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_gnutls_pkcs11_privkey_decrypt_data2(gnutls_pkcs11_privkey_t key,
|
|
Packit Service |
4684c1 |
unsigned int flags,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t * ciphertext,
|
|
Packit Service |
4684c1 |
unsigned char * plaintext,
|
|
Packit Service |
4684c1 |
size_t plaintext_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ck_rv_t rv;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
struct ck_mechanism mech;
|
|
Packit Service |
4684c1 |
unsigned long siglen = ciphertext->size;
|
|
Packit Service |
4684c1 |
unsigned req_login = 0;
|
|
Packit Service |
4684c1 |
unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC;
|
|
Packit Service |
4684c1 |
unsigned char *buffer;
|
|
Packit Service |
4684c1 |
volatile unsigned char value;
|
|
Packit Service |
4684c1 |
unsigned char mask;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
PKCS11_CHECK_INIT_PRIVKEY(key);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (key->pk_algorithm != GNUTLS_PK_RSA)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mech.mechanism = CKM_RSA_PKCS;
|
|
Packit Service |
4684c1 |
mech.parameter = NULL;
|
|
Packit Service |
4684c1 |
mech.parameter_len = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_mutex_lock(&key->mutex);
|
|
Packit Service |
4684c1 |
if (ret != 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
buffer = gnutls_malloc(siglen);
|
|
Packit Service |
4684c1 |
if (!buffer) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Initialize signing operation; using the private key discovered
|
|
Packit Service |
4684c1 |
* earlier. */
|
|
Packit Service |
4684c1 |
REPEAT_ON_INVALID_HANDLE(
|
|
Packit Service |
4684c1 |
rv = pkcs11_decrypt_init(key->sinfo.module, key->sinfo.pks,
|
|
Packit Service |
4684c1 |
&mech, key->ref)
|
|
Packit Service |
4684c1 |
);
|
|
Packit Service |
4684c1 |
if (rv != CKR_OK) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = pkcs11_rv_to_err(rv);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
retry_login:
|
|
Packit Service |
4684c1 |
if (key->reauth || req_login) {
|
|
Packit Service |
4684c1 |
if (req_login)
|
|
Packit Service |
4684c1 |
login_flags = SESSION_FORCE_LOGIN|SESSION_LOGIN;
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
pkcs11_login(&key->sinfo, &key->pin,
|
|
Packit Service |
4684c1 |
key->uinfo, login_flags);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
|
|
Packit Service |
4684c1 |
/* let's try the operation anyway */
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
siglen = ciphertext->size;
|
|
Packit Service |
4684c1 |
rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks,
|
|
Packit Service |
4684c1 |
ciphertext->data, ciphertext->size,
|
|
Packit Service |
4684c1 |
buffer, &siglen);
|
|
Packit Service |
4684c1 |
if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) {
|
|
Packit Service |
4684c1 |
req_login = 1;
|
|
Packit Service |
4684c1 |
goto retry_login;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* NOTE: These branches are not side-channel silent */
|
|
Packit Service |
4684c1 |
if (rv != CKR_OK) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = pkcs11_rv_to_err(rv);
|
|
Packit Service |
4684c1 |
} else if (siglen != plaintext_size) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* conditionally copy buffer in a side-channel silent way */
|
|
Packit Service |
4684c1 |
/* on success mask is 0xFF, on failure it is 0 */
|
|
Packit Service |
4684c1 |
mask = ((uint32_t)ret >> 31) - 1U;
|
|
Packit Service |
4684c1 |
for (size_t i = 0; i < plaintext_size; i++) {
|
|
Packit Service |
4684c1 |
value = (buffer[i] & mask) + (plaintext[i] & ~mask);
|
|
Packit Service |
4684c1 |
plaintext[i] = value;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
gnutls_mutex_unlock(&key->mutex);
|
|
Packit Service |
4684c1 |
gnutls_free(buffer);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs11_privkey_export_url:
|
|
Packit Service |
4684c1 |
* @key: Holds the PKCS 11 key
|
|
Packit Service |
4684c1 |
* @detailed: non zero if a detailed URL is required
|
|
Packit Service |
4684c1 |
* @url: will contain an allocated url
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will export a URL identifying the given key.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_privkey_export_url(gnutls_pkcs11_privkey_t key,
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_url_type_t detailed,
|
|
Packit Service |
4684c1 |
char **url)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = pkcs11_info_to_url(key->uinfo, detailed, url);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#if 0
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs11_privkey_generate:
|
|
Packit Service |
4684c1 |
* @url: a token URL
|
|
Packit Service |
4684c1 |
* @pk: the public key algorithm
|
|
Packit Service |
4684c1 |
* @bits: the security bits
|
|
Packit Service |
4684c1 |
* @label: a label
|
|
Packit Service |
4684c1 |
* @flags: should be zero
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will generate a private key in the specified
|
|
Packit Service |
4684c1 |
* by the @url token. The private key will be generate within
|
|
Packit Service |
4684c1 |
* the token and will not be exportable.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.0
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_privkey_generate(const char *url, gnutls_pk_algorithm_t pk,
|
|
Packit Service |
4684c1 |
unsigned int bits, const char *label,
|
|
Packit Service |
4684c1 |
unsigned int flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int x;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs11_privkey_generate2:
|
|
Packit Service |
4684c1 |
* @url: a token URL
|
|
Packit Service |
4684c1 |
* @pk: the public key algorithm
|
|
Packit Service |
4684c1 |
* @bits: the security bits
|
|
Packit Service |
4684c1 |
* @label: a label
|
|
Packit Service |
4684c1 |
* @fmt: the format of output params. PEM or DER
|
|
Packit Service |
4684c1 |
* @pubkey: will hold the public key (may be %NULL)
|
|
Packit Service |
4684c1 |
* @flags: zero or an OR'ed sequence of %GNUTLS_PKCS11_OBJ_FLAGs
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will generate a private key in the specified
|
|
Packit Service |
4684c1 |
* by the @url token. The private key will be generate within
|
|
Packit Service |
4684c1 |
* the token and will not be exportable. This function will
|
|
Packit Service |
4684c1 |
* store the DER-encoded public key in the SubjectPublicKeyInfo format
|
|
Packit Service |
4684c1 |
* in @pubkey. The @pubkey should be deinitialized using gnutls_free().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Note that when generating an elliptic curve key, the curve
|
|
Packit Service |
4684c1 |
* can be substituted in the place of the bits parameter using the
|
|
Packit Service |
4684c1 |
* GNUTLS_CURVE_TO_BITS() macro.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.1.5
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_privkey_generate2(const char *url, gnutls_pk_algorithm_t pk,
|
|
Packit Service |
4684c1 |
unsigned int bits, const char *label,
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_fmt_t fmt,
|
|
Packit Service |
4684c1 |
gnutls_datum_t * pubkey,
|
|
Packit Service |
4684c1 |
unsigned int flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int x;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static const char def_rsa_pub_exp[3] = { 1,0,1 }; // 65537 = 0x10001
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
struct dsa_params {
|
|
Packit Service |
4684c1 |
/* FIPS 186-3 maximal size for L and N length pair is (3072,256). */
|
|
Packit Service |
4684c1 |
uint8_t prime[384];
|
|
Packit Service |
4684c1 |
uint8_t subprime[32];
|
|
Packit Service |
4684c1 |
uint8_t generator[384];
|
|
Packit Service |
4684c1 |
};
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
_dsa_params_generate(struct ck_function_list *module, ck_session_handle_t session,
|
|
Packit Service |
4684c1 |
unsigned long bits, struct dsa_params *params,
|
|
Packit Service |
4684c1 |
struct ck_attribute *a, int *a_val)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
struct ck_mechanism mech = { CKM_DSA_PARAMETER_GEN };
|
|
Packit Service |
4684c1 |
struct ck_attribute attr = { CKA_PRIME_BITS, &bits, sizeof(bits) };
|
|
Packit Service |
4684c1 |
ck_object_handle_t key;
|
|
Packit Service |
4684c1 |
ck_rv_t rv;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Generate DSA parameters from prime length. */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
rv = pkcs11_generate_key(module, session, &mech, &attr, 1, &key);
|
|
Packit Service |
4684c1 |
if (rv != CKR_OK) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
|
|
Packit Service |
4684c1 |
return pkcs11_rv_to_err(rv);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Retrieve generated parameters to be used with the new key pair. */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[*a_val + 0].type = CKA_PRIME;
|
|
Packit Service |
4684c1 |
a[*a_val + 0].value = params->prime;
|
|
Packit Service |
4684c1 |
a[*a_val + 0].value_len = sizeof(params->prime);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[*a_val + 1].type = CKA_SUBPRIME;
|
|
Packit Service |
4684c1 |
a[*a_val + 1].value = params->subprime;
|
|
Packit Service |
4684c1 |
a[*a_val + 1].value_len = sizeof(params->subprime);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[*a_val + 2].type = CKA_BASE;
|
|
Packit Service |
4684c1 |
a[*a_val + 2].value = params->generator;
|
|
Packit Service |
4684c1 |
a[*a_val + 2].value_len = sizeof(params->generator);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
rv = pkcs11_get_attribute_value(module, session, key, &a[*a_val], 3);
|
|
Packit Service |
4684c1 |
if (rv != CKR_OK) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
|
|
Packit Service |
4684c1 |
return pkcs11_rv_to_err(rv);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*a_val += 3;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs11_privkey_generate3:
|
|
Packit Service |
4684c1 |
* @url: a token URL
|
|
Packit Service |
4684c1 |
* @pk: the public key algorithm
|
|
Packit Service |
4684c1 |
* @bits: the security bits
|
|
Packit Service |
4684c1 |
* @label: a label
|
|
Packit Service |
4684c1 |
* @cid: The CKA_ID to use for the new object
|
|
Packit Service |
4684c1 |
* @fmt: the format of output params. PEM or DER
|
|
Packit Service |
4684c1 |
* @pubkey: will hold the public key (may be %NULL)
|
|
Packit Service |
4684c1 |
* @key_usage: One of GNUTLS_KEY_*
|
|
Packit Service |
4684c1 |
* @flags: zero or an OR'ed sequence of %GNUTLS_PKCS11_OBJ_FLAGs
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will generate a private key in the specified
|
|
Packit Service |
4684c1 |
* by the @url token. The private key will be generate within
|
|
Packit Service |
4684c1 |
* the token and will not be exportable. This function will
|
|
Packit Service |
4684c1 |
* store the DER-encoded public key in the SubjectPublicKeyInfo format
|
|
Packit Service |
4684c1 |
* in @pubkey. The @pubkey should be deinitialized using gnutls_free().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Note that when generating an elliptic curve key, the curve
|
|
Packit Service |
4684c1 |
* can be substituted in the place of the bits parameter using the
|
|
Packit Service |
4684c1 |
* GNUTLS_CURVE_TO_BITS() macro.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since 3.6.3 the objects are marked as sensitive by default unless
|
|
Packit Service |
4684c1 |
* %GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE is specified.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.4.0
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_privkey_generate3(const char *url, gnutls_pk_algorithm_t pk,
|
|
Packit Service |
4684c1 |
unsigned int bits, const char *label,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t *cid,
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_fmt_t fmt,
|
|
Packit Service |
4684c1 |
gnutls_datum_t * pubkey,
|
|
Packit Service |
4684c1 |
unsigned int key_usage,
|
|
Packit Service |
4684c1 |
unsigned int flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
const ck_bool_t tval = 1;
|
|
Packit Service |
4684c1 |
const ck_bool_t fval = 0;
|
|
Packit Service |
4684c1 |
struct pkcs11_session_info sinfo;
|
|
Packit Service |
4684c1 |
struct p11_kit_uri *info = NULL;
|
|
Packit Service |
4684c1 |
ck_rv_t rv;
|
|
Packit Service |
4684c1 |
struct ck_attribute a[22], p[22];
|
|
Packit Service |
4684c1 |
ck_object_handle_t pub_ctx, priv_ctx;
|
|
Packit Service |
4684c1 |
unsigned long _bits = bits;
|
|
Packit Service |
4684c1 |
int a_val, p_val;
|
|
Packit Service |
4684c1 |
struct ck_mechanism mech;
|
|
Packit Service |
4684c1 |
gnutls_pubkey_t pkey = NULL;
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_obj_t obj = NULL;
|
|
Packit Service |
4684c1 |
gnutls_datum_t der = {NULL, 0};
|
|
Packit Service |
4684c1 |
ck_key_type_t key_type;
|
|
Packit Service |
4684c1 |
uint8_t id[20];
|
|
Packit Service |
4684c1 |
struct dsa_params dsa_params;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
PKCS11_CHECK_INIT;
|
|
Packit Service |
4684c1 |
FIX_KEY_USAGE(pk, key_usage);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memset(&sinfo, 0, sizeof(sinfo));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = pkcs11_url_to_info(url, &info, 0);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
pkcs11_open_session(&sinfo, NULL, info,
|
|
Packit Service |
4684c1 |
SESSION_WRITE |
|
|
Packit Service |
4684c1 |
pkcs11_obj_flags_to_int(flags));
|
|
Packit Service |
4684c1 |
p11_kit_uri_free(info);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* a holds the public key template
|
|
Packit Service |
4684c1 |
* and p the private key */
|
|
Packit Service |
4684c1 |
a_val = p_val = 0;
|
|
Packit Service |
4684c1 |
mech.parameter = NULL;
|
|
Packit Service |
4684c1 |
mech.parameter_len = 0;
|
|
Packit Service |
4684c1 |
mech.mechanism = pk_to_genmech(pk, &key_type);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_NO_STORE_PUBKEY)) {
|
|
Packit Service |
4684c1 |
a[a_val].type = CKA_TOKEN;
|
|
Packit Service |
4684c1 |
a[a_val].value = (void *) &tval;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
a_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[a_val].type = CKA_PRIVATE;
|
|
Packit Service |
4684c1 |
a[a_val].value = (void *) &fval;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = sizeof(fval);
|
|
Packit Service |
4684c1 |
a_val++;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[a_val].type = CKA_ID;
|
|
Packit Service |
4684c1 |
if (cid == NULL || cid->size == 0) {
|
|
Packit Service |
4684c1 |
ret = gnutls_rnd(GNUTLS_RND_NONCE, id, sizeof(id));
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[a_val].value = (void *) id;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = sizeof(id);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
a[a_val].value = (void *) cid->data;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = cid->size;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
p[p_val].type = CKA_ID;
|
|
Packit Service |
4684c1 |
p[p_val].value = a[a_val].value;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = a[a_val].value_len;
|
|
Packit Service |
4684c1 |
a_val++;
|
|
Packit Service |
4684c1 |
p_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
switch (pk) {
|
|
Packit Service |
4684c1 |
case GNUTLS_PK_RSA:
|
|
Packit Service |
4684c1 |
p[p_val].type = CKA_DECRYPT;
|
|
Packit Service |
4684c1 |
if (key_usage & (GNUTLS_KEY_DECIPHER_ONLY|GNUTLS_KEY_ENCIPHER_ONLY)) {
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) &tval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) &fval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(fval);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
p_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
p[p_val].type = CKA_SIGN;
|
|
Packit Service |
4684c1 |
if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) &tval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) &fval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(fval);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
p_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[a_val].type = CKA_ENCRYPT;
|
|
Packit Service |
4684c1 |
a[a_val].value = (void *) &tval;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
a_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[a_val].type = CKA_VERIFY;
|
|
Packit Service |
4684c1 |
a[a_val].value = (void *) &tval;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
a_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[a_val].type = CKA_MODULUS_BITS;
|
|
Packit Service |
4684c1 |
a[a_val].value = &_bits;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = sizeof(_bits);
|
|
Packit Service |
4684c1 |
a_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[a_val].type = CKA_PUBLIC_EXPONENT;
|
|
Packit Service |
4684c1 |
a[a_val].value = (char*)def_rsa_pub_exp;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = sizeof(def_rsa_pub_exp);
|
|
Packit Service |
4684c1 |
a_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
case GNUTLS_PK_DSA:
|
|
Packit Service |
4684c1 |
p[p_val].type = CKA_SIGN;
|
|
Packit Service |
4684c1 |
if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) &tval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) &fval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(fval);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
p_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[a_val].type = CKA_VERIFY;
|
|
Packit Service |
4684c1 |
a[a_val].value = (void *) &tval;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
a_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _dsa_params_generate(sinfo.module, sinfo.pks, _bits,
|
|
Packit Service |
4684c1 |
&dsa_params, a, &a_val);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
case GNUTLS_PK_ECDSA:
|
|
Packit Service |
4684c1 |
p[p_val].type = CKA_SIGN;
|
|
Packit Service |
4684c1 |
if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) &tval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) &fval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(fval);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
p_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[a_val].type = CKA_VERIFY;
|
|
Packit Service |
4684c1 |
a[a_val].value = (void *) &tval;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
a_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (GNUTLS_BITS_ARE_CURVE(bits)) {
|
|
Packit Service |
4684c1 |
bits = GNUTLS_BITS_TO_CURVE(bits);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
bits = _gnutls_ecc_bits_to_curve(pk, bits);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_x509_write_ecc_params(bits, &der;;
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[a_val].type = CKA_EC_PARAMS;
|
|
Packit Service |
4684c1 |
a[a_val].value = der.data;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = der.size;
|
|
Packit Service |
4684c1 |
a_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
case GNUTLS_PK_EDDSA_ED25519:
|
|
Packit Service |
4684c1 |
p[p_val].type = CKA_SIGN;
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) &tval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
p_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[a_val].type = CKA_VERIFY;
|
|
Packit Service |
4684c1 |
a[a_val].value = (void *) &tval;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
a_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_x509_write_ecc_params(GNUTLS_ECC_CURVE_ED25519, &der;;
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[a_val].type = CKA_EC_PARAMS;
|
|
Packit Service |
4684c1 |
a[a_val].value = der.data;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = der.size;
|
|
Packit Service |
4684c1 |
a_val++;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
default:
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* on request, add the CKA_WRAP/CKA_UNWRAP key attribute
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP) {
|
|
Packit Service |
4684c1 |
p[p_val].type = CKA_UNWRAP;
|
|
Packit Service |
4684c1 |
p[p_val].value = (void*)&tval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
p_val++;
|
|
Packit Service |
4684c1 |
a[a_val].type = CKA_WRAP;
|
|
Packit Service |
4684c1 |
a[a_val].value = (void*)&tval;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
a_val++;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* a private key is set always as private unless
|
|
Packit Service |
4684c1 |
* requested otherwise
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
|
|
Packit Service |
4684c1 |
p[p_val].type = CKA_PRIVATE;
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) &fval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(fval);
|
|
Packit Service |
4684c1 |
p_val++;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
p[p_val].type = CKA_PRIVATE;
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) &tval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
p_val++;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
p[p_val].type = CKA_TOKEN;
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) &tval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
p_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (label) {
|
|
Packit Service |
4684c1 |
p[p_val].type = CKA_LABEL;
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) label;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = strlen(label);
|
|
Packit Service |
4684c1 |
p_val++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
a[a_val].type = CKA_LABEL;
|
|
Packit Service |
4684c1 |
a[a_val].value = (void *) label;
|
|
Packit Service |
4684c1 |
a[a_val].value_len = strlen(label);
|
|
Packit Service |
4684c1 |
a_val++;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE)) {
|
|
Packit Service |
4684c1 |
p[p_val].type = CKA_SENSITIVE;
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) &tval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(tval);
|
|
Packit Service |
4684c1 |
p_val++;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
p[p_val].type = CKA_SENSITIVE;
|
|
Packit Service |
4684c1 |
p[p_val].value = (void *) &fval;
|
|
Packit Service |
4684c1 |
p[p_val].value_len = sizeof(fval);
|
|
Packit Service |
4684c1 |
p_val++;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
rv = pkcs11_generate_key_pair(sinfo.module, sinfo.pks, &mech, a,
|
|
Packit Service |
4684c1 |
a_val, p, p_val, &pub_ctx, &priv_ctx);
|
|
Packit Service |
4684c1 |
if (rv != CKR_OK) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
|
|
Packit Service |
4684c1 |
ret = pkcs11_rv_to_err(rv);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* extract the public key */
|
|
Packit Service |
4684c1 |
if (pubkey) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pubkey_init(&pkey);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pkcs11_obj_init(&obj);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
obj->pk_algorithm = pk;
|
|
Packit Service |
4684c1 |
obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
pkcs11_read_pubkey(sinfo.module, sinfo.pks, pub_ctx,
|
|
Packit Service |
4684c1 |
key_type, obj);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pubkey_import_pkcs11(pkey, obj, 0);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pubkey_export2(pkey, fmt, pubkey);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
if (obj != NULL)
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_obj_deinit(obj);
|
|
Packit Service |
4684c1 |
if (pkey != NULL)
|
|
Packit Service |
4684c1 |
gnutls_pubkey_deinit(pkey);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (sinfo.pks != 0)
|
|
Packit Service |
4684c1 |
pkcs11_close_session(&sinfo);
|
|
Packit Service |
4684c1 |
gnutls_free(der.data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* loads a the corresponding to the private key public key either from
|
|
Packit Service |
4684c1 |
* a public key object or from a certificate.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
static int load_pubkey_obj(gnutls_pkcs11_privkey_t pkey, gnutls_pubkey_t pub)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret, iret;
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_t crt;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pubkey_import_url(pub, pkey->url, pkey->flags);
|
|
Packit Service |
4684c1 |
if (ret >= 0) {
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
iret = ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* else try certificate */
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_init(&crt;;
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_set_pin_function(crt, pkey->pin.cb, pkey->pin.data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_import_url(crt, pkey->url, pkey->flags);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
ret = iret;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pubkey_import_x509(pub, crt, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(crt);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_pkcs11_privkey_get_pubkey (gnutls_pkcs11_privkey_t pkey, gnutls_pubkey_t *pub, unsigned flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
gnutls_pubkey_t pubkey = NULL;
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_obj_t obj = NULL;
|
|
Packit Service |
4684c1 |
ck_key_type_t key_type;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
PKCS11_CHECK_INIT_PRIVKEY(pkey);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!pkey) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pubkey_init(&pubkey);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pkcs11_obj_init(&obj);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
obj->pk_algorithm = gnutls_pkcs11_privkey_get_pk_algorithm(pkey, 0);
|
|
Packit Service |
4684c1 |
obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
|
|
Packit Service |
4684c1 |
pk_to_genmech(obj->pk_algorithm, &key_type);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_pubkey_set_pin_function(pubkey, pkey->pin.cb, pkey->pin.data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* we can only read the public key from RSA keys */
|
|
Packit Service |
4684c1 |
if (key_type != CKK_RSA) {
|
|
Packit Service |
4684c1 |
/* try opening the public key object if it exists */
|
|
Packit Service |
4684c1 |
ret = load_pubkey_obj(pkey, pubkey);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
ret = pkcs11_read_pubkey(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, key_type, obj);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pubkey_import_pkcs11(pubkey, obj, 0);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*pub = pubkey;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
pubkey = NULL;
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
if (obj != NULL)
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_obj_deinit(obj);
|
|
Packit Service |
4684c1 |
if (pubkey != NULL)
|
|
Packit Service |
4684c1 |
gnutls_pubkey_deinit(pubkey);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs11_privkey_export_pubkey
|
|
Packit Service |
4684c1 |
* @pkey: The private key
|
|
Packit Service |
4684c1 |
* @fmt: the format of output params. PEM or DER.
|
|
Packit Service |
4684c1 |
* @data: will hold the public key
|
|
Packit Service |
4684c1 |
* @flags: should be zero
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will extract the public key (modulus and public
|
|
Packit Service |
4684c1 |
* exponent) from the private key specified by the @url private key.
|
|
Packit Service |
4684c1 |
* This public key will be stored in @pubkey in the format specified
|
|
Packit Service |
4684c1 |
* by @fmt. @pubkey should be deinitialized using gnutls_free().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.3.7
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_privkey_export_pubkey(gnutls_pkcs11_privkey_t pkey,
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_fmt_t fmt,
|
|
Packit Service |
4684c1 |
gnutls_datum_t * data,
|
|
Packit Service |
4684c1 |
unsigned int flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_pubkey_t pubkey = NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _pkcs11_privkey_get_pubkey(pkey, &pubkey, flags);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pubkey_export2(pubkey, fmt, data);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
if (pubkey != NULL)
|
|
Packit Service |
4684c1 |
gnutls_pubkey_deinit(pubkey);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs11_privkey_set_pin_function:
|
|
Packit Service |
4684c1 |
* @key: The private key
|
|
Packit Service |
4684c1 |
* @fn: the callback
|
|
Packit Service |
4684c1 |
* @userdata: data associated with the callback
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will set a callback function to be used when
|
|
Packit Service |
4684c1 |
* required to access the object. This function overrides the global
|
|
Packit Service |
4684c1 |
* set using gnutls_pkcs11_set_pin_function().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.1.0
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
void
|
|
Packit Service |
4684c1 |
gnutls_pkcs11_privkey_set_pin_function(gnutls_pkcs11_privkey_t key,
|
|
Packit Service |
4684c1 |
gnutls_pin_callback_t fn,
|
|
Packit Service |
4684c1 |
void *userdata)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
key->pin.cb = fn;
|
|
Packit Service |
4684c1 |
key->pin.data = userdata;
|
|
Packit Service |
4684c1 |
}
|