11//! Generic RSA implementation
22
3- use alloc:: borrow:: Cow ;
43use alloc:: vec:: Vec ;
54use crypto_bigint:: modular:: BoxedResidueParams ;
6- use crypto_bigint:: { BoxedUint , NonZero } ;
7- use num_bigint:: { BigInt , BigUint , IntoBigInt , IntoBigUint , ModInverse , RandBigInt , ToBigInt } ;
5+ use crypto_bigint:: { BoxedUint , RandomMod } ;
6+ use num_bigint:: { BigUint , IntoBigInt , IntoBigUint , ModInverse , ToBigInt } ;
87use num_integer:: { sqrt, Integer } ;
98use num_traits:: { FromPrimitive , One , Pow , Signed , Zero as _} ;
109use rand_core:: CryptoRngCore ;
@@ -14,7 +13,7 @@ use zeroize::{Zeroize, Zeroizing};
1413use crate :: errors:: { Error , Result } ;
1514use crate :: key:: { reduce, to_biguint, to_uint} ;
1615use crate :: traits:: keys:: { PrivateKeyPartsNew , PublicKeyPartsNew } ;
17- use crate :: traits:: { PrivateKeyParts , PublicKeyParts } ;
16+ use crate :: traits:: PublicKeyParts ;
1817
1918/// ⚠️ Raw RSA encryption of m with the public key. No padding is performed.
2019///
@@ -38,25 +37,35 @@ pub fn rsa_encrypt<K: PublicKeyParts>(key: &K, m: &BigUint) -> Result<BigUint> {
3837#[ inline]
3938pub fn rsa_decrypt < R : CryptoRngCore + ?Sized > (
4039 mut rng : Option < & mut R > ,
41- priv_key : & impl PrivateKeyParts ,
42- c : & BigUint ,
40+ priv_key : & impl PrivateKeyPartsNew ,
41+ c_orig : & BigUint ,
4342) -> Result < BigUint > {
44- if c >= & priv_key. n ( ) {
43+ // convert to crypto bigint
44+ let c = to_uint ( c_orig. clone ( ) ) ;
45+ let n = priv_key. n ( ) ;
46+ let d = priv_key. d ( ) ;
47+
48+ if c >= * * n {
4549 return Err ( Error :: Decryption ) ;
4650 }
4751
48- if priv_key. n ( ) . is_zero ( ) {
52+ // TODO: is this fine?
53+ if n. is_zero ( ) . into ( ) {
4954 return Err ( Error :: Decryption ) ;
5055 }
5156
5257 let mut ir = None ;
5358
59+ let n_params = priv_key
60+ . residue_params ( )
61+ . cloned ( )
62+ . unwrap_or_else ( || BoxedResidueParams :: new ( n. clone ( ) . get ( ) ) . unwrap ( ) ) ;
5463 let c = if let Some ( ref mut rng) = rng {
55- let ( blinded, unblinder) = blind ( rng, priv_key, c ) ;
64+ let ( blinded, unblinder) = blind ( rng, priv_key, & c , & n_params ) ;
5665 ir = Some ( unblinder) ;
57- Cow :: Owned ( blinded)
66+ blinded
5867 } else {
59- Cow :: Borrowed ( c )
68+ c
6069 } ;
6170
6271 let dp = priv_key. dp ( ) ;
@@ -68,19 +77,21 @@ pub fn rsa_decrypt<R: CryptoRngCore + ?Sized>(
6877 ( Some ( dp) , Some ( dq) , Some ( qinv) , Some ( crt_values) ) => {
6978 // We have the precalculated values needed for the CRT.
7079
71- let p = & priv_key. primes ( ) [ 0 ] ;
72- let q = & priv_key. primes ( ) [ 1 ] ;
80+ let dp = to_biguint ( dp) ;
81+ let dq = to_biguint ( dq) ;
82+ let qinv = to_biguint ( qinv) . to_bigint ( ) . unwrap ( ) ;
83+ let p = to_biguint ( & priv_key. primes ( ) [ 0 ] ) ;
84+ let q = to_biguint ( & priv_key. primes ( ) [ 1 ] ) ;
7385
74- let mut m = c . modpow ( & dp, p) . into_bigint ( ) . unwrap ( ) ;
75- let mut m2 = c . modpow ( & dq, q) . into_bigint ( ) . unwrap ( ) ;
86+ let mut m = c_orig . modpow ( & dp, & p) . into_bigint ( ) . unwrap ( ) ;
87+ let mut m2 = c_orig . modpow ( & dq, & q) . into_bigint ( ) . unwrap ( ) ;
7688
7789 m -= & m2;
7890
7991 let mut primes: Vec < _ > = priv_key
8092 . primes ( )
8193 . iter ( )
82- . map ( ToBigInt :: to_bigint)
83- . map ( Option :: unwrap)
94+ . map ( |p| to_biguint ( p) . to_bigint ( ) . unwrap ( ) )
8495 . collect ( ) ;
8596
8697 while m. is_negative ( ) {
@@ -91,17 +102,17 @@ pub fn rsa_decrypt<R: CryptoRngCore + ?Sized>(
91102 m *= & primes[ 1 ] ;
92103 m += & m2;
93104
94- let mut c = c . into_owned ( ) . into_bigint ( ) . unwrap ( ) ;
105+ let mut c = c_orig . to_bigint ( ) . unwrap ( ) ;
95106 for ( i, value) in crt_values. iter ( ) . enumerate ( ) {
96107 let prime = & primes[ 2 + i] ;
97- m2 = c. modpow ( & value. exp , prime) ;
108+ m2 = c. modpow ( & to_biguint ( & value. exp ) . to_bigint ( ) . unwrap ( ) , prime) ;
98109 m2 -= & m;
99- m2 *= & value. coeff ;
110+ m2 *= & to_biguint ( & value. coeff ) . to_bigint ( ) . unwrap ( ) ;
100111 m2 %= prime;
101112 while m2. is_negative ( ) {
102113 m2 += prime;
103114 }
104- m2 *= & value. r ;
115+ m2 *= & to_biguint ( & value. r ) . to_bigint ( ) . unwrap ( ) ;
105116 m += & m2;
106117 }
107118
@@ -113,17 +124,21 @@ pub fn rsa_decrypt<R: CryptoRngCore + ?Sized>(
113124 c. zeroize ( ) ;
114125 m2. zeroize ( ) ;
115126
116- m. into_biguint ( ) . expect ( "failed to decrypt" )
127+ to_uint ( m. into_biguint ( ) . expect ( "failed to decrypt" ) )
128+ }
129+ _ => {
130+ let c = reduce ( & c, n_params) ;
131+ c. pow ( & d) . retrieve ( )
117132 }
118- _ => c. modpow ( & priv_key. d ( ) , & priv_key. n ( ) ) ,
119133 } ;
120134
121135 match ir {
122136 Some ( ref ir) => {
123137 // unblind
124- Ok ( unblind ( priv_key, & m, ir) )
138+ let res = to_biguint ( & unblind ( priv_key, & m, ir) ) ;
139+ Ok ( res)
125140 }
126- None => Ok ( m ) ,
141+ None => Ok ( to_biguint ( & m ) ) ,
127142 }
128143}
129144
@@ -138,29 +153,11 @@ pub fn rsa_decrypt<R: CryptoRngCore + ?Sized>(
138153/// or signature scheme. See the [module-level documentation][crate::hazmat] for more information.
139154#[ inline]
140155pub fn rsa_decrypt_and_check < R : CryptoRngCore + ?Sized > (
141- priv_key : & impl PrivateKeyParts ,
142- rng : Option < & mut R > ,
143- c : & BigUint ,
144- ) -> Result < BigUint > {
145- let m = rsa_decrypt ( rng, priv_key, c) ?;
146-
147- // In order to defend against errors in the CRT computation, m^e is
148- // calculated, which should match the original ciphertext.
149- let check = rsa_encrypt ( priv_key, & m) ?;
150-
151- if c != & check {
152- return Err ( Error :: Internal ) ;
153- }
154-
155- Ok ( m)
156- }
157-
158- pub fn rsa_decrypt_and_check_new < R : CryptoRngCore + ?Sized > (
159156 priv_key : & impl PrivateKeyPartsNew ,
160157 rng : Option < & mut R > ,
161158 c : & BigUint ,
162159) -> Result < BigUint > {
163- let m = rsa_decrypt_new ( rng, priv_key, c) ?;
160+ let m = rsa_decrypt ( rng, priv_key, c) ?;
164161
165162 // In order to defend against errors in the CRT computation, m^e is
166163 // calculated, which should match the original ciphertext.
@@ -174,38 +171,40 @@ pub fn rsa_decrypt_and_check_new<R: CryptoRngCore + ?Sized>(
174171}
175172
176173/// Returns the blinded c, along with the unblinding factor.
177- fn blind < R : CryptoRngCore , K : PublicKeyParts > (
174+ fn blind < R : CryptoRngCore , K : PublicKeyPartsNew > (
178175 rng : & mut R ,
179176 key : & K ,
180- c : & BigUint ,
181- ) -> ( BigUint , BigUint ) {
177+ c : & BoxedUint ,
178+ n_params : & BoxedResidueParams ,
179+ ) -> ( BoxedUint , BoxedUint ) {
182180 // Blinding involves multiplying c by r^e.
183181 // Then the decryption operation performs (m^e * r^e)^d mod n
184182 // which equals mr mod n. The factor of r can then be removed
185183 // by multiplying by the multiplicative inverse of r.
186184
187- let mut r: BigUint ;
188- let mut ir: Option < BigInt > ;
185+ let mut r: BoxedUint ;
186+ let mut ir: CtOption < BoxedUint > ;
189187 let unblinder;
190188 loop {
191- r = rng. gen_biguint_below ( & key. n ( ) ) ;
192- if r. is_zero ( ) {
193- r = BigUint :: one ( ) ;
189+ // TODO: use constant time gen
190+ r = BoxedUint :: random_mod ( rng, key. n ( ) ) ;
191+ // TODO: correct mapping
192+ if r. is_zero ( ) . into ( ) {
193+ r = BoxedUint :: one ( ) ;
194194 }
195- ir = r. clone ( ) . mod_inverse ( key. n ( ) ) ;
196- if let Some ( ir ) = ir {
197- if let Some ( ub ) = ir . into_biguint ( ) {
198- unblinder = ub ;
199- break ;
200- }
195+ ir = r. inv_mod ( key. n ( ) ) ;
196+
197+ // TODO: constant time?
198+ if let Some ( ir ) = ir . into ( ) {
199+ unblinder = ir ;
200+ break ;
201201 }
202202 }
203203
204204 let c = {
205- let mut rpowe = r. modpow ( & key. e ( ) , & key. n ( ) ) ; // N != 0
206- let mut c = c * & rpowe;
207- c %= key. n ( ) ;
208-
205+ let r = reduce ( & r, n_params. clone ( ) ) ;
206+ let mut rpowe = r. pow ( key. e ( ) ) . retrieve ( ) ;
207+ let c = c. mul_mod ( & rpowe, key. n ( ) ) ;
209208 rpowe. zeroize ( ) ;
210209
211210 c
@@ -215,8 +214,8 @@ fn blind<R: CryptoRngCore, K: PublicKeyParts>(
215214}
216215
217216/// Given an m and and unblinding factor, unblind the m.
218- fn unblind ( key : & impl PublicKeyParts , m : & BigUint , unblinder : & BigUint ) -> BigUint {
219- ( m * unblinder) % key. n ( )
217+ fn unblind ( key : & impl PublicKeyPartsNew , m : & BoxedUint , unblinder : & BoxedUint ) -> BoxedUint {
218+ m . mul_mod ( unblinder, key. n ( ) )
220219}
221220
222221/// The following (deterministic) algorithm also recovers the prime factors `p` and `q` of a modulus `n`, given the
@@ -326,99 +325,6 @@ pub(crate) fn compute_private_exponent_carmicheal(
326325 }
327326}
328327
329- fn blind_new < R : CryptoRngCore , K : PublicKeyPartsNew > (
330- rng : & mut R ,
331- key : & K ,
332- c : & BoxedUint ,
333- n_params : & BoxedResidueParams ,
334- ) -> ( BoxedUint , BoxedUint ) {
335- let mut r: BoxedUint ;
336- let mut ir: CtOption < BoxedUint > ;
337- let unblinder;
338- loop {
339- // TODO: use constant time gen
340- r = to_uint ( rng. gen_biguint_below ( & to_biguint ( & key. n ( ) ) ) ) ;
341- // TODO: correct mapping
342- if r. is_zero ( ) . into ( ) {
343- r = BoxedUint :: one ( ) ;
344- }
345- ir = r. inv_mod ( key. n ( ) ) ;
346-
347- // TODO: constant time?
348- if let Some ( ir) = ir. into ( ) {
349- unblinder = ir;
350- break ;
351- }
352- }
353-
354- let c = {
355- let r = reduce ( & r, n_params. clone ( ) ) ;
356- let mut rpowe = r. pow ( key. e ( ) ) . retrieve ( ) ;
357-
358- let c = c. wrapping_mul ( & rpowe) ;
359- let c = c. rem_vartime ( key. n ( ) ) ;
360-
361- rpowe. zeroize ( ) ;
362-
363- c
364- } ;
365-
366- ( c, unblinder)
367- }
368-
369- fn unblind_new ( key : & impl PublicKeyPartsNew , m : & BoxedUint , unblinder : & BoxedUint ) -> BoxedUint {
370- let a = m. wrapping_mul ( unblinder) ;
371- a. rem_vartime ( key. n ( ) )
372- }
373-
374- pub fn rsa_decrypt_new < R : CryptoRngCore + ?Sized > (
375- mut rng : Option < & mut R > ,
376- priv_key : & impl PrivateKeyPartsNew ,
377- c : & BigUint ,
378- ) -> Result < BigUint > {
379- // convert to crypto bigint
380- let c = to_uint ( c. clone ( ) ) ;
381- let n = priv_key. n ( ) ;
382- let d = priv_key. d ( ) ;
383-
384- if c >= * * n {
385- return Err ( Error :: Decryption ) ;
386- }
387-
388- // TODO: is this fine?
389- if n. is_zero ( ) . into ( ) {
390- return Err ( Error :: Decryption ) ;
391- }
392-
393- let mut ir = None ;
394-
395- let n_params = priv_key
396- . residue_params ( )
397- . cloned ( )
398- . unwrap_or_else ( || BoxedResidueParams :: new ( n. clone ( ) . get ( ) ) . unwrap ( ) ) ;
399-
400- let c = if let Some ( ref mut rng) = rng {
401- let ( blinded, unblinder) = blind_new ( rng, priv_key, & c, & n_params) ;
402- ir = Some ( unblinder) ;
403- blinded
404- } else {
405- c
406- } ;
407-
408- // TODO: fast path with precalculated values;
409- let c = reduce ( & c, n_params) ;
410- let m = c. pow ( & d) . retrieve ( ) ;
411-
412- match ir {
413- Some ( ref ir) => {
414- // unblind
415- let m = unblind_new ( priv_key, & m, ir) ;
416- Ok ( to_biguint ( & m) )
417- }
418- None => Ok ( to_biguint ( & m) ) ,
419- }
420- }
421-
422328#[ cfg( test) ]
423329mod tests {
424330 use num_traits:: FromPrimitive ;
0 commit comments