add crc8
[oweals/gnunet.git] / src / util / crypto_ecc_dlog.c
index 3a2a915321c6ce2a3c9759e77eb9562cb99d3e9d..1254a036e27ff83a814e7ea30eb7484daf01cb31 100644 (file)
  */
 static void
 extract_pk (gcry_mpi_point_t pt,
-             gcry_ctx_t ctx,
-             struct GNUNET_PeerIdentity *pid)
+            gcry_ctx_t ctx,
+            struct GNUNET_PeerIdentity *pid)
 {
   gcry_mpi_t q_y;
-  
+
   GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", pt, ctx));
   q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
   GNUNET_assert (q_y);
@@ -63,7 +63,7 @@ extract_pk (gcry_mpi_point_t pt,
 /**
  * Internal structure used to cache pre-calculated values for DLOG calculation.
  */
-struct GNUNET_CRYPTO_EccDlogContext 
+struct GNUNET_CRYPTO_EccDlogContext
 {
   /**
    * Maximum absolute value the calculation supports.
@@ -91,9 +91,64 @@ struct GNUNET_CRYPTO_EccDlogContext
 };
 
 
+/**
+ * Convert point value to binary representation.
+ *
+ * @param edc calculation context for ECC operations
+ * @param point computational point representation
+ * @param[out] bin binary point representation
+ */
+void
+GNUNET_CRYPTO_ecc_point_to_bin (struct GNUNET_CRYPTO_EccDlogContext *edc,
+                                gcry_mpi_point_t point,
+                                struct GNUNET_CRYPTO_EccPoint *bin)
+{
+  gcry_mpi_t q_y;
+
+  GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", point, edc->ctx));
+  q_y = gcry_mpi_ec_get_mpi ("q@eddsa", edc->ctx, 0);
+  GNUNET_assert (q_y);
+  GNUNET_CRYPTO_mpi_print_unsigned (bin->q_y,
+                                   sizeof (bin->q_y),
+                                    q_y);
+  gcry_mpi_release (q_y);
+}
+
+
+/**
+ * Convert binary representation of a point to computational representation.
+ *
+ * @param edc calculation context for ECC operations
+ * @param bin binary point representation
+ * @return computational representation
+ */
+gcry_mpi_point_t
+GNUNET_CRYPTO_ecc_bin_to_point (struct GNUNET_CRYPTO_EccDlogContext *edc,
+                                const struct GNUNET_CRYPTO_EccPoint *bin)
+{
+  gcry_sexp_t pub_sexpr;
+  gcry_ctx_t ctx;
+  gcry_mpi_point_t q;
+
+  if (0 != gcry_sexp_build (&pub_sexpr, NULL,
+                            "(public-key(ecc(curve " CURVE ")(q %b)))",
+                            (int) sizeof (bin->q_y),
+                            bin->q_y))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
+  gcry_sexp_release (pub_sexpr);
+  q = gcry_mpi_ec_get_point ("q", ctx, 0);
+  gcry_ctx_release (ctx);
+  return q;
+}
+
+
 /**
  * Do pre-calculation for ECC discrete logarithm for small factors.
- * 
+ *
  * @param max maximum value the factor can be
  * @param mem memory to use (should be smaller than @a max), must not be zero.
  * @return @a max if dlog failed, otherwise the factor
@@ -119,8 +174,8 @@ GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max,
   edc->map = GNUNET_CONTAINER_multipeermap_create (mem * 2,
                                                   GNUNET_NO);
 
-  GNUNET_assert (0 == gcry_mpi_ec_new (&edc->ctx, 
-                                      NULL, 
+  GNUNET_assert (0 == gcry_mpi_ec_new (&edc->ctx,
+                                      NULL,
                                       CURVE));
   g = gcry_mpi_ec_get_point ("g", edc->ctx, 0);
   GNUNET_assert (NULL != g);
@@ -161,7 +216,7 @@ GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max,
 
 /**
  * Calculate ECC discrete logarithm for small factors.
- * 
+ *
  * @param edc precalculated values, determine range of factors
  * @param input point on the curve to factor
  * @return `edc->max` if dlog failed, otherwise the factor
@@ -181,7 +236,7 @@ GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc,
   g = gcry_mpi_ec_get_point ("g", edc->ctx, 0);
   GNUNET_assert (NULL != g);
   q = gcry_mpi_point_new (0);
-  
+
   res = edc->max;
   for (i=0;i<=edc->max/edc->mem;i++)
   {
@@ -204,7 +259,7 @@ GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc,
     if (0 == i)
       gcry_mpi_ec_add (q, input, g, edc->ctx);
     else
-      gcry_mpi_ec_add (q, q, g, edc->ctx);     
+      gcry_mpi_ec_add (q, q, g, edc->ctx);
   }
   gcry_mpi_point_release (g);
   gcry_mpi_point_release (q);
@@ -237,11 +292,11 @@ GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccDlogContext *edc)
   /* generate fact < n (without bias) */
   GNUNET_assert (NULL != (r = gcry_mpi_new (0)));
   do {
-    gcry_mpi_randomize (r, 
+    gcry_mpi_randomize (r,
                        highbit + 1,
                        GCRY_STRONG_RANDOM);
   }
-  while (gcry_mpi_cmp (r, n) >= 0);  
+  while (gcry_mpi_cmp (r, n) >= 0);
   gcry_mpi_release (n);
   return r;
 }
@@ -265,10 +320,10 @@ GNUNET_CRYPTO_ecc_dlog_release (struct GNUNET_CRYPTO_EccDlogContext *edc)
  * Multiply the generator g of the elliptic curve by @a val
  * to obtain the point on the curve representing @a val.
  * Afterwards, point addition will correspond to integer
- * addition.  #GNUNET_CRYPTO_ecc_dlog() can be used to 
+ * addition.  #GNUNET_CRYPTO_ecc_dlog() can be used to
  * convert a point back to an integer (as long as the
  * integer is smaller than the MAX of the @a edc context).
- * 
+ *
  * @param edc calculation context for ECC operations
  * @param val value to encode into a point
  * @return representation of the value as an ECC point,
@@ -308,7 +363,7 @@ GNUNET_CRYPTO_ecc_dexp (struct GNUNET_CRYPTO_EccDlogContext *edc,
 /**
  * Multiply the generator g of the elliptic curve by @a val
  * to obtain the point on the curve representing @a val.
- * 
+ *
  * @param edc calculation context for ECC operations
  * @param val (positive) value to encode into a point
  * @return representation of the value as an ECC point,
@@ -332,7 +387,7 @@ GNUNET_CRYPTO_ecc_dexp_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc,
 
 /**
  * Add two points on the elliptic curve.
- * 
+ *
  * @param edc calculation context for ECC operations
  * @param a some value
  * @param b some value
@@ -344,18 +399,40 @@ GNUNET_CRYPTO_ecc_add (struct GNUNET_CRYPTO_EccDlogContext *edc,
                       gcry_mpi_point_t b)
 {
   gcry_mpi_point_t r;
-  
+
   r = gcry_mpi_point_new (0);
   gcry_mpi_ec_add (r, a, b, edc->ctx);
   return r;
 }
 
 
+/**
+ * Multiply the point @a p on the elliptic curve by @a val.
+ *
+ * @param edc calculation context for ECC operations
+ * @param p point to multiply
+ * @param val (positive) value to encode into a point
+ * @return representation of the value as an ECC point,
+ *         must be freed using #GNUNET_CRYPTO_ecc_free()
+ */
+gcry_mpi_point_t
+GNUNET_CRYPTO_ecc_pmul_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc,
+                            gcry_mpi_point_t p,
+                           gcry_mpi_t val)
+{
+  gcry_mpi_point_t r;
+
+  r = gcry_mpi_point_new (0);
+  gcry_mpi_ec_mul (r, val, p, edc->ctx);
+  return r;
+}
+
+
 /**
  * Obtain a random point on the curve and its
  * additive inverse. Both returned values
  * must be freed using #GNUNET_CRYPTO_ecc_free().
- * 
+ *
  * @param edc calculation context for ECC operations
  * @param[out] r set to a random point on the curve
  * @param[out] r_inv set to the additive inverse of @a r
@@ -380,18 +457,41 @@ GNUNET_CRYPTO_ecc_rnd (struct GNUNET_CRYPTO_EccDlogContext *edc,
   /* calculate 'r_inv' */
   n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1);
   gcry_mpi_sub (fact, n, fact); /* fact = n - fact = - fact */
-  *r_inv = gcry_mpi_point_new (0); 
+  *r_inv = gcry_mpi_point_new (0);
   gcry_mpi_ec_mul (*r_inv, fact, g, edc->ctx);
 
   gcry_mpi_release (n);
   gcry_mpi_release (fact);
   gcry_mpi_point_release (g);
 }
+
+
+/**
+ * Obtain a random scalar for point multiplication on the curve and
+ * its multiplicative inverse.
+ *
+ * @param edc calculation context for ECC operations
+ * @param[out] r set to a random scalar on the curve
+ * @param[out] r_inv set to the multiplicative inverse of @a r
+ */
+void
+GNUNET_CRYPTO_ecc_rnd_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc,
+                           gcry_mpi_t *r,
+                           gcry_mpi_t *r_inv)
+{
+  gcry_mpi_t n;
+
+  *r = GNUNET_CRYPTO_ecc_random_mod_n (edc);
+  /* r_inv = n - r = - r */
+  *r_inv = gcry_mpi_new (0);
+  n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1);
+  gcry_mpi_sub (*r_inv, n, *r);
+}
+
 
 /**
  * Free a point value returned by the API.
- * 
+ *
  * @param p point to free
  */
 void
@@ -400,6 +500,5 @@ GNUNET_CRYPTO_ecc_free (gcry_mpi_point_t p)
   gcry_mpi_point_release (p);
 }
 
-/* end of crypto_ecc_dlog.c */
 
+/* end of crypto_ecc_dlog.c */