Ejemplo n.º 1
0
static void fq_clear(element_ptr e) {
  eptr p = e->data;
  element_clear(p->x);
  element_clear(p->y);
  pbc_free(e->data);
}
Ejemplo n.º 2
0
static void point_clear(element_t e) {
    point_ptr p = DATA(e);
    element_clear(p->x);
    element_clear(p->y);
    pbc_free(p);
}
Ejemplo n.º 3
0
static void eta_T_3_clear(params *p) {
    mpz_clear(p->n);
    mpz_clear(p->n2);
    pbc_free(p);
}
Ejemplo n.º 4
0
void BSActivity(unsigned char *da, unsigned char *db, unsigned char *dc, unsigned char *dcu) {
  //signature decompress
  //printf("Verifying....\n");

  element_t cu, A, B, C;
  element_init_G1(A, pairing);
  element_init_G1(B, pairing);
  element_init_G1(C, pairing);
  element_init_Zr(cu, pairing2);
  
  element_from_bytes_compressed(A, da);
  element_from_bytes_compressed(B, db);
  element_from_bytes_compressed(C, dc);
  element_from_bytes(cu, dcu);

  pbc_free(da);
  pbc_free(db);
  pbc_free(dc);
  pbc_free(dcu);
 
  //verification I
  element_t exbcu;
  element_t tmp1, tmp2, right, left;
  element_init_GT(exbcu, pairing);
  element_init_GT(tmp1, pairing);
  element_init_GT(tmp2, pairing);
  element_init_GT(right, pairing);
  element_init_GT(left, pairing);

  element_pairing(tmp1, X, A);
  element_pairing(tmp2, X, B);
  element_pow_zn(exbcu, tmp2, cu);
  element_mul(left, tmp1, exbcu);
  element_pairing(right, g, C);

  if (!element_cmp(left, right)) {
          //printf("part 1 verifies\n");
  } else {
      printf("*BUG* part 1 does not verify *BUG*\n");
  }

  //verification II
  element_pairing(left, A, Y);
  element_pairing(right, g, B);

  if (!element_cmp(left, right)) {
          //printf("part 2 verifies\n");
  } else {
      printf("*BUG* part 2 does not verify *BUG*\n");
  }

  if(ifsize) {
    int totalsize = sizeof(tmp1) + sizeof(tmp2) + sizeof(right) + sizeof(left) + 
                    sizeof(A) + sizeof(B) + sizeof(C) + sizeof(cu);
    printf("Memory used at base station is %d bytes. \n", totalsize);

  }

  element_clear(exbcu);
  element_clear(tmp1);
  element_clear(tmp2);
  element_clear(right);
  element_clear(left);
  element_clear(A);
  element_clear(B);
  element_clear(C);
  element_clear(cu);

  return;
}
Ejemplo n.º 5
0
static void zp_clear(element_ptr e) {
	mpz_clear((mpz_ptr)e->data);
  pbc_free(e->data);
}
Ejemplo n.º 6
0
//start_index从1开始,不算0
int BCEGenPrivateKeys(byte *sys_params_path, byte *sys_priv_key, int num_user, int start_index, int length, byte *user_priv_keys_out, int check_array)
{
    global_broadcast_params_t gbs;
    broadcast_system_t sys;
    int priv_key_read, i;
    //struct single_priv_key_s user_keys[length];  // Problematic Memory Allocation

    struct single_priv_key_s *user_keys;

    char *recip;
    // char recip[num_user / NUM_USER_DIVISOR];

    if (sys_params_path == NULL)
        return 1;

    if (sys_priv_key == NULL)
        return 2;

    if (num_user % NUM_USER_DIVISOR != 0)
        return 3;

    if (start_index % NUM_USER_DIVISOR != 1)
        return 4;

    if (user_priv_keys_out == NULL)
        return 6;

    if (length > check_array)
        return -2;

    LoadParams((char *) sys_params_path, &gbs, &sys);

    priv_key_read = element_from_bytes(sys->priv_key, sys_priv_key);

    if (priv_key_read != BCE_ZR_LENGTH)
        return -1;

    recip = (char *) malloc(num_user / NUM_USER_DIVISOR);

    memset(recip, BIT_VECTOR_UNIT_VALUE, num_user / NUM_USER_DIVISOR);

    user_keys = (priv_key_t) malloc(length * sizeof(struct single_priv_key_s)); //**

    for (i = 0; i < length; i++)
    {
        Get_priv_key(gbs, sys, start_index + i, &user_keys[i]);
        Gen_decr_prod_from_bitvec(gbs, start_index + i, recip, &user_keys[i]);
    }

    for (i = 0; i < length; i++)
    {
        int_to_bytes(user_keys[i].index, user_priv_keys_out);
        user_priv_keys_out += 4;
        user_priv_keys_out += element_to_bytes(user_priv_keys_out, user_keys[i].g_i_gamma);
        user_priv_keys_out += element_to_bytes(user_priv_keys_out, user_keys[i].g_i);
        user_priv_keys_out += element_to_bytes(user_priv_keys_out, user_keys[i].h_i);
        user_priv_keys_out += element_to_bytes(user_priv_keys_out, user_keys[i].decr_prod);
    }

    memset(recip, BIT_VECTOR_CLEAR_UNIT_VALUE, num_user / NUM_USER_DIVISOR);
    free(recip);
    for (i = 0; i < length; i++)
    {
        FreePK(&user_keys[i]);
    }
    free(user_keys);
    FreeBCS(sys);
    pbc_free(sys);
    FreeGBP(gbs);
    pbc_free(gbs);

    return 0;
}
Ejemplo n.º 7
0
static void clear(void *data) {
	entry_ptr e = (entry_ptr)data;
  pbc_free(e->key);
  pbc_free(e);
}
Ejemplo n.º 8
0
Archivo: hilbert.c Proyecto: blynn/pbc
void pbc_hilbert_free(mpz_t *arr, size_t n) {
  size_t i;

  for (i = 0; i < n; i++) mpz_clear(arr[i]);
  pbc_free(arr);
}
Ejemplo n.º 9
0
void darray_clear(darray_t a)
{
    pbc_free(a->item);
    a->max = 0;
    a->count = 0;
}
Ejemplo n.º 10
0
static void curve_clear(element_ptr e) {
	point_ptr p = (point_ptr)e->data;
  element_clear(p->x);
  element_clear(p->y);
  pbc_free(e->data);
}
Ejemplo n.º 11
0
Archivo: hilbert.c Proyecto: blynn/pbc
// See Cohen; my D is -D in his notation.
size_t pbc_hilbert(mpz_t **arr, int D) {
  int a, b;
  int t;
  int B = (int)floor(sqrt((double) D / 3.0));
  mpc_t alpha;
  mpc_t j;
  mpf_t sqrtD;
  mpf_t f0;
  darray_t Pz;
  mpc_t z0, z1, z2;
  double d = 1.0;
  int h = 1;
  int jcount = 1;

  // Compute required precision.
  b = D % 2;
  for (;;) {
    t = (b*b + D) / 4;
    a = b;
    if (a <= 1) {
      a = 1;
      goto step535_4;
    }
step535_3:
    if (!(t % a)) {
      jcount++;
      if ((a == b) || (a*a == t) || !b) {
        d += 1.0 / ((double) a);
        h++;
      } else {
        d += 2.0 / ((double) a);
        h+=2;
      }
    }
step535_4:
    a++;
    if (a * a <= t) {
      goto step535_3;
    } else {
      b += 2;
      if (b > B) break;
    }
  }

  //printf("modulus: %f\n", exp(3.14159265358979 * sqrt(D)) * d * 0.5);
  d *= sqrt(D) * 3.14159265358979 / log(2);
  precision_init((int)(d + 34));
  pbc_info("class number %d, %d bit precision", h, (int) d + 34);

  darray_init(Pz);
  mpc_init(alpha);
  mpc_init(j);
  mpc_init(z0);
  mpc_init(z1);
  mpc_init(z2);
  mpf_init(sqrtD);
  mpf_init(f0);

  mpf_sqrt_ui(sqrtD, D);
  b = D % 2;
  h = 0;
  for (;;) {
    t = (b*b + D) / 4;
    if (b > 1) {
      a = b;
    } else {
      a = 1;
    }
step3:
    if (t % a) {
step4:
      a++;
      if (a * a <= t) goto step3;
    } else {
      // a, b, t/a are coeffs of an appropriate primitive reduced positive
      // definite form.
      // Compute j((-b + sqrt{-D})/(2a)).
      h++;
      pbc_info("[%d/%d] a b c = %d %d %d", h, jcount, a, b, t/a);
      mpf_set_ui(f0, 1);
      mpf_div_ui(f0, f0, 2 * a);
      mpf_mul(mpc_im(alpha), sqrtD, f0);
      mpf_mul_ui(f0, f0, b);
      mpf_neg(mpc_re(alpha), f0);

      compute_j(j, alpha);
if (0) {
  int i;
  for (i=Pz->count - 1; i>=0; i--) {
    printf("P %d = ", i);
    mpc_out_str(stdout, 10, 4, Pz->item[i]);
    printf("\n");
  }
}
      if (a == b || a * a == t || !b) {
        // P *= X - j
        int i, n;
        mpc_ptr p0;
        p0 = (mpc_ptr) pbc_malloc(sizeof(mpc_t));
        mpc_init(p0);
        mpc_neg(p0, j);
        n = Pz->count;
        if (n) {
          mpc_set(z1, Pz->item[0]);
          mpc_add(Pz->item[0], z1, p0);
          for (i=1; i<n; i++) {
            mpc_mul(z0, z1, p0);
            mpc_set(z1, Pz->item[i]);
            mpc_add(Pz->item[i], z1, z0);
          }
          mpc_mul(p0, p0, z1);
        }
        darray_append(Pz, p0);
      } else {
        // P *= X^2 - 2 Re(j) X + |j|^2
        int i, n;
        mpc_ptr p0, p1;
        p0 = (mpc_ptr) pbc_malloc(sizeof(mpc_t));
        p1 = (mpc_ptr) pbc_malloc(sizeof(mpc_t));
        mpc_init(p0);
        mpc_init(p1);
        // p1 = - 2 Re(j)
        mpf_mul_ui(f0, mpc_re(j), 2);
        mpf_neg(f0, f0);
        mpf_set(mpc_re(p1), f0);
        // p0 = |j|^2
        mpf_mul(f0, mpc_re(j), mpc_re(j));
        mpf_mul(mpc_re(p0), mpc_im(j), mpc_im(j));
        mpf_add(mpc_re(p0), mpc_re(p0), f0);
        n = Pz->count;
        if (!n) {
        } else if (n == 1) {
          mpc_set(z1, Pz->item[0]);
          mpc_add(Pz->item[0], z1, p1);
          mpc_mul(p1, z1, p1);
          mpc_add(p1, p1, p0);
          mpc_mul(p0, p0, z1);
        } else {
          mpc_set(z2, Pz->item[0]);
          mpc_set(z1, Pz->item[1]);
          mpc_add(Pz->item[0], z2, p1);
          mpc_mul(z0, z2, p1);
          mpc_add(Pz->item[1], z1, z0);
          mpc_add(Pz->item[1], Pz->item[1], p0);
          for (i=2; i<n; i++) {
            mpc_mul(z0, z1, p1);
            mpc_mul(alpha, z2, p0);
            mpc_set(z2, z1);
            mpc_set(z1, Pz->item[i]);
            mpc_add(alpha, alpha, z0);
            mpc_add(Pz->item[i], z1, alpha);
          }
          mpc_mul(z0, z2, p0);
          mpc_mul(p1, p1, z1);
          mpc_add(p1, p1, z0);
          mpc_mul(p0, p0, z1);
        }
        darray_append(Pz, p1);
        darray_append(Pz, p0);
      }
      goto step4;
    }
    b+=2;
    if (b > B) break;
  }

  // Round polynomial and assign.
  int k = 0;
  {
    *arr = pbc_malloc(sizeof(mpz_t) * (Pz->count + 1));
    int i;
    for (i=Pz->count - 1; i>=0; i--) {
      if (mpf_sgn(mpc_re(Pz->item[i])) < 0) {
        mpf_set_d(f0, -0.5);
      } else {
        mpf_set_d(f0, 0.5);
      }
      mpf_add(f0, f0, mpc_re(Pz->item[i]));
      mpz_init((*arr)[k]);
      mpz_set_f((*arr)[k], f0);
      k++;
      mpc_clear(Pz->item[i]);
      pbc_free(Pz->item[i]);
    }
    mpz_init((*arr)[k]);
    mpz_set_ui((*arr)[k], 1);
    k++;
  }
  darray_clear(Pz);
  mpc_clear(z0);
  mpc_clear(z1);
  mpc_clear(z2);
  mpf_clear(f0);
  mpf_clear(sqrtD);
  mpc_clear(alpha);
  mpc_clear(j);

  precision_clear();
  return k;
}
Ejemplo n.º 12
0
//compute c_i=a_i+b_i at one time.
static void multi_add(element_ptr c[], element_ptr a[], element_ptr b[], int n){
  int i;
  element_t* table = (element_t*)pbc_malloc(sizeof(element_t)*n);  //a big problem?
  point_ptr p, q, r;
  element_t e0, e1, e2;
  curve_data_ptr cdp = (curve_data_ptr)a[0]->field->data;

  p = (point_ptr)a[0]->data;
  q = (point_ptr)b[0]->data;
  element_init(e0, p->x->field);
  element_init(e1, p->x->field);
  element_init(e2, p->x->field);

  element_init(table[0], p->x->field);
  element_sub(table[0], q->x, p->x);
  for(i=1; i<n; i++){
	  p = (point_ptr)a[i]->data;
	  q = (point_ptr)b[i]->data;
    element_init(table[i], p->x->field);
    element_sub(table[i], q->x, p->x);
    element_mul(table[i], table[i], table[i-1]);
  }
  element_invert(e2, table[n-1]);
  for(i=n-1; i>0; i--){
	  p = (point_ptr)a[i]->data;
	  q = (point_ptr)b[i]->data;
    element_mul(table[i], table[i-1], e2);
    element_sub(e1, q->x, p->x);
    element_mul(e2,e2,e1); //e2=e2*(x2_j-x1_j)
  }
  element_set(table[0],e2); //e2 no longer used.

  for(i=0; i<n; i++){
	  p = (point_ptr)a[i]->data;
	  q = (point_ptr)b[i]->data;
	  r = (point_ptr)c[i]->data;
    if (p->inf_flag) {
      curve_set(c[i], b[i]);
      continue;
    }
    if (q->inf_flag) {
      curve_set(c[i], a[i]);
      continue;
    }
    if (!element_cmp(p->x, q->x)) { //a[i]=b[i]
      if (!element_cmp(p->y, q->y)) {
        if (element_is0(p->y)) {
          r->inf_flag = 1;
          continue;
        } else {
          double_no_check(r, p, cdp->a);
          continue;
        }
      }
      //points are inverses of each other
      r->inf_flag = 1;
      continue;
    } else {
      //lambda = (y2-y1)/(x2-x1)
      element_sub(e2, q->y, p->y);
      element_mul(e2, e2, table[i]);
      //x3 = lambda^2 - x1 - x2
      element_square(e0, e2);
      element_sub(e0, e0, p->x);
      element_sub(e0, e0, q->x);
      //y3 = (x1-x3)lambda - y1
      element_sub(e1, p->x, e0);
      element_mul(e1, e1, e2);
      element_sub(e1, e1, p->y);
      element_set(r->x, e0);
      element_set(r->y, e1);
      r->inf_flag = 0;
    }
  }
  element_clear(e0);
  element_clear(e1);
  element_clear(e2);
  for(i=0; i<n; i++){
    element_clear(table[i]);
  }
  pbc_free(table);
}
Ejemplo n.º 13
0
//compute c_i=a_i+a_i at one time.
static void multi_double(element_ptr c[], element_ptr a[], int n) {
  int i;
  element_t* table = (element_t*)pbc_malloc(sizeof(element_t)*n);  //a big problem?
  element_t e0, e1, e2;
  point_ptr q, r;
  curve_data_ptr cdp = (curve_data_ptr)a[0]->field->data;

  q = (point_ptr)a[0]->data;
  element_init(e0,q->y->field);
  element_init(e1,q->y->field);
  element_init(e2,q->y->field);

  for(i=0; i<n; i++){
	  q = (point_ptr)a[i]->data; r = (point_ptr)c[i]->data;
    element_init(table[i],q->y->field);

    if (q->inf_flag) {
      r->inf_flag = 1;
      continue;
    }
    if (element_is0(q->y)) {
      r->inf_flag = 1;
      continue;
    }
  }
  //to compute 1/2y multi. see Cohen's GTM139 Algorithm 10.3.4
  for(i=0; i<n; i++){
	  q = (point_ptr)a[i]->data;
    element_double(table[i],q->y);
    if(i>0) element_mul(table[i],table[i],table[i-1]);
  }
  element_invert(e2,table[n-1]); //ONLY ONE inv is required now.
  for(i=n-1; i>0; i--){
	  q = (point_ptr)a[i]->data;
    element_mul(table[i],table[i-1],e2);
    element_mul(e2,e2,q->y);
    element_double(e2,e2); //e2=e2*2y_j
  }
  element_set(table[0],e2); //e2 no longer used.

  for(i=0; i<n; i++){
	  q = (point_ptr)a[i]->data;
	  r = (point_ptr)c[i]->data;
    if(r->inf_flag) continue;

    //e2=lambda = (3x^2 + a) / 2y
    element_square(e2, q->x);
    element_mul_si(e2, e2, 3);
    element_add(e2, e2, cdp->a);

    element_mul(e2, e2, table[i]); //Recall that table[i]=1/2y_i
    //x1 = lambda^2 - 2x
    element_double(e1, q->x);
    element_square(e0, e2);
    element_sub(e0, e0, e1);
    //y1 = (x - x1)lambda - y
    element_sub(e1, q->x, e0);
    element_mul(e1, e1, e2);
    element_sub(e1, e1, q->y);
    element_set(r->x, e0);
    element_set(r->y, e1);
    r->inf_flag = 0;
  }

  element_clear(e0);
  element_clear(e1);
  element_clear(e2);
  for(i=0; i<n; i++){
    element_clear(table[i]);
  }
  pbc_free(table);
}
Ejemplo n.º 14
0
Archivo: d_param.c Proyecto: blynn/pbc
//do many millers at one time with affine coordinates.
static void cc_millers_no_denom_affine(element_t res, mpz_t q, element_t P[],
    element_t Qx[], element_t Qy[], int n_prod) {
  mp_bitcnt_t m;
  int i;
  element_t v;
  element_t a, b, c;
  element_t t0;
  element_t e0;
  const element_ptr cca = curve_a_coeff(P[0]);
  element_ptr Px, Py;
  element_t* Z = pbc_malloc(sizeof(element_t)*n_prod);
  element_ptr Zx, Zy;

  /* TODO: when exactly is this not needed?
  void do_vertical() {
    mapbase(e0, Z->x);
    element_sub(e0, Qx, e0);
    element_mul(v, v, e0);
  }
  */

  #define do_tangents() {                         \
    /* a = -(3 Zx^2 + cc->a) */                   \
    /* b = 2 * Zy */                              \
    /* c = -(2 Zy^2 + a Zx); */                   \
    for(i=0; i<n_prod; i++){                      \
      Px = curve_x_coord(P[i]);                   \
      Py = curve_y_coord(P[i]);                   \
      Zx = curve_x_coord(Z[i]);                   \
      Zy = curve_y_coord(Z[i]);                   \
                                                  \
      element_square(a, Zx);                      \
      element_mul_si(a, a, 3);                    \
      element_add(a, a, cca);                     \
      element_neg(a, a);                          \
                                                  \
      element_add(b, Zy, Zy);                     \
                                                  \
      element_mul(t0, b, Zy);                     \
      element_mul(c, a, Zx);                      \
      element_add(c, c, t0);                      \
      element_neg(c, c);                          \
                                                  \
      d_miller_evalfn(e0, a, b, c, Qx[i], Qy[i]); \
      element_mul(v, v, e0);                      \
    }                                             \
  }

  #define do_lines() {                                    \
    /* a = -(B.y - A.y) / (B.x - A.x); */                 \
    /* b = 1; */                                          \
    /* c = -(A.y + a * A.x); */                           \
    /* but we multiply by B.x - A.x to avoid division. */ \
    for(i=0; i<n_prod; i++){                              \
      Px = curve_x_coord(P[i]);                           \
      Py = curve_y_coord(P[i]);                           \
      Zx = curve_x_coord(Z[i]);                           \
      Zy = curve_y_coord(Z[i]);                           \
                                                          \
      element_sub(b, Px, Zx);                             \
      element_sub(a, Zy, Py);                             \
      element_mul(t0, b, Zy);                             \
      element_mul(c, a, Zx);                              \
      element_add(c, c, t0);                              \
      element_neg(c, c);                                  \
                                                          \
      d_miller_evalfn(e0, a, b, c, Qx[i], Qy[i]);         \
      element_mul(v, v, e0);                              \
    }                                                     \
  }

  Px= curve_x_coord(P[0]); //temporally used to initial a,b, c and etc.
  element_init(a, Px->field);
  element_init(b, a->field);
  element_init(c, a->field);
  element_init(t0, a->field);
  element_init(e0, res->field);

  element_init(v, res->field);
  for(i=0; i<n_prod; i++){
    element_init(Z[i], P[i]->field);
    element_set(Z[i], P[i]);
  }

  element_set1(v);
  m = (mp_bitcnt_t)mpz_sizeinbase(q, 2);
  m = (m > 2 ? m - 2 : 0);

  for(;;) {
    do_tangents();

    if (!m) break;
    element_multi_double(Z, Z, n_prod); //Z_i=Z_i+Z_i for all i.

    if (mpz_tstbit(q, m)) {
      do_lines();
      element_multi_add(Z, Z, P, n_prod); //Z_i=Z_i+P_i for all i.
    }
    m--;
    element_square(v, v);
  }

  element_set(res, v);

  element_clear(v);
  for(i=0; i<n_prod; i++){
    element_clear(Z[i]);
  }
  pbc_free(Z);
  element_clear(a);
  element_clear(b);
  element_clear(c);
  element_clear(t0);
  element_clear(e0);
  #undef do_tangents
  #undef do_lines
}
Ejemplo n.º 15
0
static void field_clear_gf3m(field_t f) {
	params *p = (params *)f->data;
    gf3m_clear(p->p);
    pbc_free(p->p);
    pbc_free(p);
}
Ejemplo n.º 16
0
void darray_free(darray_ptr a) {
  darray_clear(a);
  pbc_free(a);
}
Ejemplo n.º 17
0
static void gf32m_clear(element_t e) {
    gf32m_ptr p = (gf32m_ptr) e->data;
    element_clear(p->_0);
    element_clear(p->_1);
    pbc_free(e->data);
}
Ejemplo n.º 18
0
int BCEDecrypt(byte *global_params_path, byte *priv_key_block, byte *CT_C0, byte *CT_C1, byte *symmetric_key_out)
{
    global_broadcast_params_t gbs;
    priv_key_t priv_key;
    ct_t shared_CT;
    element_t symmetric_key;
    int suffix = 0, retlen;

    if (global_params_path == NULL)
        return 1;
    if (priv_key_block == NULL)
        return 2;
    if (CT_C0 == NULL)
        return 3;
    if (CT_C1 == NULL)
        return 4;
    if (symmetric_key_out == NULL)
        return 5;

    LoadGlobalParams((char *) global_params_path, &gbs);

    priv_key = (priv_key_t) pbc_malloc(sizeof(struct single_priv_key_s));
    // restore index
    priv_key->index = bytes_to_int(priv_key_block);
    suffix += PRK_INDEX_LENGTH;

    // restore g_i_gamma
    element_init(priv_key->g_i_gamma, gbs->pairing->G1);
    retlen = element_from_bytes(priv_key->g_i_gamma, priv_key_block + suffix);
    if (retlen != PRK_G_I_GAMMA_LENGTH)
        return 6;
    suffix += PRK_G_I_GAMMA_LENGTH;

    // restore g_i
    element_init(priv_key->g_i, gbs->pairing->G1);
    retlen = element_from_bytes(priv_key->g_i, priv_key_block + suffix);
    if (retlen != PRK_G_I_LENGTH)
        return 7;
    suffix += PRK_G_I_LENGTH;

    // restore h_i
    element_init(priv_key->h_i, gbs->pairing->G2);
    retlen = element_from_bytes(priv_key->h_i, priv_key_block + suffix);
    if (retlen != PRK_H_I_LENGTH)
        return 8;
    suffix += PRK_H_I_LENGTH;

    // restore decr_prod
    element_init(priv_key->decr_prod, gbs->pairing->G1);
    retlen = element_from_bytes(priv_key->decr_prod, priv_key_block + suffix);
    if (retlen != PRK_DECR_PROD_LENGTH)
        return 9;

    shared_CT = (ct_t) pbc_malloc(sizeof(struct ciphertext_s));
    element_init(shared_CT->C0, gbs->pairing->G2);
    element_init(shared_CT->C1, gbs->pairing->G1);
    element_from_bytes(shared_CT->C0, CT_C0);
    element_from_bytes(shared_CT->C1, CT_C1);

    DecryptKEM_using_product(gbs, priv_key, symmetric_key, shared_CT);

    retlen = element_to_bytes(symmetric_key_out, symmetric_key);
    if (retlen != SYMMETRIC_KEY_LENGTH)
        return 10;

    element_random(symmetric_key);
    element_clear(symmetric_key);
    FreeCT(shared_CT);
    pbc_free(shared_CT);
    FreePK(priv_key);
    pbc_free(priv_key);
    FreeGBP(gbs);
    pbc_free(gbs);

    return 0;
}