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