1 /**
2 * RSA
3 * 
4 * Copyright:
5 * (C) 1999-2008 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.pubkey.algo.rsa;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_PUBLIC_KEY_CRYPTO && BOTAN_HAS_RSA):
15 
16 public import botan.pubkey.pubkey;
17 public import botan.pubkey.algo.if_algo;
18 import botan.pubkey.pk_ops;
19 import botan.math.numbertheory.reducer;
20 import botan.pubkey.blinding;
21 import botan.utils.parsing;
22 import botan.math.numbertheory.numthry;
23 import botan.pubkey.algo.keypair;
24 import botan.rng.rng;
25 import memutils.helpers : Embed;
26 import std.concurrency;
27 import core.thread;
28 import std.algorithm : max;
29 
30 struct RSAOptions {
31     enum algoName = "RSA";
32 
33     /*
34     * Check Private RSA Parameters
35     */
36     static bool checkKey(in IFSchemePrivateKey privkey, RandomNumberGenerator rng, bool strong)
37     {
38         if (!privkey.checkKeyImpl(rng, strong))
39             return false;
40 
41         if (!strong)
42             return true;
43         auto p_minus_1 = privkey.getP() - 1;
44         auto q_minus_1 = privkey.getQ() - 1;
45         if ((privkey.getE() * privkey.getD()) % lcm(&p_minus_1, &q_minus_1) != 1)
46             return false;
47         
48         return signatureConsistencyCheck(rng, privkey, "EMSA4(SHA-1)");
49     }
50 }
51 
52 /**
53 * RSA Public Key
54 */
55 struct RSAPublicKey
56 {
57 public:
58     alias Options = RSAOptions;
59     __gshared immutable string algoName = Options.algoName;
60 
61     this(in AlgorithmIdentifier alg_id, const ref SecureVector!ubyte key_bits) 
62     {
63 		m_owned = true;
64         m_pub = new IFSchemePublicKey(Options(), alg_id, key_bits);
65     }
66 
67     /**
68     * Create a RSAPublicKey
69     * @arg n the modulus
70     * @arg e the exponent
71     */
72     this(BigInt n, BigInt e)
73     {
74 		m_owned = true;
75         m_pub = new IFSchemePublicKey(Options(), n.move(), e.move());
76     }
77 
78     this(PrivateKey pkey) { m_pub = cast(IFSchemePublicKey) pkey; }
79     this(PublicKey pkey) { m_pub = cast(IFSchemePublicKey) pkey; }
80 
81     mixin Embed!(m_pub, m_owned);
82 
83 	bool m_owned;
84     IFSchemePublicKey m_pub;
85 }
86 
87 /**
88 * RSA Private Key
89 */
90 struct RSAPrivateKey
91 {
92 public:
93     alias Options = RSAOptions;
94     __gshared immutable string algoName = Options.algoName;
95 
96     this(in AlgorithmIdentifier alg_id, const ref SecureVector!ubyte key_bits, RandomNumberGenerator rng) 
97     {
98 		m_owned = true;
99         m_priv = new IFSchemePrivateKey(Options(), rng, alg_id, key_bits);
100     }
101 
102     /**
103     * Construct a private key from the specified parameters.
104     *
105     * Params:
106     *  rng = a random number generator
107     *  p = the first prime
108     *  q = the second prime
109     *  e = the exponent
110     *  d = if specified, this has to be d with exp * d = 1 mod (p - 1, q - 1). Leave it as 0 if you wish 
111     * the constructor to calculate it.
112     *  n = if specified, this must be n = p * q. Leave it as 0
113     * if you wish to the constructor to calculate it.
114     */
115     this(RandomNumberGenerator rng, BigInt p, BigInt q, BigInt e, BigInt d = BigInt(0), BigInt n = BigInt(0))
116     {
117 		m_owned = true;
118         m_priv = new IFSchemePrivateKey(Options(), rng, p.move(), q.move(), e.move(), d.move(), n.move());
119     }
120 
121     /**
122     * Create a new private key with the specified bit length
123     * Params:
124     *  rng = the random number generator to use
125     *  bits = the desired bit length of the private key
126     *  exp = the public exponent to be used
127     */
128     this(RandomNumberGenerator rng, size_t bits, size_t exp = 65537)
129     {
130         if (bits < 1024)
131             throw new InvalidArgument(algoName ~ ": Can't make a key that is only " ~ to!string(bits) ~ " bits long");
132         if (exp < 3 || exp % 2 == 0)
133             throw new InvalidArgument(algoName ~ ": Invalid encryption exponent");
134         BigInt e = exp;
135         BigInt p, q, n, d, d1, d2, c;
136 
137         do
138         {
139             p = randomPrime(rng, (bits + 1) / 2, &e);
140             q = randomPrime(rng, bits - p.bits(), &e);
141             n = p * q;
142         } while (n.bits() != bits);
143 		auto one = BigInt(1);
144 		auto p_1 = p - one;
145 		auto q_1 = q - one;
146         auto d_0 = lcm(&p_1, &q_1);
147         d = inverseMod(&e, &d_0);
148 
149 		m_owned = true;
150         m_priv = new IFSchemePrivateKey(Options(), rng, p.move(), q.move(), e.move(), d.move(), n.move());
151         genCheck(rng);
152     }
153 
154     this(PrivateKey pkey) { m_priv = cast(IFSchemePrivateKey) pkey; }
155 
156     mixin Embed!(m_priv, m_owned);
157 
158 	bool m_owned;
159     IFSchemePrivateKey m_priv;
160 }
161 
162 /**
163 * RSA private (decrypt/sign) operation
164 */
165 final class RSAPrivateOperation : Signature, Decryption
166 {
167 public:
168     this(in PrivateKey pkey, RandomNumberGenerator rng) {
169         this(cast(IFSchemePrivateKey) pkey, rng);
170     }
171 
172     this(in RSAPrivateKey pkey, RandomNumberGenerator rng) {
173         this(pkey.m_priv, rng);
174     }
175 
176     this(in IFSchemePrivateKey rsa_, RandomNumberGenerator rng) 
177     {
178         rsa = rsa_;
179         assert(rsa.algoName == RSAPublicKey.algoName);
180         m_n = &rsa.getN();
181         m_q = &rsa.getQ();
182         m_c = &rsa.getC();
183         m_d1 = &rsa.getD1();
184         m_p = &rsa.getP();
185         m_powermod_e_n = FixedExponentPowerMod(&rsa.getE(), &rsa.getN());
186         m_powermod_d2_q = FixedExponentPowerMod(&rsa.getD2(), &rsa.getQ());
187         m_mod_p = ModularReducer(rsa.getP());
188         BigInt k = BigInt(rng, m_n.bits() - 1);
189         auto e = (cast()*m_powermod_e_n)(cast()&k);
190         m_blinder = Blinder(e, inverseMod(&k, m_n), *m_n);
191     }
192     override size_t messageParts() const { return 1; }
193     override size_t messagePartSize() const { return 0; }
194     override size_t maxInputBits() const { return (m_n.bits() - 1); }
195 
196     override SecureVector!ubyte
197         sign(const(ubyte)* msg, size_t msg_len, RandomNumberGenerator rng)
198     {
199         rng.addEntropy(msg, msg_len);
200         
201         /* We don't check signatures against powermod_e_n here because
202             PKSigner checks verification consistency for all signature
203             algorithms.
204         */
205         BigInt m = BigInt(msg, msg_len);
206         m = m_blinder.blind(m.dup);
207         m = privateOp(m);
208         BigInt x = m_blinder.unblind(m);
209         return BigInt.encode1363(x, m_n.bytes());
210     }
211 
212     /*
213     * RSA Decryption Operation
214     */
215     override SecureVector!ubyte decrypt(const(ubyte)* msg, size_t msg_len)
216     {
217         BigInt m = BigInt(msg, msg_len);
218         BigInt x = m_blinder.unblind(privateOp(m_blinder.blind(m)));
219         FixedExponentPowerModImpl powermod_e_n = cast(FixedExponentPowerModImpl) *m_powermod_e_n;
220         assert(m == powermod_e_n.opCall(&x), "RSA decrypt passed consistency check");
221         
222         return BigInt.encodeLocked(x);
223     }
224 private:
225     BigInt privateOp()(auto const ref BigInt m) const
226     {
227 		//import core.memory : GC; GC.disable(); scope(exit) GC.enable();
228 		import core.sync.condition;
229 		import core.sync.mutex;
230 		import core.atomic;
231 		import memutils.utils : ThreadMem;
232 		Mutex mutex = ThreadMem.alloc!Mutex();
233 		scope(exit) {
234 			ThreadMem.free(mutex);
235 		}
236         if (m >= *m_n)
237             throw new InvalidArgument("RSA private op - input is too large");
238         BigInt j1;
239 		j1.reserve(max(m_q.bytes() + m_q.bytes() % 128, m_n.bytes() + m_n.bytes() % 128));
240 
241 		struct Handler {
242 			shared(Mutex) mtx;
243 			shared(const BigInt*) d1;
244 			shared(const BigInt*) p;
245 			shared(const BigInt*) m2;
246 			shared(BigInt*) j1_2;
247 			void run() { 
248 				try {
249 					import botan.libstate.libstate : modexpInit;
250 					modexpInit(); // enable quick path for powermod
251 					BigInt* ret = cast(BigInt*) j1_2;
252 					{
253 						import memutils.utils;
254 						FixedExponentPowerMod powermod_d1_p = FixedExponentPowerMod(cast(BigInt*)d1, cast(BigInt*)p);
255 						BigInt _res =(cast()*powermod_d1_p)( cast(BigInt*) m2);
256 						synchronized(cast()mtx) ret.load(&_res);
257 					}
258 				} catch (Exception e) { logDebug("Error: ", e.toString()); }
259 			}
260 		}
261 		
262 		auto handler = Handler(cast(shared)mutex, cast(shared)m_d1, cast(shared)m_p, cast(shared)&m, cast(shared)&j1);
263 		Unique!Thread thr = new Thread(&handler.run);
264 		thr.start();
265         FixedExponentPowerModImpl powermod_d2_q = cast(FixedExponentPowerModImpl)*m_powermod_d2_q;
266         BigInt j2 = powermod_d2_q.opCall(&m);
267 		thr.join();
268 		BigInt j3;
269 		synchronized(mutex) j3 = m_mod_p.reduce(subMul(&j1, &j2, m_c));
270         return mulAdd(&j3, m_q, &j2);
271     }
272 
273     const IFSchemePrivateKey rsa;
274     const BigInt* m_n;
275     const BigInt* m_q;
276     const BigInt* m_c;
277     const BigInt* m_d1;
278     const BigInt* m_p;
279     FixedExponentPowerMod m_powermod_e_n, m_powermod_d2_q;
280     ModularReducer m_mod_p;
281     Blinder m_blinder;
282 }
283 
284 /**
285 * RSA public (encrypt/verify) operation
286 */
287 final class RSAPublicOperation : Verification, Encryption
288 {
289 public:
290     this(in PublicKey pkey) {
291         this(cast(IFSchemePublicKey) pkey);
292     }
293 
294     this(in RSAPublicKey pkey) {
295         this(pkey.m_pub);
296     }
297 
298     this(in IFSchemePublicKey rsa)
299     {
300         assert(rsa.algoName == RSAPublicKey.algoName);
301         m_rsa = rsa;
302         m_n = &m_rsa.getN();
303         m_powermod_e_n = FixedExponentPowerMod(&m_rsa.getE(), &m_rsa.getN());
304     }
305     override size_t messageParts() const { return 1; }
306     override size_t messagePartSize() const { return 0; }
307     override size_t maxInputBits() const { return (m_n.bits() - 1); }
308     override bool withRecovery() const { return true; }
309 
310     override SecureVector!ubyte encrypt(const(ubyte)* msg, size_t msg_len, RandomNumberGenerator)
311     {
312         BigInt m = BigInt(msg, msg_len);
313         return BigInt.encode1363(publicOp(m), m_n.bytes());
314     }
315 
316     override bool verify(const(ubyte)*, size_t, const(ubyte)*, size_t)
317     {
318         throw new InvalidState("Message recovery required");
319     }
320 
321     override SecureVector!ubyte verifyMr(const(ubyte)* msg, size_t msg_len)
322     {
323         BigInt m = BigInt(msg, msg_len);
324         return BigInt.encodeLocked(publicOp(m));
325     }
326 
327 private:
328     BigInt publicOp(const ref BigInt m) const
329     {
330         if (m >= *m_n)
331             throw new InvalidArgument("RSA public op - input is too large");
332         return (cast()*m_powermod_e_n)(cast(BigInt*)&m);
333     }
334 
335     const IFSchemePublicKey m_rsa;
336     const BigInt* m_n;
337     FixedExponentPowerMod m_powermod_e_n;
338 }
339 
340 static if (BOTAN_TEST):
341 
342 import botan.test;
343 import botan.pubkey.test;
344 import botan.rng.auto_rng;
345 import botan.pubkey.pubkey;
346 import botan.codec.hex;
347 import core.atomic;
348 import memutils.hashmap;
349 
350 shared size_t total_tests;
351 
352 
353 size_t rsaesKat(string e,
354                 string p,
355                 string q,
356                 string msg,
357                 string padding,
358                 string nonce,
359                 string output)
360 {
361     atomicOp!"+="(total_tests, 1);
362 	Unique!AutoSeededRNG rng = new AutoSeededRNG;
363     
364     auto privkey = RSAPrivateKey(*rng, BigInt(p), BigInt(q), BigInt(e));
365     
366     auto pubkey = RSAPublicKey(privkey);
367     
368     if (padding == "")
369         padding = "Raw";
370     
371     auto enc = scoped!PKEncryptorEME(pubkey, padding);
372     auto dec = scoped!PKDecryptorEME(privkey, padding);
373     
374     return validateEncryption(enc, dec, "RSAES/" ~ padding, msg, nonce, output);
375 }
376 
377 size_t rsaSigKat(string e,
378                    string p,
379                    string q,
380                    string msg,
381                    string padding,
382                    string nonce,
383                    string output)
384 {
385     atomicOp!"+="(total_tests, 1);
386 	Unique!AutoSeededRNG rng = new AutoSeededRNG;
387     
388     auto privkey = RSAPrivateKey(*rng, BigInt(p), BigInt(q), BigInt(e));
389     
390     auto pubkey = RSAPublicKey(privkey);
391     
392     if (padding == "")
393         padding = "Raw";
394     
395     PKVerifier verify = PKVerifier(pubkey, padding);
396     PKSigner sign = PKSigner(privkey, padding);
397     
398     return validateSignature(verify, sign, "RSA/" ~ padding, msg, *rng, nonce, output);
399 }
400 
401 size_t rsaSigVerify(string e,
402                     string n,
403                     string msg,
404                     string padding,
405                     string signature)
406 {
407     atomicOp!"+="(total_tests, 1);
408     
409     BigInt e_bn = BigInt(e);
410     BigInt n_bn = BigInt(n);
411     
412     auto key = RSAPublicKey(n_bn.move(), e_bn.move());
413     
414     if (padding == "")
415         padding = "Raw";
416     
417     PKVerifier verify = PKVerifier(key, padding);
418     
419     if (!verify.verifyMessage(hexDecode(msg), hexDecode(signature)))
420         return 1;
421     return 0;
422 }
423 
424 size_t testPkKeygen(RandomNumberGenerator rng)
425 {
426     size_t fails;
427 
428     auto rsa1024 = RSAPrivateKey(rng, 1024);
429     rsa1024.checkKey(rng, true);
430     atomicOp!"+="(total_tests, 1);
431 
432     fails += validateSaveAndLoad(rsa1024, rng);
433     
434     auto rsa2048 = RSAPrivateKey(rng, 2048);
435     rsa2048.checkKey(rng, true);
436     atomicOp!"+="(total_tests, 1);
437     fails += validateSaveAndLoad(rsa2048, rng);
438 
439     return fails;
440 }
441 
442 static if (BOTAN_HAS_TESTS && !SKIP_RSA_TEST) unittest
443 {
444     logDebug("Testing rsa.d ...");
445     size_t fails = 0;
446     
447 	Unique!AutoSeededRNG rng = new AutoSeededRNG;
448 
449     
450     File rsa_enc = File("test_data/pubkey/rsaes.vec", "r");
451     File rsa_sig = File("test_data/pubkey/rsa_sig.vec", "r");
452     File rsa_verify = File("test_data/pubkey/rsa_verify.vec", "r");
453     
454     fails += testPkKeygen(*rng);
455 
456     fails += runTestsBb(rsa_enc, "RSA Encryption", "Ciphertext", true,
457         (ref HashMap!(string, string) m)
458         {
459             return rsaesKat(m["E"], m["P"], m["Q"], m["Msg"], m.get("Padding"), m.get("Nonce"), m["Ciphertext"]);
460         });
461     
462     fails += runTestsBb(rsa_sig, "RSA Signature", "Signature", true,
463         (ref HashMap!(string, string) m)
464         {
465             return rsaSigKat(m["E"], m["P"], m["Q"], m["Msg"], m.get("Padding"), m.get("Nonce"), m["Signature"]);
466         });
467     
468     fails += runTestsBb(rsa_verify, "RSA Verify", "Signature", true,
469         (ref HashMap!(string, string) m)
470         {
471             return rsaSigVerify(m["E"], m["N"], m["Msg"], m.get("Padding"), m["Signature"]);
472         });
473     
474     testReport("rsa", total_tests, fails);
475 }