예제 #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_gen_key(
    PQ_PARAM_SET  *P,
    size_t        *privkey_blob_len,
    unsigned char *privkey_blob,
    size_t        *pubkey_blob_len,
    unsigned char *pubkey_blob)
{
  uint16_t      i;
  uint16_t      m;

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

  size_t        private_key_blob_len;
  size_t        public_key_blob_len;

  uint16_t      *f;
  uint16_t      *g;
  int64_t       *h;

  size_t        scratch_len;
  size_t        offset;
  unsigned char *scratch;
  int64_t       *a1;
  int64_t       *a2;
  int64_t       *tmpx3;

  if(!P || !privkey_blob_len || !pubkey_blob_len)
  {
    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;

  /* TODO: Standardize packed key formats */

  private_key_blob_len = PRIVKEY_PACKED_BYTES(P);
  public_key_blob_len = PUBKEY_PACKED_BYTES(P);

  if(!privkey_blob || !pubkey_blob)
  {
    if(!privkey_blob && privkey_blob_len != NULL)
    {
      *privkey_blob_len = private_key_blob_len;
    }
    if(!pubkey_blob && pubkey_blob_len != NULL)
    {
      *pubkey_blob_len = public_key_blob_len;
    }
    return PQNTRU_OK;
  }

  if((*privkey_blob_len != private_key_blob_len)
      || (*pubkey_blob_len != public_key_blob_len))
  {
    return PQNTRU_ERROR;
  }

  scratch_len = 2 * PRODUCT_FORM_BYTES(P) + 6 * POLYNOMIAL_BYTES(P);
  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);
  a1 = (int64_t*)(scratch + offset);   offset += POLYNOMIAL_BYTES(P);
  a2 = (int64_t*)(scratch + offset);   offset += POLYNOMIAL_BYTES(P);
  tmpx3 = (int64_t*)(scratch + offset);


  /* Find invertible pf mod q */
  /* TODO: Better sampling of product form keys
   *       Try to avoid keys with f(1) = 0
   */
  do
  {
    pol_gen_product(f, d1, d2, d3, N);

    /* f = p * (1 + product form poly) */
    memset(a1, 0, POLYNOMIAL_BYTES(P));
    a1[0] = p;

    pol_mul_product(a1, a1, d1, d2, d3, f, N, tmpx3);
    a1[0] += p;

  } while(PQNTRU_ERROR == pol_inv_mod2(a2, a1, N));

  /* Lift from (Z/2Z)[X]/(X^N - 1) to (Z/qZ)[X]/(X^N -1) */
  for (m = 0; m < 5; ++m)   /* assumes 2^16 < q <= 2^32 */
  {
    /* a^-1 = a^-1 * (2 - a * a^-1) mod q */

    pol_mul_product(a1, a2, d1, d2, d3, f, N, tmpx3);

    for (i = 0; i < N; ++i)
    {
      a1[i] = -p*(a1[i] + a2[i]);
    }

    a1[0] = a1[0] + 2;
    pol_mul_coefficients(a2, a2, a1, N, padN, q, tmpx3);
  }


  /* Find invertible g mod p */
  do
  {
    /* Generate product form g,
     * then expand it to find inverse mod p
     */
    pol_gen_product(g, d1, d2, d3, N);

    memset(a1, 0, POLYNOMIAL_BYTES(P));
    a1[0] = 1;

    pol_mul_product(a1, a1, d1, d2, d3, g, N, tmpx3);
    a1[0] += 1;

  } while(PQNTRU_ERROR == pol_inv_modp(tmpx3, a1, N, p));

  pack_private_key(P, f, g, tmpx3, private_key_blob_len, privkey_blob);

  /* Calculate public key, h = g/f mod q */
  pol_mul_product(h, a2, d1, d2, d3, g, N, tmpx3);
  for(i=0; i<N; i++)
  {
    h[i] = cmod(h[i] + a2[i], q);
  }

/*  int j;
  for (i=0; i<d1; i++) {
	  for (j=d1; j<2*d1; j++) {
		  if (f[i] == f[j]) {
			  printf("stupid key f: %d, %d, %d!\n", i, j, f[i]);
			  break;
		  }
		  if (g[i] == g[j]) {
			  printf("stupid key g: %d, %d, %d!\n", i, j, g[i]);
			  break;
		  }
	  }
  }
  for (i=2*d1; i<2*d1+d2; i++) {
	  for (j=2*d1+d2; j<2*(d1+d2); j++) {
		  if (f[i] == f[j]) {
			  printf("stupid key f: %d, %d, %d!\n", i, j, f[i]);
			  break;
		  }
		  if (g[i] == g[j]) {
			  printf("stupid key g: %d, %d, %d!\n", i, j, g[i]);
			  break;
		  }
	  }
  }
  for (i=2*(d1+d2); i<2*(d1+d2)+d3; i++) {
	  for (j=2*(d1+d2)+d3; j<2*(d1+d2+d3); j++) {
		  if (f[i] == f[j]) {
			  printf("stupid key f: %d, %d, %d!\n", i, j, f[i]);
			  break;
		  }
		  if (g[i] == g[j]) {
			  printf("stupid key g: %d, %d, %d!\n", i, j, g[i]);
			  break;
		  }
	  }
  }*/

  pack_public_key(P, h, public_key_blob_len, pubkey_blob);

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

  return PQNTRU_OK;
}