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,62 @@ 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 given output buffer.
75+ ///
76+ /// The output buffer should be large enough to store the signature.
77+ /// If it is large enough, the number of filled bytes is returned
78+ /// (i.e. `sig[0..size]` contains the prepared signature). Otherwise,
79+ /// [`RvError::BufferTooSmall`] will be returned.
80+ ///
81+ /// Use [`Self::sign()`] if (an upper bound for) the size of the signature
82+ /// is not known. Use [`Self::sign_init()`] etc. if the input data is being
83+ /// streamed (i.e. it is not all immediately available).
84+ pub fn sign_into (
85+ & mut self ,
86+ mechanism : & Mechanism ,
87+ key : ObjectHandle ,
88+ data : & [ u8 ] ,
89+ sig : & mut [ u8 ] ,
90+ ) -> Result < usize > {
91+ // The size of the signature buffer, into which 'C_Sign' will write the
92+ // size of the generated signature.
93+ let sig_buf_len = sig. len ( ) . try_into ( ) ?;
94+ let mut sig_len = sig_buf_len;
95+
96+ // Initialize the signing operation.
97+ self . sign_init ( mechanism, key) ?;
98+
99+ // Perform the actual signing.
100+ unsafe {
101+ Rv :: from ( get_pkcs11 ! ( self . client( ) , C_Sign ) (
102+ self . handle ( ) ,
103+ data. as_ptr ( ) as * mut u8 ,
104+ data. len ( ) . try_into ( ) ?,
105+ sig. as_mut_ptr ( ) ,
106+ & mut sig_len,
107+ ) )
108+ . into_result ( Function :: Sign ) ?;
109+ }
110+
111+ assert ! (
112+ sig_len <= sig_buf_len,
113+ "'C_Sign' succeeded but increased 'sig_len', possibly indicating out-of-bounds accesses"
114+ ) ;
115+
116+ // NOTE: As checked above, 'sig_len <= sig_buf_len <= usize::MAX'.
117+ Ok ( sig_len as usize )
118+ }
119+
59120 /// Starts new multi-part signing operation
60121 pub fn sign_init ( & self , mechanism : & Mechanism , key : ObjectHandle ) -> Result < ( ) > {
61122 let mut mechanism: CK_MECHANISM = mechanism. into ( ) ;
@@ -87,12 +148,20 @@ impl Session {
87148 Ok ( ( ) )
88149 }
89150
90- /// Finalizes ongoing multi-part signing operation,
91- /// returning the signature
151+ /// Complete an ongoing streaming signing operation.
152+ ///
153+ /// This must be preceded by [`Self::sign_init()`] and zero or more calls
154+ /// to [`Self::sign_update()`]. This method will terminate the multi-part
155+ /// signing operation. The resulting signature will be returned in a `Vec`.
156+ ///
157+ /// Use [`Self::sign_final_into()`] if (an upper bound for) the size of
158+ /// the signature is known, to avoid the heap allocation of `Vec`. Use
159+ /// [`Self::sign()`] if the input data is entirely available in a single
160+ /// buffer (i.e. does not have to be streamed).
92161 pub fn sign_final ( & self ) -> Result < Vec < u8 > > {
93162 let mut signature_len = 0 ;
94163
95- // Get the output buffer length
164+ // Get the output buffer length.
96165 unsafe {
97166 Rv :: from ( get_pkcs11 ! ( self . client( ) , C_SignFinal ) (
98167 self . handle ( ) ,
@@ -102,8 +171,10 @@ impl Session {
102171 . into_result ( Function :: SignFinal ) ?;
103172 }
104173
174+ // Allocate the output buffer.
105175 let mut signature = vec ! [ 0 ; signature_len. try_into( ) ?] ;
106176
177+ // Perform the actual signing.
107178 unsafe {
108179 Rv :: from ( get_pkcs11 ! ( self . client( ) , C_SignFinal ) (
109180 self . handle ( ) ,
@@ -113,11 +184,56 @@ impl Session {
113184 . into_result ( Function :: SignFinal ) ?;
114185 }
115186
187+ // Limit the output buffer to the size of the generated signature.
116188 signature. truncate ( signature_len. try_into ( ) ?) ;
117189
118190 Ok ( signature)
119191 }
120192
193+ /// Complete an ongoing multi-part signing operation, writing the signature
194+ /// into the given buffer.
195+ ///
196+ /// This must be preceded by [`Self::sign_init()`] and zero or more calls
197+ /// to [`Self::sign_update()`]. This method will terminate the multi-part
198+ /// signing operation.
199+ ///
200+ /// The output buffer should be large enough to store the signature.
201+ /// If it is large enough, the number of filled bytes is returned
202+ /// (i.e. `sig[0..size]` contains the prepared signature). Otherwise,
203+ /// [`RvError::BufferTooSmall`] will be returned.
204+ ///
205+ /// Use [`Self::sign_final()`] if (an upper bound for) the size of the
206+ /// signature is not known. Use [`Self::sign_into()`] if the input data
207+ /// is entirely available in a single buffer (i.e. does not have to be
208+ /// streamed).
209+ //
210+ // TODO: Is it possible to re-do this call if an incorrect buffer size
211+ // was passed in? I think so?
212+ pub fn sign_final_into ( & mut self , sig : & mut [ u8 ] ) -> Result < usize > {
213+ // The size of the signature buffer, into which 'C_SignFinal' will write
214+ // the size of the generated signature.
215+ let sig_buf_len = sig. len ( ) . try_into ( ) ?;
216+ let mut sig_len = sig_buf_len;
217+
218+ // Perform the underlying finalization.
219+ unsafe {
220+ Rv :: from ( get_pkcs11 ! ( self . client( ) , C_SignFinal ) (
221+ self . handle ( ) ,
222+ sig. as_mut_ptr ( ) ,
223+ & mut sig_len,
224+ ) )
225+ . into_result ( Function :: SignFinal ) ?;
226+ }
227+
228+ assert ! (
229+ sig_len <= sig_buf_len,
230+ "'C_SignFinal' succeeded but increased 'sig_len', possibly indicating out-of-bounds accesses"
231+ ) ;
232+
233+ // NOTE: As checked above, 'sig_len <= sig_buf_len <= usize::MAX'.
234+ Ok ( sig_len as usize )
235+ }
236+
121237 /// Verify data in single-part
122238 pub fn verify (
123239 & self ,
0 commit comments