예제 #1
0
static int
testPack(PQ_PARAM_SET_ID id)
{
  int i;
  int T;
  int rc;
  PQ_PARAM_SET *P;
  if(!(P = pq_get_param_set_by_id(id)))
  {
    return -1;
  }

  unsigned char *scratch;
  uint16_t *iF;
  uint16_t *oF;
  uint16_t *ig;
  uint16_t *og;
  int64_t *iginv;
  int64_t *oginv;
  int64_t *ih;
  int64_t *oh;
  int64_t *isig;
  int64_t *osig;
  unsigned char *priv_blob;
  unsigned char *pub_blob;
  unsigned char *sig_blob;

  size_t prod = 2*(P->d1 + P->d2 + P->d3)*sizeof(uint16_t);
  size_t full = P->N*sizeof(int64_t);
  size_t priv_blob_len = PRIVKEY_PACKED_BYTES(P);
  size_t pub_blob_len = PUBKEY_PACKED_BYTES(P);
  size_t sig_len = SIGNATURE_BYTES(P);
  size_t offset;

  scratch = malloc(4*prod + 6*full + priv_blob_len + pub_blob_len + sig_len);

  offset = 0;
  iF = (uint16_t*)(scratch + offset); offset += prod;
  oF = (uint16_t*)(scratch + offset); offset += prod;
  ig = (uint16_t*)(scratch + offset); offset += prod;
  og = (uint16_t*)(scratch + offset); offset += prod;
  iginv = (int64_t*)(scratch + offset); offset += full;
  oginv = (int64_t*)(scratch + offset); offset += full;
  isig = (int64_t*)(scratch + offset); offset += full;
  osig = (int64_t*)(scratch + offset); offset += full;
  ih = (int64_t*)(scratch + offset); offset += full;
  oh = (int64_t*)(scratch + offset); offset += full;
  priv_blob = (unsigned char*)(scratch + offset); offset += priv_blob_len;
  pub_blob = (unsigned char*)(scratch + offset); offset += pub_blob_len;
  sig_blob = (unsigned char*)(scratch + offset); offset += sig_len;

  for(T=0; T<TIMES; T++)
  {
    fastrandombytes(scratch, 4*prod + 6*full + priv_blob_len + pub_blob_len + sig_len);
    for(i = 0; i < prod; i++)
    {
      iF[i] = iF[i] % P->N;
      ig[i] = ig[i] % P->N;
    }

    for(i=0; i < P->N; i++)
    {
      iginv[i] = cmod(iginv[i], P->p);
      ih[i] = cmod(ih[i], P->q);
      isig[i] = isig[i] % P->q;
      isig[i] = (isig[i] + P->q) % P->q;
      isig[i] -= isig[i] % P->p;
      isig[i] /= P->p;
    }

    rc = pack_private_key(P, iF, ig, iginv, priv_blob_len, priv_blob);
    if(PQNTRU_ERROR == rc) { printf("Private key pack error\n"); return -1; }

    rc = unpack_private_key(P, oF, og, oginv, priv_blob_len, priv_blob);
    if(PQNTRU_ERROR == rc) { printf("Private key unpack error\n"); return -1; }

    rc = pack_public_key(P, ih, pub_blob_len, pub_blob);
    if(PQNTRU_ERROR == rc) { printf("Public key pack error\n"); return -1; }

    rc = unpack_public_key(P, oh, pub_blob_len, pub_blob);
    if(PQNTRU_ERROR == rc) { printf("Public key unpack error\n"); return -1; }

    rc = pack_signature(P, isig, sig_len, sig_blob);
    if(PQNTRU_ERROR == rc) { printf("Signature pack error\n"); return -1; }

    rc = unpack_signature(P, osig, sig_len, sig_blob);
    if(PQNTRU_ERROR == rc) { printf("Signature unpack error\n"); return -1; }

    for(i=0; i<2*(P->d1 + P->d2 + P->d3); i++)
    {
      if(iF[i] != oF[i] || ig[i] != og[i])
      {
        printf("product form keys not equal\n");
        break;
      }
    }

    for(i=0; i<P->N; i++)
    {
      oh[i] = cmod(oh[i], P->q);
      oginv[i] = cmod(oginv[i], P->p);
      if(ih[i] != oh[i] || iginv[i] != oginv[i])
      {
        printf("%d %ld %ld %ld %ld\n", i, ih[i], oh[i], iginv[i], oginv[i]);
        printf("public key or iginv not equal\n");
        return -1;
      }

      if(isig[i] != osig[i])
      {
        printf("%d %ld %ld\n", i, isig[i], osig[i]);
        printf("signatures not equal\n");
        return -1;
      }
    }
  }
}
예제 #2
0
int
pq_verify(
    const size_t        packed_sig_len,
    const unsigned char *packed_sig,
    const size_t        public_key_blob_len,
    const unsigned char *public_key_blob,
    const size_t        msg_len,
    const unsigned char *msg)
{
  uint16_t      i;

  PQ_PARAM_SET  *P;
  size_t        scratch_len;
  unsigned char *scratch;
  int8_t        *sp;
  int8_t        *tp;
  int64_t       *h;
  int64_t       *sig;
  int64_t       *tmpx3;

  uint16_t      N;
  uint16_t      padN;
  int64_t       q;
  int8_t        p;
  uint16_t      error = 0;
  int           result;


  result = get_blob_params(&P, public_key_blob_len, public_key_blob);
  if(PQNTRU_ERROR == result)
  {
    return PQNTRU_ERROR;
  }

  N = P->N;
  padN = P->padded_N;
  p = P->p;
  q = P->q;

  scratch_len = 2 * N + 5 * POLYNOMIAL_BYTES(P);
  if(!(scratch = malloc(scratch_len)))
  {
    return PQNTRU_ERROR;
  }
  memset(scratch, 0, scratch_len);

  sig  = (int64_t*)scratch;
  h    = (int64_t*)(scratch + POLYNOMIAL_BYTES(P));
  tmpx3 = (int64_t*)(scratch + 2*POLYNOMIAL_BYTES(P));
  sp    =  (int8_t*)(scratch + 5*POLYNOMIAL_BYTES(P));
  tp    =  (int8_t*)(scratch + 5*POLYNOMIAL_BYTES(P) + N);

  result = unpack_public_key(P, h, public_key_blob_len, public_key_blob);
  if(PQNTRU_ERROR == result)
  {
    free(scratch);
    return PQNTRU_ERROR;
  }

  challenge(sp, tp,
            public_key_blob_len, public_key_blob,
            msg_len, msg);

  result = unpack_signature(P, sig, sp, packed_sig_len, packed_sig);
  if(PQNTRU_ERROR == result)
  {
    free(scratch);
    return PQNTRU_ERROR;
  }

  for(i=0; i<N; i++)
  {
    error |= (cmod(sig[i] - sp[i], p));
    error |= (sig[i] > P->norm_bound_s) || (-sig[i] > P->norm_bound_s);
  }
  pol_mul_coefficients(tmpx3, sig, h, N, padN, q, tmpx3);

  for(i=0; i<N; i++)
  {
    error |= (cmod(tmpx3[i], p) - tp[i]);
    error |= (tmpx3[i] > P->norm_bound_t) || (-tmpx3[i] > P->norm_bound_t) ;
  }



  free(scratch);

  if(0 == error)
  {
    return PQNTRU_OK;
  }
  return PQNTRU_ERROR;
}
예제 #3
0
static int
testKeyGen(PQ_PARAM_SET_ID id)
{
  uint16_t i;
  uint16_t j;

  PQ_PARAM_SET *P;
  size_t privkey_blob_len;
  size_t pubkey_blob_len;

  unsigned char *privkey_blob;
  unsigned char *pubkey_blob;

  unsigned char *scratch;
  size_t         scratch_len;

  int rc;

  if(!(P = pq_get_param_set_by_id(id)))
  {
    return -1;
  }

  size_t prod = 2*(P->d1 + P->d2 + P->d3)*sizeof(uint16_t);
  size_t full = POLYNOMIAL_BYTES(P);
  scratch_len = 2*prod + 6*full;
  scratch = malloc(scratch_len);
  size_t offset = 0;
  uint16_t *f = (uint16_t*)(scratch); offset += prod;
  uint16_t *g = (uint16_t*)(scratch+offset); offset += prod;
  int64_t *ginv = (int64_t*)(scratch+offset); offset += full;
  int64_t *h = (int64_t*)(scratch+offset); offset += full;
  int64_t *a1 = (int64_t*)(scratch+offset); offset += full;
  int64_t *a2 = (int64_t*)(scratch+offset); offset += 3*full;

  for(i=0; i<TIMES; i++)
  {
    memset(scratch, 0, scratch_len);

    /* Generate a key */
    pq_gen_key(P, &privkey_blob_len, NULL, &pubkey_blob_len, NULL);

    privkey_blob = malloc(privkey_blob_len);
    pubkey_blob = malloc(pubkey_blob_len);

    if(PQNTRU_ERROR == pq_gen_key(P,
               &privkey_blob_len, privkey_blob,
               &pubkey_blob_len, pubkey_blob))
    {
      fprintf(stderr, "\t fail in keygen\n");
    }

    /* Unpack the key */
    rc = unpack_private_key(P, f, g, ginv, privkey_blob_len, privkey_blob);
    if(PQNTRU_ERROR == rc) { printf("Private key unpack error\n"); return -1; }

    rc = unpack_public_key(P, h, pubkey_blob_len, pubkey_blob);
    if(PQNTRU_ERROR == rc) { printf("Public key unpack error\n"); return -1; }

    /* Multiply h by f mod q, should have g in a1 */
    pol_mul_product(a1, h, P->d1, P->d2, P->d3, f, P->N, a2);
    for(j=0; j<P->N; j++)
    {
      a1[j] = cmod(P->p * (h[j] + a1[j]), P->q);
    }

    /* Multiply a1 by g inverse mod p, should have 1 in a2 */
    pol_mul_coefficients(a2, a1, ginv, P->N, P->padded_N, P->p, a2);
    for(j=1; j<P->N; j++)
    {
      if(a2[0] != 1 || a2[j] != 0)
      {
        fprintf(stderr, "\t bad key");
        free(privkey_blob);
        free(pubkey_blob);
        free(scratch);
        return -1;
      }
    }

    free(privkey_blob);
    free(pubkey_blob);
  }
  free(scratch);

  return 0;
}
예제 #4
0
int
pq_sign(
    size_t              *packed_sig_len,
    unsigned char       *packed_sig,
    const size_t        private_key_len,
    const unsigned char *private_key_blob,
    const size_t        public_key_len,
    const unsigned char *public_key_blob,
    const size_t        msg_len,
    const unsigned char *msg)
{

  uint16_t i;
  int error = 0;

  uint16_t  N;
  uint16_t  padN;
  int64_t   q;
  int8_t    p;
  uint16_t  d1;
  uint16_t  d2;
  uint16_t  d3;
  int64_t   m;

  size_t        scratch_len;
  unsigned char *scratch;
  size_t        offset;

  uint16_t      *f;    /* Private key product form f indices */
  uint16_t      *g;    /* .. product form g indices */
  int64_t       *ginv; /* Private key; coefficients of g^{-1} */
  int64_t       *h;    /* Public key coefficients */
  int64_t       *s0;   /* scratch space for random lattice point */
  int64_t       *t0;

  int64_t       *a;    /* scratch space for 3 polynomials */
  int64_t       *tmpx2;/* scratch space for 2 polynomials (aliased by a) */

  int8_t        *sp;   /* Document hash */
  int8_t        *tp;


  PQ_PARAM_SET  *P;

  int rc = PQNTRU_OK;

  if(!private_key_blob || !public_key_blob || !packed_sig_len)
  {
    return PQNTRU_ERROR;
  }

  rc = get_blob_params(&P, private_key_len, private_key_blob);
  if(PQNTRU_ERROR == rc)
  {
    return PQNTRU_ERROR;
  }

  if(!packed_sig) /* Return signature size in packed_sig_len */
  {
    *packed_sig_len = SIGNATURE_BYTES(P);
    return PQNTRU_OK;
  }

  if(!msg || msg_len == 0)
  {
    return PQNTRU_ERROR;
  }

  N = P->N;
  padN = P->padded_N;
  q = P->q;
  p = P->p;
  d1 = P->d1;
  d2 = P->d2;
  d3 = P->d3;

  scratch_len = 2 * PRODUCT_FORM_BYTES(P) /* f and g */
              + 7 * POLYNOMIAL_BYTES(P)   /* h, ginv, and 5 scratch polys */
              + 2 * N;                    /* sp, tp */
  if(!(scratch = malloc(scratch_len)))
  {
    return PQNTRU_ERROR;
  }
  memset(scratch, 0, scratch_len);

  offset = 0;
  f    = (uint16_t*)(scratch);          offset += PRODUCT_FORM_BYTES(P);
  g    = (uint16_t*)(scratch + offset); offset += PRODUCT_FORM_BYTES(P);
  h    =  (int64_t*)(scratch + offset); offset += POLYNOMIAL_BYTES(P);
  ginv =  (int64_t*)(scratch + offset); offset += POLYNOMIAL_BYTES(P);
  s0   =  (int64_t*)(scratch + offset); offset += POLYNOMIAL_BYTES(P);
  t0   =  (int64_t*)(scratch + offset); offset += POLYNOMIAL_BYTES(P);
  /* a is treated as 3 polynomials, aliases tmpx2 */
  a    =  (int64_t*)(scratch + offset); offset += POLYNOMIAL_BYTES(P);
  tmpx2=  (int64_t*)(scratch + offset); offset += 2* POLYNOMIAL_BYTES(P);
  sp   =   (int8_t*)(scratch + offset); offset += N;
  tp   =   (int8_t*)(scratch + offset);


  /* Unpack the keys */
  rc = unpack_private_key(P, f, g, ginv, private_key_len, private_key_blob);
  if(PQNTRU_ERROR == rc)
  {
    shred(scratch, scratch_len);
    free(scratch);
    return PQNTRU_ERROR;
  }

  rc = unpack_public_key(P, h, public_key_len, public_key_blob);
  if(PQNTRU_ERROR == rc)
  {
    shred(scratch, scratch_len);
    free(scratch);
    return PQNTRU_ERROR;
  }


  /* Generate a document hash to sign */
  challenge(sp, tp,
            public_key_len, public_key_blob,
            msg_len, msg);

  int64_t *t = (int64_t *)malloc(N*sizeof(int64_t));
  int64_t *s = (int64_t *)malloc(N*sizeof(int64_t));

  do
  {
    error = 0;

    /* Choose random s0 satisfying s0 = sp (mod p) */
    pol_unidrnd_pZ(s0, N, q, p);
    for(i=0; i<N; i++)
    {
      s0[i] += sp[i];
    }

    /* Load h into a zero padded polynomial */
    memcpy(t0, h, N*sizeof(int64_t));

    /* t0 = h*s0 */
    pol_mul_coefficients(t0, t0, s0, N, padN, q, a);

    /* t0 = tp - (s0*h) */
    for(i=0; i<N; i++)
    {
      t0[i] *= -1;
      t0[i] += tp[i];
    }

    /* a = ginv * (tp - t0) (mod p) */
    pol_mul_coefficients(a, t0, ginv, N, padN, p, a);

    /* tmpx2 = a * F = (a * (f-1)/p) */
    pol_mul_product(tmpx2, a, d1, d2, d3, f, N, tmpx2);
    for(i=0; i<N; i++)
    {
      m = p * (a[i] + tmpx2[i]);
      error |= (m > P->B_s) || (-m > P->B_s);
      s[i] = m;
      /* s0 = s0 + p*(a + tmpx2) = s0 + a*f */
      s0[i] += m;

      error |= (cmod(s0[i], p) - sp[i]); /* Not necessary to check this */
      error |= (s0[i] > P->norm_bound_s) || (-s0[i] > P->norm_bound_s);
    }

    /* tmpx2 = a * G = (a * (g - 1)) */
    pol_mul_product(tmpx2, a, d1, d2, d3, g, N, tmpx2);
    for(i=0; i<N; i++)
    {
      m = (a[i] + tmpx2[i]);
      error |= (m > P->B_t) || (-m > P->B_t);
      t[i] = m;
      /* t0 = (a + tmpx2) - t0 + tp = a*g - tp + s0*h + tp = s0*h + a*g */
      t0[i] = m - t0[i] + tp[i];
      error |= (cmod(t0[i], p) - tp[i]); /* Not necessary to check this */
      error |= (t0[i] > P->norm_bound_t) || (-t0[i] > P->norm_bound_t) ;
    }


//    attempts ++;

  } while(0 != error);

  for (i=0; i<N; i++) {
	  if (s[i] > P->B_s || -s[i] > P->B_s)
		  printf("s\tholy shit\n");
	  if (t[i] > P->B_t || -t[i] > P->B_t)
		  printf("t\tholy shit\n");
  }

  for(i=0; i<N; i++)
  {
    s0[i] = (s0[i] - sp[i])/P->p;
    s0[i] += P->q / (2*P->p);
  }

  pack_signature(P, s0, *packed_sig_len, packed_sig);

  shred(scratch, scratch_len);
  free(scratch);

  return PQNTRU_OK;
}