From 2421956502379899736ef7e9fa8b1893c2de7cd7 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Mon, 16 Apr 2012 15:04:59 +0200 Subject: WIP daemon --- common/compat.c | 55 ++ common/compat.h | 4 + daemon/loop.c | 201 +++++ daemon/main.c | 113 +++ daemon/tpool.c | 73 ++ p11-kit/Makefile.am | 1 + p11-kit/daemon.c | 1405 ------------------------------- p11-kit/rpc-client-old.c | 2067 ++++++++++++++++++++++++++++++++++++++++++++++ p11-kit/rpc-client.c | 65 +- p11-kit/rpc-client.h | 24 +- p11-kit/rpc-message.c | 40 + p11-kit/rpc-message.h | 25 +- p11-kit/rpc-server.c | 1925 ++++++++++++++++++++++++++++++++++++++++++ p11-kit/rpc-server.h | 32 + 14 files changed, 4557 insertions(+), 1473 deletions(-) create mode 100644 daemon/loop.c create mode 100644 daemon/main.c create mode 100644 daemon/tpool.c delete mode 100644 p11-kit/daemon.c create mode 100644 p11-kit/rpc-client-old.c create mode 100644 p11-kit/rpc-server.c create mode 100644 p11-kit/rpc-server.h diff --git a/common/compat.c b/common/compat.c index 0f7cb78..4af3eae 100644 --- a/common/compat.c +++ b/common/compat.c @@ -273,3 +273,58 @@ vwarnx (const char *fmt, } #endif /* HAVE_ERR_H */ + +#ifndef HAVE_DAEMON + +#include +#include +#include +#include +#include +#include + +int +daemon (int nochdir, + int noclose) +{ + struct sigaction osa, sa; + int oerrno, fd, osa_ok; + pid_t newgrp; + + /* A SIGHUP may be thrown when the parent exits below. */ + sigemptyset (&sa.sa_mask); + sa.sa_handler = SIG_IGN; + sa.sa_flags = 0; + osa_ok = sigaction (SIGHUP, &sa, &osa); + + switch (fork ()) { + case -1: + return -1; + case 0: + break; + default: + _exit (0); + } + + newgrp = setsid (); + oerrno = errno; + if (osa_ok != -1) + sigaction (SIGHUP, &osa, NULL); + if (newgrp == -1) { + errno = oerrno; + return -1; + } + if (!nochdir) + chdir ("/"); + if (!noclose && (fd = open ("/dev/null", O_RDWR, 0)) != -1) { + dup2 (fd, STDIN_FILENO); + dup2 (fd, STDOUT_FILENO); + dup2 (fd, STDERR_FILENO); + if (fd > 2) + close (fd); + } + + return 0; +} + +#endif /* HAVE_DAEMON */ diff --git a/common/compat.h b/common/compat.h index 8b3ac21..1af5832 100644 --- a/common/compat.h +++ b/common/compat.h @@ -53,6 +53,10 @@ const char * getprogname (void); #endif +#ifndef HAVE_DAEMON +int daemon (int nochdir, int noclose); +#endif + #ifdef HAVE_ERR_H #include diff --git a/daemon/loop.c b/daemon/loop.c new file mode 100644 index 0000000..7a3bc49 --- /dev/null +++ b/daemon/loop.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2005 Stefan Walter + * Copyright (c) 2011 Collabora Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * CONTRIBUTORS + * Stef Walter + */ + +#include "config.h" + +typedef struct { + pthread_t *thread; + pthread_mutex_t mutex; + void *action; +} ThreadData + +void * +thread_routine (void *arg) +{ + ThreadData *data = arg; + + pthread_mutex_lock (&data->mutex); + + while (data->) + pthread_mutex_ + + pthread_mutex_unlock (&data->mutex); +} + +pop_or_create_thread () +{ + +} + +typedef struct { + int fd; + +} LoopSocket; + +typedef struct { + poll + hash_map +} LoopContext; + +static struct pollfd * +add_poll (struct pollfd **polls, + int *n_polls, + int fd, + short events) +{ + struct pollfd *poll; + int index; + + (*n_polls)++; + *polls = xrealloc (*polls, sizeof (struct pollfd) * (*n_polls)); + if (*polls == NULL) + return NULL; + poll = *polls + (*n_polls - 1); + memset (poll, 0, sizeof (struct pollfd)); + poll->fd = fd; + poll->events = events; + return poll; +} + +typedef struct { + struct pollfd *polls; + int n_polls; +} Loop; + +typedef void (* LoopIoFunc) (int fd, + int revents, + void *data); + +typedef struct { + int fd; + LoopIoFunc callback; + void *data; +} LoopIo; + +Loop * +_p11_loop_init (void) +{ + Loop *loop; + + loop = calloc (1, sizeof (Loop)); + if (loop == NULL) + return NULL; + + +} + +int +_p11_loop_add_fd (Loop *loop, + int fd, + int events, + LoopIoFunc func, + void *data) +{ + struct pollfd *polls; + LoopIo *io; + + polls = realloc (loop->polls, sizeof (struct pollfd) * loop->n_polls + 1); + if (polls == NULL) { + errno = ENOMEM; + return -1; + } + + loop->polls = polls; + io = calloc (1, sizeof (LoopIo)); + if (io == NULL) { + errno = ENOMEM; + return -1; + } + + io->callback = func; + io->fd = fd; + io->data = data; + + io->events = events; + memset (polls + loop->n_polls, 0, sizeof (struct pollfd)); + polls[loop->n_polls] + loop->polls = +} + +void +_p11_loop_run (Loop *loop) +{ + struct pollfd *polls; + int quit = 0; + int n_polls; + int ret; + + polls = calloc (2, sizeof (struct pollfd)); + if (polls == NULL) + fatal ("out of memory while adding polls"); + + /* The zero and first polls are special */ + polls[0].fd = master; + polls[1].fd = signal_pipe[0]; + polls[0].events = polls[1].events = POLLIN; + n_polls = 2; + + while (!quit) { + ret = poll (polls, n_polls, -1); + if (ret < 0) + fatal ("couldn't poll file descriptors: %s", strerror (errno)); + + for (i = 0; i < n_polls; i++) { + if (poll->revents != 0) + continue; + switch (i) { + case 0: + ret = accept (poll[i].fd, NULL, NULL); + if (ret < 0 && errno != EAGAIN) + fatal ("couldn't accept new connection: %s", strerror (errno)); + xxxxx; + break; + case 1: + ret = read (poll[i].fd, &sig, sizeof (sig)); + if (ret < 0 && errno != EAGAIN) + fatal ("couldn't read from signal fd: %s", strerror (errno)); + if (ret == sizeof (s) && sig != SIGHUP) + quit = 1; + break; + default: + + } + } + } + + +} diff --git a/daemon/main.c b/daemon/main.c new file mode 100644 index 0000000..8b5603a --- /dev/null +++ b/daemon/main.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2005 Stefan Walter + * Copyright (c) 2011 Collabora Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * CONTRIBUTORS + * Stef Walter + */ + +#include "config.h" + +static struct pollfd *poll_fds = NULL; +static int n_poll_fds = 0; + +static int signal_pipe[2] = { -1, -1 }; + +static int +nonblock_fd (int fd) +{ + int flags; + + if ((flags = fcntl (fd, F_GETFL)) < 0) + return -1; + if (!(flags & O_NONBLOCK)) { + flags |= O_NONBLOCK; + if (fcntl(fd, F_SETFL, flags) < 0) + return -1; + } + + return 0; +} + +static void +signal_handler (int sig) +{ + int save_errno = errno; + write (signal_pipe[1], &sig, sizeof (sig)); + errno = save_errno; +} + +static void +signal_setup (void) +{ + sigset_t ss; + struct sigaction sa; + + if (pipe (signal_pipe) < 0) + fatal ("couldn't signal create pipe: %s", strerror (errno)); + if (nonblock_fd (signal_pipe[0]) < 0 || nonblock_fd (signal_pipe[1])) + fatal ("couldn't change signal pipe to non-blocking: %s", strerror (errno)); + + if (sigemptyset (&ss) < 0 || + sigaddset (&ss, SIG_HUP) < 0 || + sigaddset (&ss, SIG_TERM) < 0 || + sigaddset (&ss, SIG_QUIT) < 0 || + sigprocmask (SIG_UNBLOCK, &ss, NULL) < 0) + fatal ("couldn't unblock signals: %s", strerror (errno)); + + memset (&sa, 0, sizeof(sa)); + sa.sa_handler = signal_handler; + sigemptyset (&sa.sa_mask); + sa.sa_flags = SA_RESTART; + + if (sigaction (SIG_HUP, &sa, NULL) < 0 || + sigaction (SIG_TERM, &sa, NULL) < 0 || + sigaction (SIG_QUIT, &sa, NULL) < 0) + fatal ("couldn't install signal handlers: %s", strerror (errno)); +} + +int +main (int argc, + char *argv[]) +{ + Setup logging. + + signal_setup (); + + if (daemonize && daemon(0, 0) == -1) { + fatal ("couldn't run httpauth as daemon: %s", strerror (errno)); + return 1; + } + + + Start the main loop. +} diff --git a/daemon/tpool.c b/daemon/tpool.c new file mode 100644 index 0000000..b0fb9ae --- /dev/null +++ b/daemon/tpool.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2005 Stefan Walter + * Copyright (c) 2011 Collabora Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * CONTRIBUTORS + * Stef Walter + */ + +#include "config.h" + +typedef void (* TpoolFunc) (void *data); + +typedef struct _TpoolTask { + TpoolFunc func; + void *data; + struct _TpoolTask *next; +} TpoolTask; + +static pthread_mutex_t pool_mutex; +static int threads_waiting = 0; +static int threads_idle = 0; +static TpoolTask *tasks_waiting = NULL; + +int +tpool_init (int fd) +{ + int ret; + + ret = pthread_mutex_init (&pool_mutex, NULL); + if (ret != 0) { + errno = ret; + return -1; + } + + xxxxxxx; +} + +static int +tpool_run (xxx) +{ + pthread_mutex_lock (&pool_mutex); + + pthread_mutex_unlock (&pool_mutex); +} diff --git a/p11-kit/Makefile.am b/p11-kit/Makefile.am index 3471648..ffb2ebd 100644 --- a/p11-kit/Makefile.am +++ b/p11-kit/Makefile.am @@ -28,6 +28,7 @@ MODULE_SRCS = \ rpc-client.c rpc-client.h \ rpc-mechanism.c rpc-mechanism.h \ rpc-message.c rpc-message.h \ + rpc-server.c rpc-server.h \ rpc-socket.c rpc-socket.h \ unix-credentials.c unix-credentials.h \ uri.c \ diff --git a/p11-kit/daemon.c b/p11-kit/daemon.c deleted file mode 100644 index 882924e..0000000 --- a/p11-kit/daemon.c +++ /dev/null @@ -1,1405 +0,0 @@ -/* - * Copyright (C) 2008 Stefan Walter - * Copyright (C) 2011 Collabora Ltd. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * * Redistributions in binary form must reproduce the - * above copyright notice, this list of conditions and - * the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * * The names of contributors to this software may not be - * used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * Author: Stef Walter - */ - -#include "config.h" - -#define DEBUG_FLAG DEBUG_PROXY -#include "debug.h" -#include "hashmap.h" -#define CRYPTOKI_EXPORTS -#include "pkcs11.h" -#include "p11-kit.h" -#include "private.h" -#include "util.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -/* Start wrap slots slightly higher for testing */ -#define MAPPING_OFFSET 0x10 -#define FIRST_HANDLE 0x10 - -typedef struct _Mapping { - CK_SLOT_ID wrap_slot; - CK_SLOT_ID real_slot; - CK_FUNCTION_LIST_PTR funcs; -} Mapping; - -typedef struct _Session { - CK_SESSION_HANDLE wrap_session; - CK_SESSION_HANDLE real_session; - CK_SLOT_ID wrap_slot; -} Session; - -/* Forward declaration */ -static CK_FUNCTION_LIST proxy_function_list; - -/* - * Shared data between threads, protected by the mutex, a structure so - * we can audit thread safety easier. - */ -static struct _Shared { - Mapping *mappings; - unsigned int n_mappings; - int mappings_refs; - hashmap *sessions; - CK_ULONG last_handle; -} gl = { NULL, 0, 0, NULL, FIRST_HANDLE }; - -#define MANUFACTURER_ID "PKCS#11 Kit " -#define LIBRARY_DESCRIPTION "PKCS#11 Kit Proxy Module " -#define LIBRARY_VERSION_MAJOR 1 -#define LIBRARY_VERSION_MINOR 1 - -/* ----------------------------------------------------------------------------- - * PKCS#11 PROXY MODULE - */ - -static CK_RV -map_slot_unlocked (CK_SLOT_ID slot, Mapping *mapping) -{ - assert (mapping); - - if (slot < MAPPING_OFFSET) - return CKR_SLOT_ID_INVALID; - slot -= MAPPING_OFFSET; - - if (slot > gl.n_mappings) { - return CKR_SLOT_ID_INVALID; - } else { - assert (gl.mappings); - memcpy (mapping, &gl.mappings[slot], sizeof (Mapping)); - return CKR_OK; - } -} - -static CK_RV -map_slot_to_real (CK_SLOT_ID_PTR slot, Mapping *mapping) -{ - CK_RV rv; - - assert (mapping); - - _p11_lock (); - - if (!gl.mappings) - rv = CKR_CRYPTOKI_NOT_INITIALIZED; - else - rv = map_slot_unlocked (*slot, mapping); - if (rv == CKR_OK) - *slot = mapping->real_slot; - - _p11_unlock (); - - return rv; -} - -static CK_RV -map_session_to_real (CK_SESSION_HANDLE_PTR handle, Mapping *mapping, Session *session) -{ - CK_RV rv = CKR_OK; - Session *sess; - - assert (handle); - assert (mapping); - - _p11_lock (); - - if (!gl.sessions) { - rv = CKR_CRYPTOKI_NOT_INITIALIZED; - } else { - assert (gl.sessions); - sess = _p11_hash_get (gl.sessions, handle); - if (sess != NULL) { - *handle = sess->real_session; - rv = map_slot_unlocked (sess->wrap_slot, mapping); - if (session != NULL) - memcpy (session, sess, sizeof (Session)); - } else { - rv = CKR_SESSION_HANDLE_INVALID; - } - } - - _p11_unlock (); - - return rv; -} - -static void -finalize_mappings_unlocked (void) -{ - assert (gl.mappings_refs); - - if (--gl.mappings_refs) - return; - - /* No more mappings */ - free (gl.mappings); - gl.mappings = NULL; - gl.n_mappings = 0; - - /* no more sessions */ - _p11_hash_free (gl.sessions); - gl.sessions = NULL; -} - -void -_p11_kit_proxy_after_fork (void) -{ - /* - * After a fork the callers are supposed to call C_Initialize and all. - * In addition the underlying libraries may change their state so free - * up any mappings and all - */ - - _p11_lock (); - - gl.mappings_refs = 1; - finalize_mappings_unlocked (); - assert (!gl.mappings); - - _p11_unlock (); -} - -static CK_RV -proxy_C_Finalize (CK_VOID_PTR reserved) -{ - CK_RV rv; - - _p11_debug ("in"); - - /* WARNING: This function must be reentrant */ - - if (reserved) { - rv = CKR_ARGUMENTS_BAD; - - } else { - _p11_lock (); - - /* WARNING: Reentrancy can occur here */ - rv = _p11_kit_finalize_registered_unlocked_reentrant (); - - /* - * If modules are all gone, then this was the last - * finalize, so cleanup our mappings - */ - if (gl.mappings_refs) - finalize_mappings_unlocked (); - - _p11_unlock (); - } - - _p11_debug ("out: %lu", rv); - return rv; -} - -static CK_RV -initialize_mappings_unlocked_reentrant (void) -{ - CK_FUNCTION_LIST_PTR *funcss, *f; - CK_FUNCTION_LIST_PTR funcs; - Mapping *mappings = NULL; - int n_mappings = 0; - CK_SLOT_ID_PTR slots; - CK_ULONG i, count; - CK_RV rv = CKR_OK; - - assert (!gl.mappings); - - funcss = _p11_kit_registered_modules_unlocked (); - for (f = funcss; *f; ++f) { - funcs = *f; - - assert (funcs); - slots = NULL; - - _p11_unlock (); - - /* Ask module for its slots */ - rv = (funcs->C_GetSlotList) (FALSE, NULL, &count); - if (rv == CKR_OK && count) { - slots = calloc (sizeof (CK_SLOT_ID), count); - if (!slots) - rv = CKR_HOST_MEMORY; - else - rv = (funcs->C_GetSlotList) (FALSE, slots, &count); - } - - _p11_lock (); - - if (rv != CKR_OK) { - free (slots); - break; - } - - mappings = _p11_realloc (mappings, sizeof (Mapping) * (n_mappings + count)); - if (!mappings) { - free (slots); - rv = CKR_HOST_MEMORY; - break; - } - - /* And now add a mapping for each of those slots */ - for (i = 0; i < count; ++i) { - mappings[n_mappings].funcs = funcs; - mappings[n_mappings].wrap_slot = n_mappings + MAPPING_OFFSET; - mappings[n_mappings].real_slot = slots[i]; - ++n_mappings; - } - - free (slots); - } - - /* Another thread raced us here due to above reentrancy */ - if (gl.mappings) { - free (mappings); - return CKR_OK; - } - - assert (!gl.sessions); - gl.mappings = mappings; - gl.n_mappings = n_mappings; - gl.sessions = _p11_hash_create (_p11_hash_ulongptr_hash, _p11_hash_ulongptr_equal, NULL, free); - ++gl.mappings_refs; - - /* Any cleanup necessary for failure will happen at caller */ - return rv; -} - -static CK_RV -proxy_C_Initialize (CK_VOID_PTR init_args) -{ - CK_RV rv; - - _p11_library_init_once (); - - /* WARNING: This function must be reentrant */ - - _p11_debug ("in"); - - _p11_lock (); - - /* WARNING: Reentrancy can occur here */ - rv = _p11_kit_initialize_registered_unlocked_reentrant (); - - /* WARNING: Reentrancy can occur here */ - if (rv == CKR_OK && gl.mappings_refs == 0) - rv = initialize_mappings_unlocked_reentrant (); - - _p11_unlock (); - - _p11_debug ("here"); - - if (rv != CKR_OK) - proxy_C_Finalize (NULL); - - _p11_debug ("out: %lu", rv); - return rv; -} - -static CK_RV -proxy_C_GetInfo (CK_INFO_PTR info) -{ - CK_RV rv = CKR_OK; - - _p11_library_init_once (); - - if (info == NULL) - return CKR_ARGUMENTS_BAD; - - _p11_lock (); - - if (!gl.mappings) - rv = CKR_CRYPTOKI_NOT_INITIALIZED; - - _p11_unlock (); - - if (rv != CKR_OK) - return rv; - - info->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR; - info->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR; - info->libraryVersion.major = LIBRARY_VERSION_MAJOR; - info->libraryVersion.minor = LIBRARY_VERSION_MINOR; - info->flags = 0; - strncpy ((char*)info->manufacturerID, MANUFACTURER_ID, 32); - strncpy ((char*)info->libraryDescription, LIBRARY_DESCRIPTION, 32); - return CKR_OK; -} - -static CK_RV -proxy_C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list) -{ - /* Can be called before C_Initialize */ - - if (!list) - return CKR_ARGUMENTS_BAD; - *list = &proxy_function_list; - return CKR_OK; -} - -static CK_RV -proxy_C_GetSlotList (CK_BBOOL token_present, CK_SLOT_ID_PTR slot_list, - CK_ULONG_PTR count) -{ - CK_SLOT_INFO info; - Mapping *mapping; - CK_ULONG index; - CK_RV rv = CKR_OK; - int i; - - if (!count) - return CKR_ARGUMENTS_BAD; - - _p11_lock (); - - if (!gl.mappings) { - rv = CKR_CRYPTOKI_NOT_INITIALIZED; - } else { - index = 0; - - /* Go through and build up a map */ - for (i = 0; i < gl.n_mappings; ++i) { - mapping = &gl.mappings[i]; - - /* Skip ones without a token if requested */ - if (token_present) { - rv = (mapping->funcs->C_GetSlotInfo) (mapping->real_slot, &info); - if (rv != CKR_OK) - break; - if (!(info.flags & CKF_TOKEN_PRESENT)) - continue; - } - - /* Fill in the slot if we can */ - if (slot_list && *count > index) - slot_list[index] = mapping->wrap_slot; - - ++index; - } - - if (slot_list && *count < index) - rv = CKR_BUFFER_TOO_SMALL; - - *count = index; - } - - _p11_unlock (); - - return rv; -} - -static CK_RV -proxy_C_GetSlotInfo (CK_SLOT_ID id, CK_SLOT_INFO_PTR info) -{ - Mapping map; - CK_RV rv; - - rv = map_slot_to_real (&id, &map); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_GetSlotInfo) (id, info); -} - -static CK_RV -proxy_C_GetTokenInfo (CK_SLOT_ID id, CK_TOKEN_INFO_PTR info) -{ - Mapping map; - CK_RV rv; - - rv = map_slot_to_real (&id, &map); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_GetTokenInfo) (id, info); -} - -static CK_RV -proxy_C_GetMechanismList (CK_SLOT_ID id, CK_MECHANISM_TYPE_PTR mechanism_list, - CK_ULONG_PTR count) -{ - Mapping map; - CK_RV rv; - - rv = map_slot_to_real (&id, &map); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_GetMechanismList) (id, mechanism_list, count); -} - -static CK_RV -proxy_C_GetMechanismInfo (CK_SLOT_ID id, CK_MECHANISM_TYPE type, - CK_MECHANISM_INFO_PTR info) -{ - Mapping map; - CK_RV rv; - - rv = map_slot_to_real (&id, &map); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_GetMechanismInfo) (id, type, info); -} - -static CK_RV -proxy_C_InitToken (CK_SLOT_ID id, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len, CK_UTF8CHAR_PTR label) -{ - Mapping map; - CK_RV rv; - - rv = map_slot_to_real (&id, &map); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_InitToken) (id, pin, pin_len, label); -} - -static CK_RV -proxy_C_WaitForSlotEvent (CK_FLAGS flags, CK_SLOT_ID_PTR slot, CK_VOID_PTR reserved) -{ - return CKR_FUNCTION_NOT_SUPPORTED; -} - -static CK_RV -proxy_C_OpenSession (CK_SLOT_ID id, CK_FLAGS flags, CK_VOID_PTR user_data, - CK_NOTIFY callback, CK_SESSION_HANDLE_PTR handle) -{ - Session *sess; - Mapping map; - CK_RV rv; - - if (handle == NULL) - return CKR_ARGUMENTS_BAD; - - rv = map_slot_to_real (&id, &map); - if (rv != CKR_OK) - return rv; - - rv = (map.funcs->C_OpenSession) (id, flags, user_data, callback, handle); - - if (rv == CKR_OK) { - _p11_lock (); - - if (!gl.sessions) { - /* - * The underlying module should have returned an error, so this - * code should never be reached with properly behaving modules. - * That's why we don't cleanup and close the newly opened session here - * or anything like that. - */ - rv = CKR_CRYPTOKI_NOT_INITIALIZED; - - } else { - sess = calloc (1, sizeof (Session)); - sess->wrap_slot = map.wrap_slot; - sess->real_session = *handle; - sess->wrap_session = ++gl.last_handle; /* TODO: Handle wrapping, and then collisions */ - _p11_hash_set (gl.sessions, &sess->wrap_session, sess); - *handle = sess->wrap_session; - } - - _p11_unlock (); - } - - return rv; -} - -static CK_RV -proxy_C_CloseSession (CK_SESSION_HANDLE handle) -{ - CK_SESSION_HANDLE key; - Mapping map; - CK_RV rv; - - key = handle; - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - rv = (map.funcs->C_CloseSession) (handle); - - if (rv == CKR_OK) { - _p11_lock (); - - if (gl.sessions) - _p11_hash_remove (gl.sessions, &key); - - _p11_unlock (); - } - - return rv; -} - -static CK_RV -proxy_C_CloseAllSessions (CK_SLOT_ID id) -{ - CK_SESSION_HANDLE_PTR to_close; - CK_RV rv = CKR_OK; - Session *sess; - CK_ULONG i, count = 0; - hashiter iter; - - _p11_lock (); - - if (!gl.sessions) { - rv = CKR_CRYPTOKI_NOT_INITIALIZED; - } else { - to_close = calloc (sizeof (CK_SESSION_HANDLE), _p11_hash_size (gl.sessions)); - if (!to_close) { - rv = CKR_HOST_MEMORY; - } else { - _p11_hash_iterate (gl.sessions, &iter); - count = 0; - while (_p11_hash_next (&iter, NULL, (void**)&sess)) { - if (sess->wrap_slot == id && to_close) - to_close[count++] = sess->wrap_session; - } - } - } - - _p11_unlock (); - - if (rv != CKR_OK) - return rv; - - for (i = 0; i < count; ++i) - proxy_C_CloseSession (to_close[i]); - - free (to_close); - return CKR_OK; -} - -static CK_RV -proxy_C_GetFunctionStatus (CK_SESSION_HANDLE handle) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_GetFunctionStatus) (handle); -} - -static CK_RV -proxy_C_CancelFunction (CK_SESSION_HANDLE handle) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_CancelFunction) (handle); -} - -static CK_RV -proxy_C_GetSessionInfo (CK_SESSION_HANDLE handle, CK_SESSION_INFO_PTR info) -{ - Mapping map; - CK_RV rv; - - if (info == NULL) - return CKR_ARGUMENTS_BAD; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - - rv = (map.funcs->C_GetSessionInfo) (handle, info); - if (rv == CKR_OK) - info->slotID = map.wrap_slot; - - return rv; -} - -static CK_RV -proxy_C_InitPIN (CK_SESSION_HANDLE handle, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - - return (map.funcs->C_InitPIN) (handle, pin, pin_len); -} - -static CK_RV -proxy_C_SetPIN (CK_SESSION_HANDLE handle, CK_UTF8CHAR_PTR old_pin, CK_ULONG old_pin_len, - CK_UTF8CHAR_PTR new_pin, CK_ULONG new_pin_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - - return (map.funcs->C_SetPIN) (handle, old_pin, old_pin_len, new_pin, new_pin_len); -} - -static CK_RV -proxy_C_GetOperationState (CK_SESSION_HANDLE handle, CK_BYTE_PTR operation_state, CK_ULONG_PTR operation_state_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_GetOperationState) (handle, operation_state, operation_state_len); -} - -static CK_RV -proxy_C_SetOperationState (CK_SESSION_HANDLE handle, CK_BYTE_PTR operation_state, - CK_ULONG operation_state_len, CK_OBJECT_HANDLE encryption_key, - CK_OBJECT_HANDLE authentication_key) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_SetOperationState) (handle, operation_state, operation_state_len, encryption_key, authentication_key); -} - -static CK_RV -proxy_C_Login (CK_SESSION_HANDLE handle, CK_USER_TYPE user_type, - CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - - return (map.funcs->C_Login) (handle, user_type, pin, pin_len); -} - -static CK_RV -proxy_C_Logout (CK_SESSION_HANDLE handle) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_Logout) (handle); -} - -static CK_RV -proxy_C_CreateObject (CK_SESSION_HANDLE handle, CK_ATTRIBUTE_PTR template, - CK_ULONG count, CK_OBJECT_HANDLE_PTR new_object) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - - return (map.funcs->C_CreateObject) (handle, template, count, new_object); -} - -static CK_RV -proxy_C_CopyObject (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object, - CK_ATTRIBUTE_PTR template, CK_ULONG count, - CK_OBJECT_HANDLE_PTR new_object) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_CopyObject) (handle, object, template, count, new_object); -} - -static CK_RV -proxy_C_DestroyObject (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_DestroyObject) (handle, object); -} - -static CK_RV -proxy_C_GetObjectSize (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object, - CK_ULONG_PTR size) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_GetObjectSize) (handle, object, size); -} - -static CK_RV -proxy_C_GetAttributeValue (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object, - CK_ATTRIBUTE_PTR template, CK_ULONG count) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_GetAttributeValue) (handle, object, template, count); -} - -static CK_RV -proxy_C_SetAttributeValue (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE object, - CK_ATTRIBUTE_PTR template, CK_ULONG count) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_SetAttributeValue) (handle, object, template, count); -} - -static CK_RV -proxy_C_FindObjectsInit (CK_SESSION_HANDLE handle, CK_ATTRIBUTE_PTR template, - CK_ULONG count) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_FindObjectsInit) (handle, template, count); -} - -static CK_RV -proxy_C_FindObjects (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE_PTR objects, - CK_ULONG max_count, CK_ULONG_PTR count) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_FindObjects) (handle, objects, max_count, count); -} - -static CK_RV -proxy_C_FindObjectsFinal (CK_SESSION_HANDLE handle) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_FindObjectsFinal) (handle); -} - -static CK_RV -proxy_C_EncryptInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_EncryptInit) (handle, mechanism, key); -} - -static CK_RV -proxy_C_Encrypt (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR encrypted_data, CK_ULONG_PTR encrypted_data_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_Encrypt) (handle, data, data_len, encrypted_data, encrypted_data_len); -} - -static CK_RV -proxy_C_EncryptUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part, - CK_ULONG part_len, CK_BYTE_PTR encrypted_part, - CK_ULONG_PTR encrypted_part_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_EncryptUpdate) (handle, part, part_len, encrypted_part, encrypted_part_len); -} - -static CK_RV -proxy_C_EncryptFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR last_part, - CK_ULONG_PTR last_part_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_EncryptFinal) (handle, last_part, last_part_len); -} - -static CK_RV -proxy_C_DecryptInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_DecryptInit) (handle, mechanism, key); -} - -static CK_RV -proxy_C_Decrypt (CK_SESSION_HANDLE handle, CK_BYTE_PTR enc_data, - CK_ULONG enc_data_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_Decrypt) (handle, enc_data, enc_data_len, data, data_len); -} - -static CK_RV -proxy_C_DecryptUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR enc_part, - CK_ULONG enc_part_len, CK_BYTE_PTR part, CK_ULONG_PTR part_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_DecryptUpdate) (handle, enc_part, enc_part_len, part, part_len); -} - -static CK_RV -proxy_C_DecryptFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR last_part, - CK_ULONG_PTR last_part_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_DecryptFinal) (handle, last_part, last_part_len); -} - -static CK_RV -proxy_C_DigestInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_DigestInit) (handle, mechanism); -} - -static CK_RV -proxy_C_Digest (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR digest, CK_ULONG_PTR digest_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_Digest) (handle, data, data_len, digest, digest_len); -} - -static CK_RV -proxy_C_DigestUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part, CK_ULONG part_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_DigestUpdate) (handle, part, part_len); -} - -static CK_RV -proxy_C_DigestKey (CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE key) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_DigestKey) (handle, key); -} - -static CK_RV -proxy_C_DigestFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR digest, - CK_ULONG_PTR digest_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_DigestFinal) (handle, digest, digest_len); -} - -static CK_RV -proxy_C_SignInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_SignInit) (handle, mechanism, key); -} - -static CK_RV -proxy_C_Sign (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR signature, CK_ULONG_PTR signature_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_Sign) (handle, data, data_len, signature, signature_len); -} - -static CK_RV -proxy_C_SignUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part, CK_ULONG part_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_SignUpdate) (handle, part, part_len); -} - -static CK_RV -proxy_C_SignFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR signature, - CK_ULONG_PTR signature_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_SignFinal) (handle, signature, signature_len); -} - -static CK_RV -proxy_C_SignRecoverInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_SignRecoverInit) (handle, mechanism, key); -} - -static CK_RV -proxy_C_SignRecover (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR signature, CK_ULONG_PTR signature_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_SignRecover) (handle, data, data_len, signature, signature_len); -} - -static CK_RV -proxy_C_VerifyInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_VerifyInit) (handle, mechanism, key); -} - -static CK_RV -proxy_C_Verify (CK_SESSION_HANDLE handle, CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR signature, CK_ULONG signature_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_Verify) (handle, data, data_len, signature, signature_len); -} - -static CK_RV -proxy_C_VerifyUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part, CK_ULONG part_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_VerifyUpdate) (handle, part, part_len); -} - -static CK_RV -proxy_C_VerifyFinal (CK_SESSION_HANDLE handle, CK_BYTE_PTR signature, - CK_ULONG signature_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_VerifyFinal) (handle, signature, signature_len); -} - -static CK_RV -proxy_C_VerifyRecoverInit (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_VerifyRecoverInit) (handle, mechanism, key); -} - -static CK_RV -proxy_C_VerifyRecover (CK_SESSION_HANDLE handle, CK_BYTE_PTR signature, - CK_ULONG signature_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_VerifyRecover) (handle, signature, signature_len, data, data_len); -} - -static CK_RV -proxy_C_DigestEncryptUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part, - CK_ULONG part_len, CK_BYTE_PTR enc_part, - CK_ULONG_PTR enc_part_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_DigestEncryptUpdate) (handle, part, part_len, enc_part, enc_part_len); -} - -static CK_RV -proxy_C_DecryptDigestUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR enc_part, - CK_ULONG enc_part_len, CK_BYTE_PTR part, - CK_ULONG_PTR part_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_DecryptDigestUpdate) (handle, enc_part, enc_part_len, part, part_len); -} - -static CK_RV -proxy_C_SignEncryptUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR part, - CK_ULONG part_len, CK_BYTE_PTR enc_part, - CK_ULONG_PTR enc_part_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_SignEncryptUpdate) (handle, part, part_len, enc_part, enc_part_len); -} - -static CK_RV -proxy_C_DecryptVerifyUpdate (CK_SESSION_HANDLE handle, CK_BYTE_PTR enc_part, - CK_ULONG enc_part_len, CK_BYTE_PTR part, - CK_ULONG_PTR part_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_DecryptVerifyUpdate) (handle, enc_part, enc_part_len, part, part_len); -} - -static CK_RV -proxy_C_GenerateKey (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism, - CK_ATTRIBUTE_PTR template, CK_ULONG count, - CK_OBJECT_HANDLE_PTR key) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_GenerateKey) (handle, mechanism, template, count, key); -} - -static CK_RV -proxy_C_GenerateKeyPair (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism, - CK_ATTRIBUTE_PTR pub_template, CK_ULONG pub_count, - CK_ATTRIBUTE_PTR priv_template, CK_ULONG priv_count, - CK_OBJECT_HANDLE_PTR pub_key, CK_OBJECT_HANDLE_PTR priv_key) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_GenerateKeyPair) (handle, mechanism, pub_template, pub_count, priv_template, priv_count, pub_key, priv_key); -} - -static CK_RV -proxy_C_WrapKey (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, - CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_WrapKey) (handle, mechanism, wrapping_key, key, wrapped_key, wrapped_key_len); -} - -static CK_RV -proxy_C_UnwrapKey (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key, - CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR template, - CK_ULONG count, CK_OBJECT_HANDLE_PTR key) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_UnwrapKey) (handle, mechanism, unwrapping_key, wrapped_key, wrapped_key_len, template, count, key); -} - -static CK_RV -proxy_C_DeriveKey (CK_SESSION_HANDLE handle, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE_PTR template, - CK_ULONG count, CK_OBJECT_HANDLE_PTR key) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_DeriveKey) (handle, mechanism, base_key, template, count, key); -} - -static CK_RV -proxy_C_SeedRandom (CK_SESSION_HANDLE handle, CK_BYTE_PTR seed, CK_ULONG seed_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_SeedRandom) (handle, seed, seed_len); -} - -static CK_RV -proxy_C_GenerateRandom (CK_SESSION_HANDLE handle, CK_BYTE_PTR random_data, - CK_ULONG random_len) -{ - Mapping map; - CK_RV rv; - - rv = map_session_to_real (&handle, &map, NULL); - if (rv != CKR_OK) - return rv; - return (map.funcs->C_GenerateRandom) (handle, random_data, random_len); -} - -/* -------------------------------------------------------------------- - * MODULE ENTRY POINT - */ - -static CK_FUNCTION_LIST proxy_function_list = { - { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR }, /* version */ - proxy_C_Initialize, - proxy_C_Finalize, - proxy_C_GetInfo, - proxy_C_GetFunctionList, - proxy_C_GetSlotList, - proxy_C_GetSlotInfo, - proxy_C_GetTokenInfo, - proxy_C_GetMechanismList, - proxy_C_GetMechanismInfo, - proxy_C_InitToken, - proxy_C_InitPIN, - proxy_C_SetPIN, - proxy_C_OpenSession, - proxy_C_CloseSession, - proxy_C_CloseAllSessions, - proxy_C_GetSessionInfo, - proxy_C_GetOperationState, - proxy_C_SetOperationState, - proxy_C_Login, - proxy_C_Logout, - proxy_C_CreateObject, - proxy_C_CopyObject, - proxy_C_DestroyObject, - proxy_C_GetObjectSize, - proxy_C_GetAttributeValue, - proxy_C_SetAttributeValue, - proxy_C_FindObjectsInit, - proxy_C_FindObjects, - proxy_C_FindObjectsFinal, - proxy_C_EncryptInit, - proxy_C_Encrypt, - proxy_C_EncryptUpdate, - proxy_C_EncryptFinal, - proxy_C_DecryptInit, - proxy_C_Decrypt, - proxy_C_DecryptUpdate, - proxy_C_DecryptFinal, - proxy_C_DigestInit, - proxy_C_Digest, - proxy_C_DigestUpdate, - proxy_C_DigestKey, - proxy_C_DigestFinal, - proxy_C_SignInit, - proxy_C_Sign, - proxy_C_SignUpdate, - proxy_C_SignFinal, - proxy_C_SignRecoverInit, - proxy_C_SignRecover, - proxy_C_VerifyInit, - proxy_C_Verify, - proxy_C_VerifyUpdate, - proxy_C_VerifyFinal, - proxy_C_VerifyRecoverInit, - proxy_C_VerifyRecover, - proxy_C_DigestEncryptUpdate, - proxy_C_DecryptDigestUpdate, - proxy_C_SignEncryptUpdate, - proxy_C_DecryptVerifyUpdate, - proxy_C_GenerateKey, - proxy_C_GenerateKeyPair, - proxy_C_WrapKey, - proxy_C_UnwrapKey, - proxy_C_DeriveKey, - proxy_C_SeedRandom, - proxy_C_GenerateRandom, - proxy_C_GetFunctionStatus, - proxy_C_CancelFunction, - proxy_C_WaitForSlotEvent -}; - -#ifdef OS_WIN32 -__declspec(dllexport) -#endif - -CK_RV -C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list) -{ - _p11_library_init_once (); - return proxy_C_GetFunctionList (list); -} diff --git a/p11-kit/rpc-client-old.c b/p11-kit/rpc-client-old.c new file mode 100644 index 0000000..48468c3 --- /dev/null +++ b/p11-kit/rpc-client-old.c @@ -0,0 +1,2067 @@ + if (!_p11_rpc_socket_is_open (module->socket)) + return CKR_DEVICE_REMOVED; + + _p11_rpc_socket_ref (module->socket); + +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* client.c - a PKCS#11 module which communicates with another process + + Copyright (C) 2012 Red Hat Inc. + + The Gnome Keyring Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Keyring Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Stef Walter +*/ + +#include "config.h" + +#define DEBUG_FLAG DEBUG_RPC +#include "debug.h" +#include "pkcs11.h" +#include "private.h" +#include "rpc-client.h" +#include "rpc-mechanism.h" +#include "rpc-message.h" +#include "rpc-socket.h" +#include "unix-credentials.h" + +#include +#include +#include + +/* The error used by us when parsing of rpc message fails */ +#define PARSE_ERROR CKR_DEVICE_ERROR + +#define return_val_if_fail(x, v) \ + if (!(x)) { _p11_message ("'%s' not true at %s", #x, __func__); return v; } + +typedef struct { + int check; + CK_FUNCTION_LIST_PTR function_list; + pthread_mutex_t mutex; + const RpcClientVtable *vtable; + RpcSocket *socket; + pid_t initialized_pid; +} RpcModule; + +#define RPC_MODULE_INIT(id, function_list) \ + { id, (CK_FUNCTION_LIST_PTR)function_list, PTHREAD_MUTEX_INITIALIZER, NULL, 0 } + +/* Allocator for call session buffers */ +static void* +call_allocator (void *pointer, + size_t size) +{ + void *result = realloc (pointer, (size_t)size); + if (!result && size) + _p11_message ("memory allocation of %lu bytes failed", size); + return result; +} + +static CK_RV +call_prepare (RpcModule *module, + RpcMessage *msg, + int call_id) +{ + assert (module != NULL); + assert (msg != NULL); + + if (!module->socket) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + if (!_p11_rpc_socket_is_open (module->socket)) + return CKR_DEVICE_REMOVED; + + _p11_rpc_socket_ref (module->socket); + _p11_rpc_message_init (msg, call_allocator); + + /* Put in the Call ID and signature */ + if (!_p11_rpc_message_prep (msg, call_id, RPC_REQUEST)) + return CKR_HOST_MEMORY; + + _p11_debug ("prepared call: %d", call_id); + return CKR_OK; +} + +static CK_RV +call_run (RpcModule *module, + RpcMessage *msg) +{ + CK_RV ret = CKR_OK; + CK_ULONG ckerr; + int call_id; + + assert (module != NULL); + assert (msg != NULL); + + /* Did building the call fail? */ + if (_p11_rpc_message_buffer_error (msg)) { + _p11_message ("couldn't allocate request area: out of memory"); + return CKR_HOST_MEMORY; + } + + /* Make sure that the signature is valid */ + assert (_p11_rpc_message_is_verified (msg)); + call_id = msg->call_id; + + /* Do the dialog with daemon */ + ret = _p11_rpc_socket_send_recv (module->socket, msg); + if (ret != CKR_OK) + return ret; + + /* If it's an error code then return it */ + if (msg->call_id == RPC_CALL_ERROR) { + if (!_p11_rpc_message_read_ulong (msg, &ckerr)) { + _p11_message ("invalid error response from gnome-keyring-daemon: too short"); + return CKR_DEVICE_ERROR; + } + + if (ckerr <= CKR_OK) { + _p11_message ("invalid error response from gnome-keyring-daemon: bad error code"); + return CKR_DEVICE_ERROR; + } + + /* An error code from the daemon */ + return (CK_RV)ckerr; + } + + /* Make sure daemon answered the right call */ + if (call_id != msg->call_id) { + _p11_message ("invalid response from gnome-keyring-daemon: call mismatch"); + return CKR_DEVICE_ERROR; + } + + assert (!_p11_rpc_message_buffer_error (msg)); + + _p11_debug ("parsing response values"); + return CKR_OK; +} + +static CK_RV +call_done (RpcModule *module, + RpcMessage *msg, + CK_RV ret) +{ + assert (module != NULL); + assert (msg != NULL); + + /* Check for parsing errors that were not caught elsewhere */ + if (ret == CKR_OK) { + if (_p11_rpc_message_buffer_error (msg)) { + _p11_message ("invalid response from gnome-keyring-daemon: bad argument data"); + ret = CKR_GENERAL_ERROR; + } else { + /* Double check that the signature matched our decoding */ + assert (_p11_rpc_message_is_verified (msg)); + } + } + + _p11_rpc_socket_unref (module->socket); + _p11_rpc_message_clear (msg); + return ret; +} + +/* ----------------------------------------------------------------------------- + * MODULE SPECIFIC PROTOCOL CODE + */ + +static CK_RV +proto_read_attribute_array (RpcMessage *msg, + CK_ATTRIBUTE_PTR arr, + CK_ULONG len) +{ + uint32_t i, num, value, type; + CK_ATTRIBUTE_PTR attr; + const unsigned char *attrval; + size_t attrlen; + unsigned char validity; + CK_RV ret; + + assert (len != 0); + assert (msg != NULL); + + /* Make sure this is in the right order */ + assert (!msg->signature || _p11_rpc_message_verify_part (msg, "aA")); + + /* Get the number of items. We need this value to be correct */ + if (!_p11_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &num)) + return PARSE_ERROR; + + /* + * This should never happen in normal operation. It denotes a goof up + * on the other side of our RPC. We should be indicating the exact number + * of attributes to the other side. And it should respond with the same + * number. + */ + if (len != num) { + _p11_message ("received an attribute array with wrong number of attributes"); + return PARSE_ERROR; + } + + ret = CKR_OK; + + /* We need to go ahead and read everything in all cases */ + for (i = 0; i < num; ++i) { + + /* The attribute type */ + _p11_buffer_get_uint32 (&msg->buffer, msg->parsed, + &msg->parsed, &type); + + /* Attribute validity */ + _p11_buffer_get_byte (&msg->buffer, msg->parsed, + &msg->parsed, &validity); + + /* And the data itself */ + if (validity) { + if (_p11_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &value) && + _p11_buffer_get_byte_array (&msg->buffer, msg->parsed, &msg->parsed, &attrval, &attrlen)) { + if (attrval && value != attrlen) { + _p11_message ("attribute length does not match attribute data"); + return PARSE_ERROR; + } + attrlen = value; + } + } + + /* Don't act on this data unless no errors */ + if (_p11_buffer_has_error (&msg->buffer)) + break; + + /* Try and stuff it in the output data */ + if (arr) { + attr = &(arr[i]); + if (attr->type != type) { + _p11_message ("returned attributes in invalid order"); + return PARSE_ERROR; + } + + if (validity) { + /* Just requesting the attribute size */ + if (!attr->pValue) { + attr->ulValueLen = attrlen; + + /* Wants attribute data, but too small */ + } else if (attr->ulValueLen < attrlen) { + attr->ulValueLen = attrlen; + ret = CKR_BUFFER_TOO_SMALL; + + /* Wants attribute data, value is null */ + } else if (attrval == NULL) { + attr->ulValueLen = 0; + + /* Wants attribute data, enough space */ + } else { + attr->ulValueLen = attrlen; + memcpy (attr->pValue, attrval, attrlen); + } + + /* Not a valid attribute */ + } else { + attr->ulValueLen = ((CK_ULONG)-1); + } + } + } + + if (_p11_buffer_has_error (&msg->buffer)) + return PARSE_ERROR; + + /* Read in the code that goes along with these attributes */ + if (!_p11_rpc_message_read_ulong (msg, &ret)) + return PARSE_ERROR; + + return ret; +} + +static CK_RV +proto_read_byte_array (RpcMessage *msg, + CK_BYTE_PTR arr, + CK_ULONG_PTR len, + CK_ULONG max) +{ + const unsigned char *val; + unsigned char valid; + uint32_t length; + size_t vlen; + + assert (len != NULL); + assert (msg != NULL); + + /* Make sure this is in the right order */ + assert (!msg->signature || _p11_rpc_message_verify_part (msg, "ay")); + + /* A single byte which determines whether valid or not */ + if (!_p11_buffer_get_byte (&msg->buffer, msg->parsed, &msg->parsed, &valid)) + return PARSE_ERROR; + + /* If not valid, then just the length is encoded, this can signify CKR_BUFFER_TOO_SMALL */ + if (!valid) { + if (!_p11_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &length)) + return PARSE_ERROR; + + *len = length; + + if (arr) + return CKR_BUFFER_TOO_SMALL; + else + return CKR_OK; + } + + /* Get the actual bytes */ + if (!_p11_buffer_get_byte_array (&msg->buffer, msg->parsed, &msg->parsed, &val, &vlen)) + return PARSE_ERROR; + + *len = vlen; + + /* Just asking us for size */ + if (!arr) + return CKR_OK; + + if (max < vlen) + return CKR_BUFFER_TOO_SMALL; + + /* Enough space, yay */ + memcpy (arr, val, vlen); + return CKR_OK; +} + +static CK_RV +proto_read_ulong_array (RpcMessage *msg, CK_ULONG_PTR arr, + CK_ULONG_PTR len, CK_ULONG max) +{ + uint32_t i, num; + uint64_t val; + unsigned char valid; + + assert (len != NULL); + assert (msg != NULL); + + /* Make sure this is in the right order */ + assert (!msg->signature || _p11_rpc_message_verify_part (msg, "au")); + + /* A single byte which determines whether valid or not */ + if (!_p11_buffer_get_byte (&msg->buffer, msg->parsed, &msg->parsed, &valid)) + return PARSE_ERROR; + + /* Get the number of items. */ + if (!_p11_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &num)) + return PARSE_ERROR; + + *len = num; + + /* If not valid, then just the length is encoded, this can signify CKR_BUFFER_TOO_SMALL */ + if (!valid) { + if (arr) + return CKR_BUFFER_TOO_SMALL; + else + return CKR_OK; + } + + if (max < num) + return CKR_BUFFER_TOO_SMALL; + + /* We need to go ahead and read everything in all cases */ + for (i = 0; i < num; ++i) { + _p11_buffer_get_uint64 (&msg->buffer, msg->parsed, &msg->parsed, &val); + if (arr) + arr[i] = (CK_ULONG)val; + } + + return _p11_buffer_has_error (&msg->buffer) ? PARSE_ERROR : CKR_OK; +} + +static CK_RV +proto_write_mechanism (RpcMessage *msg, + CK_MECHANISM_PTR mech) +{ + assert (msg != NULL); + assert (mech != NULL); + + /* Make sure this is in the right order */ + assert (!msg->signature || _p11_rpc_message_verify_part (msg, "M")); + + /* The mechanism type */ + _p11_buffer_add_uint32 (&msg->buffer, mech->mechanism); + + /* + * PKCS#11 mechanism parameters are not easy to serialize. They're + * completely different for so many mechanisms, they contain + * pointers to arbitrary memory, and many callers don't initialize + * them completely or properly. + * + * We only support certain mechanisms. + * + * Also callers do yucky things like leaving parts of the structure + * pointing to garbage if they don't think it's going to be used. + */ + + if (_p11_rpc_mechanism_has_no_parameters (mech->mechanism)) + _p11_buffer_add_byte_array (&msg->buffer, NULL, 0); + else if (_p11_rpc_mechanism_has_sane_parameters (mech->mechanism)) + _p11_buffer_add_byte_array (&msg->buffer, mech->pParameter, + mech->ulParameterLen); + else + return CKR_MECHANISM_INVALID; + + return _p11_buffer_has_error (&msg->buffer) ? CKR_HOST_MEMORY : CKR_OK; +} + +static CK_RV +proto_read_info (RpcMessage *msg, + CK_INFO_PTR info) +{ + assert (msg != NULL); + assert (info != NULL); + + if (!_p11_rpc_message_read_version (msg, &info->cryptokiVersion) || + !_p11_rpc_message_read_space_string (msg, info->manufacturerID, 32) || + !_p11_rpc_message_read_ulong (msg, &info->flags) || + !_p11_rpc_message_read_space_string (msg, info->libraryDescription, 32) || + !_p11_rpc_message_read_version (msg, &info->libraryVersion)) + return PARSE_ERROR; + + return CKR_OK; +} + +static CK_RV +proto_read_slot_info (RpcMessage *msg, + CK_SLOT_INFO_PTR info) +{ + assert (msg != NULL); + assert (info != NULL); + + if (!_p11_rpc_message_read_space_string (msg, info->slotDescription, 64) || + !_p11_rpc_message_read_space_string (msg, info->manufacturerID, 32) || + !_p11_rpc_message_read_ulong (msg, &info->flags) || + !_p11_rpc_message_read_version (msg, &info->hardwareVersion) || + !_p11_rpc_message_read_version (msg, &info->firmwareVersion)) + return PARSE_ERROR; + + return CKR_OK; +} + +static CK_RV +proto_read_token_info (RpcMessage *msg, + CK_TOKEN_INFO_PTR info) +{ + assert (msg != NULL); + assert (info != NULL); + + if (!_p11_rpc_message_read_space_string (msg, info->label, 32) || + !_p11_rpc_message_read_space_string (msg, info->manufacturerID, 32) || + !_p11_rpc_message_read_space_string (msg, info->model, 16) || + !_p11_rpc_message_read_space_string (msg, info->serialNumber, 16) || + !_p11_rpc_message_read_ulong (msg, &info->flags) || + !_p11_rpc_message_read_ulong (msg, &info->ulMaxSessionCount) || + !_p11_rpc_message_read_ulong (msg, &info->ulSessionCount) || + !_p11_rpc_message_read_ulong (msg, &info->ulMaxRwSessionCount) || + !_p11_rpc_message_read_ulong (msg, &info->ulRwSessionCount) || + !_p11_rpc_message_read_ulong (msg, &info->ulMaxPinLen) || + !_p11_rpc_message_read_ulong (msg, &info->ulMinPinLen) || + !_p11_rpc_message_read_ulong (msg, &info->ulTotalPublicMemory) || + !_p11_rpc_message_read_ulong (msg, &info->ulFreePublicMemory) || + !_p11_rpc_message_read_ulong (msg, &info->ulTotalPrivateMemory) || + !_p11_rpc_message_read_ulong (msg, &info->ulFreePrivateMemory) || + !_p11_rpc_message_read_version (msg, &info->hardwareVersion) || + !_p11_rpc_message_read_version (msg, &info->firmwareVersion) || + !_p11_rpc_message_read_space_string (msg, info->utcTime, 16)) + return PARSE_ERROR; + + return CKR_OK; +} + +static CK_RV +proto_read_mechanism_info (RpcMessage *msg, + CK_MECHANISM_INFO_PTR info) +{ + assert (msg != NULL); + assert (info != NULL); + + if (!_p11_rpc_message_read_ulong (msg, &info->ulMinKeySize) || + !_p11_rpc_message_read_ulong (msg, &info->ulMaxKeySize) || + !_p11_rpc_message_read_ulong (msg, &info->flags)) + return PARSE_ERROR; + + return CKR_OK; +} + +static CK_RV +proto_read_sesssion_info (RpcMessage *msg, + CK_SESSION_INFO_PTR info) +{ + assert (msg != NULL); + assert (info != NULL); + + if (!_p11_rpc_message_read_ulong (msg, &info->slotID) || + !_p11_rpc_message_read_ulong (msg, &info->state) || + !_p11_rpc_message_read_ulong (msg, &info->flags) || + !_p11_rpc_message_read_ulong (msg, &info->ulDeviceError)) + return PARSE_ERROR; + + return CKR_OK; +} + +/* ------------------------------------------------------------------- + * CALL MACROS + */ + +#define BEGIN_CALL_OR(call_id, module, if_no_daemon) \ + _p11_debug (#call_id ": enter"); \ + { \ + RpcModule *_mod = module; RpcMessage _msg; \ + CK_RV _ret = call_prepare (_mod, &_msg, RPC_CALL_##call_id); \ + if (_ret == CKR_DEVICE_REMOVED) return (if_no_daemon); \ + if (_ret != CKR_OK) return _ret; + +#define PROCESS_CALL \ + _ret = call_run (_mod, &_msg); \ + if (_ret != CKR_OK) goto _cleanup; + +#define RETURN(ret) \ + _ret = ret; \ + goto _cleanup; + +#define END_CALL \ + _cleanup: \ + _ret = call_done (_mod, &_msg, _ret); \ + _p11_debug ("ret: %d", _ret); \ + return _ret; \ + } + +#define IN_BYTE(val) \ + if (!_p11_rpc_message_write_byte (&_msg, val)) \ + { _ret = CKR_HOST_MEMORY; goto _cleanup; } + +#define IN_ULONG(val) \ + if (!_p11_rpc_message_write_ulong (&_msg, val)) \ + { _ret = CKR_HOST_MEMORY; goto _cleanup; } + +#define IN_STRING(val) \ + if (!_p11_rpc_message_write_zero_string (&_msg, val)) \ + { _ret = CKR_HOST_MEMORY; goto _cleanup; } + +#define IN_BYTE_BUFFER(arr, len) \ + if (len == NULL) \ + { _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \ + if (!_p11_rpc_message_write_byte_buffer (&_msg, arr ? *len : 0)) \ + { _ret = CKR_HOST_MEMORY; goto _cleanup; } + +#define IN_BYTE_ARRAY(arr, len) \ + if (len != 0 && arr == NULL) \ + { _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \ + if (!_p11_rpc_message_write_byte_array (&_msg, arr, len)) \ + { _ret = CKR_HOST_MEMORY; goto _cleanup; } + +#define IN_ULONG_BUFFER(arr, len) \ + if (len == NULL) \ + { _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \ + if (!_p11_rpc_message_write_ulong_buffer (&_msg, arr ? *len : 0)) \ + { _ret = CKR_HOST_MEMORY; goto _cleanup; } + +#define IN_ULONG_ARRAY(arr, len) \ + if (len != 0 && arr == NULL) \ + { _ret = CKR_ARGUMENTS_BAD; goto _cleanup; }\ + if (!_p11_rpc_message_write_ulong_array (&_msg, arr, len)) \ + { _ret = CKR_HOST_MEMORY; goto _cleanup; } + +#define IN_ATTRIBUTE_BUFFER(arr, num) \ + if (num != 0 && arr == NULL) \ + { _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \ + if (!_p11_rpc_message_write_attribute_buffer (&_msg, (arr), (num))) \ + { _ret = CKR_HOST_MEMORY; goto _cleanup; } + +#define IN_ATTRIBUTE_ARRAY(arr, num) \ + if (num != 0 && arr == NULL) \ + { _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \ + if (!_p11_rpc_message_write_attribute_array (&_msg, (arr), (num))) \ + { _ret = CKR_HOST_MEMORY; goto _cleanup; } + +#define IN_MECHANISM_TYPE(val) \ + if(!_p11_rpc_mechanism_is_supported (val)) \ + { _ret = CKR_MECHANISM_INVALID; goto _cleanup; } \ + if (!_p11_rpc_message_write_ulong (&_msg, val)) \ + { _ret = CKR_HOST_MEMORY; goto _cleanup; } + +#define IN_MECHANISM(val) \ + if (val == NULL) \ + { _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \ + _ret = proto_write_mechanism (&_msg, val); \ + if (_ret != CKR_OK) goto _cleanup; + + + +#define OUT_ULONG(val) \ + if (val == NULL) \ + _ret = CKR_ARGUMENTS_BAD; \ + if (_ret == CKR_OK && !_p11_rpc_message_read_ulong (&_msg, val)) \ + _ret = PARSE_ERROR; + +#define OUT_BYTE_ARRAY(arr, len) \ + if (len == NULL) \ + _ret = CKR_ARGUMENTS_BAD; \ + if (_ret == CKR_OK) \ + _ret = proto_read_byte_array (&_msg, (arr), (len), *(len)); + +#define OUT_ULONG_ARRAY(a, len) \ + if (len == NULL) \ + _ret = CKR_ARGUMENTS_BAD; \ + if (_ret == CKR_OK) \ + _ret = proto_read_ulong_array (&_msg, (a), (len), *(len)); + +#define OUT_ATTRIBUTE_ARRAY(arr, num) \ + if (_ret == CKR_OK) \ + _ret = proto_read_attribute_array (&_msg, (arr), (num)); + +#define OUT_INFO(info) \ + if (info == NULL) \ + _ret = CKR_ARGUMENTS_BAD; \ + if (_ret == CKR_OK) \ + _ret = proto_read_info (&_msg, info); + +#define OUT_SLOT_INFO(info) \ + if (info == NULL) \ + _ret = CKR_ARGUMENTS_BAD; \ + if (_ret == CKR_OK) \ + _ret = proto_read_slot_info (&_msg, info); + +#define OUT_TOKEN_INFO(info) \ + if (info == NULL) \ + _ret = CKR_ARGUMENTS_BAD; \ + if (_ret == CKR_OK) \ + _ret = proto_read_token_info (&_msg, info); + +#define OUT_SESSION_INFO(info) \ + if (info == NULL) \ + _ret = CKR_ARGUMENTS_BAD; \ + if (_ret == CKR_OK) \ + _ret = proto_read_sesssion_info (&_msg, info); + +#define OUT_MECHANISM_TYPE_ARRAY(arr, len) \ + if (len == NULL) \ + _ret = CKR_ARGUMENTS_BAD; \ + if (_ret == CKR_OK) \ + _ret = proto_read_ulong_array (&_msg, (arr), (len), *(len)); \ + if (_ret == CKR_OK && arr) \ + _p11_rpc_mechanism_list_purge (arr, len); + +#define OUT_MECHANISM_INFO(info) \ + if (info == NULL) \ + _ret = CKR_ARGUMENTS_BAD; \ + if (_ret == CKR_OK) \ + _ret = proto_read_mechanism_info (&_msg, info); + + +/* ------------------------------------------------------------------- + * INITIALIZATION and 'GLOBAL' CALLS + */ + +static CK_RV +rpc_C_Initialize (RpcModule *module, + CK_VOID_PTR init_args) +{ + CK_C_INITIALIZE_ARGS_PTR args = NULL; + RpcSocket *socket = NULL; + void *reserved = NULL; + CK_RV ret = CKR_OK; + RpcMessage msg; + pid_t pid; + + assert (module != NULL); + _p11_debug ("C_Initialize: enter"); + + if (init_args != NULL) { + int supplied_ok; + + /* pReserved must be NULL */ + args = init_args; + + /* ALL supplied function pointers need to have the value either NULL or non-NULL. */ + supplied_ok = (args->CreateMutex == NULL && args->DestroyMutex == NULL && + args->LockMutex == NULL && args->UnlockMutex == NULL) || + (args->CreateMutex != NULL && args->DestroyMutex != NULL && + args->LockMutex != NULL && args->UnlockMutex != NULL); + if (!supplied_ok) { + _p11_message ("invalid set of mutex calls supplied"); + return CKR_ARGUMENTS_BAD; + } + + /* + * When the CKF_OS_LOCKING_OK flag isn't set return an error. + * We must be able to use our pthread functionality. + */ + if (!(args->flags & CKF_OS_LOCKING_OK)) { + _p11_message ("can't do without os locking"); + return CKR_CANT_LOCK; + } + + if (args->pReserved) + reserved = args->pReserved; + } + + pthread_mutex_lock (&module->mutex); + + pid = getpid (); + if (module->socket == NULL) { + /* This process has called C_Initialize already */ + if (pid == module->initialized_pid) { + _p11_message ("C_Initialize called twice for same process"); + ret = CKR_CRYPTOKI_ALREADY_INITIALIZED; + goto done; + } + } + + /* Call out to initialize client callback */ + if (module->vtable->initialize) { + ret = (module->vtable->initialize) (module->vtable->data, reserved, &socket); + if (ret != CKR_OK) + goto done; + module->socket = socket; + } + + if (module->socket == NULL) { + ret = CKR_DEVICE_ERROR; + goto done; + } + + /* If we don't have read and write fds now, then initialize other side */ + ret = call_prepare (module, &msg, RPC_CALL_C_Initialize); + if (ret == CKR_OK) + if (!_p11_rpc_message_write_byte_array (&msg, RPC_HANDSHAKE, RPC_HANDSHAKE_LEN)) + ret = CKR_HOST_MEMORY; + if (ret == CKR_OK) + ret = call_run (module, &msg); + call_done (module, &msg, ret); + +done: + /* Mark us as officially initialized */ + if (ret == CKR_OK) { + module->initialized_pid = pid; + + } else if (ret != CKR_CRYPTOKI_ALREADY_INITIALIZED) { + if (module->socket) + _p11_rpc_socket_unref (module->socket); + module->socket = NULL; + module->initialized_pid = 0; + } + + pthread_mutex_unlock (&module->mutex); + + _p11_debug ("C_Initialize: %d", ret); + return ret; +} + +static CK_RV +rpc_C_Finalize (RpcModule *module, + CK_VOID_PTR reserved) +{ + CK_RV ret = CKR_OK; + RpcMessage msg; + + _p11_debug ("C_Finalize: enter"); + return_val_if_fail (module->socket == NULL, CKR_CRYPTOKI_NOT_INITIALIZED); + return_val_if_fail (!reserved, CKR_ARGUMENTS_BAD); + + pthread_mutex_lock (&module->mutex); + + ret = call_prepare (module, &msg, RPC_CALL_C_Finalize); + if (ret == CKR_OK) + ret = call_run (module, &msg); + call_done (module, &msg, ret); + if (ret != CKR_OK) + _p11_message ("finalizing the daemon returned an error: %d", ret); + + /* This should stop all other calls in */ + _p11_rpc_socket_unref (module->socket); + module->socket = NULL; + module->initialized_pid = 0; + + pthread_mutex_unlock (&module->mutex); + + _p11_debug ("C_Finalize: %d", CKR_OK); + + /* We return okay anyway, meaning we are finalized */ + return CKR_OK; +} + +static CK_RV +fill_stand_in_info (CK_INFO_PTR info) +{ + static CK_INFO stand_in_info = { + { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR }, + "GNOME Keyring ", + 0, + "GNOME Keyring (without daemon) ", + { 1, 1 }, + }; + memcpy (info, &stand_in_info, sizeof (CK_INFO)); + return CKR_OK; + +} + +static CK_RV +rpc_C_GetInfo (RpcModule *module, + CK_INFO_PTR info) +{ + return_val_if_fail (info, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_GetInfo, module, fill_stand_in_info (info)); + PROCESS_CALL; + OUT_INFO (info); + END_CALL; +} + +static CK_RV +rpc_C_GetFunctionList (RpcModule *module, + CK_FUNCTION_LIST_PTR_PTR list) +{ + return_val_if_fail (list != NULL, CKR_ARGUMENTS_BAD); + *list = module->function_list; + return CKR_OK; +} + +static CK_RV +rpc_C_GetSlotList (RpcModule *module, + CK_BBOOL token_present, + CK_SLOT_ID_PTR slot_list, + CK_ULONG_PTR count) +{ + return_val_if_fail (count, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_GetSlotList, module, (*count = 0, CKR_OK)); + IN_BYTE (token_present); + IN_ULONG_BUFFER (slot_list, count); + PROCESS_CALL; + OUT_ULONG_ARRAY (slot_list, count); + END_CALL; +} + +static CK_RV +rpc_C_GetSlotInfo (RpcModule *module, + CK_SLOT_ID slot_id, + CK_SLOT_INFO_PTR info) +{ + return_val_if_fail (info, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_GetSlotInfo, module, CKR_SLOT_ID_INVALID); + IN_ULONG (slot_id); + PROCESS_CALL; + OUT_SLOT_INFO (info); + END_CALL; +} + +static CK_RV +rpc_C_GetTokenInfo (RpcModule *module, + CK_SLOT_ID slot_id, + CK_TOKEN_INFO_PTR info) +{ + return_val_if_fail (info, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_GetTokenInfo, module, CKR_SLOT_ID_INVALID); + IN_ULONG (slot_id); + PROCESS_CALL; + OUT_TOKEN_INFO (info); + END_CALL; +} + +static CK_RV +rpc_C_GetMechanismList (RpcModule *module, + CK_SLOT_ID slot_id, + CK_MECHANISM_TYPE_PTR mechanism_list, + CK_ULONG_PTR count) +{ + return_val_if_fail (count, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_GetMechanismList, module, CKR_SLOT_ID_INVALID); + IN_ULONG (slot_id); + IN_ULONG_BUFFER (mechanism_list, count); + PROCESS_CALL; + OUT_MECHANISM_TYPE_ARRAY (mechanism_list, count); + END_CALL; + +} + +static CK_RV +rpc_C_GetMechanismInfo (RpcModule *module, + CK_SLOT_ID slot_id, + CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR info) +{ + return_val_if_fail (info, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_GetMechanismInfo, module, CKR_SLOT_ID_INVALID); + IN_ULONG (slot_id); + IN_MECHANISM_TYPE (type); + PROCESS_CALL; + OUT_MECHANISM_INFO (info); + END_CALL; +} + +static CK_RV +rpc_C_InitToken (RpcModule *module, + CK_SLOT_ID slot_id, + CK_UTF8CHAR_PTR pin, CK_ULONG pin_len, + CK_UTF8CHAR_PTR label) +{ + BEGIN_CALL_OR (C_InitToken, module, CKR_SLOT_ID_INVALID); + IN_ULONG (slot_id); + IN_BYTE_ARRAY (pin, pin_len); + IN_STRING (label); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_WaitForSlotEvent (RpcModule *module, + CK_FLAGS flags, + CK_SLOT_ID_PTR slot, + CK_VOID_PTR reserved) +{ + return_val_if_fail (slot, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_WaitForSlotEvent, module, CKR_DEVICE_REMOVED); + IN_ULONG (flags); + PROCESS_CALL; + OUT_ULONG (slot); + END_CALL; +} + +static CK_RV +rpc_C_OpenSession (RpcModule *module, + CK_SLOT_ID slot_id, + CK_FLAGS flags, + CK_VOID_PTR user_data, + CK_NOTIFY callback, + CK_SESSION_HANDLE_PTR session) +{ + return_val_if_fail (session, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_OpenSession, module, CKR_SLOT_ID_INVALID); + IN_ULONG (slot_id); + IN_ULONG (flags); + PROCESS_CALL; + OUT_ULONG (session); + END_CALL; +} + +static CK_RV +rpc_C_CloseSession (RpcModule *module, + CK_SESSION_HANDLE session) +{ + BEGIN_CALL_OR (C_CloseSession, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_CloseAllSessions (RpcModule *module, + CK_SLOT_ID slot_id) +{ + BEGIN_CALL_OR (C_CloseAllSessions, module, CKR_SLOT_ID_INVALID); + IN_ULONG (slot_id); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_GetFunctionStatus (RpcModule *module, + CK_SESSION_HANDLE session) +{ + BEGIN_CALL_OR (C_GetFunctionStatus, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_CancelFunction (RpcModule *module, + CK_SESSION_HANDLE session) +{ + BEGIN_CALL_OR (C_CancelFunction, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_GetSessionInfo (RpcModule *module, + CK_SESSION_HANDLE session, + CK_SESSION_INFO_PTR info) +{ + return_val_if_fail (info, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_GetSessionInfo, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + PROCESS_CALL; + OUT_SESSION_INFO (info); + END_CALL; +} + +static CK_RV +rpc_C_InitPIN (RpcModule *module, + CK_SESSION_HANDLE session, + CK_UTF8CHAR_PTR pin, + CK_ULONG pin_len) +{ + BEGIN_CALL_OR (C_InitPIN, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (pin, pin_len); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_SetPIN (RpcModule *module, + CK_SESSION_HANDLE session, + CK_UTF8CHAR_PTR old_pin, + CK_ULONG old_pin_len, + CK_UTF8CHAR_PTR new_pin, + CK_ULONG new_pin_len) +{ + BEGIN_CALL_OR (C_SetPIN, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (old_pin, old_pin_len); + IN_BYTE_ARRAY (new_pin, old_pin_len); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_GetOperationState (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR operation_state, + CK_ULONG_PTR operation_state_len) +{ + return_val_if_fail (operation_state_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_GetOperationState, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_BUFFER (operation_state, operation_state_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (operation_state, operation_state_len); + END_CALL; +} + +static CK_RV +rpc_C_SetOperationState (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR operation_state, + CK_ULONG operation_state_len, + CK_OBJECT_HANDLE encryption_key, + CK_OBJECT_HANDLE authentication_key) +{ + BEGIN_CALL_OR (C_SetOperationState, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (operation_state, operation_state_len); + IN_ULONG (encryption_key); + IN_ULONG (authentication_key); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_Login (RpcModule *module, + CK_SESSION_HANDLE session, + CK_USER_TYPE user_type, + CK_UTF8CHAR_PTR pin, + CK_ULONG pin_len) +{ + BEGIN_CALL_OR (C_Login, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_ULONG (user_type); + IN_BYTE_ARRAY (pin, pin_len); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_Logout (RpcModule *module, + CK_SESSION_HANDLE session) +{ + BEGIN_CALL_OR (C_Logout, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_CreateObject (RpcModule *module, + CK_SESSION_HANDLE session, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR new_object) +{ + return_val_if_fail (new_object, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_CreateObject, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_ATTRIBUTE_ARRAY (template, count); + PROCESS_CALL; + OUT_ULONG (new_object); + END_CALL; +} + +static CK_RV +rpc_C_CopyObject (RpcModule *module, + CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR new_object) +{ + return_val_if_fail (new_object, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_CopyObject, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_ULONG (object); + IN_ATTRIBUTE_ARRAY (template, count); + PROCESS_CALL; + OUT_ULONG (new_object); + END_CALL; +} + + +static CK_RV +rpc_C_DestroyObject (RpcModule *module, + CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object) +{ + BEGIN_CALL_OR (C_DestroyObject, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_ULONG (object); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_GetObjectSize (RpcModule *module, + CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ULONG_PTR size) +{ + return_val_if_fail (size, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_GetObjectSize, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_ULONG (object); + PROCESS_CALL; + OUT_ULONG (size); + END_CALL; +} + +static CK_RV +rpc_C_GetAttributeValue (RpcModule *module, + CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR template, + CK_ULONG count) +{ + BEGIN_CALL_OR (C_GetAttributeValue, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_ULONG (object); + IN_ATTRIBUTE_BUFFER (template, count); + PROCESS_CALL; + OUT_ATTRIBUTE_ARRAY (template, count); + END_CALL; +} + +static CK_RV +rpc_C_SetAttributeValue (RpcModule *module, + CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR template, + CK_ULONG count) +{ + BEGIN_CALL_OR (C_SetAttributeValue, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_ULONG (object); + IN_ATTRIBUTE_ARRAY (template, count); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_FindObjectsInit (RpcModule *module, + CK_SESSION_HANDLE session, + CK_ATTRIBUTE_PTR template, + CK_ULONG count) +{ + BEGIN_CALL_OR (C_FindObjectsInit, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_ATTRIBUTE_ARRAY (template, count); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_FindObjects (RpcModule *module, + CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE_PTR objects, + CK_ULONG max_count, + CK_ULONG_PTR count) +{ + /* HACK: To fix a stupid gcc warning */ + CK_ULONG_PTR address_of_max_count = &max_count; + + return_val_if_fail (count, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_FindObjects, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_ULONG_BUFFER (objects, address_of_max_count); + PROCESS_CALL; + *count = max_count; + OUT_ULONG_ARRAY (objects, count); + END_CALL; +} + +static CK_RV +rpc_C_FindObjectsFinal (RpcModule *module, + CK_SESSION_HANDLE session) +{ + BEGIN_CALL_OR (C_FindObjectsFinal, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_EncryptInit (RpcModule *module, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + BEGIN_CALL_OR (C_EncryptInit, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (key); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_Encrypt (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR encrypted_data, + CK_ULONG_PTR encrypted_data_len) +{ + return_val_if_fail (encrypted_data_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_Encrypt, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (data, data_len); + IN_BYTE_BUFFER (encrypted_data, encrypted_data_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (encrypted_data, encrypted_data_len); + END_CALL; +} + +static CK_RV +rpc_C_EncryptUpdate (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len, + CK_BYTE_PTR encrypted_part, + CK_ULONG_PTR encrypted_part_len) +{ + return_val_if_fail (encrypted_part_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_EncryptUpdate, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (part, part_len); + IN_BYTE_BUFFER (encrypted_part, encrypted_part_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (encrypted_part, encrypted_part_len); + END_CALL; +} + +static CK_RV +rpc_C_EncryptFinal (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR last_part, + CK_ULONG_PTR last_part_len) +{ + return_val_if_fail (last_part_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_EncryptFinal, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_BUFFER (last_part, last_part_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (last_part, last_part_len); + END_CALL; +} + +static CK_RV +rpc_C_DecryptInit (RpcModule *module, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + BEGIN_CALL_OR (C_DecryptInit, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (key); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_Decrypt (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR enc_data, + CK_ULONG enc_data_len, + CK_BYTE_PTR data, + CK_ULONG_PTR data_len) +{ + return_val_if_fail (data_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_Decrypt, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (enc_data, enc_data_len); + IN_BYTE_BUFFER (data, data_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (data, data_len); + END_CALL; +} + +static CK_RV +rpc_C_DecryptUpdate (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR enc_part, + CK_ULONG enc_part_len, + CK_BYTE_PTR part, + CK_ULONG_PTR part_len) +{ + return_val_if_fail (part_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_DecryptUpdate, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (enc_part, enc_part_len); + IN_BYTE_BUFFER (part, part_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (part, part_len); + END_CALL; +} + +static CK_RV +rpc_C_DecryptFinal (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR last_part, + CK_ULONG_PTR last_part_len) +{ + return_val_if_fail (last_part_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_DecryptFinal, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_BUFFER (last_part, last_part_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (last_part, last_part_len); + END_CALL; +} + +static CK_RV +rpc_C_DigestInit (RpcModule *module, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism) +{ + BEGIN_CALL_OR (C_DigestInit, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_MECHANISM (mechanism); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_Digest (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR digest, + CK_ULONG_PTR digest_len) +{ + return_val_if_fail (digest_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_Digest, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (data, data_len); + IN_BYTE_BUFFER (digest, digest_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (digest, digest_len); + END_CALL; +} + +static CK_RV +rpc_C_DigestUpdate (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len) +{ + BEGIN_CALL_OR (C_DigestUpdate, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (part, part_len); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_DigestKey (RpcModule *module, + CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE key) +{ + BEGIN_CALL_OR (C_DigestKey, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_ULONG (key); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_DigestFinal (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR digest, + CK_ULONG_PTR digest_len) +{ + return_val_if_fail (digest_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_DigestFinal, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_BUFFER (digest, digest_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (digest, digest_len); + END_CALL; +} + +static CK_RV +rpc_C_SignInit (RpcModule *module, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + BEGIN_CALL_OR (C_SignInit, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (key); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_Sign (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR signature, + CK_ULONG_PTR signature_len) +{ + return_val_if_fail (signature_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_Sign, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (data, data_len); + IN_BYTE_BUFFER (signature, signature_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (signature, signature_len); + END_CALL; +} + +static CK_RV +rpc_C_SignUpdate (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len) +{ + return_val_if_fail (part_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_SignUpdate, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (part, part_len); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_SignFinal (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR signature, + CK_ULONG_PTR signature_len) +{ + return_val_if_fail (signature_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_SignFinal, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_BUFFER (signature, signature_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (signature, signature_len); + END_CALL; +} + +static CK_RV +rpc_C_SignRecoverInit (RpcModule *module, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + BEGIN_CALL_OR (C_SignRecoverInit, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (key); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_SignRecover (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR signature, CK_ULONG_PTR signature_len) +{ + return_val_if_fail (signature_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_SignRecover, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (data, data_len); + IN_BYTE_BUFFER (signature, signature_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (signature, signature_len); + END_CALL; +} + +static CK_RV +rpc_C_VerifyInit (RpcModule *module, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + BEGIN_CALL_OR (C_VerifyInit, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (key); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_Verify (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR signature, + CK_ULONG signature_len) +{ + BEGIN_CALL_OR (C_Verify, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (data, data_len); + IN_BYTE_ARRAY (signature, signature_len); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_VerifyUpdate (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len) +{ + BEGIN_CALL_OR (C_VerifyUpdate, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (part, part_len); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_VerifyFinal (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR signature, + CK_ULONG signature_len) +{ + BEGIN_CALL_OR (C_VerifyFinal, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (signature, signature_len); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_VerifyRecoverInit (RpcModule *module, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + BEGIN_CALL_OR (C_VerifyRecoverInit, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (key); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_VerifyRecover (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR signature, + CK_ULONG signature_len, + CK_BYTE_PTR data, + CK_ULONG_PTR data_len) +{ + return_val_if_fail (data_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_VerifyRecover, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (signature, signature_len); + IN_BYTE_BUFFER (data, data_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (data, data_len); + END_CALL; +} + +static CK_RV +rpc_C_DigestEncryptUpdate (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len, + CK_BYTE_PTR enc_part, + CK_ULONG_PTR enc_part_len) +{ + return_val_if_fail (enc_part_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_DigestEncryptUpdate, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (part, part_len); + IN_BYTE_BUFFER (enc_part, enc_part_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (enc_part, enc_part_len); + END_CALL; +} + +static CK_RV +rpc_C_DecryptDigestUpdate (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR enc_part, + CK_ULONG enc_part_len, + CK_BYTE_PTR part, + CK_ULONG_PTR part_len) +{ + return_val_if_fail (part_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_DecryptDigestUpdate, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (enc_part, enc_part_len); + IN_BYTE_BUFFER (part, part_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (part, part_len); + END_CALL; +} + +static CK_RV +rpc_C_SignEncryptUpdate (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len, + CK_BYTE_PTR enc_part, + CK_ULONG_PTR enc_part_len) +{ + return_val_if_fail (enc_part_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_SignEncryptUpdate, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (part, part_len); + IN_BYTE_BUFFER (enc_part, enc_part_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (enc_part, enc_part_len); + END_CALL; +} + +static CK_RV +rpc_C_DecryptVerifyUpdate (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR enc_part, + CK_ULONG enc_part_len, + CK_BYTE_PTR part, + CK_ULONG_PTR part_len) +{ + return_val_if_fail (part_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_DecryptVerifyUpdate, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (enc_part, enc_part_len); + IN_BYTE_BUFFER (part, part_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (part, part_len); + END_CALL; +} + +static CK_RV +rpc_C_GenerateKey (RpcModule *module, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + BEGIN_CALL_OR (C_GenerateKey, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ATTRIBUTE_ARRAY (template, count); + PROCESS_CALL; + OUT_ULONG (key); + END_CALL; +} + +static CK_RV +rpc_C_GenerateKeyPair (RpcModule *module, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_ATTRIBUTE_PTR pub_template, + CK_ULONG pub_count, + CK_ATTRIBUTE_PTR priv_template, + CK_ULONG priv_count, + CK_OBJECT_HANDLE_PTR pub_key, + CK_OBJECT_HANDLE_PTR priv_key) +{ + BEGIN_CALL_OR (C_GenerateKeyPair, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ATTRIBUTE_ARRAY (pub_template, pub_count); + IN_ATTRIBUTE_ARRAY (priv_template, priv_count); + PROCESS_CALL; + OUT_ULONG (pub_key); + OUT_ULONG (priv_key); + END_CALL; +} + +static CK_RV +rpc_C_WrapKey (RpcModule *module, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE wrapping_key, + CK_OBJECT_HANDLE key, + CK_BYTE_PTR wrapped_key, + CK_ULONG_PTR wrapped_key_len) +{ + return_val_if_fail (wrapped_key_len, CKR_ARGUMENTS_BAD); + + BEGIN_CALL_OR (C_WrapKey, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (wrapping_key); + IN_ULONG (key); + IN_BYTE_BUFFER (wrapped_key, wrapped_key_len); + PROCESS_CALL; + OUT_BYTE_ARRAY (wrapped_key, wrapped_key_len); + END_CALL; +} + +static CK_RV +rpc_C_UnwrapKey (RpcModule *module, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE unwrapping_key, + CK_BYTE_PTR wrapped_key, + CK_ULONG wrapped_key_len, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + BEGIN_CALL_OR (C_UnwrapKey, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (unwrapping_key); + IN_BYTE_ARRAY (wrapped_key, wrapped_key_len); + IN_ATTRIBUTE_ARRAY (template, count); + PROCESS_CALL; + OUT_ULONG (key); + END_CALL; +} + +static CK_RV +rpc_C_DeriveKey (RpcModule *module, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE base_key, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + BEGIN_CALL_OR (C_DeriveKey, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (base_key); + IN_ATTRIBUTE_ARRAY (template, count); + PROCESS_CALL; + OUT_ULONG (key); + END_CALL; +} + +static CK_RV +rpc_C_SeedRandom (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR seed, + CK_ULONG seed_len) +{ + BEGIN_CALL_OR (C_SeedRandom, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_ARRAY (seed, seed_len); + PROCESS_CALL; + END_CALL; +} + +static CK_RV +rpc_C_GenerateRandom (RpcModule *module, + CK_SESSION_HANDLE session, + CK_BYTE_PTR random_data, + CK_ULONG random_len) +{ + CK_ULONG_PTR address = &random_len; + BEGIN_CALL_OR (C_GenerateRandom, module, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_BYTE_BUFFER (random_data, address); + PROCESS_CALL; + OUT_BYTE_ARRAY (random_data, address); + END_CALL; +} + +/* + * This macro defines an RPC PKCS#11 module. + * + * Sadly PKCS#11 is not fully OOP does not pass the pointer to the module to + * each module function. Thus we have to define different functions for each + * RPC module which "know" which module they belong to. + * + * This macro defines PKCS#11 functions and function list which pass their + * RpcModule to the actual implementation functions above. + */ + +#define RPC_DEFINE_MODULE(id) \ + static RpcModule rpc_module_##id; \ + static CK_RV rpc_C_Initialize_##id (CK_VOID_PTR init_args) \ + { return rpc_C_Initialize (&rpc_module_##id, init_args); } \ + static CK_RV rpc_C_Finalize_##id (CK_VOID_PTR reserved) \ + { return rpc_C_Finalize (&rpc_module_##id, reserved); } \ + static CK_RV rpc_C_GetInfo_##id (CK_INFO_PTR info) \ + { return rpc_C_GetInfo (&rpc_module_##id, info); } \ + static CK_RV rpc_C_GetFunctionList_##id (CK_FUNCTION_LIST_PTR_PTR list) \ + { return rpc_C_GetFunctionList (&rpc_module_##id, list); } \ + static CK_RV rpc_C_GetSlotList_##id (CK_BBOOL token_present, CK_SLOT_ID_PTR slot_list, CK_ULONG_PTR count) \ + { return rpc_C_GetSlotList (&rpc_module_##id, token_present, slot_list, count); } \ + static CK_RV rpc_C_GetSlotInfo_##id (CK_SLOT_ID slot_id, CK_SLOT_INFO_PTR info) \ + { return rpc_C_GetSlotInfo (&rpc_module_##id, slot_id, info); } \ + static CK_RV rpc_C_GetTokenInfo_##id (CK_SLOT_ID slot_id, CK_TOKEN_INFO_PTR info) \ + { return rpc_C_GetTokenInfo (&rpc_module_##id, slot_id, info); } \ + static CK_RV rpc_C_GetMechanismList_##id (CK_SLOT_ID slot_id, CK_MECHANISM_TYPE_PTR mechanism_list, CK_ULONG_PTR count) \ + { return rpc_C_GetMechanismList (&rpc_module_##id, slot_id, mechanism_list, count); } \ + static CK_RV rpc_C_GetMechanismInfo_##id (CK_SLOT_ID slot_id, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR info) \ + { return rpc_C_GetMechanismInfo (&rpc_module_##id, slot_id, type, info); } \ + static CK_RV rpc_C_InitToken_##id (CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len, CK_UTF8CHAR_PTR label) \ + { return rpc_C_InitToken (&rpc_module_##id, slot_id, pin, pin_len, label); } \ + static CK_RV rpc_C_WaitForSlotEvent_##id (CK_FLAGS flags, CK_SLOT_ID_PTR slot, CK_VOID_PTR reserved) \ + { return rpc_C_WaitForSlotEvent (&rpc_module_##id, flags, slot, reserved); } \ + static CK_RV rpc_C_OpenSession_##id (CK_SLOT_ID slot_id, CK_FLAGS flags, CK_VOID_PTR user_data, CK_NOTIFY callback, CK_SESSION_HANDLE_PTR session) \ + { return rpc_C_OpenSession (&rpc_module_##id, slot_id, flags, user_data, callback, session); } \ + static CK_RV rpc_C_CloseSession_##id (CK_SESSION_HANDLE session) \ + { return rpc_C_CloseSession (&rpc_module_##id, session); } \ + static CK_RV rpc_C_CloseAllSessions_##id (CK_SLOT_ID slot_id) \ + { return rpc_C_CloseAllSessions (&rpc_module_##id, slot_id); } \ + static CK_RV rpc_C_GetFunctionStatus_##id (CK_SESSION_HANDLE session) \ + { return rpc_C_GetFunctionStatus (&rpc_module_##id, session); } \ + static CK_RV rpc_C_CancelFunction_##id (CK_SESSION_HANDLE session) \ + { return rpc_C_CancelFunction (&rpc_module_##id, session); } \ + static CK_RV rpc_C_GetSessionInfo_##id (CK_SESSION_HANDLE session, CK_SESSION_INFO_PTR info) \ + { return rpc_C_GetSessionInfo (&rpc_module_##id, session, info); } \ + static CK_RV rpc_C_InitPIN_##id (CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) \ + { return rpc_C_InitPIN (&rpc_module_##id, session, pin, pin_len); } \ + static CK_RV rpc_C_SetPIN_##id (CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR old_pin, CK_ULONG old_pin_len, CK_UTF8CHAR_PTR new_pin, CK_ULONG new_pin_len) \ + { return rpc_C_SetPIN (&rpc_module_##id, session, old_pin, old_pin_len, new_pin, new_pin_len); } \ + static CK_RV rpc_C_GetOperationState_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR operation_state, CK_ULONG_PTR operation_state_len) \ + { return rpc_C_GetOperationState (&rpc_module_##id, session, operation_state, operation_state_len); } \ + static CK_RV rpc_C_SetOperationState_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR operation_state, CK_ULONG operation_state_len, CK_OBJECT_HANDLE encryption_key, CK_OBJECT_HANDLE authentication_key) \ + { return rpc_C_SetOperationState (&rpc_module_##id, session, operation_state, operation_state_len, encryption_key, authentication_key); } \ + static CK_RV rpc_C_Login_##id (CK_SESSION_HANDLE session, CK_USER_TYPE user_type, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) \ + { return rpc_C_Login (&rpc_module_##id, session, user_type, pin, pin_len); } \ + static CK_RV rpc_C_Logout_##id (CK_SESSION_HANDLE session) \ + { return rpc_C_Logout (&rpc_module_##id, session); } \ + static CK_RV rpc_C_CreateObject_##id (CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR template, CK_ULONG count, CK_OBJECT_HANDLE_PTR new_object) \ + { return rpc_C_CreateObject (&rpc_module_##id, session, template, count, new_object); } \ + static CK_RV rpc_C_CopyObject_##id (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, CK_ATTRIBUTE_PTR template, CK_ULONG count, CK_OBJECT_HANDLE_PTR new_object) \ + { return rpc_C_CopyObject (&rpc_module_##id, session, object, template, count, new_object); } \ + static CK_RV rpc_C_DestroyObject_##id (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) \ + { return rpc_C_DestroyObject (&rpc_module_##id, session, object); } \ + static CK_RV rpc_C_GetObjectSize_##id (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, CK_ULONG_PTR size) \ + { return rpc_C_GetObjectSize (&rpc_module_##id, session, object, size); } \ + static CK_RV rpc_C_GetAttributeValue_##id (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, CK_ATTRIBUTE_PTR template, CK_ULONG count) \ + { return rpc_C_GetAttributeValue (&rpc_module_##id, session, object, template, count); } \ + static CK_RV rpc_C_SetAttributeValue_##id (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, CK_ATTRIBUTE_PTR template, CK_ULONG count) \ + { return rpc_C_SetAttributeValue (&rpc_module_##id, session, object, template, count); } \ + static CK_RV rpc_C_FindObjectsInit_##id (CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR template, CK_ULONG count) \ + { return rpc_C_FindObjectsInit (&rpc_module_##id, session, template, count); } \ + static CK_RV rpc_C_FindObjects_##id (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE_PTR objects, CK_ULONG max_count, CK_ULONG_PTR count) \ + { return rpc_C_FindObjects (&rpc_module_##id, session, objects, max_count, count); } \ + static CK_RV rpc_C_FindObjectsFinal_##id (CK_SESSION_HANDLE session) \ + { return rpc_C_FindObjectsFinal (&rpc_module_##id, session); } \ + static CK_RV rpc_C_EncryptInit_##id (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key) \ + { return rpc_C_EncryptInit (&rpc_module_##id, session, mechanism, key); } \ + static CK_RV rpc_C_Encrypt_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, CK_BYTE_PTR encrypted_data, CK_ULONG_PTR encrypted_data_len) \ + { return rpc_C_Encrypt (&rpc_module_##id, session, data, data_len, encrypted_data, encrypted_data_len); } \ + static CK_RV rpc_C_EncryptUpdate_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len, CK_BYTE_PTR encrypted_part, CK_ULONG_PTR encrypted_part_len) \ + { return rpc_C_EncryptUpdate (&rpc_module_##id, session, part, part_len, encrypted_part, encrypted_part_len); } \ + static CK_RV rpc_C_EncryptFinal_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR last_part, CK_ULONG_PTR last_part_len) \ + { return rpc_C_EncryptFinal (&rpc_module_##id, session, last_part, last_part_len); } \ + static CK_RV rpc_C_DecryptInit_##id (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key) \ + { return rpc_C_DecryptInit (&rpc_module_##id, session, mechanism, key); } \ + static CK_RV rpc_C_Decrypt_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR enc_data, CK_ULONG enc_data_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len) \ + { return rpc_C_Decrypt (&rpc_module_##id, session, enc_data, enc_data_len, data, data_len); } \ + static CK_RV rpc_C_DecryptUpdate_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR enc_part, CK_ULONG enc_part_len, CK_BYTE_PTR part, CK_ULONG_PTR part_len) \ + { return rpc_C_DecryptUpdate (&rpc_module_##id, session, enc_part, enc_part_len, part, part_len); } \ + static CK_RV rpc_C_DecryptFinal_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR last_part, CK_ULONG_PTR last_part_len) \ + { return rpc_C_DecryptFinal (&rpc_module_##id, session, last_part, last_part_len); } \ + static CK_RV rpc_C_DigestInit_##id (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism) \ + { return rpc_C_DigestInit (&rpc_module_##id, session, mechanism); } \ + static CK_RV rpc_C_Digest_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, CK_BYTE_PTR digest, CK_ULONG_PTR digest_len) \ + { return rpc_C_Digest (&rpc_module_##id, session, data, data_len, digest, digest_len); } \ + static CK_RV rpc_C_DigestUpdate_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len) \ + { return rpc_C_DigestUpdate (&rpc_module_##id, session, part, part_len); } \ + static CK_RV rpc_C_DigestKey_##id (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) \ + { return rpc_C_DigestKey (&rpc_module_##id, session, key); } \ + static CK_RV rpc_C_DigestFinal_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR digest, CK_ULONG_PTR digest_len) \ + { return rpc_C_DigestFinal (&rpc_module_##id, session, digest, digest_len); } \ + static CK_RV rpc_C_SignInit_##id (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key) \ + { return rpc_C_SignInit (&rpc_module_##id, session, mechanism, key); } \ + static CK_RV rpc_C_Sign_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, CK_BYTE_PTR signature, CK_ULONG_PTR signature_len) \ + { return rpc_C_Sign (&rpc_module_##id, session, data, data_len, signature, signature_len); } \ + static CK_RV rpc_C_SignUpdate_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len) \ + { return rpc_C_SignUpdate (&rpc_module_##id, session, part, part_len); } \ + static CK_RV rpc_C_SignFinal_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR signature, CK_ULONG_PTR signature_len) \ + { return rpc_C_SignFinal (&rpc_module_##id, session, signature, signature_len); } \ + static CK_RV rpc_C_SignRecoverInit_##id (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key) \ + { return rpc_C_SignRecoverInit (&rpc_module_##id, session, mechanism, key); } \ + static CK_RV rpc_C_SignRecover_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, CK_BYTE_PTR signature, CK_ULONG_PTR signature_len) \ + { return rpc_C_SignRecover (&rpc_module_##id, session, data, data_len, signature, signature_len); } \ + static CK_RV rpc_C_VerifyInit_##id (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key) \ + { return rpc_C_VerifyInit (&rpc_module_##id, session, mechanism, key); } \ + static CK_RV rpc_C_Verify_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, CK_BYTE_PTR signature, CK_ULONG signature_len) \ + { return rpc_C_Verify (&rpc_module_##id, session, data, data_len, signature, signature_len); } \ + static CK_RV rpc_C_VerifyUpdate_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len) \ + { return rpc_C_VerifyUpdate (&rpc_module_##id, session, part, part_len); } \ + static CK_RV rpc_C_VerifyFinal_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR signature, CK_ULONG signature_len) \ + { return rpc_C_VerifyFinal (&rpc_module_##id, session, signature, signature_len); } \ + static CK_RV rpc_C_VerifyRecoverInit_##id (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key) \ + { return rpc_C_VerifyRecoverInit (&rpc_module_##id, session, mechanism, key); } \ + static CK_RV rpc_C_VerifyRecover_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR signature, CK_ULONG signature_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len) \ + { return rpc_C_VerifyRecover (&rpc_module_##id, session, signature, signature_len, data, data_len); } \ + static CK_RV rpc_C_DigestEncryptUpdate_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len, CK_BYTE_PTR enc_part, CK_ULONG_PTR enc_part_len) \ + { return rpc_C_DigestEncryptUpdate (&rpc_module_##id, session, part, part_len, enc_part, enc_part_len); } \ + static CK_RV rpc_C_DecryptDigestUpdate_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR enc_part, CK_ULONG enc_part_len, CK_BYTE_PTR part, CK_ULONG_PTR part_len) \ + { return rpc_C_DecryptDigestUpdate (&rpc_module_##id, session, enc_part, enc_part_len, part, part_len); } \ + static CK_RV rpc_C_SignEncryptUpdate_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len, CK_BYTE_PTR enc_part, CK_ULONG_PTR enc_part_len) \ + { return rpc_C_SignEncryptUpdate (&rpc_module_##id, session, part, part_len, enc_part, enc_part_len); } \ + static CK_RV rpc_C_DecryptVerifyUpdate_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR enc_part, CK_ULONG enc_part_len, CK_BYTE_PTR part, CK_ULONG_PTR part_len) \ + { return rpc_C_DecryptVerifyUpdate (&rpc_module_##id, session, enc_part, enc_part_len, part, part_len); } \ + static CK_RV rpc_C_GenerateKey_##id (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_ATTRIBUTE_PTR template, CK_ULONG count, CK_OBJECT_HANDLE_PTR key) \ + { return rpc_C_GenerateKey (&rpc_module_##id, session, mechanism, template, count, key); } \ + static CK_RV rpc_C_GenerateKeyPair_##id (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_ATTRIBUTE_PTR pub_template, CK_ULONG pub_count, CK_ATTRIBUTE_PTR priv_template, CK_ULONG priv_count, CK_OBJECT_HANDLE_PTR pub_key, CK_OBJECT_HANDLE_PTR priv_key) \ + { return rpc_C_GenerateKeyPair (&rpc_module_##id, session, mechanism, pub_template, pub_count, priv_template, priv_count, pub_key, priv_key); } \ + static CK_RV rpc_C_WrapKey_##id (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len) \ + { return rpc_C_WrapKey (&rpc_module_##id, session, mechanism, wrapping_key, key, wrapped_key, wrapped_key_len); } \ + static CK_RV rpc_C_UnwrapKey_##id (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key, CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR template, CK_ULONG count, CK_OBJECT_HANDLE_PTR key) \ + { return rpc_C_UnwrapKey (&rpc_module_##id, session, mechanism, unwrapping_key, wrapped_key, wrapped_key_len, template, count, key); } \ + static CK_RV rpc_C_DeriveKey_##id (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE_PTR template, CK_ULONG count, CK_OBJECT_HANDLE_PTR key) \ + { return rpc_C_DeriveKey (&rpc_module_##id, session, mechanism, base_key, template, count, key); } \ + static CK_RV rpc_C_SeedRandom_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR seed, CK_ULONG seed_len) \ + { return rpc_C_SeedRandom (&rpc_module_##id, session, seed, seed_len); } \ + static CK_RV rpc_C_GenerateRandom_##id (CK_SESSION_HANDLE session, CK_BYTE_PTR random_data, CK_ULONG random_len) \ + { return rpc_C_GenerateRandom (&rpc_module_##id, session, random_data, random_len); } \ + static const CK_FUNCTION_LIST rpc_function_list##id = { { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR }, \ + rpc_C_Initialize_##id, rpc_C_Finalize_##id, rpc_C_GetInfo_##id, rpc_C_GetFunctionList_##id, \ + rpc_C_GetSlotList_##id, rpc_C_GetSlotInfo_##id, rpc_C_GetTokenInfo_##id, rpc_C_GetMechanismList_##id, \ + rpc_C_GetMechanismInfo_##id, rpc_C_InitToken_##id, rpc_C_InitPIN_##id, rpc_C_SetPIN_##id, \ + rpc_C_OpenSession_##id, rpc_C_CloseSession_##id, rpc_C_CloseAllSessions_##id, rpc_C_GetSessionInfo_##id, \ + rpc_C_GetOperationState_##id, rpc_C_SetOperationState_##id, rpc_C_Login_##id, rpc_C_Logout_##id, \ + rpc_C_CreateObject_##id, rpc_C_CopyObject_##id, rpc_C_DestroyObject_##id, rpc_C_GetObjectSize_##id, \ + rpc_C_GetAttributeValue_##id, rpc_C_SetAttributeValue_##id, rpc_C_FindObjectsInit_##id, \ + rpc_C_FindObjects_##id, rpc_C_FindObjectsFinal_##id, rpc_C_EncryptInit_##id, rpc_C_Encrypt_##id, \ + rpc_C_EncryptUpdate_##id, rpc_C_EncryptFinal_##id, rpc_C_DecryptInit_##id, rpc_C_Decrypt_##id, \ + rpc_C_DecryptUpdate_##id, rpc_C_DecryptFinal_##id, rpc_C_DigestInit_##id, rpc_C_Digest_##id, \ + rpc_C_DigestUpdate_##id, rpc_C_DigestKey_##id, rpc_C_DigestFinal_##id, rpc_C_SignInit_##id, \ + rpc_C_Sign_##id, rpc_C_SignUpdate_##id, rpc_C_SignFinal_##id, rpc_C_SignRecoverInit_##id, \ + rpc_C_SignRecover_##id, rpc_C_VerifyInit_##id, rpc_C_Verify_##id, rpc_C_VerifyUpdate_##id, \ + rpc_C_VerifyFinal_##id, rpc_C_VerifyRecoverInit_##id, rpc_C_VerifyRecover_##id, rpc_C_DigestEncryptUpdate_##id, \ + rpc_C_DecryptDigestUpdate_##id, rpc_C_SignEncryptUpdate_##id, rpc_C_DecryptVerifyUpdate_##id, \ + rpc_C_GenerateKey_##id, rpc_C_GenerateKeyPair_##id, rpc_C_WrapKey_##id, rpc_C_UnwrapKey_##id, \ + rpc_C_DeriveKey_##id, rpc_C_SeedRandom_##id, rpc_C_GenerateRandom_##id, rpc_C_GetFunctionStatus_##id, \ + rpc_C_CancelFunction_##id, rpc_C_WaitForSlotEvent_##id, }; \ + static RpcModule rpc_module_##id = RPC_MODULE_INIT (id, &rpc_function_list##id); + +/* + * This macro is to save typing in the two definitions below. + * RPC_MODULE is redefined as needed below. The numbers must be sequential. + */ +#define RPC_MODULE_ELEMENTS \ + RPC_MODULE (0) RPC_MODULE (1) RPC_MODULE (2) RPC_MODULE (3) RPC_MODULE (4) \ + RPC_MODULE (5) RPC_MODULE (6) RPC_MODULE (7) RPC_MODULE (8) RPC_MODULE (9) \ + RPC_MODULE (10) RPC_MODULE (11) RPC_MODULE (12) RPC_MODULE (13) RPC_MODULE (14) \ + RPC_MODULE (15) RPC_MODULE (16) RPC_MODULE (17) RPC_MODULE (18) RPC_MODULE (19) \ + RPC_MODULE (20) RPC_MODULE (21) RPC_MODULE (22) RPC_MODULE (23) RPC_MODULE (24) \ + RPC_MODULE (25) RPC_MODULE (26) RPC_MODULE (27) RPC_MODULE (28) RPC_MODULE (29) \ + RPC_MODULE (30) RPC_MODULE (31) RPC_MODULE (32) + +/* + * Use RPC_DEFINE_MODULE to define all the RPC functions and function lists + * for each module. + */ +#define RPC_MODULE(id) RPC_DEFINE_MODULE (id) +RPC_MODULE_ELEMENTS +#undef RPC_MODULE + +/* Now init the array of modules */ +static RpcModule *RPC_MODULES[] = { + #define RPC_MODULE(id) &rpc_module_##id, + #undef RPC_MODULE +}; + +#define N_RPC_MODULES \ + sizeof (RPC_MODULES) / sizeof (RPC_MODULES[0]) + +CK_FUNCTION_LIST_PTR +_p11_rpc_client_register (const RpcClientVtable *vtable) +{ + static pthread_mutex_t register_mutex = PTHREAD_MUTEX_INITIALIZER; + CK_FUNCTION_LIST_PTR function_list = NULL; + int i; + + assert (vtable != NULL); + RPC_CHECK_CALLS (); + + pthread_mutex_lock (®ister_mutex); + + /* Find an rpc module function list that's free */ + for (i = 0; i < N_RPC_MODULES; i++) { + assert (RPC_MODULES[i]->check == i); + if (RPC_MODULES[i]->vtable == NULL) { + RPC_MODULES[i]->vtable = vtable; + function_list = RPC_MODULES[i]->function_list; + assert (function_list != NULL); + break; + } + } + + pthread_mutex_unlock (®ister_mutex); + + if (function_list == NULL) + _p11_message ("too many rpc client modules: %d", N_RPC_MODULES); + + return function_list; +} diff --git a/p11-kit/rpc-client.c b/p11-kit/rpc-client.c index 5292d89..d2b28a2 100644 --- a/p11-kit/rpc-client.c +++ b/p11-kit/rpc-client.c @@ -30,12 +30,11 @@ #include "rpc-client.h" #include "rpc-mechanism.h" #include "rpc-message.h" -#include "rpc-socket.h" -#include "unix-credentials.h" #include #include #include +#include /* The error used by us when parsing of rpc message fails */ #define PARSE_ERROR CKR_DEVICE_ERROR @@ -47,8 +46,7 @@ typedef struct { int check; CK_FUNCTION_LIST_PTR function_list; pthread_mutex_t mutex; - const RpcClientVtable *vtable; - RpcSocket *socket; + RpcClientVtable *vtable; pid_t initialized_pid; } RpcModule; @@ -56,9 +54,9 @@ typedef struct { { id, (CK_FUNCTION_LIST_PTR)function_list, PTHREAD_MUTEX_INITIALIZER, NULL, 0 } /* Allocator for call session buffers */ -static void* -call_allocator (void *pointer, - size_t size) +static void * +log_allocator (void *pointer, + size_t size) { void *result = realloc (pointer, (size_t)size); if (!result && size) @@ -74,14 +72,10 @@ call_prepare (RpcModule *module, assert (module != NULL); assert (msg != NULL); - if (!module->socket) + if (module->initialized_pid == 0) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (!_p11_rpc_socket_is_open (module->socket)) - return CKR_DEVICE_REMOVED; - - _p11_rpc_socket_ref (module->socket); - _p11_rpc_message_init (msg, call_allocator); + _p11_rpc_message_init (msg, log_allocator); /* Put in the Call ID and signature */ if (!_p11_rpc_message_prep (msg, call_id, RPC_REQUEST)) @@ -97,6 +91,9 @@ call_run (RpcModule *module, { CK_RV ret = CKR_OK; CK_ULONG ckerr; + unsigned char *data; + size_t n_data; + int call_id; assert (module != NULL); @@ -112,8 +109,12 @@ call_run (RpcModule *module, assert (_p11_rpc_message_is_verified (msg)); call_id = msg->call_id; - /* Do the dialog with daemon */ - ret = _p11_rpc_socket_send_recv (module->socket, msg); + /* Do the transport send and receive */ + assert (module->vtable->transport != NULL); + data = _p11_buffer_uninit_steal (&msg->buffer, &n_data); + ret = (module->vtable->transport) (module->vtable, &data, &n_data); + _p11_buffer_init_allocated (&msg->buffer, data, n_data, log_allocator); + if (ret != CKR_OK) return ret; @@ -164,7 +165,6 @@ call_done (RpcModule *module, } } - _p11_rpc_socket_unref (module->socket); _p11_rpc_message_clear (msg); return ret; } @@ -667,7 +667,6 @@ rpc_C_Initialize (RpcModule *module, CK_VOID_PTR init_args) { CK_C_INITIALIZE_ARGS_PTR args = NULL; - RpcSocket *socket = NULL; void *reserved = NULL; CK_RV ret = CKR_OK; RpcMessage msg; @@ -708,7 +707,7 @@ rpc_C_Initialize (RpcModule *module, pthread_mutex_lock (&module->mutex); pid = getpid (); - if (module->socket == NULL) { + if (module->initialized_pid != 0) { /* This process has called C_Initialize already */ if (pid == module->initialized_pid) { _p11_message ("C_Initialize called twice for same process"); @@ -718,17 +717,10 @@ rpc_C_Initialize (RpcModule *module, } /* Call out to initialize client callback */ - if (module->vtable->initialize) { - ret = (module->vtable->initialize) (module->vtable->data, reserved, &socket); - if (ret != CKR_OK) - goto done; - module->socket = socket; - } - - if (module->socket == NULL) { - ret = CKR_DEVICE_ERROR; + assert (module->vtable->initialize); + ret = (module->vtable->initialize) (module->vtable->data, reserved); + if (ret != CKR_OK) goto done; - } /* If we don't have read and write fds now, then initialize other side */ ret = call_prepare (module, &msg, RPC_CALL_C_Initialize); @@ -741,15 +733,11 @@ rpc_C_Initialize (RpcModule *module, done: /* Mark us as officially initialized */ - if (ret == CKR_OK) { + if (ret == CKR_OK) module->initialized_pid = pid; - } else if (ret != CKR_CRYPTOKI_ALREADY_INITIALIZED) { - if (module->socket) - _p11_rpc_socket_unref (module->socket); - module->socket = NULL; + else if (ret != CKR_CRYPTOKI_ALREADY_INITIALIZED) module->initialized_pid = 0; - } pthread_mutex_unlock (&module->mutex); @@ -765,7 +753,7 @@ rpc_C_Finalize (RpcModule *module, RpcMessage msg; _p11_debug ("C_Finalize: enter"); - return_val_if_fail (module->socket == NULL, CKR_CRYPTOKI_NOT_INITIALIZED); + return_val_if_fail (module->initialized_pid == 0, CKR_CRYPTOKI_NOT_INITIALIZED); return_val_if_fail (!reserved, CKR_ARGUMENTS_BAD); pthread_mutex_lock (&module->mutex); @@ -777,9 +765,8 @@ rpc_C_Finalize (RpcModule *module, if (ret != CKR_OK) _p11_message ("finalizing the daemon returned an error: %d", ret); - /* This should stop all other calls in */ - _p11_rpc_socket_unref (module->socket); - module->socket = NULL; + assert (module->vtable->finalize); + (module->vtable->finalize) (module->vtable, reserved); module->initialized_pid = 0; pthread_mutex_unlock (&module->mutex); @@ -2031,7 +2018,7 @@ static RpcModule *RPC_MODULES[] = { sizeof (RPC_MODULES) / sizeof (RPC_MODULES[0]) CK_FUNCTION_LIST_PTR -_p11_rpc_client_register (const RpcClientVtable *vtable) +_p11_rpc_client_register (RpcClientVtable *vtable) { static pthread_mutex_t register_mutex = PTHREAD_MUTEX_INITIALIZER; CK_FUNCTION_LIST_PTR function_list = NULL; diff --git a/p11-kit/rpc-client.h b/p11-kit/rpc-client.h index 46ee7bf..695ade8 100644 --- a/p11-kit/rpc-client.h +++ b/p11-kit/rpc-client.h @@ -20,18 +20,26 @@ Author: Stef Walter */ +#ifndef __RPC_CLIENT_H__ +#define __RPC_CLIENT_H__ + #include "pkcs11.h" -#include "rpc-socket.h" typedef struct _RpcClientVtable RpcClientVtable; - -typedef CK_RV (*_p11_rpc_client_initialize) (RpcClientVtable *vtable, - void *init_reserved, - RpcSocket **socket); - struct _RpcClientVtable { void *data; - _p11_rpc_client_initialize initialize; + + CK_RV (* initialize) (RpcClientVtable *vtable, + void *init_reserved); + + CK_RV (* transport) (RpcClientVtable *vtable, + unsigned char **data, + size_t *length); + + void (* finalize) (RpcClientVtable *vtable, + void *fini_reserved); }; -CK_FUNCTION_LIST_PTR _p11_rpc_client_register (const RpcClientVtable *vtable); +CK_FUNCTION_LIST_PTR _p11_rpc_client_register (RpcClientVtable *vtable); + +#endif /* __RPC_CLIENT_H__ */ diff --git a/p11-kit/rpc-message.c b/p11-kit/rpc-message.c index 7045e85..810d417 100644 --- a/p11-kit/rpc-message.c +++ b/p11-kit/rpc-message.c @@ -44,10 +44,50 @@ _p11_rpc_message_init (RpcMessage *msg, void _p11_rpc_message_clear (RpcMessage *msg) { + void *allocated; + void **data; + assert (msg != NULL); assert (msg->buffer.allocator); _p11_buffer_uninit (&msg->buffer); + + /* Free up the extra allocated memory */ + allocated = msg->extra; + while (allocated != NULL) { + data = (void **)allocated; + + /* Pointer to the next allocation */ + allocated = *data; + (msg->buffer.allocator) (data, 0); + } + msg->extra = NULL; +} + +void * +_p11_rpc_message_alloc_extra (RpcMessage *msg, + size_t length) +{ + void **data; + + assert (msg != NULL); + + if (length > 0x7fffffff) + return NULL; + + data = (msg->buffer.allocator) (NULL, sizeof (void *) + length); + if (data == NULL) + return NULL; + + /* Munch up the memory to help catch bugs */ + memset (data, 0xff, sizeof (void *) + length); + + /* Store pointer to next allocated block at beginning */ + *data = msg->extra; + msg->extra = data; + + /* Data starts after first pointer */ + return (void *)(data + 1); } void diff --git a/p11-kit/rpc-message.h b/p11-kit/rpc-message.h index c3bf081..1924a2c 100644 --- a/p11-kit/rpc-message.h +++ b/p11-kit/rpc-message.h @@ -218,9 +218,9 @@ typedef struct _RpcMessage { RpcMessageType call_type; const char *signature; Buffer buffer; - size_t parsed; const char *sigverify; + void *extra; } RpcMessage; void _p11_rpc_message_init (RpcMessage *msg, @@ -234,6 +234,9 @@ void _p11_rpc_message_reset (RpcMessage *m #define _p11_rpc_message_buffer_error(msg) (_p11_buffer_has_error (&(msg)->buffer)) +void * _p11_rpc_message_alloc_extra (RpcMessage *msg, + size_t length); + int _p11_rpc_message_prep (RpcMessage *msg, int call_id, RpcMessageType type); @@ -295,24 +298,4 @@ int _p11_rpc_message_read_space_string (RpcMessage *m int _p11_rpc_message_read_version (RpcMessage *msg, CK_VERSION* version); -#if 0 -/* - * PKCS#11 mechanism parameters are not easy to serialize. They're - * completely different for so many mechanisms, they contain - * pointers to arbitrary memory, and many callers don't initialize - * them completely or properly. - * - * We only support certain mechanisms. - * - * Also callers do yucky things like leaving parts of the structure - * pointing to garbage if they don't think it's going to be used. - */ - -int _p11_rpc_mechanism_is_supported (CK_MECHANISM_TYPE mech); -void _p11_rpc_mechanism_list_purge (CK_MECHANISM_TYPE_PTR mechs, - CK_ULONG_PTR n_mechs); -int _p11_rpc_mechanism_has_sane_parameters (CK_MECHANISM_TYPE type); -int _p11_rpc_mechanism_has_no_parameters (CK_MECHANISM_TYPE mech); -#endif - #endif /* _RPC_MESSAGE_H */ diff --git a/p11-kit/rpc-server.c b/p11-kit/rpc-server.c new file mode 100644 index 0000000..e0904aa --- /dev/null +++ b/p11-kit/rpc-server.c @@ -0,0 +1,1925 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* rpc-dispatch.h - receiver of our PKCS#11 protocol. + + Copyright (C) 2008, Stef Walter + Copyright (C) 2012, Stef Walter + + The Gnome Keyring Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Keyring Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Stef Walter +*/ + +#include "config.h" + +#define DEBUG_FLAG DEBUG_RPC +#include "debug.h" +#include "pkcs11.h" +#include "private.h" +#include "rpc-message.h" +#include "rpc-server.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* The error returned on protocol failures */ +#define PARSE_ERROR CKR_DEVICE_ERROR +#define PREP_ERROR CKR_DEVICE_MEMORY + +#define return_val_if_fail(x, v) \ + if (!(x)) { _p11_message ("'%s' not true at %s", #x, __func__); return v; } + +/* Allocator for call session buffers */ +static void * +log_allocator (void *pointer, + size_t size) +{ + void *result = realloc (pointer, (size_t)size); + if (!result && size) + _p11_message ("memory allocation of %lu bytes failed", size); + return result; +} + +static CK_RV +proto_read_byte_buffer (RpcMessage *msg, + CK_BYTE_PTR *buffer, + CK_ULONG *n_buffer) +{ + uint32_t length; + + assert (msg != NULL); + assert (buffer != NULL); + assert (n_buffer != NULL); + + /* Check that we're supposed to be reading this at this point */ + assert (!msg->signature || _p11_rpc_message_verify_part (msg, "fy")); + + /* The number of ulongs there's room for on the other end */ + if (!_p11_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &length)) + return PARSE_ERROR; + + *n_buffer = length; + *buffer = NULL; + + /* If set to zero, then they just want the length */ + if (length == 0) + return CKR_OK; + + *buffer = _p11_rpc_message_alloc_extra (msg, length * sizeof (CK_BYTE)); + if (*buffer == NULL) + return CKR_DEVICE_MEMORY; + + return CKR_OK; +} + +static CK_RV +proto_read_byte_array (RpcMessage *msg, + CK_BYTE_PTR *array, + CK_ULONG *n_array) +{ + const unsigned char *data; + unsigned char valid; + size_t n_data; + + assert (msg != NULL); + + /* Check that we're supposed to have this at this point */ + assert (!msg->signature || _p11_rpc_message_verify_part (msg, "ay")); + + /* Read out the byte which says whether data is present or not */ + if (!_p11_buffer_get_byte (&msg->buffer, msg->parsed, &msg->parsed, &valid)) + return PARSE_ERROR; + + if (!valid) { + *array = NULL; + *n_array = 0; + return CKR_OK; + } + + /* Point our arguments into the buffer */ + if (!_p11_buffer_get_byte_array (&msg->buffer, msg->parsed, &msg->parsed, + &data, &n_data)) + return PARSE_ERROR; + + *array = (CK_BYTE_PTR)data; + *n_array = n_data; + return CKR_OK; +} + +static CK_RV +proto_write_byte_array (RpcMessage *msg, + CK_BYTE_PTR array, + CK_ULONG len, + CK_RV ret) +{ + assert (msg != NULL); + + /* + * When returning an byte array, in many cases we need to pass + * an invalid array along with a length, which signifies CKR_BUFFER_TOO_SMALL. + */ + + switch (ret) { + case CKR_BUFFER_TOO_SMALL: + array = NULL; + /* fall through */ + case CKR_OK: + break; + + /* Pass all other errors straight through */ + default: + return ret; + }; + + if (!_p11_rpc_message_write_byte_array (msg, array, len)) + return PREP_ERROR; + + return CKR_OK; +} + +static CK_RV +proto_read_ulong_buffer (RpcMessage *msg, + CK_ULONG_PTR *buffer, + CK_ULONG *n_buffer) +{ + uint32_t length; + + assert (msg != NULL); + assert (buffer != NULL); + assert (n_buffer != NULL); + + /* Check that we're supposed to be reading this at this point */ + assert (!msg->signature || _p11_rpc_message_verify_part (msg, "fu")); + + /* The number of ulongs there's room for on the other end */ + if (!_p11_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &length)) + return PARSE_ERROR; + + *n_buffer = length; + *buffer = NULL; + + /* If set to zero, then they just want the length */ + if (length == 0) + return CKR_OK; + + *buffer = _p11_rpc_message_alloc_extra (msg, length * sizeof (CK_ULONG)); + if (!*buffer) + return CKR_DEVICE_MEMORY; + + return CKR_OK; +} + +static CK_RV +proto_write_ulong_array (RpcMessage *msg, + CK_ULONG_PTR array, + CK_ULONG len, + CK_RV ret) +{ + assert (msg != NULL); + + /* + * When returning an ulong array, in many cases we need to pass + * an invalid array along with a length, which signifies CKR_BUFFER_TOO_SMALL. + */ + + switch (ret) { + case CKR_BUFFER_TOO_SMALL: + array = NULL; + /* fall through */ + case CKR_OK: + break; + + /* Pass all other errors straight through */ + default: + return ret; + }; + + if (!_p11_rpc_message_write_ulong_array (msg, array, len)) + return PREP_ERROR; + + return CKR_OK; +} + +static CK_RV +proto_read_attribute_buffer (RpcMessage *msg, + CK_ATTRIBUTE_PTR *result, + CK_ULONG *n_result) +{ + CK_ATTRIBUTE_PTR attrs; + uint32_t n_attrs, i; + uint32_t value; + + assert (msg != NULL); + assert (result != NULL); + assert (n_result != NULL); + + /* Make sure this is in the rigth order */ + assert (!msg->signature || _p11_rpc_message_verify_part (msg, "fA")); + + /* Read the number of attributes */ + if (!_p11_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &n_attrs)) + return PARSE_ERROR; + + /* Allocate memory for the attribute structures */ + attrs = _p11_rpc_message_alloc_extra (msg, n_attrs * sizeof (CK_ATTRIBUTE)); + if (attrs == NULL) + return CKR_DEVICE_MEMORY; + + /* Now go through and fill in each one */ + for (i = 0; i < n_attrs; ++i) { + + /* The attribute type */ + if (!_p11_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &value)) + return PARSE_ERROR; + + attrs[i].type = value; + + /* The number of bytes to allocate */ + if (!_p11_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &value)) + return PARSE_ERROR; + + if (value == 0) { + attrs[i].pValue = NULL; + attrs[i].ulValueLen = 0; + } else { + attrs[i].pValue = _p11_rpc_message_alloc_extra (msg, value); + if (!attrs[i].pValue) + return CKR_DEVICE_MEMORY; + attrs[i].ulValueLen = value; + } + } + + *result = attrs; + *n_result = n_attrs; + return CKR_OK; +} + +static CK_RV +proto_read_attribute_array (RpcMessage *msg, + CK_ATTRIBUTE_PTR *result, + CK_ULONG *n_result) +{ + CK_ATTRIBUTE_PTR attrs; + const unsigned char *data; + unsigned char valid; + uint32_t n_attrs, i; + uint32_t value; + size_t n_data; + + assert (msg != NULL); + assert (result != NULL); + assert (n_result != NULL); + + /* Make sure this is in the rigth order */ + assert (!msg->signature || _p11_rpc_message_verify_part (msg, "aA")); + + /* Read the number of attributes */ + if (!_p11_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &n_attrs)) + return PARSE_ERROR; + + /* Allocate memory for the attribute structures */ + attrs = _p11_rpc_message_alloc_extra (msg, n_attrs * sizeof (CK_ATTRIBUTE)); + if (attrs == NULL) + return CKR_DEVICE_MEMORY; + + /* Now go through and fill in each one */ + for (i = 0; i < n_attrs; ++i) { + + /* The attribute type */ + if (!_p11_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &value)) + return PARSE_ERROR; + + attrs[i].type = value; + + /* Whether this one is valid or not */ + if (!_p11_buffer_get_byte (&msg->buffer, msg->parsed, &msg->parsed, &valid)) + return PARSE_ERROR; + + if (valid) { + if (!_p11_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &value)) + return PARSE_ERROR; + if (!_p11_buffer_get_byte_array (&msg->buffer, msg->parsed, &msg->parsed, &data, &n_data)) + return PARSE_ERROR; + + if (data != NULL && n_data != value) { + _p11_message ("attribute length and data do not match"); + return PARSE_ERROR; + } + + attrs[i].pValue = (CK_VOID_PTR)data; + attrs[i].ulValueLen = value; + } else { + attrs[i].pValue = NULL; + attrs[i].ulValueLen = -1; + } + } + + *result = attrs; + *n_result = n_attrs; + return CKR_OK; +} + +static CK_RV +proto_write_attribute_array (RpcMessage *msg, + CK_ATTRIBUTE_PTR array, + CK_ULONG len, + CK_RV ret) +{ + assert (msg != NULL); + + /* + * When returning an attribute array, certain errors aren't + * actually real errors, these are passed through to the other + * side along with the attribute array. + */ + + switch (ret) { + case CKR_ATTRIBUTE_SENSITIVE: + case CKR_ATTRIBUTE_TYPE_INVALID: + case CKR_BUFFER_TOO_SMALL: + case CKR_OK: + break; + + /* Pass all other errors straight through */ + default: + return ret; + }; + + if (!_p11_rpc_message_write_attribute_array (msg, array, len) || + !_p11_rpc_message_write_ulong (msg, ret)) + return PREP_ERROR; + + return CKR_OK; +} + +static CK_RV +proto_read_null_string (RpcMessage *msg, + CK_UTF8CHAR_PTR *val) +{ + const unsigned char *data; + size_t n_data; + + assert (msg != NULL); + assert (val != NULL); + + /* Check that we're supposed to have this at this point */ + assert (!msg->signature || _p11_rpc_message_verify_part (msg, "z")); + + if (!_p11_buffer_get_byte_array (&msg->buffer, msg->parsed, &msg->parsed, &data, &n_data)) + return PARSE_ERROR; + + /* Allocate a block of memory for it */ + *val = _p11_rpc_message_alloc_extra (msg, n_data); + if (*val == NULL) + return CKR_DEVICE_MEMORY; + + memcpy (*val, data, n_data); + (*val)[n_data] = 0; + + return CKR_OK; +} + +static CK_RV +proto_read_mechanism (RpcMessage *msg, + CK_MECHANISM_PTR mech) +{ + const unsigned char *data; + uint32_t value; + size_t n_data; + + assert (msg != NULL); + assert (mech != NULL); + + /* Make sure this is in the right order */ + assert (!msg->signature || _p11_rpc_message_verify_part (msg, "M")); + + /* The mechanism type */ + if (!_p11_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &value)) + return PARSE_ERROR; + + /* The mechanism data */ + if (!_p11_buffer_get_byte_array (&msg->buffer, msg->parsed, &msg->parsed, &data, &n_data)) + return PARSE_ERROR; + + mech->mechanism = value; + mech->pParameter = (CK_VOID_PTR)data; + mech->ulParameterLen = n_data; + return CKR_OK; +} + +static CK_RV +proto_write_info (RpcMessage *msg, + CK_INFO_PTR info) +{ + assert (msg != NULL); + assert (info != NULL); + + if (!_p11_rpc_message_write_version (msg, &info->cryptokiVersion) || + !_p11_rpc_message_write_space_string (msg, info->manufacturerID, 32) || + !_p11_rpc_message_write_ulong (msg, info->flags) || + !_p11_rpc_message_write_space_string (msg, info->libraryDescription, 32) || + !_p11_rpc_message_write_version (msg, &info->libraryVersion)) + return PREP_ERROR; + + return CKR_OK; +} + +static CK_RV +proto_write_slot_info (RpcMessage *msg, + CK_SLOT_INFO_PTR info) +{ + assert (msg != NULL); + assert (info != NULL); + + if (!_p11_rpc_message_write_space_string (msg, info->slotDescription, 64) || + !_p11_rpc_message_write_space_string (msg, info->manufacturerID, 32) || + !_p11_rpc_message_write_ulong (msg, info->flags) || + !_p11_rpc_message_write_version (msg, &info->hardwareVersion) || + !_p11_rpc_message_write_version (msg, &info->firmwareVersion)) + return PREP_ERROR; + + return CKR_OK; +} + +static CK_RV +proto_write_token_info (RpcMessage *msg, + CK_TOKEN_INFO_PTR info) +{ + assert (msg != NULL); + assert (info != NULL); + + if (!_p11_rpc_message_write_space_string (msg, info->label, 32) || + !_p11_rpc_message_write_space_string (msg, info->manufacturerID, 32) || + !_p11_rpc_message_write_space_string (msg, info->model, 16) || + !_p11_rpc_message_write_space_string (msg, info->serialNumber, 16) || + !_p11_rpc_message_write_ulong (msg, info->flags) || + !_p11_rpc_message_write_ulong (msg, info->ulMaxSessionCount) || + !_p11_rpc_message_write_ulong (msg, info->ulSessionCount) || + !_p11_rpc_message_write_ulong (msg, info->ulMaxRwSessionCount) || + !_p11_rpc_message_write_ulong (msg, info->ulRwSessionCount) || + !_p11_rpc_message_write_ulong (msg, info->ulMaxPinLen) || + !_p11_rpc_message_write_ulong (msg, info->ulMinPinLen) || + !_p11_rpc_message_write_ulong (msg, info->ulTotalPublicMemory) || + !_p11_rpc_message_write_ulong (msg, info->ulFreePublicMemory) || + !_p11_rpc_message_write_ulong (msg, info->ulTotalPrivateMemory) || + !_p11_rpc_message_write_ulong (msg, info->ulFreePrivateMemory) || + !_p11_rpc_message_write_version (msg, &info->hardwareVersion) || + !_p11_rpc_message_write_version (msg, &info->firmwareVersion) || + !_p11_rpc_message_write_space_string (msg, info->utcTime, 16)) + return PREP_ERROR; + + return CKR_OK; +} + +static CK_RV +proto_write_mechanism_info (RpcMessage *msg, + CK_MECHANISM_INFO_PTR info) +{ + assert (msg != NULL); + assert (info != NULL); + + if (!_p11_rpc_message_write_ulong (msg, info->ulMinKeySize) || + !_p11_rpc_message_write_ulong (msg, info->ulMaxKeySize) || + !_p11_rpc_message_write_ulong (msg, info->flags)) + return PREP_ERROR; + + return CKR_OK; +} + +static CK_RV +proto_write_session_info (RpcMessage *msg, + CK_SESSION_INFO_PTR info) +{ + assert (msg != NULL); + assert (info != NULL); + + if (!_p11_rpc_message_write_ulong (msg, info->slotID) || + !_p11_rpc_message_write_ulong (msg, info->state) || + !_p11_rpc_message_write_ulong (msg, info->flags) || + !_p11_rpc_message_write_ulong (msg, info->ulDeviceError)) + return PREP_ERROR; + + return CKR_OK; +} + +static CK_RV +call_ready (RpcMessage *msg) +{ + /* + * Called right before invoking the actual PKCS#11 function + * Reading out of data is complete, get ready to write return values. + */ + + if (_p11_rpc_message_buffer_error (msg)) { + _p11_message ("invalid request from module, probably too short"); \ + return PARSE_ERROR; + } + + assert (_p11_rpc_message_is_verified (msg)); + + if (!_p11_rpc_message_prep (msg, msg->call_id, RPC_RESPONSE)) { + _p11_message ("couldn't initialize rpc response"); + return CKR_DEVICE_MEMORY; + } + + return CKR_OK; +} + +/* ------------------------------------------------------------------- + * CALL MACROS + */ + +#define BEGIN_CALL(call_id) \ + _p11_debug (#call_id ": enter"); \ + assert (msg != NULL); \ + assert (module != NULL); \ + { \ + CK_ ## call_id _func = module-> call_id; \ + CK_RV _ret = CKR_OK; \ + if (!_func) { _ret = CKR_GENERAL_ERROR; goto _cleanup; } + +#define PROCESS_CALL(args) \ + _ret = call_ready (msg); \ + if (_ret != CKR_OK) { goto _cleanup; } \ + _ret = _func args + +#define END_CALL \ + _cleanup: \ + _p11_debug ("ret: %d", _ret); \ + return _ret; \ + } + +#define IN_BYTE(val) \ + if (!_p11_rpc_message_read_byte (msg, &val)) \ + { _ret = PARSE_ERROR; goto _cleanup; } + +#define IN_ULONG(val) \ + if (!_p11_rpc_message_read_ulong (msg, &val)) \ + { _ret = PARSE_ERROR; goto _cleanup; } + +#define IN_STRING(val) \ + _ret = proto_read_null_string (msg, &val); \ + if (_ret != CKR_OK) goto _cleanup; + +#define IN_BYTE_BUFFER(buffer, buffer_len) \ + _ret = proto_read_byte_buffer (msg, &buffer, &buffer_len); \ + if (_ret != CKR_OK) goto _cleanup; + +#define IN_BYTE_ARRAY(buffer, buffer_len) \ + _ret = proto_read_byte_array (msg, &buffer, &buffer_len); \ + if (_ret != CKR_OK) goto _cleanup; + +#define IN_ULONG_BUFFER(buffer, buffer_len) \ + _ret = proto_read_ulong_buffer (msg, &buffer, &buffer_len); \ + if (_ret != CKR_OK) goto _cleanup; + +#define IN_ATTRIBUTE_BUFFER(buffer, buffer_len) \ + _ret = proto_read_attribute_buffer (msg, &buffer, &buffer_len); \ + if (_ret != CKR_OK) goto _cleanup; + +#define IN_ATTRIBUTE_ARRAY(attrs, n_attrs) \ + _ret = proto_read_attribute_array (msg, &attrs, &n_attrs); \ + if (_ret != CKR_OK) goto _cleanup; + +#define IN_MECHANISM(mech) \ + _ret = proto_read_mechanism (msg, &mech); \ + if (_ret != CKR_OK) goto _cleanup; + + +#define OUT_ULONG(val) \ + if (_ret == CKR_OK && !_p11_rpc_message_write_ulong (msg, val)) \ + _ret = PREP_ERROR; + +#define OUT_BYTE_ARRAY(array, len) \ + /* Note how we filter return codes */ \ + _ret = proto_write_byte_array (msg, array, len, _ret); + +#define OUT_ULONG_ARRAY(array, len) \ + /* Note how we filter return codes */ \ + _ret = proto_write_ulong_array (msg, array, len, _ret); + +#define OUT_ATTRIBUTE_ARRAY(array, len) \ + /* Note how we filter return codes */ \ + _ret = proto_write_attribute_array (msg, array, len, _ret); + +#define OUT_INFO(val) \ + if (_ret == CKR_OK) \ + _ret = proto_write_info (msg, &val); + +#define OUT_SLOT_INFO(val) \ + if (_ret == CKR_OK) \ + _ret = proto_write_slot_info (msg, &val); + +#define OUT_TOKEN_INFO(val) \ + if (_ret == CKR_OK) \ + _ret = proto_write_token_info (msg, &val); + +#define OUT_MECHANISM_INFO(val) \ + if (_ret == CKR_OK) \ + _ret = proto_write_mechanism_info (msg, &val); + +#define OUT_SESSION_INFO(val) \ + if (_ret == CKR_OK) \ + _ret = proto_write_session_info (msg, &val); + +/* --------------------------------------------------------------------------- + * DISPATCH SPECIFIC CALLS + */ + +static CK_RV +rpc_C_Initialize (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_C_Initialize func; + CK_C_INITIALIZE_ARGS init_args; + CK_BYTE_PTR handshake; + CK_ULONG n_handshake; + CK_RV ret = CKR_OK; + + _p11_debug ("C_Initialize: enter"); + + assert (msg != NULL); + assert (module != NULL); + + ret = proto_read_byte_array (msg, &handshake, &n_handshake); + if (ret == CKR_OK) { + + /* Check to make sure the header matches */ + if (n_handshake != RPC_HANDSHAKE_LEN || + memcmp (handshake, RPC_HANDSHAKE, n_handshake) != 0) { + _p11_message ("invalid handshake received from connecting module"); + ret = CKR_GENERAL_ERROR; + } + + assert (_p11_rpc_message_is_verified (msg)); + } + + memset (&init_args, 0, sizeof (init_args)); + init_args.flags = CKF_OS_LOCKING_OK; + + func = module->C_Initialize; + assert (func != NULL); + ret = (func) (&init_args); + + /* Empty response */ + if (ret == CKR_OK) + ret = call_ready (msg); + + _p11_debug ("ret: %d", ret); + return ret; +} + +static CK_RV +rpc_C_Finalize (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + BEGIN_CALL (C_Finalize); + PROCESS_CALL ((NULL)); + END_CALL; +} + +static CK_RV +rpc_C_GetInfo (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_INFO info; + + BEGIN_CALL (C_GetInfo); + PROCESS_CALL ((&info)); + OUT_INFO (info); + END_CALL; +} + +static CK_RV +rpc_C_GetSlotList (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_BBOOL token_present; + CK_SLOT_ID_PTR slot_list; + CK_ULONG count; + + BEGIN_CALL (C_GetSlotList); + IN_BYTE (token_present); + IN_ULONG_BUFFER (slot_list, count); + PROCESS_CALL ((token_present, slot_list, &count)); + OUT_ULONG_ARRAY (slot_list, count); + END_CALL; +} + +static CK_RV +rpc_C_GetSlotInfo (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SLOT_ID slot_id; + CK_SLOT_INFO info; + + BEGIN_CALL (C_GetSlotInfo); + IN_ULONG (slot_id); + PROCESS_CALL ((slot_id, &info)); + OUT_SLOT_INFO (info); + END_CALL; +} + +static CK_RV +rpc_C_GetTokenInfo (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SLOT_ID slot_id; + CK_TOKEN_INFO info; + + BEGIN_CALL (C_GetTokenInfo); + IN_ULONG (slot_id); + PROCESS_CALL ((slot_id, &info)); + OUT_TOKEN_INFO (info); + END_CALL; +} + +static CK_RV +rpc_C_GetMechanismList (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SLOT_ID slot_id; + CK_MECHANISM_TYPE_PTR mechanism_list; + CK_ULONG count; + + BEGIN_CALL (C_GetMechanismList); + IN_ULONG (slot_id); + IN_ULONG_BUFFER (mechanism_list, count); + PROCESS_CALL ((slot_id, mechanism_list, &count)); + OUT_ULONG_ARRAY (mechanism_list, count); + END_CALL; +} + +static CK_RV +rpc_C_GetMechanismInfo (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SLOT_ID slot_id; + CK_MECHANISM_TYPE type; + CK_MECHANISM_INFO info; + + BEGIN_CALL (C_GetMechanismInfo); + IN_ULONG (slot_id); + IN_ULONG (type); + PROCESS_CALL ((slot_id, type, &info)); + OUT_MECHANISM_INFO (info); + END_CALL; +} + +static CK_RV +rpc_C_InitToken (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SLOT_ID slot_id; + CK_UTF8CHAR_PTR pin; + CK_ULONG pin_len; + CK_UTF8CHAR_PTR label; + + BEGIN_CALL (C_InitToken); + IN_ULONG (slot_id); + IN_BYTE_ARRAY (pin, pin_len); + IN_STRING (label); + PROCESS_CALL ((slot_id, pin, pin_len, label)); + END_CALL; +} + +static CK_RV +rpc_C_WaitForSlotEvent (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_FLAGS flags; + CK_SLOT_ID slot_id; + + BEGIN_CALL (C_WaitForSlotEvent); + IN_ULONG (flags); + PROCESS_CALL ((flags, &slot_id, NULL)); + OUT_ULONG (slot_id); + END_CALL; +} + +static CK_RV +rpc_C_OpenSession (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SLOT_ID slot_id; + CK_FLAGS flags; + CK_SESSION_HANDLE session; + + BEGIN_CALL (C_OpenSession); + IN_ULONG (slot_id); + IN_ULONG (flags); + PROCESS_CALL ((slot_id, flags, NULL, NULL, &session)); + OUT_ULONG (session); + END_CALL; +} + + +static CK_RV +rpc_C_CloseSession (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + + BEGIN_CALL (C_CloseSession); + IN_ULONG (session); + PROCESS_CALL ((session)); + END_CALL; +} + +static CK_RV +rpc_C_CloseAllSessions (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SLOT_ID slot_id; + + /* Slot id becomes appartment so lower layers can tell clients apart. */ + + BEGIN_CALL (C_CloseAllSessions); + IN_ULONG (slot_id); + PROCESS_CALL ((slot_id)); + END_CALL; +} + +static CK_RV +rpc_C_GetFunctionStatus (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + + BEGIN_CALL (C_GetFunctionStatus); + IN_ULONG (session); + PROCESS_CALL ((session)); + END_CALL; +} + +static CK_RV +rpc_C_CancelFunction (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + + BEGIN_CALL (C_CancelFunction); + IN_ULONG (session); + PROCESS_CALL ((session)); + END_CALL; +} + +static CK_RV +rpc_C_GetSessionInfo (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_SESSION_INFO info; + + BEGIN_CALL (C_GetSessionInfo); + IN_ULONG (session); + PROCESS_CALL ((session, &info)); + OUT_SESSION_INFO (info); + END_CALL; +} + +static CK_RV +rpc_C_InitPIN (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_UTF8CHAR_PTR pin; + CK_ULONG pin_len; + + BEGIN_CALL (C_InitPIN); + IN_ULONG (session); + IN_BYTE_ARRAY (pin, pin_len); + PROCESS_CALL ((session, pin, pin_len)); + END_CALL; +} + +static CK_RV +rpc_C_SetPIN (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_UTF8CHAR_PTR old_pin; + CK_ULONG old_len; + CK_UTF8CHAR_PTR new_pin; + CK_ULONG new_len; + + BEGIN_CALL (C_SetPIN); + IN_ULONG (session); + IN_BYTE_ARRAY (old_pin, old_len); + IN_BYTE_ARRAY (new_pin, new_len); + PROCESS_CALL ((session, old_pin, old_len, new_pin, new_len)); + END_CALL; +} + +static CK_RV +rpc_C_GetOperationState (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR operation_state; + CK_ULONG operation_state_len; + + BEGIN_CALL (C_GetOperationState); + IN_ULONG (session); + IN_BYTE_BUFFER (operation_state, operation_state_len); + PROCESS_CALL ((session, operation_state, &operation_state_len)); + OUT_BYTE_ARRAY (operation_state, operation_state_len); + END_CALL; +} + +static CK_RV +rpc_C_SetOperationState (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR operation_state; + CK_ULONG operation_state_len; + CK_OBJECT_HANDLE encryption_key; + CK_OBJECT_HANDLE authentication_key; + + BEGIN_CALL (C_SetOperationState); + IN_ULONG (session); + IN_BYTE_ARRAY (operation_state, operation_state_len); + IN_ULONG (encryption_key); + IN_ULONG (authentication_key); + PROCESS_CALL ((session, operation_state, operation_state_len, encryption_key, authentication_key)); + END_CALL; +} + +static CK_RV +rpc_C_Login (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_USER_TYPE user_type; + CK_UTF8CHAR_PTR pin; + CK_ULONG pin_len; + + BEGIN_CALL (C_Login); + IN_ULONG (session); + IN_ULONG (user_type); + IN_BYTE_ARRAY (pin, pin_len); + PROCESS_CALL ((session, user_type, pin, pin_len)); + END_CALL; +} + +static CK_RV +rpc_C_Logout (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + + BEGIN_CALL (C_Logout); + IN_ULONG (session); + PROCESS_CALL ((session)); + END_CALL; +} + +/* ----------------------------------------------------------------------------- + * OBJECT OPERATIONS + */ + +static CK_RV +rpc_C_CreateObject (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_ATTRIBUTE_PTR template; + CK_ULONG count; + CK_OBJECT_HANDLE new_object; + + BEGIN_CALL (C_CreateObject); + IN_ULONG (session); + IN_ATTRIBUTE_ARRAY (template, count); + PROCESS_CALL ((session, template, count, &new_object)); + OUT_ULONG (new_object); + END_CALL; +} + +static CK_RV +rpc_C_CopyObject (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_OBJECT_HANDLE object; + CK_ATTRIBUTE_PTR template; + CK_ULONG count; + CK_OBJECT_HANDLE new_object; + + BEGIN_CALL (C_CopyObject); + IN_ULONG (session); + IN_ULONG (object); + IN_ATTRIBUTE_ARRAY (template, count); + PROCESS_CALL ((session, object, template, count, &new_object)); + OUT_ULONG (new_object); + END_CALL; +} + +static CK_RV +rpc_C_DestroyObject (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_OBJECT_HANDLE object; + + BEGIN_CALL (C_DestroyObject); + IN_ULONG (session); + IN_ULONG (object); + PROCESS_CALL ((session, object)); + END_CALL; +} + +static CK_RV +rpc_C_GetObjectSize (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_OBJECT_HANDLE object; + CK_ULONG size; + + BEGIN_CALL (C_GetObjectSize); + IN_ULONG (session); + IN_ULONG (object); + PROCESS_CALL ((session, object, &size)); + OUT_ULONG (size); + END_CALL; +} + +static CK_RV +rpc_C_GetAttributeValue (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_OBJECT_HANDLE object; + CK_ATTRIBUTE_PTR template; + CK_ULONG count; + + BEGIN_CALL (C_GetAttributeValue); + IN_ULONG (session); + IN_ULONG (object); + IN_ATTRIBUTE_BUFFER (template, count); + PROCESS_CALL ((session, object, template, count)); + OUT_ATTRIBUTE_ARRAY (template, count); + END_CALL; +} + +static CK_RV +rpc_C_SetAttributeValue (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_OBJECT_HANDLE object; + CK_ATTRIBUTE_PTR template; + CK_ULONG count; + + BEGIN_CALL (C_SetAttributeValue); + IN_ULONG (session); + IN_ULONG (object); + IN_ATTRIBUTE_ARRAY (template, count); + PROCESS_CALL ((session, object, template, count)); + END_CALL; +} + +static CK_RV +rpc_C_FindObjectsInit (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_ATTRIBUTE_PTR template; + CK_ULONG count; + + BEGIN_CALL (C_FindObjectsInit); + IN_ULONG (session); + IN_ATTRIBUTE_ARRAY (template, count); + PROCESS_CALL ((session, template, count)); + END_CALL; +} + +static CK_RV +rpc_C_FindObjects (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_OBJECT_HANDLE_PTR objects; + CK_ULONG max_object_count; + CK_ULONG object_count; + + BEGIN_CALL (C_FindObjects); + IN_ULONG (session); + IN_ULONG_BUFFER (objects, max_object_count); + PROCESS_CALL ((session, objects, max_object_count, &object_count)); + OUT_ULONG_ARRAY (objects, object_count); + END_CALL; +} + +static CK_RV +rpc_C_FindObjectsFinal (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + + BEGIN_CALL (C_FindObjectsFinal); + IN_ULONG (session); + PROCESS_CALL ((session)); + END_CALL; +} + +static CK_RV +rpc_C_EncryptInit (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + CK_OBJECT_HANDLE key; + + BEGIN_CALL (C_EncryptInit); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (key); + PROCESS_CALL ((session, &mechanism, key)); + END_CALL; + +} + +static CK_RV +rpc_C_Encrypt (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR data; + CK_ULONG data_len; + CK_BYTE_PTR encrypted_data; + CK_ULONG encrypted_data_len; + + BEGIN_CALL (C_Encrypt); + IN_ULONG (session); + IN_BYTE_ARRAY (data, data_len); + IN_BYTE_BUFFER (encrypted_data, encrypted_data_len); + PROCESS_CALL ((session, data, data_len, encrypted_data, &encrypted_data_len)); + OUT_BYTE_ARRAY (encrypted_data, encrypted_data_len); + END_CALL; +} + +static CK_RV +rpc_C_EncryptUpdate (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR part; + CK_ULONG part_len; + CK_BYTE_PTR encrypted_part; + CK_ULONG encrypted_part_len; + + BEGIN_CALL (C_EncryptUpdate); + IN_ULONG (session); + IN_BYTE_ARRAY (part, part_len); + IN_BYTE_BUFFER (encrypted_part, encrypted_part_len); + PROCESS_CALL ((session, part, part_len, encrypted_part, &encrypted_part_len)); + OUT_BYTE_ARRAY (encrypted_part, encrypted_part_len); + END_CALL; +} + +static CK_RV +rpc_C_EncryptFinal (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR last_encrypted_part; + CK_ULONG last_encrypted_part_len; + + BEGIN_CALL (C_EncryptFinal); + IN_ULONG (session); + IN_BYTE_BUFFER (last_encrypted_part, last_encrypted_part_len); + PROCESS_CALL ((session, last_encrypted_part, &last_encrypted_part_len)); + OUT_BYTE_ARRAY (last_encrypted_part, last_encrypted_part_len); + END_CALL; +} + +static CK_RV +rpc_C_DecryptInit (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + CK_OBJECT_HANDLE key; + + BEGIN_CALL (C_DecryptInit); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (key); + PROCESS_CALL ((session, &mechanism, key)); + END_CALL; +} + +static CK_RV +rpc_C_Decrypt (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR encrypted_data; + CK_ULONG encrypted_data_len; + CK_BYTE_PTR data; + CK_ULONG data_len; + + BEGIN_CALL (C_Decrypt); + IN_ULONG (session); + IN_BYTE_ARRAY (encrypted_data, encrypted_data_len); + IN_BYTE_BUFFER (data, data_len); + PROCESS_CALL ((session, encrypted_data, encrypted_data_len, data, &data_len)); + OUT_BYTE_ARRAY (data, data_len); + END_CALL; +} + +static CK_RV +rpc_C_DecryptUpdate (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR encrypted_part; + CK_ULONG encrypted_part_len; + CK_BYTE_PTR part; + CK_ULONG part_len; + + BEGIN_CALL (C_DecryptUpdate); + IN_ULONG (session); + IN_BYTE_ARRAY (encrypted_part, encrypted_part_len); + IN_BYTE_BUFFER (part, part_len); + PROCESS_CALL ((session, encrypted_part, encrypted_part_len, part, &part_len)); + OUT_BYTE_ARRAY (part, part_len); + END_CALL; +} + +static CK_RV +rpc_C_DecryptFinal (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR last_part; + CK_ULONG last_part_len; + + BEGIN_CALL (C_DecryptFinal); + IN_ULONG (session); + IN_BYTE_BUFFER (last_part, last_part_len); + PROCESS_CALL ((session, last_part, &last_part_len)); + OUT_BYTE_ARRAY (last_part, last_part_len); + END_CALL; +} + +static CK_RV +rpc_C_DigestInit (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + + BEGIN_CALL (C_DigestInit); + IN_ULONG (session); + IN_MECHANISM (mechanism); + PROCESS_CALL ((session, &mechanism)); + END_CALL; +} + +static CK_RV +rpc_C_Digest (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR data; + CK_ULONG data_len; + CK_BYTE_PTR digest; + CK_ULONG digest_len; + + BEGIN_CALL (C_Digest); + IN_ULONG (session); + IN_BYTE_ARRAY (data, data_len); + IN_BYTE_BUFFER (digest, digest_len); + PROCESS_CALL ((session, data, data_len, digest, &digest_len)); + OUT_BYTE_ARRAY (digest, digest_len); + END_CALL; +} + +static CK_RV +rpc_C_DigestUpdate (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR part; + CK_ULONG part_len; + + BEGIN_CALL (C_DigestUpdate); + IN_ULONG (session); + IN_BYTE_ARRAY (part, part_len); + PROCESS_CALL ((session, part, part_len)); + END_CALL; +} + +static CK_RV +rpc_C_DigestKey (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_OBJECT_HANDLE key; + + BEGIN_CALL (C_DigestKey); + IN_ULONG (session); + IN_ULONG (key); + PROCESS_CALL ((session, key)); + END_CALL; +} + +static CK_RV +rpc_C_DigestFinal (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR digest; + CK_ULONG digest_len; + + BEGIN_CALL (C_DigestFinal); + IN_ULONG (session); + IN_BYTE_BUFFER (digest, digest_len); + PROCESS_CALL ((session, digest, &digest_len)); + OUT_BYTE_ARRAY (digest, digest_len); + END_CALL; +} + +static CK_RV +rpc_C_SignInit (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + CK_OBJECT_HANDLE key; + + BEGIN_CALL (C_SignInit); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (key); + PROCESS_CALL ((session, &mechanism, key)); + END_CALL; +} + +static CK_RV +rpc_C_Sign (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR part; + CK_ULONG part_len; + CK_BYTE_PTR signature; + CK_ULONG signature_len; + + BEGIN_CALL (C_Sign); + IN_ULONG (session); + IN_BYTE_ARRAY (part, part_len); + IN_BYTE_BUFFER (signature, signature_len); + PROCESS_CALL ((session, part, part_len, signature, &signature_len)); + OUT_BYTE_ARRAY (signature, signature_len); + END_CALL; + +} + +static CK_RV +rpc_C_SignUpdate (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR part; + CK_ULONG part_len; + + BEGIN_CALL (C_SignUpdate); + IN_ULONG (session); + IN_BYTE_ARRAY (part, part_len); + PROCESS_CALL ((session, part, part_len)); + END_CALL; +} + +static CK_RV +rpc_C_SignFinal (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR signature; + CK_ULONG signature_len; + + BEGIN_CALL (C_SignFinal); + IN_ULONG (session); + IN_BYTE_BUFFER (signature, signature_len); + PROCESS_CALL ((session, signature, &signature_len)); + OUT_BYTE_ARRAY (signature, signature_len); + END_CALL; +} + +static CK_RV +rpc_C_SignRecoverInit (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + CK_OBJECT_HANDLE key; + + BEGIN_CALL (C_SignRecoverInit); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (key); + PROCESS_CALL ((session, &mechanism, key)); + END_CALL; +} + +static CK_RV +rpc_C_SignRecover (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR data; + CK_ULONG data_len; + CK_BYTE_PTR signature; + CK_ULONG signature_len; + + BEGIN_CALL (C_SignRecover); + IN_ULONG (session); + IN_BYTE_ARRAY (data, data_len); + IN_BYTE_BUFFER (signature, signature_len); + PROCESS_CALL ((session, data, data_len, signature, &signature_len)); + OUT_BYTE_ARRAY (signature, signature_len); + END_CALL; +} + +static CK_RV +rpc_C_VerifyInit (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + CK_OBJECT_HANDLE key; + + BEGIN_CALL (C_VerifyInit); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (key); + PROCESS_CALL ((session, &mechanism, key)); + END_CALL; +} + +static CK_RV +rpc_C_Verify (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR data; + CK_ULONG data_len; + CK_BYTE_PTR signature; + CK_ULONG signature_len; + + BEGIN_CALL (C_Verify); + IN_ULONG (session); + IN_BYTE_ARRAY (data, data_len); + IN_BYTE_ARRAY (signature, signature_len); + PROCESS_CALL ((session, data, data_len, signature, signature_len)); + END_CALL; +} + +static CK_RV +rpc_C_VerifyUpdate (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR part; + CK_ULONG part_len; + + BEGIN_CALL (C_VerifyUpdate); + IN_ULONG (session); + IN_BYTE_ARRAY (part, part_len); + PROCESS_CALL ((session, part, part_len)); + END_CALL; +} + +static CK_RV +rpc_C_VerifyFinal (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR signature; + CK_ULONG signature_len; + + BEGIN_CALL (C_VerifyFinal); + IN_ULONG (session); + IN_BYTE_ARRAY (signature, signature_len); + PROCESS_CALL ((session, signature, signature_len)); + END_CALL; +} + +static CK_RV +rpc_C_VerifyRecoverInit (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + CK_OBJECT_HANDLE key; + + BEGIN_CALL (C_VerifyRecoverInit); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (key); + PROCESS_CALL ((session, &mechanism, key)); + END_CALL; +} + +static CK_RV +rpc_C_VerifyRecover (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR signature; + CK_ULONG signature_len; + CK_BYTE_PTR data; + CK_ULONG data_len; + + BEGIN_CALL (C_VerifyRecover); + IN_ULONG (session); + IN_BYTE_ARRAY (signature, signature_len); + IN_BYTE_BUFFER (data, data_len); + PROCESS_CALL ((session, signature, signature_len, data, &data_len)); + OUT_BYTE_ARRAY (data, data_len); + END_CALL; +} + +static CK_RV +rpc_C_DigestEncryptUpdate (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR part; + CK_ULONG part_len; + CK_BYTE_PTR encrypted_part; + CK_ULONG encrypted_part_len; + + BEGIN_CALL (C_DigestEncryptUpdate); + IN_ULONG (session); + IN_BYTE_ARRAY (part, part_len); + IN_BYTE_BUFFER (encrypted_part, encrypted_part_len); + PROCESS_CALL ((session, part, part_len, encrypted_part, &encrypted_part_len)); + OUT_BYTE_ARRAY (encrypted_part, encrypted_part_len); + END_CALL; +} + +static CK_RV +rpc_C_DecryptDigestUpdate (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR encrypted_part; + CK_ULONG encrypted_part_len; + CK_BYTE_PTR part; + CK_ULONG part_len; + + BEGIN_CALL (C_DecryptDigestUpdate); + IN_ULONG (session); + IN_BYTE_ARRAY (encrypted_part, encrypted_part_len); + IN_BYTE_BUFFER (part, part_len); + PROCESS_CALL ((session, encrypted_part, encrypted_part_len, part, &part_len)); + OUT_BYTE_ARRAY (part, part_len); + END_CALL; +} + +static CK_RV +rpc_C_SignEncryptUpdate (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR part; + CK_ULONG part_len; + CK_BYTE_PTR encrypted_part; + CK_ULONG encrypted_part_len; + + BEGIN_CALL (C_SignEncryptUpdate); + IN_ULONG (session); + IN_BYTE_ARRAY (part, part_len); + IN_BYTE_BUFFER (encrypted_part, encrypted_part_len); + PROCESS_CALL ((session, part, part_len, encrypted_part, &encrypted_part_len)); + OUT_BYTE_ARRAY (encrypted_part, encrypted_part_len); + END_CALL; +} + +static CK_RV +rpc_C_DecryptVerifyUpdate (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR encrypted_part; + CK_ULONG encrypted_part_len; + CK_BYTE_PTR part; + CK_ULONG part_len; + + BEGIN_CALL (C_DecryptVerifyUpdate); + IN_ULONG (session); + IN_BYTE_ARRAY (encrypted_part, encrypted_part_len); + IN_BYTE_BUFFER (part, part_len); + PROCESS_CALL ((session, encrypted_part, encrypted_part_len, part, &part_len)); + OUT_BYTE_ARRAY (part, part_len); + END_CALL; +} + +static CK_RV +rpc_C_GenerateKey (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + CK_ATTRIBUTE_PTR template; + CK_ULONG count; + CK_OBJECT_HANDLE key; + + BEGIN_CALL (C_GenerateKey); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ATTRIBUTE_ARRAY (template, count); + PROCESS_CALL ((session, &mechanism, template, count, &key)); + OUT_ULONG (key); + END_CALL; +} + +static CK_RV +rpc_C_GenerateKeyPair (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + CK_ATTRIBUTE_PTR public_key_template; + CK_ULONG public_key_attribute_count; + CK_ATTRIBUTE_PTR private_key_template; + CK_ULONG private_key_attribute_count; + CK_OBJECT_HANDLE public_key; + CK_OBJECT_HANDLE private_key; + + BEGIN_CALL (C_GenerateKeyPair); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ATTRIBUTE_ARRAY (public_key_template, public_key_attribute_count); + IN_ATTRIBUTE_ARRAY (private_key_template, private_key_attribute_count); + PROCESS_CALL ((session, &mechanism, public_key_template, public_key_attribute_count, private_key_template, private_key_attribute_count, &public_key, &private_key)); + OUT_ULONG (public_key); + OUT_ULONG (private_key); + END_CALL; +} + +static CK_RV +rpc_C_WrapKey (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + CK_OBJECT_HANDLE wrapping_key; + CK_OBJECT_HANDLE key; + CK_BYTE_PTR wrapped_key; + CK_ULONG wrapped_key_len; + + BEGIN_CALL (C_WrapKey); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (wrapping_key); + IN_ULONG (key); + IN_BYTE_BUFFER (wrapped_key, wrapped_key_len); + PROCESS_CALL ((session, &mechanism, wrapping_key, key, wrapped_key, &wrapped_key_len)); + OUT_BYTE_ARRAY (wrapped_key, wrapped_key_len); + END_CALL; +} + +static CK_RV +rpc_C_UnwrapKey (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + CK_OBJECT_HANDLE unwrapping_key; + CK_BYTE_PTR wrapped_key; + CK_ULONG wrapped_key_len; + CK_ATTRIBUTE_PTR template; + CK_ULONG attribute_count; + CK_OBJECT_HANDLE key; + + BEGIN_CALL (C_UnwrapKey); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (unwrapping_key); + IN_BYTE_ARRAY (wrapped_key, wrapped_key_len); + IN_ATTRIBUTE_ARRAY (template, attribute_count); + PROCESS_CALL ((session, &mechanism, unwrapping_key, wrapped_key, wrapped_key_len, template, attribute_count, &key)); + OUT_ULONG (key); + END_CALL; +} + +static CK_RV +rpc_C_DeriveKey (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + CK_OBJECT_HANDLE base_key; + CK_ATTRIBUTE_PTR template; + CK_ULONG attribute_count; + CK_OBJECT_HANDLE key; + + BEGIN_CALL (C_DeriveKey); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (base_key); + IN_ATTRIBUTE_ARRAY (template, attribute_count); + PROCESS_CALL ((session, &mechanism, base_key, template, attribute_count, &key)); + OUT_ULONG (key); + END_CALL; +} + +static CK_RV +rpc_C_SeedRandom (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR seed; + CK_ULONG seed_len; + + BEGIN_CALL (C_SeedRandom); + IN_ULONG (session); + IN_BYTE_ARRAY (seed, seed_len); + PROCESS_CALL ((session, seed, seed_len)); + END_CALL; +} + +static CK_RV +rpc_C_GenerateRandom (CK_FUNCTION_LIST_PTR module, + RpcMessage *msg) +{ + CK_SESSION_HANDLE session; + CK_BYTE_PTR random_data; + CK_ULONG random_len; + + BEGIN_CALL (C_GenerateRandom); + IN_ULONG (session); + IN_BYTE_BUFFER (random_data, random_len); + PROCESS_CALL ((session, random_data, random_len)); + OUT_BYTE_ARRAY (random_data, random_len); + END_CALL; +} + +int +_p11_rpc_server_perform (CK_FUNCTION_LIST_PTR module, + unsigned char **data, + size_t *n_data) +{ + RpcMessage msg; + CK_RV ret; + int req_id; + + assert (module != NULL); + assert (data != NULL); + assert (n_data != NULL); + + _p11_rpc_message_init (&msg, log_allocator); + _p11_buffer_init_allocated (&msg.buffer, *data, *n_data, log_allocator); + + if (!_p11_rpc_message_parse (&msg, RPC_REQUEST)) { + _p11_rpc_message_clear (&msg); + return 0; + } + + /* This should have been checked by the parsing code */ + assert (msg.call_id > RPC_CALL_ERROR); + assert (msg.call_id < RPC_CALL_MAX); + req_id = msg.call_id; + + switch(req_id) { + #define CASE_CALL(name) \ + case RPC_CALL_##name: \ + ret = rpc_##name (module, &msg); \ + break; + CASE_CALL (C_Initialize) + CASE_CALL (C_Finalize) + CASE_CALL (C_GetInfo) + CASE_CALL (C_GetSlotList) + CASE_CALL (C_GetSlotInfo) + CASE_CALL (C_GetTokenInfo) + CASE_CALL (C_GetMechanismList) + CASE_CALL (C_GetMechanismInfo) + CASE_CALL (C_InitToken) + CASE_CALL (C_WaitForSlotEvent) + CASE_CALL (C_OpenSession) + CASE_CALL (C_CloseSession) + CASE_CALL (C_CloseAllSessions) + CASE_CALL (C_GetFunctionStatus) + CASE_CALL (C_CancelFunction) + CASE_CALL (C_GetSessionInfo) + CASE_CALL (C_InitPIN) + CASE_CALL (C_SetPIN) + CASE_CALL (C_GetOperationState) + CASE_CALL (C_SetOperationState) + CASE_CALL (C_Login) + CASE_CALL (C_Logout) + CASE_CALL (C_CreateObject) + CASE_CALL (C_CopyObject) + CASE_CALL (C_DestroyObject) + CASE_CALL (C_GetObjectSize) + CASE_CALL (C_GetAttributeValue) + CASE_CALL (C_SetAttributeValue) + CASE_CALL (C_FindObjectsInit) + CASE_CALL (C_FindObjects) + CASE_CALL (C_FindObjectsFinal) + CASE_CALL (C_EncryptInit) + CASE_CALL (C_Encrypt) + CASE_CALL (C_EncryptUpdate) + CASE_CALL (C_EncryptFinal) + CASE_CALL (C_DecryptInit) + CASE_CALL (C_Decrypt) + CASE_CALL (C_DecryptUpdate) + CASE_CALL (C_DecryptFinal) + CASE_CALL (C_DigestInit) + CASE_CALL (C_Digest) + CASE_CALL (C_DigestUpdate) + CASE_CALL (C_DigestKey) + CASE_CALL (C_DigestFinal) + CASE_CALL (C_SignInit) + CASE_CALL (C_Sign) + CASE_CALL (C_SignUpdate) + CASE_CALL (C_SignFinal) + CASE_CALL (C_SignRecoverInit) + CASE_CALL (C_SignRecover) + CASE_CALL (C_VerifyInit) + CASE_CALL (C_Verify) + CASE_CALL (C_VerifyUpdate) + CASE_CALL (C_VerifyFinal) + CASE_CALL (C_VerifyRecoverInit) + CASE_CALL (C_VerifyRecover) + CASE_CALL (C_DigestEncryptUpdate) + CASE_CALL (C_DecryptDigestUpdate) + CASE_CALL (C_SignEncryptUpdate) + CASE_CALL (C_DecryptVerifyUpdate) + CASE_CALL (C_GenerateKey) + CASE_CALL (C_GenerateKeyPair) + CASE_CALL (C_WrapKey) + CASE_CALL (C_UnwrapKey) + CASE_CALL (C_DeriveKey) + CASE_CALL (C_SeedRandom) + CASE_CALL (C_GenerateRandom) + #undef CASE_CALL + default: + /* This should have been caught by the parse code */ + assert (0 && "Unchecked call"); + break; + }; + + if (ret == CKR_OK) { + if (_p11_rpc_message_buffer_error (&msg)) { + _p11_message ("out of memory error putting together message"); + ret = PREP_ERROR; + } + } + + /* A filled in response */ + if (ret == CKR_OK) { + + /* + * Since we're dealing with many many functions above generating + * these messages we want to make sure each of them actually + * does what it's supposed to. + */ + + assert (_p11_rpc_message_is_verified (&msg)); + assert (msg.call_type == RPC_RESPONSE); + assert (msg.call_id == req_id); + assert (rpc_calls[msg.call_id].response); + assert (strcmp (rpc_calls[msg.call_id].response, msg.signature) == 0); + + /* Fill in an error respnose */ + } else { + if (!_p11_rpc_message_prep (&msg, RPC_CALL_ERROR, RPC_RESPONSE) || + !_p11_rpc_message_write_ulong (&msg, (uint32_t)ret) || + _p11_rpc_message_buffer_error (&msg)) { + _p11_message ("out of memory responding with error"); + _p11_rpc_message_clear (&msg); + return 0; + } + } + + *data = _p11_buffer_uninit_steal (&msg.buffer, n_data); + _p11_rpc_message_clear (&msg); + return 1; +} diff --git a/p11-kit/rpc-server.h b/p11-kit/rpc-server.h new file mode 100644 index 0000000..bffa8fe --- /dev/null +++ b/p11-kit/rpc-server.h @@ -0,0 +1,32 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + Copyright (C) 2012 Stefan Walter + + The Gnome Keyring Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Keyring Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Stef Walter +*/ + +#ifndef __RPC_SERVER_H__ +#define __RPC_SERVER_H__ + +#include "pkcs11.h" + +int _p11_rpc_server_perform (CK_FUNCTION_LIST_PTR module, + unsigned char **data, + size_t *n_data); + +#endif /* __RPC_SERVER_H__ */ -- cgit v1.2.1