|
Packit |
aea12f |
/*
|
|
Packit |
aea12f |
* GnuTLS PKCS#11 support
|
|
Packit |
aea12f |
* Copyright (C) 2010-2012 Free Software Foundation, Inc.
|
|
Packit |
aea12f |
* Copyright (C) 2008, Joe Orton <joe@manyfish.co.uk>
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Authors: Nikos Mavrogiannopoulos, Stef Walter
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Inspired and some parts (pkcs11_login) based on neon PKCS #11 support
|
|
Packit |
aea12f |
* by Joe Orton. More ideas came from the pkcs11-helper library by
|
|
Packit |
aea12f |
* Alon Bar-Lev.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit |
aea12f |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit |
aea12f |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
aea12f |
* the License, or (at your option) any later version.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This library is distributed in the hope that it will be useful, but
|
|
Packit |
aea12f |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
aea12f |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
aea12f |
* Lesser General Public License for more details.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
aea12f |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#include "gnutls_int.h"
|
|
Packit |
aea12f |
#include <gnutls/pkcs11.h>
|
|
Packit |
aea12f |
#include <stdio.h>
|
|
Packit |
aea12f |
#include <string.h>
|
|
Packit |
aea12f |
#include "errors.h"
|
|
Packit |
aea12f |
#include <datum.h>
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#include <pin.h>
|
|
Packit |
aea12f |
#include <pkcs11_int.h>
|
|
Packit |
aea12f |
#include <p11-kit/p11-kit.h>
|
|
Packit |
aea12f |
#include <p11-kit/pkcs11.h>
|
|
Packit |
aea12f |
#include <p11-kit/pin.h>
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_get_slot_list(struct ck_function_list * module,
|
|
Packit |
aea12f |
unsigned char token_present, ck_slot_id_t * slot_list,
|
|
Packit |
aea12f |
unsigned long *count)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_GetSlotList(token_present, slot_list, count);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_get_module_info(struct ck_function_list * module,
|
|
Packit |
aea12f |
struct ck_info * info)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_GetInfo(info);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_get_slot_info(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_slot_id_t slot_id, struct ck_slot_info * info)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_GetSlotInfo(slot_id, info);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_get_token_info(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_slot_id_t slot_id, struct ck_token_info * info)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_GetTokenInfo(slot_id, info);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_find_objects_init(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess,
|
|
Packit |
aea12f |
struct ck_attribute * templ, unsigned long count)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_FindObjectsInit(sess, templ, count);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_find_objects(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess,
|
|
Packit |
aea12f |
ck_object_handle_t * objects,
|
|
Packit |
aea12f |
unsigned long max_object_count,
|
|
Packit |
aea12f |
unsigned long *object_count)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_FindObjects(sess, objects, max_object_count,
|
|
Packit |
aea12f |
object_count);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t pkcs11_find_objects_final(struct pkcs11_session_info * sinfo)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (sinfo->module)->C_FindObjectsFinal(sinfo->pks);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t pkcs11_close_session(struct pkcs11_session_info * sinfo)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
sinfo->init = 0;
|
|
Packit |
aea12f |
return (sinfo->module)->C_CloseSession(sinfo->pks);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_set_attribute_value(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess,
|
|
Packit |
aea12f |
ck_object_handle_t object,
|
|
Packit |
aea12f |
struct ck_attribute * templ,
|
|
Packit |
aea12f |
unsigned long count)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_SetAttributeValue(sess, object, templ, count);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_get_attribute_value(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess,
|
|
Packit |
aea12f |
ck_object_handle_t object,
|
|
Packit |
aea12f |
struct ck_attribute * templ,
|
|
Packit |
aea12f |
unsigned long count)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_GetAttributeValue(sess, object, templ, count);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Returns only a single attribute value, but allocates its data
|
|
Packit |
aea12f |
* Only the type needs to be set.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_get_attribute_avalue(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess,
|
|
Packit |
aea12f |
ck_object_handle_t object,
|
|
Packit |
aea12f |
ck_attribute_type_t type,
|
|
Packit |
aea12f |
gnutls_datum_t *res)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
ck_rv_t rv;
|
|
Packit |
aea12f |
struct ck_attribute templ;
|
|
Packit |
aea12f |
void *t;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
res->data = NULL;
|
|
Packit |
aea12f |
res->size = 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
templ.type = type;
|
|
Packit |
aea12f |
templ.value = NULL;
|
|
Packit |
aea12f |
templ.value_len = 0;
|
|
Packit |
aea12f |
rv = (module)->C_GetAttributeValue(sess, object, &templ, 1);
|
|
Packit |
aea12f |
if (rv == CKR_OK) {
|
|
Packit |
aea12f |
/* PKCS#11 v2.20 requires sensitive values to set a length
|
|
Packit |
aea12f |
* of -1. In that case an error should have been returned,
|
|
Packit |
aea12f |
* but some implementations return CKR_OK instead. */
|
|
Packit |
aea12f |
if (templ.value_len == (unsigned long)-1)
|
|
Packit |
aea12f |
return CKR_ATTRIBUTE_SENSITIVE;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (templ.value_len == 0)
|
|
Packit |
aea12f |
return rv;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
templ.type = type;
|
|
Packit |
aea12f |
t = gnutls_malloc(templ.value_len);
|
|
Packit |
aea12f |
if (t == NULL)
|
|
Packit |
aea12f |
return gnutls_assert_val(CKR_HOST_MEMORY);
|
|
Packit |
aea12f |
templ.value = t;
|
|
Packit |
aea12f |
rv = (module)->C_GetAttributeValue(sess, object, &templ, 1);
|
|
Packit |
aea12f |
if (rv != CKR_OK) {
|
|
Packit |
aea12f |
gnutls_free(t);
|
|
Packit |
aea12f |
return rv;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
res->data = t;
|
|
Packit |
aea12f |
res->size = templ.value_len;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
return rv;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_get_mechanism_list(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_slot_id_t slot_id,
|
|
Packit |
aea12f |
ck_mechanism_type_t * mechanism_list,
|
|
Packit |
aea12f |
unsigned long *count)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_GetMechanismList(slot_id, mechanism_list,
|
|
Packit |
aea12f |
count);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_get_mechanism_info(struct ck_function_list *module,
|
|
Packit |
aea12f |
ck_slot_id_t slot_id,
|
|
Packit |
aea12f |
ck_mechanism_type_t mechanism,
|
|
Packit |
aea12f |
struct ck_mechanism_info *ptr)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_GetMechanismInfo(slot_id, mechanism,
|
|
Packit |
aea12f |
ptr);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_sign_init(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess,
|
|
Packit |
aea12f |
struct ck_mechanism * mechanism, ck_object_handle_t key)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_SignInit(sess, mechanism, key);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_sign(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess,
|
|
Packit |
aea12f |
unsigned char *data,
|
|
Packit |
aea12f |
unsigned long data_len,
|
|
Packit |
aea12f |
unsigned char *signature, unsigned long *signature_len)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_Sign(sess, data, data_len, signature,
|
|
Packit |
aea12f |
signature_len);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_generate_key(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess,
|
|
Packit |
aea12f |
struct ck_mechanism * mechanism,
|
|
Packit |
aea12f |
struct ck_attribute * templ,
|
|
Packit |
aea12f |
unsigned long count,
|
|
Packit |
aea12f |
ck_object_handle_t * key)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_GenerateKey(sess, mechanism, templ, count, key);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_generate_key_pair(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess,
|
|
Packit |
aea12f |
struct ck_mechanism * mechanism,
|
|
Packit |
aea12f |
struct ck_attribute * pub_templ,
|
|
Packit |
aea12f |
unsigned long pub_templ_count,
|
|
Packit |
aea12f |
struct ck_attribute * priv_templ,
|
|
Packit |
aea12f |
unsigned long priv_templ_count,
|
|
Packit |
aea12f |
ck_object_handle_t * pub_ctx,
|
|
Packit |
aea12f |
ck_object_handle_t * priv_ctx)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_GenerateKeyPair(sess, mechanism, pub_templ,
|
|
Packit |
aea12f |
pub_templ_count, priv_templ,
|
|
Packit |
aea12f |
priv_templ_count, pub_ctx, priv_ctx);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_decrypt_init(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess,
|
|
Packit |
aea12f |
struct ck_mechanism * mechanism,
|
|
Packit |
aea12f |
ck_object_handle_t key_ctx)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_DecryptInit(sess, mechanism, key_ctx);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_decrypt(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess,
|
|
Packit |
aea12f |
unsigned char *encrypted_data,
|
|
Packit |
aea12f |
unsigned long encrypted_data_len,
|
|
Packit |
aea12f |
unsigned char *data, unsigned long *data_len)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_Decrypt(sess, encrypted_data,
|
|
Packit |
aea12f |
encrypted_data_len, data, data_len);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_create_object(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess,
|
|
Packit |
aea12f |
struct ck_attribute * templ,
|
|
Packit |
aea12f |
unsigned long count, ck_object_handle_t * ctx)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_CreateObject(sess, templ, count, ctx);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_destroy_object(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess, ck_object_handle_t ctx)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_DestroyObject(sess, ctx);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_init_token(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_slot_id_t slot_id, unsigned char *pin,
|
|
Packit |
aea12f |
unsigned long pin_len, unsigned char *label)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_InitToken(slot_id, pin, pin_len, label);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_init_pin(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess,
|
|
Packit |
aea12f |
unsigned char *pin, unsigned long pin_len)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_InitPIN(sess, pin, pin_len);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
pkcs11_set_pin(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess,
|
|
Packit |
aea12f |
const char *old_pin,
|
|
Packit |
aea12f |
unsigned long old_len,
|
|
Packit |
aea12f |
const char *new_pin, unsigned long new_len)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_SetPIN(sess, (uint8_t *) old_pin, old_len,
|
|
Packit |
aea12f |
(uint8_t *) new_pin, new_len);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ck_rv_t
|
|
Packit |
aea12f |
_gnutls_pkcs11_get_random(struct ck_function_list * module,
|
|
Packit |
aea12f |
ck_session_handle_t sess, void *data, size_t len)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return (module)->C_GenerateRandom(sess, data, len);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
const char *pkcs11_strerror(ck_rv_t rv)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return p11_kit_strerror(rv);
|
|
Packit |
aea12f |
}
|