Kaynağa Gözat

Establishing standard return values for questions.

Providing a "good" documentation base for new questions, and tuning the
pre-existent ones to the adapted model.
Specific changes:
* return defined (and fixed) in setup, teardown, test, ask_rsa
* documenting example question, questions.h's qa_question_t
* prettify interface, displaying error and success messages in stderr.
* qualifying the RSA* argument in qa_question_t.ask_rsa to const.
Michele Orrù 11 yıl önce
ebeveyn
işleme
3437ddba11

+ 47 - 7
src/qa.c

@@ -75,19 +75,59 @@ int qa_init(const struct qa_conf* conf)
 
 void qa_dispose(X509 *crt)
 {
-  RSA *rsa;
+  RSA *pub = X509_get_pubkey(crt)->pkey.rsa;
+  RSA *priv;
   qa_question_t *q;
 
-  rsa = X509_get_pubkey(crt)->pkey.rsa;
-
   printf("[+] Certificate acquired\n");
   LIST_FOREACH(q, &questions, qs) {
     printf( "[-] Running: %s\n", q->pretty_name);
-    if (q->setup)    q->setup();
-    if (q->test)     q->test(crt);
-    if (q->ask_rsa)  q->ask_rsa(rsa);
+
+    /*
+     * Run setup. If it fails, then print an error message and go to the next
+     * question.
+     */
+    if (q->setup && q->setup() <= 0)  {
+      fprintf(stderr, "[x] Unexpected error loading question %s\n", q->pretty_name);
+      continue;
+    }
+
+    /*
+     * Run test. If the test is undecidible or either okk, go on. Otherwise,
+     * print an error message and go to the next question.
+     */
+    if (q->test && q->test(crt) < 0) {
+      fprintf(stderr, "[|] Question %s cannot attack the given certificate.\n", q->pretty_name);
+      continue;
+    }
+
+    /*
+     * Attempt to attack RSA. If the attack went ok, there's no need to go
+     * on. Print out a nice message and then quit.
+     */
+    if (q->ask_rsa &&
+        (priv = q->ask_rsa(pub))) {
+      fprintf(stderr, "[\\] Key Broken using %s.\n", q->pretty_name);
+
+    }
+
+    /*
+     * Attempt to attack the X509 certificate.
+     */
     if (q->ask_crt)  q->ask_crt(crt);
-    if (q->teardown) q->teardown();
+
+    /*
+     * Shut down the given question. If it fails, print an error messae and go
+     * on.
+     */
+    if (q->teardown && q->teardown() <= 0) {
+      fprintf(stderr, "[x] Unexpected error shutting down question %s.\n", q->pretty_name);
+      continue;
+    }
   }
 
+  /*
+   *  Key seems resistent: exit with status -1
+   */
+  exit(-1);
 }

+ 9 - 5
src/questions/dixon.c

@@ -165,7 +165,7 @@ int dixon_question_setup(void)
   BN_zero(zero);
 
   extend_B_pool(BPOOL_STARTING_BITS);
-  return 0;
+  return 1;
 }
 
 int dixon_question_teardown(void) {
@@ -177,8 +177,9 @@ int dixon_question_teardown(void) {
 }
 
 
-int dixon_question_ask_rsa(RSA *rsa) {
+RSA* dixon_question_ask_rsa(const RSA *rsa) {
   /* key data */
+  RSA *ret = NULL;
   BIGNUM
     *n,
     *p, *q;
@@ -247,8 +248,11 @@ int dixon_question_ask_rsa(RSA *rsa) {
     if (!BN_cmp(x, y)) continue;
 
     /* p, q found :) */
-    p = BN_new();
-    q = BN_new();
+    ret = RSA_new();
+    ret->e = rsa->e;
+    ret->n = rsa->n;
+    ret->p = p = BN_new();
+    ret->q = q = BN_new();
 
     BN_uadd(tmp, x, y);
     BN_gcd(p, tmp, n, ctx);
@@ -265,7 +269,7 @@ int dixon_question_ask_rsa(RSA *rsa) {
   free(U_bucket);
   free(even_powers);
 
-  return 0;
+  return ret;
 }
 
 qa_question_t DixonQuestion = {

+ 45 - 11
src/questions/example.c

@@ -1,29 +1,59 @@
+/**
+ * \file example.c
+ * \brief Template for future Questions.
+ *
+ * This file has the purpose of showing and documenting how a
+ * \ref{qa_question_t} is supposed to be used.
+ *
+ */
 #include <openssl/bio.h>
 #include <openssl/rsa.h>
 #include <openssl/x509.h>
 
-
 #include "qa/questions/questions.h"
 
+
 static BIO* out;
 
-int example_question_setup(void) {
+/**
+ * \brief Example Setup.
+ *
+ * This functions returns false if `out` could not be opened.
+ */
+static int
+example_question_setup(void) {
   out = BIO_new_fp(stdout, BIO_NOCLOSE);
-  return 0;
+
+  return (out != NULL);
 }
 
-int example_question_teardown(void)
+/**
+ * \brief Example Teardown.
+ *
+ * This function returns an error if `out` could not be closed.
+ */
+static int
+example_question_teardown(void)
 {
+  return BIO_free(out);
+}
 
+/**
+ * \brief Example Test.
+ *
+ * This function always returns zero, as its attack is undecidible.
+ */
+static int
+example_question_test(X509* cert) {
   return 0;
 }
 
-/* XXX. apparently openssl does not allow const X509* in get_pkey() func */
-int example_question_test(X509* cert) {
-  return 1;
-}
 
-int example_question_ask_crt(X509* cert)
+/**
+ * \brief Example Attack to X509 certificate
+ */
+static int
+example_question_ask_crt(X509* cert)
 {
   EVP_PKEY* pkey;
 
@@ -32,9 +62,13 @@ int example_question_ask_crt(X509* cert)
   return 1;
 }
 
-int example_question_ask_rsa(RSA *rsa)
+/**
+ * \brief Example Attack on a RSA key.
+ */
+RSA*
+example_question_ask_rsa(const RSA *rsa)
 {
-  return 0;
+  return NULL;
 }
 
 

+ 22 - 11
src/questions/include/questions.h

@@ -9,18 +9,29 @@
  * A question: name, command-line name, callbacks.
  */
 typedef struct qa_question {
-  const char* name;            /**< short name - name given as command-line argument */
-  const char* pretty_name;     /**< full name - name used for identifying the question */
-
-  int (* setup) (void);        /**< setup callback - initializes static glabal
-                                  variables.*/
-  int (* teardown) ();         /**< teardown callback - frees static global
-                                  variables */
+  const char* name;    /**< short name - name given as command-line argument */
+  const char* pretty_name;    /**< full name - name used for identifying the question */
+
+  int (* setup) (void);    /**< setup callback - initializes static glabal
+                              variables.
+                              Return <= 0 in case of error */
+  int (* teardown) ();    /**< teardown callback - frees static global
+                             variables
+                             Return <= 0 in case of error*/
   int (* test) (X509 *cert);   /**< test callback - assert the attack can be
-                                  performed over the certificate cert */
-  int (* ask_rsa) (RSA *rsa);  /**< ask_rsa callback - attack the RSA key rsa */
-  int (* ask_crt) (X509 *crt); /**< ask_crt callback - attack the certificate
-                                  crt */
+                                  performed over the certificate cert.
+                                  Return 1 if it is possible to attack the
+                                  certificate, -1 if not, 0 if undecidible. */
+  RSA* (* ask_rsa) (const RSA *rsa);    /**< ask_rsa callback - attack the RSA
+                                           key rsa. Return NULL if the key was
+                                           not broken, a valid private key
+                                           structure otherwise.*/
+  int (* ask_crt) (X509 *crt);    /**< ask_crt callback - attack the certificate
+                                     crt.
+                                     XXX. Return type has still to be
+                                     established here.
+                                     XXX. apparently openssl does not allow const
+                                     X509* in get_pkey() func. */
 
   LIST_ENTRY(qa_question) qs;
 } qa_question_t;

+ 9 - 9
src/questions/pollard.c

@@ -38,13 +38,13 @@ int pollard1_question_setup(void)
   two = BN_new();
   BN_one(two);
   BN_uadd(two, two, BN_value_one());
-  return 0;
+  return 1;
 }
 
 int pollard1_question_teardown(void)
 {
   BN_free(two);
-  return 0;
+  return 1;
 }
 
 
@@ -60,9 +60,9 @@ int pollard1_question_teardown(void)
  * about 3^(−3) = 1/27 that a B value of n^(1/6) will yield a factorisation.»
  *
  */
-int pollard1_question_ask_rsa(RSA *rsa)
+RSA* pollard1_question_ask_rsa(const RSA *rsa)
 {
-  int ret = 1;
+  RSA *ret = NULL;
   BIGNUM *a, *B, *a1;
   BIGNUM *gcd, *rem;
   BIGNUM *n;
@@ -92,12 +92,12 @@ int pollard1_question_ask_rsa(RSA *rsa)
   }
 
   /* Either p or q found :) */
-  ret = BN_is_zero(B);
-  if (!ret) {
-    p = BN_dup(gcd);
-    q = BN_new();
+  if (!BN_is_zero(B)) {
+    ret = RSA_new();
+    ret->n = rsa->e;
+    ret->p = p = BN_dup(gcd);
+    ret->q = q = BN_new();
     BN_div(q, NULL, n, gcd, ctx);
-    printf("p:%s, q=%s \n", BN_bn2dec(p), BN_bn2dec(q));
   }
 
   BN_free(a);

+ 8 - 5
src/questions/wiener.c

@@ -146,9 +146,10 @@ bigfraction_t* cf_next(cf_t *f)
 /*
  *  Weiner Attack Implementation
  */
-int wiener_question_ask_rsa(RSA *rsa)
+RSA* wiener_question_ask_rsa(const RSA *rsa)
 {
   /* key data */
+  RSA *ret = NULL;
   BIGNUM *n, *e, *d, *phi;
   BIGNUM *p, *q;
   /* continued fractions coefficient, and mod */
@@ -209,11 +210,13 @@ int wiener_question_ask_rsa(RSA *rsa)
     BN_usub(delta, tmp, n);
     if (!BN_sqrtmod(tmp, rem, delta, ctx)) continue;
     /* key found :) */
-    p = BN_new();
-    q = BN_new();
+    ret = RSA_new();
+    ret->n = rsa->n;
+    ret->e = rsa->e;
+    ret->p = p = BN_new();
+    ret->q = q = BN_new();
     BN_usub(p, b2, tmp);
     BN_uadd(q, b2, tmp);
-    //printf("Primes: %s %s", BN_bn2dec(p), BN_bn2dec(q));
     break;
   }
 
@@ -224,7 +227,7 @@ int wiener_question_ask_rsa(RSA *rsa)
   BN_free(delta);
   BN_free(phi);
 
-  return i;
+  return ret;
 }