33//! Signing and authentication functions
44
55use crate :: context:: Function ;
6+ #[ cfg( doc) ]
7+ use crate :: error:: RvError ;
68use crate :: error:: { Result , Rv } ;
79use crate :: mechanism:: Mechanism ;
810use crate :: object:: ObjectHandle ;
911use crate :: session:: Session ;
1012use cryptoki_sys:: * ;
1113use std:: convert:: TryInto ;
1214
15+ /// # Generating and Verifying Signatures
16+ ///
17+ /// Several functions are provided for signing data and verifying signatures.
18+ /// This includes message authentication codes (MACs). The signed data can be
19+ /// provided in one-shot and streaming modes.
1320impl Session {
14- /// Sign data in single-part
21+ /// Sign data in one-shot mode.
22+ ///
23+ /// `data` should be a byte sequence representing the input message. It will
24+ /// be signed using the specified key, and the resulting signature will be
25+ /// returned in a `Vec`.
26+ ///
27+ /// Use [`Self::sign_into()`] if (an upper bound for) the size of the
28+ /// signature is known, to avoid the heap allocation of `Vec`. Use
29+ /// [`Self::sign_init()`] etc. if the input data is being streamed (i.e. it
30+ /// is not all immediately available).
1531 pub fn sign ( & self , mechanism : & Mechanism , key : ObjectHandle , data : & [ u8 ] ) -> Result < Vec < u8 > > {
16- let mut mechanism: CK_MECHANISM = mechanism. into ( ) ;
1732 let mut signature_len = 0 ;
1833
19- unsafe {
20- Rv :: from ( get_pkcs11 ! ( self . client( ) , C_SignInit ) (
21- self . handle ( ) ,
22- & mut mechanism as CK_MECHANISM_PTR ,
23- key. handle ( ) ,
24- ) )
25- . into_result ( Function :: SignInit ) ?;
26- }
34+ // Initialize the signing operation.
35+ self . sign_init ( mechanism, key) ?;
2736
28- // Get the output buffer length
37+ // Get the output buffer length.
2938 unsafe {
3039 Rv :: from ( get_pkcs11 ! ( self . client( ) , C_Sign ) (
3140 self . handle ( ) ,
@@ -37,9 +46,10 @@ impl Session {
3746 . into_result ( Function :: Sign ) ?;
3847 }
3948
49+ // Allocate the output buffer.
4050 let mut signature = vec ! [ 0 ; signature_len. try_into( ) ?] ;
4151
42- //TODO: we should add a new error instead of those unwrap!
52+ // Perform the actual signing.
4353 unsafe {
4454 Rv :: from ( get_pkcs11 ! ( self . client( ) , C_Sign ) (
4555 self . handle ( ) ,
@@ -51,11 +61,68 @@ impl Session {
5161 . into_result ( Function :: Sign ) ?;
5262 }
5363
64+ // Limit the output buffer to the size of the generated signature.
5465 signature. truncate ( signature_len. try_into ( ) ?) ;
5566
5667 Ok ( signature)
5768 }
5869
70+ /// Sign data into the given buffer.
71+ ///
72+ /// `data` should be a byte sequence representing the input message. It will
73+ /// be signed using the specified key, and the resulting signature will be
74+ /// written to the buffer `sig`.
75+ ///
76+ /// `sig` should be large enough to store the signature. The number of
77+ /// filled bytes will be returned, such that `sig[0..size]` contains the
78+ /// prepared signature. `sig[size..]` might be modified.
79+ ///
80+ /// Use [`Self::sign()`] if (an upper bound for) the size of the signature
81+ /// is not known. Use [`Self::sign_init()`] etc. if the input data is being
82+ /// streamed (i.e. it is not all immediately available).
83+ ///
84+ /// ## Errors
85+ ///
86+ /// Returns [`RvError::BufferTooSmall`] if the generated signature does not
87+ /// fit in `sig`. `sig` might be modified. The size of the actual signature
88+ /// is **not** returned. This method should only be used if the caller knows
89+ /// an upper bound for the signature size.
90+ pub fn sign_into (
91+ & self ,
92+ mechanism : & Mechanism ,
93+ key : ObjectHandle ,
94+ data : & [ u8 ] ,
95+ sig : & mut [ u8 ] ,
96+ ) -> Result < usize > {
97+ // The size of the signature buffer, into which 'C_Sign' will write the
98+ // size of the generated signature.
99+ let sig_buf_len = sig. len ( ) . try_into ( ) ?;
100+ let mut sig_len = sig_buf_len;
101+
102+ // Initialize the signing operation.
103+ self . sign_init ( mechanism, key) ?;
104+
105+ // Perform the actual signing.
106+ unsafe {
107+ Rv :: from ( get_pkcs11 ! ( self . client( ) , C_Sign ) (
108+ self . handle ( ) ,
109+ data. as_ptr ( ) as * mut u8 ,
110+ data. len ( ) . try_into ( ) ?,
111+ sig. as_mut_ptr ( ) ,
112+ & mut sig_len,
113+ ) )
114+ . into_result ( Function :: Sign ) ?;
115+ }
116+
117+ assert ! (
118+ sig_len <= sig_buf_len,
119+ "'C_Sign' succeeded but increased 'sig_len', possibly indicating out-of-bounds accesses"
120+ ) ;
121+
122+ // NOTE: As checked above, 'sig_len <= sig_buf_len <= usize::MAX'.
123+ Ok ( sig_len as usize )
124+ }
125+
59126 /// Starts new multi-part signing operation
60127 pub fn sign_init ( & self , mechanism : & Mechanism , key : ObjectHandle ) -> Result < ( ) > {
61128 let mut mechanism: CK_MECHANISM = mechanism. into ( ) ;
@@ -87,12 +154,20 @@ impl Session {
87154 Ok ( ( ) )
88155 }
89156
90- /// Finalizes ongoing multi-part signing operation,
91- /// returning the signature
157+ /// Complete an ongoing streaming signing operation.
158+ ///
159+ /// This must be preceded by [`Self::sign_init()`] and zero or more calls
160+ /// to [`Self::sign_update()`]. This method will terminate the multi-part
161+ /// signing operation. The resulting signature will be returned in a `Vec`.
162+ ///
163+ /// Use [`Self::sign_final_into()`] if (an upper bound for) the size of
164+ /// the signature is known, to avoid the heap allocation of `Vec`. Use
165+ /// [`Self::sign()`] if the input data is entirely available in a single
166+ /// buffer (i.e. does not have to be streamed).
92167 pub fn sign_final ( & self ) -> Result < Vec < u8 > > {
93168 let mut signature_len = 0 ;
94169
95- // Get the output buffer length
170+ // Get the output buffer length.
96171 unsafe {
97172 Rv :: from ( get_pkcs11 ! ( self . client( ) , C_SignFinal ) (
98173 self . handle ( ) ,
@@ -102,8 +177,10 @@ impl Session {
102177 . into_result ( Function :: SignFinal ) ?;
103178 }
104179
180+ // Allocate the output buffer.
105181 let mut signature = vec ! [ 0 ; signature_len. try_into( ) ?] ;
106182
183+ // Perform the actual signing.
107184 unsafe {
108185 Rv :: from ( get_pkcs11 ! ( self . client( ) , C_SignFinal ) (
109186 self . handle ( ) ,
@@ -113,11 +190,59 @@ impl Session {
113190 . into_result ( Function :: SignFinal ) ?;
114191 }
115192
193+ // Limit the output buffer to the size of the generated signature.
116194 signature. truncate ( signature_len. try_into ( ) ?) ;
117195
118196 Ok ( signature)
119197 }
120198
199+ /// Complete an ongoing multi-part signing operation, writing the signature
200+ /// into the given buffer.
201+ ///
202+ /// This must be preceded by [`Self::sign_init()`] and zero or more calls
203+ /// to [`Self::sign_update()`]. This method will terminate the multi-part
204+ /// signing operation, and write the signature to the buffer `sig`.
205+ ///
206+ /// `sig` should be large enough to store the signature. The number of
207+ /// filled bytes will be returned, such that `sig[0..size]` contains the
208+ /// prepared signature. `sig[size..]` might be modified.
209+ ///
210+ /// Use [`Self::sign_final()`] if (an upper bound for) the size of the
211+ /// signature is not known. Use [`Self::sign_into()`] if the input data
212+ /// is entirely available in a single buffer (i.e. does not have to be
213+ /// streamed).
214+ ///
215+ /// ## Errors
216+ ///
217+ /// Returns [`RvError::BufferTooSmall`] if the generated signature does not
218+ /// fit in `sig`. `sig` might be modified. The size of the actual signature
219+ /// is **not** returned. This method should only be used if the caller knows
220+ /// an upper bound for the signature size.
221+ pub fn sign_final_into ( & self , sig : & mut [ u8 ] ) -> Result < usize > {
222+ // The size of the signature buffer, into which 'C_SignFinal' will write
223+ // the size of the generated signature.
224+ let sig_buf_len = sig. len ( ) . try_into ( ) ?;
225+ let mut sig_len = sig_buf_len;
226+
227+ // Perform the underlying finalization.
228+ unsafe {
229+ Rv :: from ( get_pkcs11 ! ( self . client( ) , C_SignFinal ) (
230+ self . handle ( ) ,
231+ sig. as_mut_ptr ( ) ,
232+ & mut sig_len,
233+ ) )
234+ . into_result ( Function :: SignFinal ) ?;
235+ }
236+
237+ assert ! (
238+ sig_len <= sig_buf_len,
239+ "'C_SignFinal' succeeded but increased 'sig_len', possibly indicating out-of-bounds accesses"
240+ ) ;
241+
242+ // NOTE: As checked above, 'sig_len <= sig_buf_len <= usize::MAX'.
243+ Ok ( sig_len as usize )
244+ }
245+
121246 /// Verify data in single-part
122247 pub fn verify (
123248 & self ,
0 commit comments