@@ -49,8 +49,12 @@ enum FunctionList {
4949 V3_2 ( cryptoki_sys:: CK_FUNCTION_LIST_3_2 ) ,
5050}
5151
52- // Implementation of Pkcs11 class that can be enclosed in a single Arc
53- pub ( crate ) struct Pkcs11Impl {
52+ /// Implementation of Pkcs11 class that can be enclosed in a single [`std::sync::Arc`].
53+ ///
54+ /// This object never finalizes the underlying PKCS#11 implementation.
55+ /// For most cases it is advisable to use [`Pkcs11`][`crate::context::Pkcs11`] object instead, which implements proper lifecycle functions.
56+ /// For advanced use cases, where the PKCS#11 lifecycle is managed externally use [`Pkcs11Impl::new_unchecked`].
57+ pub struct Pkcs11Impl {
5458 // Even if this field is never read, it is needed for the pointers in function_list to remain
5559 // valid.
5660 _pkcs11_lib : cryptoki_sys:: Pkcs11 ,
@@ -74,9 +78,67 @@ impl Pkcs11Impl {
7478 FunctionList :: V3_2 ( l) => l,
7579 }
7680 }
81+
82+ /// Initializes Pkcs11 using raw Pkcs11 object.
83+ ///
84+ /// The caller is responsible for ensuring the validity of `pkcs11_lib` object and managing its lifecycle (e.g. calling `finalize`).
85+ /// For most use cases it is advisable to use [`crate::context::Pkcs11`] instead.
86+ ///
87+ /// # Safety
88+ ///
89+ /// `pkcs11_lib` must point to a valid Pkcs11 object.
90+ pub unsafe fn new_unchecked ( pkcs11_lib : cryptoki_sys:: Pkcs11 ) -> Result < Self > {
91+ /* First try the 3.* API to get default interface. It might have some more functions than
92+ * the 2.40 API */
93+ let mut interface: * mut cryptoki_sys:: CK_INTERFACE = ptr:: null_mut ( ) ;
94+ if pkcs11_lib. C_GetInterface . is_ok ( ) {
95+ Rv :: from ( pkcs11_lib. C_GetInterface (
96+ ptr:: null_mut ( ) ,
97+ ptr:: null_mut ( ) ,
98+ & mut interface,
99+ 0 ,
100+ ) )
101+ . into_result ( Function :: GetInterface ) ?;
102+ if !interface. is_null ( ) {
103+ let ifce: cryptoki_sys:: CK_INTERFACE = * interface;
104+
105+ let list_ptr: * mut cryptoki_sys:: CK_FUNCTION_LIST =
106+ ifce. pFunctionList as * mut cryptoki_sys:: CK_FUNCTION_LIST ;
107+ let list: cryptoki_sys:: CK_FUNCTION_LIST = * list_ptr;
108+ if list. version . major >= 3 {
109+ if list. version . minor >= 2 {
110+ let list32_ptr: * mut cryptoki_sys:: CK_FUNCTION_LIST_3_2 =
111+ ifce. pFunctionList as * mut cryptoki_sys:: CK_FUNCTION_LIST_3_2 ;
112+ return Ok ( Pkcs11Impl {
113+ _pkcs11_lib : pkcs11_lib,
114+ function_list : FunctionList :: V3_2 ( * list32_ptr) ,
115+ } ) ;
116+ }
117+ let list30_ptr: * mut cryptoki_sys:: CK_FUNCTION_LIST_3_0 =
118+ ifce. pFunctionList as * mut cryptoki_sys:: CK_FUNCTION_LIST_3_0 ;
119+ return Ok ( Pkcs11Impl {
120+ _pkcs11_lib : pkcs11_lib,
121+ function_list : FunctionList :: V3_0 ( v30tov32 ( * list30_ptr) ) ,
122+ } ) ;
123+ }
124+ /* fall back to the 2.* API */
125+ }
126+ }
127+
128+ let mut list_ptr: * mut cryptoki_sys:: CK_FUNCTION_LIST = ptr:: null_mut ( ) ;
129+ Rv :: from ( pkcs11_lib. C_GetFunctionList ( & mut list_ptr) )
130+ . into_result ( Function :: GetFunctionList ) ?;
131+
132+ Ok ( Pkcs11Impl {
133+ _pkcs11_lib : pkcs11_lib,
134+ function_list : FunctionList :: V2 ( v2tov3 ( * list_ptr) ) ,
135+ } )
136+ }
77137}
78138
79139/// Main PKCS11 context. Should usually be unique per application.
140+ ///
141+ /// After this object goes out of scope the `Finalize` function of the PKCS#11 implementation will be called.
80142#[ derive( Debug ) ]
81143pub struct Pkcs11 {
82144 pub ( crate ) impl_ : Pkcs11Impl ,
@@ -117,7 +179,10 @@ impl Pkcs11 {
117179 unsafe {
118180 let pkcs11_lib =
119181 cryptoki_sys:: Pkcs11 :: new ( filename. as_ref ( ) ) . map_err ( Error :: LibraryLoading ) ?;
120- Self :: _new ( pkcs11_lib)
182+ Ok ( Self {
183+ impl_ : Pkcs11Impl :: new_unchecked ( pkcs11_lib) ?,
184+ initialized : RwLock :: new ( false ) ,
185+ } )
121186 }
122187 }
123188
@@ -129,67 +194,13 @@ impl Pkcs11 {
129194 #[ cfg( windows) ]
130195 let this_lib = libloading:: os:: windows:: Library :: this ( ) ?;
131196 let pkcs11_lib = cryptoki_sys:: Pkcs11 :: from_library ( this_lib) ?;
132- Self :: _new ( pkcs11_lib)
197+ Ok ( Self {
198+ impl_ : Pkcs11Impl :: new_unchecked ( pkcs11_lib) ?,
199+ initialized : RwLock :: new ( false ) ,
200+ } )
133201 }
134202 }
135203
136- unsafe fn _new ( pkcs11_lib : cryptoki_sys:: Pkcs11 ) -> Result < Self > {
137- /* First try the 3.* API to get default interface. It might have some more functions than
138- * the 2.40 API */
139- let mut interface: * mut cryptoki_sys:: CK_INTERFACE = ptr:: null_mut ( ) ;
140- if pkcs11_lib. C_GetInterface . is_ok ( ) {
141- Rv :: from ( pkcs11_lib. C_GetInterface (
142- ptr:: null_mut ( ) ,
143- ptr:: null_mut ( ) ,
144- & mut interface,
145- 0 ,
146- ) )
147- . into_result ( Function :: GetInterface ) ?;
148- if !interface. is_null ( ) {
149- let ifce: cryptoki_sys:: CK_INTERFACE = * interface;
150-
151- let list_ptr: * mut cryptoki_sys:: CK_FUNCTION_LIST =
152- ifce. pFunctionList as * mut cryptoki_sys:: CK_FUNCTION_LIST ;
153- let list: cryptoki_sys:: CK_FUNCTION_LIST = * list_ptr;
154- if list. version . major >= 3 {
155- if list. version . minor >= 2 {
156- let list32_ptr: * mut cryptoki_sys:: CK_FUNCTION_LIST_3_2 =
157- ifce. pFunctionList as * mut cryptoki_sys:: CK_FUNCTION_LIST_3_2 ;
158- return Ok ( Pkcs11 {
159- impl_ : Pkcs11Impl {
160- _pkcs11_lib : pkcs11_lib,
161- function_list : FunctionList :: V3_2 ( * list32_ptr) ,
162- } ,
163- initialized : RwLock :: new ( false ) ,
164- } ) ;
165- }
166- let list30_ptr: * mut cryptoki_sys:: CK_FUNCTION_LIST_3_0 =
167- ifce. pFunctionList as * mut cryptoki_sys:: CK_FUNCTION_LIST_3_0 ;
168- return Ok ( Pkcs11 {
169- impl_ : Pkcs11Impl {
170- _pkcs11_lib : pkcs11_lib,
171- function_list : FunctionList :: V3_0 ( v30tov32 ( * list30_ptr) ) ,
172- } ,
173- initialized : RwLock :: new ( false ) ,
174- } ) ;
175- }
176- /* fall back to the 2.* API */
177- }
178- }
179-
180- let mut list_ptr: * mut cryptoki_sys:: CK_FUNCTION_LIST = ptr:: null_mut ( ) ;
181- Rv :: from ( pkcs11_lib. C_GetFunctionList ( & mut list_ptr) )
182- . into_result ( Function :: GetFunctionList ) ?;
183-
184- Ok ( Pkcs11 {
185- impl_ : Pkcs11Impl {
186- _pkcs11_lib : pkcs11_lib,
187- function_list : FunctionList :: V2 ( v2tov3 ( * list_ptr) ) ,
188- } ,
189- initialized : RwLock :: new ( false ) ,
190- } )
191- }
192-
193204 /// Initialize the PKCS11 library
194205 pub fn initialize ( & self , init_args : CInitializeArgs ) -> Result < ( ) > {
195206 let mut init_lock = self . initialized . write ( ) . expect ( "lock not to be poisoned" ) ;
0 commit comments