/*
 ============================================================================
 Name        : BRAINPOOL_mulx.c
 Author      : Josef Brychta
 Description : multiplication x
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <openssl/ec.h>
#include <openssl/bn.h>
#include <openssl/obj_mac.h>

int
EC_POINT_GET_RND_POINT (const EC_GROUP * group, EC_POINT * r, BN_CTX * ctx)
{
  int ok = 0;
  BN_CTX *new_ctx = NULL;
  BIGNUM *k;

  if (ctx == NULL)
    {
      ctx = new_ctx = BN_CTX_new ();
      if (ctx == NULL)
	return -1;
    }
  k = BN_new ();

  if (!EC_GROUP_get_order (group, k, ctx))
    goto err;
  if (!BN_pseudo_rand (k, BN_num_bits (k), 0, 0))
    goto err;
  if (!EC_POINT_mul (group, r, k, NULL, NULL, ctx))
    goto err;

  ok = 1;
err:
  if (k)
    BN_free (k);
  if (new_ctx != NULL)
    BN_CTX_free (new_ctx);
  return ok;
}

int
main ()
{
  EC_POINT *R;
  EC_POINT *A, *B;
  BIGNUM *x, *y;
  const EC_GROUP *group;
  BN_CTX *ctx;

  double final = 0;

  x = BN_new ();
  y = BN_new ();
  ctx = BN_CTX_new ();		// ctx is an optional buffer to save time from allocating and deallocating memory whenever required

  for (int i = 704; i <= 716; i++)
    {

      group = EC_GROUP_new_by_curve_name (i);
      R = EC_POINT_new (group);
      A = EC_POINT_new (group);
      B = EC_POINT_new (group);


      for (int j = 1; j <= 1000; j++)
	{

	  EC_POINT_GET_RND_POINT (group, A, ctx);
	  EC_POINT_GET_RND_POINT (group, B, ctx);
	  if (!EC_POINT_is_on_curve (group, B, ctx))
	    return -1;
	  if (!EC_POINT_get_affine_coordinates_GFp (group, B, x, y, ctx))
	    return -1;

	  clock_t start = clock ();

	  /* pub_key is a new uninitialized `EC_POINT*`.  priv_key res is a `BIGNUM*`. */
	  EC_POINT_mul (group, R, NULL, A, x, ctx);

	  clock_t stop = clock ();
	  final += (stop - start) / (double) CLOCKS_PER_SEC;
	}

      // vypise ID krivky dle obj_mac.h a prumerny cas generovani jednoho bodu na krivce v ms (final/1000*1000)
      printf ("%.4f\n", final);
    }
  return 0;
}
