/*
 ============================================================================
 Name        : BRAINPOOL_dbl.c
 Author      : Josef Brychta
 Description : BRAINPOOL doubling
 ============================================================================
 */

#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 ()
{
  BN_CTX *ctx;
  BIGNUM *x, *y;
  EC_GROUP *group;
  EC_POINT *A;
  EC_POINT *B;

  ctx = BN_CTX_new ();
  x = BN_new ();
  y = BN_new ();

  double final = 0;

  for (int i = 921; i <= 934; i++)
    {
      // pouzije ID preddefinovane elipticke krivky dle obj_mac.h
      group = EC_GROUP_new_by_curve_name (i);
      A = EC_POINT_new (group);
      B = EC_POINT_new (group);

      for (int i = 1; i <= 1000; i++)
	{
	  EC_POINT_GET_RND_POINT (group, A, ctx);

	  // kontrola bodu na krivce a prevod na affine souradnicovy system
	  if (!EC_POINT_is_on_curve (group, A, ctx))
	    return -1;
	  if (!EC_POINT_get_affine_coordinates_GFp (group, A, x, y, ctx))
	    return -1;

	  clock_t start = clock ();

	  EC_POINT_dbl (group, B, A, 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
      printf ("%d;%.4f\n", i, final);
    }

  return 0;
}