| 
					
				 | 
			
			
				@@ -16,19 +16,26 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * exponent. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <assert.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <stdlib.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <strings.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <openssl/bn.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "qarith.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "questions.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define EPOCHS             100 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define REPOP_EPOCHS        50 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define BPOOL_EXTEND_STEP   42 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define BPOOL_STARTING_BITS  7 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define RPOOL_EXTEND_STEP   42 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define U_SIZE              10 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define qa_rand rand 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static BIGNUM* zero; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * \struct dixon_number_t 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * \brief Auxiliary structure holding informations for R_pool. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -50,13 +57,19 @@ static BIGNUM** B_pool = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static size_t B_size = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * \brief Extends the factor base, and then adjusts R_pool 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void extend_B_pool(int max_bits) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  size_t i, old_B_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  size_t i, j, old_B_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int bits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   old_B_size = B_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   B_size += BPOOL_EXTEND_STEP; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* check for size_t overflow */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  assert(old_B_size < B_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   B_pool = realloc(B_pool, B_size * sizeof(BIGNUM*)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -64,7 +77,11 @@ static void extend_B_pool(int max_bits) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     bits = 1 + qa_rand() % max_bits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     B_pool[i] = BN_generate_prime(NULL, bits, 0, NULL, NULL, NULL, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /* XXX. reallocate space for vectors in R_pool */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* reallocate space for vectors in R_pool */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i=0; i!=R_size; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    R_pool[i].v = realloc(R_pool[i].v, sizeof(BIGNUM*) * B_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (j=old_B_size; j!=B_size; j++) R_pool[i].v[j] = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define B_pool_free() free(B_pool) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -84,45 +101,183 @@ static void extend_B_pool(int max_bits) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  *          3. Find an r = √(s + tN) , t ∈ {1..N-1} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * This algorithm shall have complexity O(k|B| + (N-1)lg N) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void extend_R_pool(BIGNUM* max_s) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void extend_R_pool(BIGNUM* N) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const size_t old_R_size = R_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t i, j; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int e_bits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_CTX *ctx = BN_CTX_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BIGNUM 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *e, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *tmp = BN_new(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *rem = BN_new(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *t = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   dixon_number_t *d; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  i = R_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   R_size += RPOOL_EXTEND_STEP; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* size_t overflow */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  assert(R_size > old_R_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   R_pool = realloc(R_pool, sizeof(dixon_number_t)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * XXX. There is much more to think about this. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * We are trying to generate some random exponents e₀…eₖ such that s < N . 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * Hence, log(N) = ae₀ + be₁ + … + leₖ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  e_bits = BN_num_bits(N) / 5; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (; i!= R_size; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i=old_R_size; i!= R_size; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     d = &R_pool[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     d->s = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    d->r = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /* generate exponents and calculate s */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    while (BN_cmp(d->s, max_s) != -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      for (j=0; j != B_size; j++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (j=0; j != B_size && BN_cmp(N, d->s) == 1; j++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      e = d->v[j] = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* XXX. better check for error here. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BN_pseudo_rand(e, e_bits, -1, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BN_exp(tmp, B_pool[j], e, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BN_mul(d->s, tmp, d->s, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /*  Find an r = √(s + tN) , t ∈ {1..N-1} */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_sqr(tmp, N, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_one(t); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (BN_add(t, t, N); BN_cmp(tmp, t) == 1; BN_add(t, t, N)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (BN_sqrtmod(d->r, rem, t, ctx)) break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_CTX_free(ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(rem); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(tmp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(t); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define R_pool_free() free(R_pool) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 int dixon_question_setup(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  extern BIGNUM* zero; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  zero = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_zero(zero); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   extend_B_pool(BPOOL_STARTING_BITS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  extend_R_pool(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 int dixon_question_teardown(void) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(zero); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   B_pool_free(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   R_pool_free(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-int dixon_question_test(X509* cert) { return 1; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int dixon_question_test(X509* cert) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int is_vzero(void *v, size_t len) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  char unsigned *s = (char unsigned *) v; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  while (len--) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (*(s++)) return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 int dixon_question_ask(X509* cert) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  RSA *rsa; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* key data */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BIGNUM 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *n, *e, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *p, *q; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* x, y */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BIGNUM 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *x, *x2, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *y, *y2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_CTX *ctx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* U ⊆ R */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ssize_t *U_bucket; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* internal data */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int epoch; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BIGNUM *tmp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  char *even_powers; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  size_t i, j, k; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  rsa = X509_get_pubkey(cert)->pkey.rsa; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  n = rsa->n; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  e = rsa->e; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  U_bucket = malloc(sizeof(ssize_t) * U_SIZE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  even_powers = malloc(sizeof(char) * B_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ctx = BN_CTX_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  x = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  y = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  x2 = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  y2 = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tmp = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* mainloop: iterate until a key is found, or convergence. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (epoch=0; epoch < EPOCHS; epoch++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* depending on the epoch, populate R_pool and B_pool */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (epoch % REPOP_EPOCHS) extend_R_pool(n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* reset variables */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (i=0; i!=U_SIZE; i++) U_bucket[i] =  -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bzero(even_powers, B_size * sizeof(char)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    j = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* choose a subset of R such that the product of primes can be squared */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    do { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      for (i=0; i!=B_size && j < U_SIZE; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /* choose whether to take or not R_pool[i] */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (qa_rand() % 2) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /* add the number */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        U_bucket[j++] = i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (k=0; k!=B_size; k++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          even_powers[k] ^= BN_is_odd(R_pool[i].v[j]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } while (!is_vzero(even_powers, B_size * sizeof(char))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* let x = Πᵢ rᵢ , y² = Πᵢ sᵢ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_one(x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_one(y2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (i=0; i != U_SIZE; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (U_bucket[i] == -1) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      j = U_bucket[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BN_mul(x, x, R_pool[j].r, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BN_mul(y2, y2, R_pool[j].s, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* retrieve x² from x */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_sqr(x2, x, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* retrieve y from y² */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* test: shall *always* be a perfect square */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!BN_sqrtmod(y, tmp, y2, ctx)) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* test: assert that x ≡ y (mod N) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!BN_cmp(x, y)) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* p, q found :) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    p = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    q = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_uadd(tmp, x, y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_gcd(p, tmp, n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert(!BN_is_one(p) && BN_cmp(p, n)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_usub(tmp, x, y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_gcd(q, tmp, n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert(!BN_is_one(q) && BN_cmp(q, n)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(x2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(y2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  free(U_bucket); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  free(even_powers); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |