| 
					
				 | 
			
			
				@@ -24,7 +24,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 lucas(BIGNUM *v, BIGNUM *w, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       BIGNUM *h, BIGNUM *tau, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      BN_CTX *ctx) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BIGNUM *n, BN_CTX *ctx) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   BIGNUM *vv; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   BIGNUM *vw; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -35,23 +35,23 @@ lucas(BIGNUM *v, BIGNUM *w, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   u = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       BN_ucmp(h, BN_value_one()) > 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       !BN_is_one(h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        BN_rshift1(h, h)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (BN_is_odd(h)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      BN_sqr(vv, v, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BN_mod_sqr(vv, v, n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       /* v = τv² - vw - τ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      BN_mul(u, tau, vv, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      BN_mul(vw, v, w, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BN_mod_mul(u, tau, vv, n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BN_mod_mul(vw, v, w, n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       BN_sub(u, u, vw); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       BN_sub(u, u, tau); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       /* w = w² - 2 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       BN_sub(w, vv, BN_value_two()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      BN_sqr(vv, v, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BN_mod_sqr(vv, v, n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       /* v = v² - 2 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       BN_sub(u, vv, BN_value_two()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       /* w = vw - τ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      BN_mul(vw, v, w, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BN_mod_mul(vw, v, w, n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       BN_sub(w, vw, tau); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     BN_copy(v, u); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -79,39 +79,67 @@ williams_question_ask_rsa(const RSA* rsa) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     *q = BN_new(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     *p = BN_new(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     *g = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  int e, k, j, m = 100; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int e, k, j, m = 50; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   BN_CTX *ctx = BN_CTX_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   pit_t *pit; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BIGNUM *p; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BIGNUM *v; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BIGNUM *w; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int k; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } back = {BN_new(), BN_new(), BN_new(), 0}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  BN_one(g); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   BN_one(w); BN_uiadd1(w); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  BN_pseudo_rand(tau, 512, 0, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_pseudo_rand_range(tau, n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   BN_copy(v, tau); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  BN_one(q); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_copy(back.v, v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_copy(back.w, w); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_copy(back.p, BN_value_two()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  back.k = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_one(g); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_one(q); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (pit = primes_init(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        BN_is_one(g) && primes_next(pit, p); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    e = BN_num_bits(n) / (BN_num_bits(p)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    e = BN_num_bits(n) / (BN_num_bits(p)) + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for (k = 0; k < e && BN_is_one(g); k += m) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       for (j = (m > e) ? e : m; j; j--) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        lucas(v, w, p, tau, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        /* XXX. unsafe. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BN_mod(v, v, n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BN_mod(w, w, n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        lucas(v, w, p, tau, n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /* q = v - 2 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BN_sub(v2, v, BN_value_one()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BN_sub(v2, v2, BN_value_one()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BN_sub(v2, v, BN_value_two()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         BN_mod_mul(q, q, v2, n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       /* gcd test */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       BN_gcd(g, q, n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (BN_is_one(g)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BN_copy(back.p, p); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BN_copy(back.v, v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BN_copy(back.w, w); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        back.k = k; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (BN_cmp(g, n)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!BN_cmp(g, n)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_copy(p, back.p); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_one(g); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_copy(v, back.v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_copy(w, back.w); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (k = back.k; k < e; k++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      lucas(v, w, p, tau, n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BN_sub(v2, v, BN_value_two()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BN_gcd(g, v2, n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (BN_is_one(g)) break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!BN_is_one(g) && BN_cmp(g, n)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ret = qa_RSA_recover(rsa, g, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(back.v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(back.w); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(back.p); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   BN_free(v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   BN_free(v2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   BN_free(w); 
			 |