@@ -19,22 +19,30 @@ use untrusted;
19
19
#[ cfg( feature = "rsa_signing" ) ]
20
20
use rand;
21
21
22
+ /// Common features of both RSA padding encoding and RSA padding verification.
23
+ pub trait RSAPadding : ' static + Sync + :: private:: Private {
24
+ // The digest algorithm used for digesting the message (and maybe for
25
+ // other things).
26
+ fn digest_alg ( & self ) -> & ' static digest:: Algorithm ;
27
+ }
28
+
22
29
/// An RSA signature encoding as described in [RFC 3447 Section 8].
23
30
///
24
31
/// [RFC 3447 Section 8]: https://tools.ietf.org/html/rfc3447#section-8
25
32
#[ cfg( feature = "rsa_signing" ) ]
26
- pub trait RSAEncoding : ' static + Sync + :: private :: Private {
33
+ pub trait RSAEncoding : RSAPadding {
27
34
#[ doc( hidden) ]
28
- fn encode ( & self , msg : & [ u8 ] , m_out : & mut [ u8 ] , mod_bits : bits:: BitLength ,
29
- rng : & rand:: SecureRandom ) -> Result < ( ) , error:: Unspecified > ;
35
+ fn encode ( & self , m_hash : & digest:: Digest , m_out : & mut [ u8 ] ,
36
+ mod_bits : bits:: BitLength , rng : & rand:: SecureRandom )
37
+ -> Result < ( ) , error:: Unspecified > ;
30
38
}
31
39
32
40
/// Verification of an RSA signature encoding as described in
33
41
/// [RFC 3447 Section 8].
34
42
///
35
43
/// [RFC 3447 Section 8]: https://tools.ietf.org/html/rfc3447#section-8
36
- pub trait RSAVerification : ' static + Sync + :: private :: Private {
37
- fn verify ( & self , msg : untrusted :: Input , m : & mut untrusted:: Reader ,
44
+ pub trait RSAVerification : RSAPadding {
45
+ fn verify ( & self , m_hash : & digest :: Digest , m : & mut untrusted:: Reader ,
38
46
mod_bits : bits:: BitLength ) -> Result < ( ) , error:: Unspecified > ;
39
47
}
40
48
@@ -51,24 +59,29 @@ pub struct PKCS1 {
51
59
52
60
impl :: private:: Private for PKCS1 { }
53
61
62
+ impl RSAPadding for PKCS1 {
63
+ fn digest_alg ( & self ) -> & ' static digest:: Algorithm { self . digest_alg }
64
+ }
65
+
54
66
#[ cfg( feature ="rsa_signing" ) ]
55
67
impl RSAEncoding for PKCS1 {
56
- fn encode ( & self , msg : & [ u8 ] , m_out : & mut [ u8 ] , _mod_bits : bits:: BitLength ,
57
- _rng : & rand:: SecureRandom ) -> Result < ( ) , error:: Unspecified > {
58
- pkcs1_encode ( & self , msg, m_out) ;
68
+ fn encode ( & self , m_hash : & digest:: Digest , m_out : & mut [ u8 ] ,
69
+ _mod_bits : bits:: BitLength , _rng : & rand:: SecureRandom )
70
+ -> Result < ( ) , error:: Unspecified > {
71
+ pkcs1_encode ( & self , m_hash, m_out) ;
59
72
Ok ( ( ) )
60
73
}
61
74
}
62
75
63
76
impl RSAVerification for PKCS1 {
64
- fn verify ( & self , msg : untrusted :: Input , m : & mut untrusted:: Reader ,
77
+ fn verify ( & self , m_hash : & digest :: Digest , m : & mut untrusted:: Reader ,
65
78
mod_bits : bits:: BitLength ) -> Result < ( ) , error:: Unspecified > {
66
79
// `mod_bits.as_usize_bytes_rounded_up() <=
67
80
// PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN` is ensured by `verify_rsa()`.
68
81
let mut calculated = [ 0u8 ; PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN ] ;
69
82
let calculated =
70
83
& mut calculated[ ..mod_bits. as_usize_bytes_rounded_up ( ) ] ;
71
- pkcs1_encode ( & self , msg . as_slice_less_safe ( ) , calculated) ;
84
+ pkcs1_encode ( & self , m_hash , calculated) ;
72
85
if m. skip_to_end ( ) != polyfill:: ref_from_mut_ref ( calculated) {
73
86
return Err ( error:: Unspecified ) ;
74
87
}
@@ -80,7 +93,7 @@ impl RSAVerification for PKCS1 {
80
93
// https://tools.ietf.org/html/rfc3447#section-9.2. This is used by both
81
94
// verification and signing so it needs to be able to handle moduli of the
82
95
// minimum and maximum sizes for both operations.
83
- fn pkcs1_encode ( pkcs1 : & PKCS1 , msg : & [ u8 ] , m_out : & mut [ u8 ] ) {
96
+ fn pkcs1_encode ( pkcs1 : & PKCS1 , m_hash : & digest :: Digest , m_out : & mut [ u8 ] ) {
84
97
let em = m_out;
85
98
86
99
let digest_len =
@@ -100,7 +113,7 @@ fn pkcs1_encode(pkcs1: &PKCS1, msg: &[u8], m_out: &mut [u8]) {
100
113
let ( digest_prefix, digest_dst) = em[ 3 + pad_len..]
101
114
. split_at_mut ( pkcs1. digestinfo_prefix . len ( ) ) ;
102
115
digest_prefix. copy_from_slice ( pkcs1. digestinfo_prefix ) ;
103
- digest_dst. copy_from_slice ( digest :: digest ( pkcs1 . digest_alg , msg ) . as_ref ( ) ) ;
116
+ digest_dst. copy_from_slice ( m_hash . as_ref ( ) ) ;
104
117
}
105
118
106
119
macro_rules! rsa_pkcs1_padding {
@@ -174,12 +187,17 @@ impl ::private::Private for PSS { }
174
187
// In practice, this is constrained by the maximum digest length.
175
188
const MAX_SALT_LEN : usize = digest:: MAX_OUTPUT_LEN ;
176
189
190
+ impl RSAPadding for PSS {
191
+ fn digest_alg ( & self ) -> & ' static digest:: Algorithm { self . digest_alg }
192
+ }
193
+
177
194
#[ cfg( feature = "rsa_signing" ) ]
178
195
impl RSAEncoding for PSS {
179
196
// Implement padding procedure per EMSA-PSS,
180
197
// https://tools.ietf.org/html/rfc3447#section-9.1.
181
- fn encode ( & self , msg : & [ u8 ] , m_out : & mut [ u8 ] , mod_bits : bits:: BitLength ,
182
- rng : & rand:: SecureRandom ) -> Result < ( ) , error:: Unspecified > {
198
+ fn encode ( & self , m_hash : & digest:: Digest , m_out : & mut [ u8 ] ,
199
+ mod_bits : bits:: BitLength , rng : & rand:: SecureRandom )
200
+ -> Result < ( ) , error:: Unspecified > {
183
201
let metrics = try!( PSSMetrics :: new ( self . digest_alg , mod_bits) ) ;
184
202
185
203
// The `m_out` this function fills is the big-endian-encoded value of `m`
@@ -196,7 +214,7 @@ impl RSAEncoding for PSS {
196
214
} ;
197
215
assert_eq ! ( em. len( ) , metrics. em_len) ;
198
216
199
- // Steps 1 and 2 are done later, out of order .
217
+ // Steps 1 and 2 are done by the caller to produce `m_hash` .
200
218
201
219
// Step 3 is done by `PSSMetrics::new()` above.
202
220
@@ -206,7 +224,7 @@ impl RSAEncoding for PSS {
206
224
try!( rng. fill ( salt) ) ;
207
225
208
226
// Step 5 and 6.
209
- let h_hash = pss_digest ( self . digest_alg , msg , salt) ;
227
+ let h_hash = pss_digest ( self . digest_alg , m_hash , salt) ;
210
228
211
229
// Re-order steps 7, 8, 9 and 10 so that we first output the db mask
212
230
// into `em`, and then XOR the value of db.
@@ -246,7 +264,7 @@ impl RSAEncoding for PSS {
246
264
impl RSAVerification for PSS {
247
265
// RSASSA-PSS-VERIFY from https://tools.ietf.org/html/rfc3447#section-8.1.2
248
266
// where steps 1, 2(a), and 2(b) have been done for us.
249
- fn verify ( & self , msg : untrusted :: Input , m : & mut untrusted:: Reader ,
267
+ fn verify ( & self , m_hash : & digest :: Digest , m : & mut untrusted:: Reader ,
250
268
mod_bits : bits:: BitLength ) -> Result < ( ) , error:: Unspecified > {
251
269
let metrics = try!( PSSMetrics :: new ( self . digest_alg , mod_bits) ) ;
252
270
@@ -269,7 +287,7 @@ impl RSAVerification for PSS {
269
287
// The rest of this function is EMSA-PSS-VERIFY from
270
288
// https://tools.ietf.org/html/rfc3447#section-9.1.2.
271
289
272
- // Steps 1 and 2 are done later, out of order .
290
+ // Steps 1 and 2 are done by the caller to produce `m_hash` .
273
291
274
292
// Step 3 is done by `PSSMetrics::new()` above.
275
293
@@ -321,8 +339,7 @@ impl RSAVerification for PSS {
321
339
let salt = & db[ ( db. len ( ) - metrics. s_len ) ..] ;
322
340
323
341
// Step 12 and 13.
324
- let h_prime =
325
- pss_digest ( self . digest_alg , msg. as_slice_less_safe ( ) , salt) ;
342
+ let h_prime = pss_digest ( self . digest_alg , m_hash, salt) ;
326
343
327
344
// Step 14.
328
345
if h_hash != h_prime. as_ref ( ) {
@@ -402,15 +419,11 @@ fn mgf1(digest_alg: &'static digest::Algorithm, seed: &[u8], mask: &mut [u8])
402
419
Ok ( ( ) )
403
420
}
404
421
405
- fn pss_digest ( digest_alg : & ' static digest:: Algorithm , msg : & [ u8 ] , salt : & [ u8 ] )
406
- -> digest:: Digest {
422
+ fn pss_digest ( digest_alg : & ' static digest:: Algorithm , m_hash : & digest :: Digest ,
423
+ salt : & [ u8 ] ) -> digest:: Digest {
407
424
// Fixed prefix.
408
425
const PREFIX_ZEROS : [ u8 ; 8 ] = [ 0u8 ; 8 ] ;
409
426
410
- // Steps 1 & 2 for both encoding and verification. Step 1 is delegated to
411
- // the digest implementation.
412
- let m_hash = digest:: digest ( digest_alg, msg) ;
413
-
414
427
// Encoding step 5 and 6, Verification step 12 and 13.
415
428
let mut ctx = digest:: Context :: new ( digest_alg) ;
416
429
ctx. update ( & PREFIX_ZEROS ) ;
@@ -444,7 +457,7 @@ rsa_pss_padding!(RSA_PSS_SHA512, &digest::SHA512,
444
457
445
458
#[ cfg( test) ]
446
459
mod test {
447
- use { error, test} ;
460
+ use { digest , error, test} ;
448
461
use super :: * ;
449
462
use untrusted;
450
463
@@ -464,6 +477,8 @@ mod test {
464
477
465
478
let msg = test_case. consume_bytes ( "Msg" ) ;
466
479
let msg = untrusted:: Input :: from ( & msg) ;
480
+ let m_hash = digest:: digest ( alg. digest_alg ( ) ,
481
+ msg. as_slice_less_safe ( ) ) ;
467
482
468
483
let encoded = test_case. consume_bytes ( "Encoded" ) ;
469
484
let encoded = untrusted:: Input :: from ( & encoded) ;
@@ -473,7 +488,7 @@ mod test {
473
488
474
489
let actual_result =
475
490
encoded. read_all ( error:: Unspecified ,
476
- |m| alg. verify ( msg , m, bit_len) ) ;
491
+ |m| alg. verify ( & m_hash , m, bit_len) ) ;
477
492
assert_eq ! ( actual_result. is_ok( ) , expected_result == "P" ) ;
478
493
479
494
Ok ( ( ) )
0 commit comments