Raw File
blst_wrapper.c
#include "blst.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

size_t blst_scalar_sizeof() { return sizeof(blst_scalar); }

size_t blst_fr_sizeof() { return sizeof(blst_fr); }

int blst_fr_compare(blst_fr *s_c, blst_fr *t_c) {
  uint64_t s_uint64[4];
  uint64_t t_uint64[4];

  blst_uint64_from_fr(s_uint64, s_c);
  blst_uint64_from_fr(t_uint64, t_c);

  // Check first it is equal.
  bool is_equal = 1;
  is_equal = is_equal && (s_uint64[0] == t_uint64[0]);
  is_equal = is_equal && (s_uint64[1] == t_uint64[1]);
  is_equal = is_equal && (s_uint64[2] == t_uint64[2]);
  is_equal = is_equal && (s_uint64[3] == t_uint64[3]);
  if (is_equal == 1) {
    return (0);
  }
  bool lt = 1;
  lt = lt && (s_uint64[0] <= t_uint64[0]);
  lt = lt && (s_uint64[1] <= t_uint64[1]);
  lt = lt && (s_uint64[2] <= t_uint64[2]);
  lt = lt && (s_uint64[3] <= t_uint64[3]);
  return (lt ? -1 : 1);
}

bool blst_fr_from_lendian(blst_fr *x, byte b[32]) {
  blst_scalar s;
  blst_scalar_from_lendian(&s, b);
  bool is_ok = blst_scalar_fr_check(&s);
  if (is_ok) {
    blst_fr_from_scalar(x, &s);
  }
  return (is_ok);
}

void blst_lendian_from_fr(byte b[32], blst_fr *x) {
  blst_scalar s;
  blst_scalar_from_fr(&s, x);
  blst_lendian_from_scalar(b, &s);
}

int blst_fr_pow(blst_fr *out, blst_fr *x, byte *exp, int exp_nb_bits) {
  if (exp_nb_bits == 0) {
    // out = x^0 = one
    blst_fr_set_to_one(out);
    return 0;
  }

  if (blst_fr_is_zero(x) || blst_fr_is_one(x)) {
    // out = 0^exp = 0 (exp <> 0) or out = 1^exp = 1
    memcpy(out, x, sizeof(blst_fr));
    return 0;
  }

  // Assert that the most significant bit of exp is 1, otherwise
  // fail with error value 2 (Invalid_Argument).
  if (!(exp[(exp_nb_bits - 1) / 8] & (1 << (exp_nb_bits - 1) % 8)))
    return 2;

  // Given that the msb of exp is 1, we set our accumulator to x and
  // start the square and multiply algorithm from the second msb.
  memcpy(out, x, sizeof(blst_fr));

  // Square and multiply
  for (int i = exp_nb_bits - 2; i >= 0; i--) {
    blst_fr_sqr(out, out);
    if (exp[i / 8] & (1 << (i % 8)))
      blst_fr_mul(out, out, x);
  }
  return 0;
}

size_t blst_fp_sizeof() { return sizeof(blst_fp); }

size_t blst_fp2_sizeof() { return sizeof(blst_fp2); }

void blst_fp2_assign(blst_fp2 *p_c, blst_fp *x1_c, blst_fp *x2_c) {
  (p_c->fp[0]).l[0] = x1_c->l[0];
  (p_c->fp[0]).l[1] = x1_c->l[1];
  (p_c->fp[0]).l[2] = x1_c->l[2];
  (p_c->fp[0]).l[3] = x1_c->l[3];
  (p_c->fp[1]).l[0] = x2_c->l[0];
  (p_c->fp[1]).l[1] = x2_c->l[1];
  (p_c->fp[1]).l[2] = x2_c->l[2];
  (p_c->fp[1]).l[3] = x2_c->l[3];
}

void blst_fp2_zero(blst_fp2 *buffer_c) {
  byte zero_bytes[48] = {0};
  blst_fp_from_lendian(&buffer_c->fp[0], zero_bytes);
  blst_fp_from_lendian(&buffer_c->fp[1], zero_bytes);
}

void blst_fp2_set_to_one(blst_fp2 *buffer_c) {
  byte bytes[48] = {0};
  blst_fp_from_lendian(&buffer_c->fp[0], bytes);
  bytes[0] = 1;
  blst_fp_from_lendian(&buffer_c->fp[1], bytes);
}

void blst_fp2_of_bytes_components(blst_fp2 *buffer_c, byte *x1, byte *x2) {
  // FIXME: add a check on the length
  blst_fp_from_lendian(&buffer_c->fp[0], x1);
  blst_fp_from_lendian(&buffer_c->fp[1], x2);
}

void blst_fp2_to_bytes(byte *out, blst_fp2 *p_c) {
  blst_lendian_from_fp(out, &p_c->fp[0]);
  blst_lendian_from_fp(out + 48, &p_c->fp[1]);
}

size_t blst_fp12_sizeof() { return sizeof(blst_fp12); }

void blst_fp12_set_to_one(blst_fp12 *buffer_c) {
  // Set all coordinates to 0. If allocated with allocate_fp12_stubs it's
  // normally fine, but doing it just in case...
  memset(buffer_c, 0, sizeof(blst_fp12));
  // And override for 1.
  byte out[48] = {0};
  out[0] = 1;
  blst_fp_from_lendian(&(buffer_c->fp6[0].fp2[0].fp[0]), out);
}

bool blst_fp12_is_zero(blst_fp12 *p) {
  unsigned char zero[48 * 12] = {0};
  return memcmp(p, zero, sizeof(blst_fp12)) == 0;
}

void blst_fp12_to_bytes(byte *buffer, blst_fp12 *p_c) {
  // FIXME: add a check on the length
  blst_lendian_from_fp(buffer, &(p_c->fp6[0].fp2[0].fp[0]));
  blst_lendian_from_fp(buffer + 1 * 48, &(p_c->fp6[0].fp2[0].fp[1]));
  blst_lendian_from_fp(buffer + 2 * 48, &(p_c->fp6[0].fp2[1].fp[0]));
  blst_lendian_from_fp(buffer + 3 * 48, &(p_c->fp6[0].fp2[1].fp[1]));
  blst_lendian_from_fp(buffer + 4 * 48, &(p_c->fp6[0].fp2[2].fp[0]));
  blst_lendian_from_fp(buffer + 5 * 48, &(p_c->fp6[0].fp2[2].fp[1]));
  blst_lendian_from_fp(buffer + 6 * 48, &(p_c->fp6[1].fp2[0].fp[0]));
  blst_lendian_from_fp(buffer + 7 * 48, &(p_c->fp6[1].fp2[0].fp[1]));
  blst_lendian_from_fp(buffer + 8 * 48, &(p_c->fp6[1].fp2[1].fp[0]));
  blst_lendian_from_fp(buffer + 9 * 48, &(p_c->fp6[1].fp2[1].fp[1]));
  blst_lendian_from_fp(buffer + 10 * 48, &(p_c->fp6[1].fp2[2].fp[0]));
  blst_lendian_from_fp(buffer + 11 * 48, &(p_c->fp6[1].fp2[2].fp[1]));
}

void blst_fp12_of_bytes(blst_fp12 *buffer_c, byte *p) {
  // FIXME: add a check on the length
  blst_fp_from_lendian(&(buffer_c->fp6[0].fp2[0].fp[0]), p);
  blst_fp_from_lendian(&(buffer_c->fp6[0].fp2[0].fp[1]), p + 48);
  blst_fp_from_lendian(&(buffer_c->fp6[0].fp2[1].fp[0]), p + 2 * 48);
  blst_fp_from_lendian(&(buffer_c->fp6[0].fp2[1].fp[1]), p + 3 * 48);
  blst_fp_from_lendian(&(buffer_c->fp6[0].fp2[2].fp[0]), p + 4 * 48);
  blst_fp_from_lendian(&(buffer_c->fp6[0].fp2[2].fp[1]), p + 5 * 48);
  blst_fp_from_lendian(&(buffer_c->fp6[1].fp2[0].fp[0]), p + 6 * 48);
  blst_fp_from_lendian(&(buffer_c->fp6[1].fp2[0].fp[1]), p + 7 * 48);
  blst_fp_from_lendian(&(buffer_c->fp6[1].fp2[1].fp[0]), p + 8 * 48);
  blst_fp_from_lendian(&(buffer_c->fp6[1].fp2[1].fp[1]), p + 9 * 48);
  blst_fp_from_lendian(&(buffer_c->fp6[1].fp2[2].fp[0]), p + 10 * 48);
  blst_fp_from_lendian(&(buffer_c->fp6[1].fp2[2].fp[1]), p + 11 * 48);
}

bool blst_fp12_is_ff_one(blst_fp12 *p) {
  unsigned char one[48 * 12] = {0};
  one[0] = 1;
  return memcmp(p, one, sizeof(blst_fp12)) == 0;
}

int blst_fp12_pow(blst_fp12 *out, blst_fp12 *x, byte *exp, int exp_nb_bits) {
  if (exp_nb_bits == 0) {
    // out = x^0 = one
    blst_fp12_set_to_one(out);
    return 0;
  }

  // We use blst_fq12_is_ff_one because in blst, blst_fq12_is_one is defined as
  // the generator of the prime subgroup of Fq12.
  if (blst_fp12_is_zero(x) || blst_fp12_is_ff_one(x)) {
    // out = 0^exp = 0 (exp <> 0) or out = 1^exp = 1
    memcpy(out, x, sizeof(blst_fp12));
    return 0;
  }

  // Assert that the most significant bit of exp is 1, otherwise
  // fail with error value 2 (Invalid_Argument).
  if (!(exp[(exp_nb_bits - 1) / 8] & (1 << (exp_nb_bits - 1) % 8)))
    return 2;

  // Given that the msb of exp is 1, we set our accumulator to x and
  // start the square and multiply algorithm from the second msb.
  memcpy(out, x, sizeof(blst_fp12));

  // Square and multiply
  for (int i = exp_nb_bits - 2; i >= 0; i--) {
    blst_fp12_sqr(out, out);
    if (exp[i / 8] & (1 << (i % 8)))
      blst_fp12_mul(out, out, x);
  }
  return 0;
}

size_t blst_p1_sizeof() { return sizeof(blst_p1); }

size_t blst_p1_affine_sizeof() { return sizeof(blst_p1_affine); }

void blst_p1_set_coordinates(blst_p1 *buffer_c, blst_fp *x_c, blst_fp *y_c) {
  buffer_c->x = *x_c;
  buffer_c->y = *y_c;
}

size_t blst_p2_sizeof() { return sizeof(blst_p2); }

size_t blst_p2_affine_sizeof() { return sizeof(blst_p2_affine); }

void blst_p2_set_coordinates(blst_p2 *buffer_c, blst_fp2 *x_c, blst_fp2 *y_c) {
  byte out[96];

  blst_lendian_from_fp(out, &x_c->fp[0]);
  blst_lendian_from_fp(out + 48, &x_c->fp[1]);
  blst_fp_from_lendian(&buffer_c->x.fp[0], out);
  blst_fp_from_lendian(&buffer_c->x.fp[1], out + 48);

  blst_lendian_from_fp(out, &y_c->fp[0]);
  blst_lendian_from_fp(out + 48, &y_c->fp[1]);
  blst_fp_from_lendian(&buffer_c->y.fp[0], out);
  blst_fp_from_lendian(&buffer_c->y.fp[1], out + 48);
}
back to top