diff --git a/configure.ac b/configure.ac index fcd162fd8..9c5b6f079 100644 --- a/configure.ac +++ b/configure.ac @@ -195,22 +195,19 @@ if test "$with_libffi" != "no"; then AC_SUBST(LIBFFI_CFLAGS) AC_SUBST(LIBFFI_LIBS) - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $LIBFFI_CFLAGS" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], - [ #if FFI_CLOSURES - #else - #error no closures - #endif - ])], - [], [AC_MSG_ERROR([the libffi on this system has no support for closures.])]) - CFLAGS="$SAVE_CFLAGS" - with_libffi="yes" fi AM_CONDITIONAL(WITH_FFI, test "$with_libffi" = "yes") +AC_ARG_WITH([fixed-closure], + [AS_HELP_STRING([--with-fixed-closure=integer], [Precompile fallback closures if libffi closures are not available])], + [fixed_closure=$withval], + [fixed_closure=64]) + +AC_DEFINE_UNQUOTED(P11_VIRTUAL_MAX_FIXED, [$fixed_closure], [The number of fallback closures compiled in]) +AC_SUBST(fixed_closure) + # -------------------------------------------------------------------- # Hash implementation diff --git a/p11-kit/Makefile.am b/p11-kit/Makefile.am index 0b2778a7f..743571885 100644 --- a/p11-kit/Makefile.am +++ b/p11-kit/Makefile.am @@ -205,8 +205,6 @@ print_messages_LDADD = $(p11_kit_LIBS) frob_setuid_SOURCES = p11-kit/frob-setuid.c frob_setuid_LDADD = $(p11_kit_LIBS) -if WITH_FFI - CHECK_PROGS += \ test-virtual \ test-managed \ @@ -226,8 +224,6 @@ test_transport_LDADD = $(p11_kit_LIBS) test_virtual_SOURCES = p11-kit/test-virtual.c test_virtual_LDADD = $(p11_kit_LIBS) -endif - noinst_LTLIBRARIES += \ mock-one.la \ mock-two.la \ diff --git a/p11-kit/gen-wrapper.py b/p11-kit/gen-wrapper.py index 03cad1e4a..b3db0c2ed 100644 --- a/p11-kit/gen-wrapper.py +++ b/p11-kit/gen-wrapper.py @@ -410,6 +410,114 @@ def wrapper_function_name(self, function): return 'binding_C_{function}'.format(function=function.name) +class FixedFunctionTemplate(FunctionTemplate): + def __init__(self): + super(FixedFunctionTemplate, self).__init__('''\ +static CK_RV \\ +${wrapper_function_name} (${arglist}) \\ +{ \\ + CK_FUNCTION_LIST *bound; \\ + Wrapper *wrapper; \\ + CK_X_FUNCTION_LIST *funcs; \\ + bound = fixed_closures[fixed_index]; \\ + return_val_if_fail (bound != NULL, CKR_GENERAL_ERROR); \\ + wrapper = (Wrapper *) bound; \\ + funcs = &wrapper->virt->funcs; \\ + return funcs->C_${function_name} (funcs, ${args}); \\ +} \\ +\\''') + + @property + def arglist(self): + function = self.substitute_kwargs['function'] + return self.format_arglist(function.args, sep=', \\\n') + + +class FixedFunctionListTemplate(FunctionListTemplate): + def __init__(self): + super(FixedFunctionListTemplate, self).__init__( + '''\ +#define P11_VIRTUAL_FIXED_FUNCTIONS(fixed_index) \\ +${function_list} +static CK_RV \\ +fixed ## fixed_index ## _C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list); + +#define P11_VIRTUAL_FIXED_GET_FUNCTION_LIST(fixed_index) \\ +static CK_RV \\ +fixed ## fixed_index ## _C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list) \\ +{ \\ + if (!list) \\ + return CKR_ARGUMENTS_BAD; \\ + *list = fixed_closures[fixed_index]; \\ + return CKR_OK; \\ +} + +#define P11_VIRTUAL_FIXED_INITIALIZER(fixed_index) \\ +{ \\ + { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR }, /* version */ \\ +${initializer_list} \\ +} + +${fixed_function_list} + +CK_FUNCTION_LIST p11_virtual_fixed[P11_VIRTUAL_MAX_FIXED] = { +${fixed_initializer_list} +}; + +${fixed_get_function_list} +''', + FixedFunctionTemplate()) + + def wrapper_function_name(self, function): + return 'fixed ## fixed_index ## _C_{function}'.format( + function=function.name) + + @property + def fixed_function_list(self): + fixed_number = self.substitute_kwargs['fixed_number'] + initializers = [ + 'P11_VIRTUAL_FIXED_FUNCTIONS({fixed_index})'.format( + fixed_index=fixed_index) + for fixed_index in range(0, fixed_number) + ] + return '\n'.join(initializers) + + @property + def fixed_initializer_list(self): + fixed_number = self.substitute_kwargs['fixed_number'] + initializers = [ + '\tP11_VIRTUAL_FIXED_INITIALIZER({fixed_index})'.format( + fixed_index=fixed_index) + for fixed_index in range(0, fixed_number) + ] + return ', \\\n'.join(initializers) + + @property + def fixed_get_function_list(self): + fixed_number = self.substitute_kwargs['fixed_number'] + initializers = [ + 'P11_VIRTUAL_FIXED_GET_FUNCTION_LIST({fixed_index})'.format( + fixed_index=fixed_index) + for fixed_index in range(0, fixed_number) + ] + return '\n'.join(initializers) + + def excluded_functions(self): + return ['GetFunctionList'] + list(P11_SHORT_FUNCTIONS) + + @property + def initializer_list(self): + result = list() + parser = self.substitute_kwargs['parser'] + for function in parser.functions: + short_function_name = P11_SHORT_FUNCTIONS.get(function.name) + if short_function_name: + result.append('\t' + short_function_name) + else: + result.append('\t' + self.wrapper_function_name(function)) + return ', \\\n'.join(result) + + class MaxFunctionsTemplate(Template): def __init__(self): super(MaxFunctionsTemplate, self).__init__('${max_functions}') @@ -434,13 +542,9 @@ def max_args(self): class FunctionInfoTemplate(FunctionTemplate): def __init__(self): super(FunctionInfoTemplate, self).__init__('''\ - { FUNCTION (${function_name}), { ${args}, NULL } },\ + { FUNCTION (${function_name}) },\ ''') - def format_args(self, args, sep=', '): - l = [type_to_ffi_type(arg.type) for arg in args] - return sep.join(l).strip() - class FunctionInfoListTemplate(FunctionListTemplate): def __init__(self): @@ -460,6 +564,34 @@ def wrapper_function_name(self, function): return function.name +class BindingInfoTemplate(FunctionTemplate): + def __init__(self): + super(BindingInfoTemplate, self).__init__('''\ + { binding_C_##${function_name}, { ${args}, NULL } },\ +''') + + def format_args(self, args, sep=', '): + l = [type_to_ffi_type(arg.type) for arg in args] + return sep.join(l).strip() + + +class BindingInfoListTemplate(FunctionListTemplate): + def __init__(self): + super(BindingInfoListTemplate, self).__init__( + '''\ +static const BindingInfo binding_info[] = { +${function_list} + { 0, } +}; +''', + BindingInfoTemplate()) + + def excluded_functions(self): + return ['GetFunctionList'] + list(P11_SHORT_FUNCTIONS) + + def wrapper_function_name(self, function): + return function.name + class FileTemplate(Template): def __init__(self, infile): super(FileTemplate, self).__init__(infile.read()) @@ -479,6 +611,11 @@ def binding_function_list(self): template = BindingFunctionListTemplate() return template.substitute(**self.substitute_kwargs) + @property + def fixed_function_list(self): + template = FixedFunctionListTemplate() + return template.substitute(**self.substitute_kwargs) + @property def max_functions(self): template = MaxFunctionsTemplate() @@ -494,6 +631,11 @@ def function_info_list(self): template = FunctionInfoListTemplate() return template.substitute(**self.substitute_kwargs) + @property + def binding_info_list(self): + template = BindingInfoListTemplate() + return template.substitute(**self.substitute_kwargs) + if __name__ == '__main__': import argparse @@ -504,9 +646,12 @@ def function_info_list(self): help='the pkcs11.h header file') parser.add_argument('pkcs11i', type=argparse.FileType('r'), help='the pkcs11i.h header file') + parser.add_argument('-n', '--fixed-number', type=int, + default=64, + help='exclude functions') args = parser.parse_args() parser = Parser() parser.parse(args.pkcs11, args.pkcs11i) template = FileTemplate(args.template) - print(template.substitute(parser=parser)) + print(template.substitute(parser=parser, fixed_number=args.fixed_number)) diff --git a/p11-kit/modules.c b/p11-kit/modules.c index fc456ce7b..e49e5e8fe 100644 --- a/p11-kit/modules.c +++ b/p11-kit/modules.c @@ -1758,22 +1758,11 @@ lookup_managed_option (Module *mod, value = _p11_conf_parse_boolean (string, def_value); if (!supported && value != supported) { - if (!p11_virtual_can_wrap ()) { - /* - * This is because libffi dependency was not built. The libffi dependency - * is highly recommended and building without it results in a large loss - * of functionality. - */ - p11_message ("the '%s' option for module '%s' is not supported on this system", - option, mod->name); - } else { - /* - * This is because the module is running in unmanaged mode, so turn off the - */ - p11_message ("the '%s' option for module '%s' is only supported for managed modules", - option, mod->name); - } - return false; + /* + * This is because the module is running in unmanaged mode, so turn off the + */ + p11_message ("the '%s' option for module '%s' is only supported for managed modules", + option, mod->name); } return value; @@ -1795,7 +1784,6 @@ release_module_inlock_rentrant (CK_FUNCTION_LIST *module, assert_not_reached (); p11_virtual_unwrap (module); } - /* If an unmanaged module then caller should have finalized */ } else { mod = p11_dict_get (gl.unmanaged_by_funcs, module); @@ -1855,7 +1843,7 @@ prepare_module_inlock_reentrant (Module *mod, is_managed = false; with_log = false; } else { - is_managed = lookup_managed_option (mod, p11_virtual_can_wrap (), "managed", true); + is_managed = lookup_managed_option (mod, true, "managed", true); with_log = lookup_managed_option (mod, is_managed, "log-calls", false); } diff --git a/p11-kit/proxy.c b/p11-kit/proxy.c index c55451133..475aa1940 100644 --- a/p11-kit/proxy.c +++ b/p11-kit/proxy.c @@ -2364,7 +2364,7 @@ C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list) } } - if (rv == CKR_OK && p11_virtual_can_wrap ()) { + if (rv == CKR_OK) { state = calloc (1, sizeof (State)); if (!state) { rv = CKR_HOST_MEMORY; diff --git a/p11-kit/test-init.c b/p11-kit/test-init.c index c4fcecb87..18eb025d6 100644 --- a/p11-kit/test-init.c +++ b/p11-kit/test-init.c @@ -402,16 +402,14 @@ main (int argc, p11_library_init (); /* These only work when managed */ - if (p11_virtual_can_wrap ()) { - p11_test (test_recursive_initialization, "/init/test_recursive_initialization"); - p11_test (test_threaded_initialization, "/init/test_threaded_initialization"); - p11_test (test_mutexes, "/init/test_mutexes"); - p11_test (test_load_and_initialize, "/init/test_load_and_initialize"); + p11_test (test_recursive_initialization, "/init/test_recursive_initialization"); + p11_test (test_threaded_initialization, "/init/test_threaded_initialization"); + p11_test (test_mutexes, "/init/test_mutexes"); + p11_test (test_load_and_initialize, "/init/test_load_and_initialize"); #ifdef OS_UNIX - p11_test (test_fork_initialization, "/init/test_fork_initialization"); + p11_test (test_fork_initialization, "/init/test_fork_initialization"); #endif - } p11_test (test_initalize_fail, "/init/test_initalize_fail"); p11_test (test_finalize_fail, "/init/test_finalize_fail"); diff --git a/p11-kit/test-virtual.c b/p11-kit/test-virtual.c index e6428202e..fd9eba95c 100644 --- a/p11-kit/test-virtual.c +++ b/p11-kit/test-virtual.c @@ -162,7 +162,6 @@ main (int argc, mock_module_init (); p11_library_init (); - assert (p11_virtual_can_wrap ()); p11_test (test_initialize, "/virtual/test_initialize"); p11_test (test_fall_through, "/virtual/test_fall_through"); p11_test (test_get_function_list, "/virtual/test_get_function_list"); diff --git a/p11-kit/util.c b/p11-kit/util.c index 325d66904..816952f4d 100644 --- a/p11-kit/util.c +++ b/p11-kit/util.c @@ -45,6 +45,7 @@ #include "p11-kit.h" #include "private.h" #include "proxy.h" +#include "virtual.h" #include #include @@ -251,6 +252,7 @@ void _p11_kit_init (void) { p11_library_init_once (); + p11_virtual_init_fixed (); } #ifdef __GNUC__ @@ -260,6 +262,7 @@ void _p11_kit_fini (void) { p11_proxy_module_cleanup (); + p11_virtual_uninit_fixed (); p11_library_uninit (); } @@ -277,12 +280,14 @@ DllMain (HINSTANCE instance, switch (reason) { case DLL_PROCESS_ATTACH: p11_library_init (); + p11_virtual_init_fixed (); break; case DLL_THREAD_DETACH: p11_library_thread_cleanup (); break; case DLL_PROCESS_DETACH: p11_proxy_module_cleanup (); + p11_virtual_uninit_fixed (); p11_library_uninit (); break; default: diff --git a/p11-kit/virtual.c.template b/p11-kit/virtual.c.template index 4e190f4ab..392c81b9f 100644 --- a/p11-kit/virtual.c.template +++ b/p11-kit/virtual.c.template @@ -46,7 +46,7 @@ #include #include -#ifdef WITH_FFI +#if defined(WITH_FFI) && WITH_FFI /* * We use libffi to build closures. Note that even with libffi certain @@ -61,9 +61,7 @@ */ #define LIBFFI_FREE_CLOSURES 0 -#include "ffi.h" -#ifndef FFI_CLOSURES -#error "FFI_CLOSURES should be checked in configure.ac" +#include #endif /* There are ${max_functions} functions in PKCS#11, with a maximum of ${max_args} args */ @@ -78,12 +76,46 @@ typedef struct { p11_virtual *virt; p11_destroyer destroyer; +#if defined(FFI_CLOSURES) && FFI_CLOSURES /* A list of our libffi built closures, for cleanup later */ ffi_closure *ffi_closures[MAX_FUNCTIONS]; ffi_cif ffi_cifs[MAX_FUNCTIONS]; int ffi_used; +#endif /* FFI_CLOSURES */ + + int fixed_index; } Wrapper; +static p11_mutex_t fixed_mutex; +static CK_FUNCTION_LIST *fixed_closures[P11_VIRTUAL_MAX_FIXED]; + +static Wrapper *create_fixed_wrapper (p11_virtual *virt, + size_t index, + p11_destroyer destroyer); +static CK_FUNCTION_LIST * + p11_virtual_wrap_fixed (p11_virtual *virt, + p11_destroyer destroyer); +static void + p11_virtual_unwrap_fixed + (CK_FUNCTION_LIST_PTR module); + +void +p11_virtual_init_fixed (void) +{ + p11_lock (); + p11_mutex_init (&fixed_mutex); + memset (fixed_closures, 0, sizeof (fixed_closures)); + p11_unlock (); +} + +void +p11_virtual_uninit_fixed (void) +{ + p11_lock (); + p11_mutex_uninit (&fixed_mutex); + p11_unlock (); +} + static CK_RV short_C_GetFunctionStatus (CK_SESSION_HANDLE handle) { @@ -96,6 +128,8 @@ short_C_CancelFunction (CK_SESSION_HANDLE handle) return CKR_FUNCTION_NOT_PARALLEL; } +#if defined(FFI_CLOSURES) && FFI_CLOSURES + static void binding_C_GetFunctionList (ffi_cif *cif, CK_RV *ret, @@ -114,7 +148,7 @@ binding_C_GetFunctionList (ffi_cif *cif, ${binding_function_list} -#endif /* WITH_FFI */ +#endif /* FFI_CLOSURES */ ${stack_function_list} ${base_function_list} @@ -137,16 +171,55 @@ p11_virtual_uninit (p11_virtual *virt) (virt->lower_destroy) (virt->lower_module); } -#ifdef WITH_FFI +bool +p11_virtual_is_wrapper (CK_FUNCTION_LIST_PTR module) +{ + /* + * We use these functions as a marker to indicate whether this is + * one of our CK_FUNCTION_LIST_PTR sets of functions or not. These + * functions are defined to always have the same standard implementation + * in PKCS#11 2.x so we don't need to call through to the base for + * these guys. + */ + return (module->C_GetFunctionStatus == short_C_GetFunctionStatus && + module->C_CancelFunction == short_C_CancelFunction); +} + +void +p11_virtual_unwrap (CK_FUNCTION_LIST_PTR module) +{ + Wrapper *wrapper; + + return_if_fail (p11_virtual_is_wrapper (module)); + + /* The bound CK_FUNCTION_LIST_PTR sits at the front of Context */ + wrapper = (Wrapper *)module; + + if (wrapper->fixed_index >= 0) + p11_virtual_unwrap_fixed (module); + + /* + * Make sure that the CK_FUNCTION_LIST_PTR is invalid, and that + * p11_virtual_is_wrapper() recognizes this. This is in case the + * destroyer callback tries to do something fancy. + */ + memset (&wrapper->bound, 0xFE, sizeof (wrapper->bound)); + + if (wrapper->destroyer) + (wrapper->destroyer) (wrapper->virt); + +#if defined(LIBFFI_FREE_CLOSURES) && LIBFFI_FREE_CLOSURES + uninit_wrapper_funcs (wrapper); +#endif + free (wrapper); +} typedef struct { const char *name; - void *binding_function; void *stack_fallback; size_t virtual_offset; void *base_fallback; size_t module_offset; - ffi_type *types[MAX_ARGS+1]; } FunctionInfo; #define STRUCT_OFFSET(struct_type, member) \ @@ -157,12 +230,10 @@ typedef struct { (*(member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset))) #define FUNCTION(name) \ - #name, binding_C_##name, \ + #name, \ stack_C_##name, STRUCT_OFFSET (CK_X_FUNCTION_LIST, C_##name), \ base_C_##name, STRUCT_OFFSET (CK_FUNCTION_LIST, C_##name) -${function_info_list} - static bool lookup_fall_through (p11_virtual *virt, const FunctionInfo *info, @@ -197,6 +268,16 @@ lookup_fall_through (p11_virtual *virt, return false; } +${function_info_list} + +#if defined(FFI_CLOSURES) && FFI_CLOSURES +typedef struct { + void *function; + ffi_type *types[MAX_ARGS+1]; +} BindingInfo; + +${binding_info_list} + static bool bind_ffi_closure (Wrapper *wrapper, void *binding_data, @@ -274,9 +355,10 @@ init_wrapper_funcs (Wrapper *wrapper) * fall through, then this returns the original module function. */ if (!lookup_fall_through (wrapper->virt, info, bound)) { + BindingInfo *binding = binding_info + i; if (!bind_ffi_closure (wrapper, over, - info->binding_function, - (ffi_type **)info->types, bound)) + binding->function, + (ffi_type **)binding->types, bound)) return_val_if_reached (false); } } @@ -312,9 +394,9 @@ uninit_wrapper_funcs (Wrapper *wrapper) } #endif -CK_FUNCTION_LIST * -p11_virtual_wrap (p11_virtual *virt, - p11_destroyer destroyer) +static Wrapper * +create_ffi_wrapper (p11_virtual *virt, + p11_destroyer destroyer) { Wrapper *wrapper; @@ -327,6 +409,7 @@ p11_virtual_wrap (p11_virtual *virt, wrapper->destroyer = destroyer; wrapper->bound.version.major = CRYPTOKI_VERSION_MAJOR; wrapper->bound.version.minor = CRYPTOKI_VERSION_MINOR; + wrapper->fixed_index = -1; if (!init_wrapper_funcs (wrapper)) return_val_if_reached (NULL); @@ -334,80 +417,134 @@ p11_virtual_wrap (p11_virtual *virt, assert ((void *)wrapper == (void *)&wrapper->bound); assert (p11_virtual_is_wrapper (&wrapper->bound)); assert (wrapper->bound.C_GetFunctionList != NULL); - return &wrapper->bound; + return wrapper; } -bool -p11_virtual_can_wrap (void) -{ - return TRUE; -} - -bool -p11_virtual_is_wrapper (CK_FUNCTION_LIST_PTR module) -{ - /* - * We use these functions as a marker to indicate whether this is - * one of our CK_FUNCTION_LIST_PTR sets of functions or not. These - * functions are defined to always have the same standard implementation - * in PKCS#11 2.x so we don't need to call through to the base for - * these guys. - */ - return (module->C_GetFunctionStatus == short_C_GetFunctionStatus && - module->C_CancelFunction == short_C_CancelFunction); -} - -void -p11_virtual_unwrap (CK_FUNCTION_LIST_PTR module) +CK_FUNCTION_LIST * +p11_virtual_wrap (p11_virtual *virt, + p11_destroyer destroyer) { Wrapper *wrapper; - return_if_fail (p11_virtual_is_wrapper (module)); - - /* The bound CK_FUNCTION_LIST_PTR sits at the front of Context */ - wrapper = (Wrapper *)module; + wrapper = create_ffi_wrapper (virt, destroyer); + if (wrapper) + return &wrapper->bound; - /* - * Make sure that the CK_FUNCTION_LIST_PTR is invalid, and that - * p11_virtual_is_wrapper() recognizes this. This is in case the - * destroyer callback tries to do something fancy. - */ - memset (&wrapper->bound, 0xFE, sizeof (wrapper->bound)); - - if (wrapper->destroyer) - (wrapper->destroyer) (wrapper->virt); - -#if LIBFFI_FREE_CLOSURES - uninit_wrapper_funcs (wrapper); -#endif - free (wrapper); + return p11_virtual_wrap_fixed (virt, destroyer); } -#else /* !WITH_FFI */ +#else /* !FFI_CLOSURES */ CK_FUNCTION_LIST * p11_virtual_wrap (p11_virtual *virt, p11_destroyer destroyer) { - assert_not_reached (); + return p11_virtual_wrap_fixed (virt, destroyer); } -bool -p11_virtual_can_wrap (void) +#endif /* !FFI_CLOSURES */ + +${fixed_function_list} + +static CK_FUNCTION_LIST * +p11_virtual_wrap_fixed (p11_virtual *virt, + p11_destroyer destroyer) { - return FALSE; + CK_FUNCTION_LIST *result = NULL; + size_t i; + + p11_mutex_lock (&fixed_mutex); + for (i = 0; i < P11_VIRTUAL_MAX_FIXED; i++) { + if (fixed_closures[i] == NULL) { + Wrapper *wrapper; + wrapper = create_fixed_wrapper (virt, i, destroyer); + result = &wrapper->bound; + fixed_closures[i] = result; + break; + } + } + p11_mutex_unlock (&fixed_mutex); + + return result; } -bool -p11_virtual_is_wrapper (CK_FUNCTION_LIST_PTR module) +static void +p11_virtual_unwrap_fixed (CK_FUNCTION_LIST_PTR module) { - return FALSE; + size_t i; + + p11_mutex_lock (&fixed_mutex); + for (i = 0; i < P11_VIRTUAL_MAX_FIXED; i++) { + if (fixed_closures[i] == module) { + fixed_closures[i] = NULL; + break; + } + } + p11_mutex_unlock (&fixed_mutex); } -void -p11_virtual_unwrap (CK_FUNCTION_LIST_PTR module) +static bool +init_wrapper_funcs_fixed (Wrapper *wrapper, CK_FUNCTION_LIST *fixed) { - assert_not_reached (); + const FunctionInfo *info; + void **bound_to, **bound_from; + int i; + + for (i = 0; function_info[i].name != NULL; i++) { + info = function_info + i; + + /* Address to where we're placing the bound function */ + bound_to = &STRUCT_MEMBER (void *, &wrapper->bound, info->module_offset); + bound_from = &STRUCT_MEMBER (void *, fixed, info->module_offset); + + /* + * See if we can just shoot straight through to the module function + * without wrapping at all. If all the stacked virtual modules just + * fall through, then this returns the original module function. + */ + if (!lookup_fall_through (wrapper->virt, info, bound_to)) + *bound_to = *bound_from; + } + + /* Always bind the C_GetFunctionList function itself */ + wrapper->bound.C_GetFunctionList = fixed->C_GetFunctionList; + + /* + * These functions are used as a marker to indicate whether this is + * one of our CK_FUNCTION_LIST_PTR sets of functions or not. These + * functions are defined to always have the same standard implementation + * in PKCS#11 2.x so we don't need to call through to the base for + * these guys. + */ + wrapper->bound.C_CancelFunction = short_C_CancelFunction; + wrapper->bound.C_GetFunctionStatus = short_C_GetFunctionStatus; + + return true; } -#endif /* !WITH_FFI */ +static Wrapper * +create_fixed_wrapper (p11_virtual *virt, + size_t index, + p11_destroyer destroyer) +{ + Wrapper *wrapper; + + return_val_if_fail (virt != NULL, NULL); + + wrapper = calloc (1, sizeof (Wrapper)); + return_val_if_fail (wrapper != NULL, NULL); + + wrapper->virt = virt; + wrapper->destroyer = destroyer; + wrapper->bound.version.major = CRYPTOKI_VERSION_MAJOR; + wrapper->bound.version.minor = CRYPTOKI_VERSION_MINOR; + wrapper->fixed_index = index; + + if (!init_wrapper_funcs_fixed (wrapper, &p11_virtual_fixed[index])) + return_val_if_reached (NULL); + + assert ((void *)wrapper == (void *)&wrapper->bound); + assert (p11_virtual_is_wrapper (&wrapper->bound)); + assert (wrapper->bound.C_GetFunctionList != NULL); + return wrapper; +} diff --git a/p11-kit/virtual.h b/p11-kit/virtual.h index 97d2a7c0d..23b21cf9b 100644 --- a/p11-kit/virtual.h +++ b/p11-kit/virtual.h @@ -65,4 +65,8 @@ bool p11_virtual_is_wrapper (CK_FUNCTION_LIST *module); void p11_virtual_unwrap (CK_FUNCTION_LIST *module); +void p11_virtual_init_fixed (void); +void p11_virtual_uninit_fixed + (void); + #endif /* __P11_VIRTUAL_H__ */