예제 #1
0
파일: dsa.c 프로젝트: gygy/asuswrt
int DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer)
{
    mp_int w, u1, u2, v, r, s;
    int    ret = 0;

    if (mp_init_multi(&w, &u1, &u2, &v, &r, &s) != MP_OKAY)
        return MP_INIT_E;

    /* set r and s from signature */
    if (mp_read_unsigned_bin(&r, sig, DSA_HALF_SIZE) != MP_OKAY ||
        mp_read_unsigned_bin(&s, sig + DSA_HALF_SIZE, DSA_HALF_SIZE) != MP_OKAY)
        ret = MP_READ_E;

    /* sanity checks */


    /* put H into u1 from sha digest */
    if (ret == 0 && mp_read_unsigned_bin(&u1,digest,SHA_DIGEST_SIZE) != MP_OKAY)
        ret = MP_READ_E;

    /* w = s invmod q */
    if (ret == 0 && mp_invmod(&s, &key->q, &w) != MP_OKAY)
        ret = MP_INVMOD_E;

    /* u1 = (H * w) % q */
    if (ret == 0 && mp_mulmod(&u1, &w, &key->q, &u1) != MP_OKAY)
        ret = MP_MULMOD_E;

    /* u2 = (r * w) % q */
    if (ret == 0 && mp_mulmod(&r, &w, &key->q, &u2) != MP_OKAY)
        ret = MP_MULMOD_E;

    /* verify v = ((g^u1 * y^u2) mod p) mod q */
    if (ret == 0 && mp_exptmod(&key->g, &u1, &key->p, &u1) != MP_OKAY)
        ret = MP_EXPTMOD_E;

    if (ret == 0 && mp_exptmod(&key->y, &u2, &key->p, &u2) != MP_OKAY)
        ret = MP_EXPTMOD_E;

    if (ret == 0 && mp_mulmod(&u1, &u2, &key->p, &v) != MP_OKAY)
        ret = MP_MULMOD_E;

    if (ret == 0 && mp_mod(&v, &key->q, &v) != MP_OKAY)
        ret = MP_MULMOD_E;

    /* do they match */
    if (ret == 0 && mp_cmp(&r, &v) == MP_EQ)
        *answer = 1;
    else
        *answer = 0;

    mp_clear(&s);
    mp_clear(&r);
    mp_clear(&u1);
    mp_clear(&u2);
    mp_clear(&w);
    mp_clear(&v);

    return ret;
}
/* d = a * b (mod c) */
int mp_mulmod_montgomery (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{
	int res;
	mp_int R;
	mp_digit mp;
	
	/* initialize R */
	if ((res = mp_init(&R)) != MP_OKAY) {
		printf("Error initializing the number. %s", mp_error_to_string(res));
		return EXIT_FAILURE;
	}
	
	/* get normalizzation */
	if ((res = mp_montgomery_calc_normalization(&R,c)) != MP_OKAY) {
		printf("Error getting norm. %s", mp_error_to_string(res));
		return EXIT_FAILURE;
	}
	
	/* get mp value */
	if ((res = mp_montgomery_setup(c, &mp)) != MP_OKAY) {
		printf("Error setting up montgomery. %s", mp_error_to_string(res));
		return EXIT_FAILURE;
	}
	
	/* normalize ‘a’ so now a is equal to aR */
	if ((res = mp_mulmod(a, &R, c, a)) != MP_OKAY) {
		printf("Error computing aR. %s", mp_error_to_string(res));
		return EXIT_FAILURE;
	}
	
	/* normalize ‘b’ so now a is equal to bR */
	if ((res = mp_mulmod(b, &R, c, b)) != MP_OKAY) {
		printf("Error computing aR. %s", mp_error_to_string(res));
		return EXIT_FAILURE;
	}
	
	/* compute a * b in Montgomery domain */
	if ((res = mp_mul(a, b, d)) != MP_OKAY) {
		printf("Error multiplying. %s", mp_error_to_string(res));
		return EXIT_FAILURE;
	}
	
	/* now reduce ‘d’ back down to d = a*b*R^2 * R^-1 == a*b*R */
	if ((res = mp_montgomery_reduce(d, c, mp)) != MP_OKAY) {
		printf("Error reducing. %s", mp_error_to_string(res));
	        return EXIT_FAILURE;
	}
	
	/* now reduce ‘d’ back down to d = a*b*R * R^-1 == a*b */
	if ((res = mp_montgomery_reduce(d, c, mp)) != MP_OKAY) {
		printf("Error reducing. %s", mp_error_to_string(res));
	        return EXIT_FAILURE;
	}
	
	mp_clear (&R);
	
	return res;
}
/**
  Verify a DSA signature
  @param r        DSA "r" parameter
  @param s        DSA "s" parameter
  @param hash     The hash that was signed
  @param hashlen  The length of the hash that was signed
  @param stat     [out] The result of the signature verification, 1==valid, 0==invalid
  @param key      The corresponding public DH key
  @return CRYPT_OK if successful (even if the signature is invalid)
*/
int dsa_verify_hash_raw(         mp_int *r,          mp_int *s,
                    const unsigned char *hash, unsigned long hashlen, 
                                    int *stat,      dsa_key *key)
{
   mp_int        w, v, u1, u2;
   int           err;

   LTC_ARGCHK(r    != NULL);
   LTC_ARGCHK(s    != NULL);
   LTC_ARGCHK(stat != NULL);
   LTC_ARGCHK(key  != NULL);

   /* default to invalid signature */
   *stat = 0;

   /* init our variables */
   if ((err = mp_init_multi(&w, &v, &u1, &u2, NULL)) != MP_OKAY) {
      return mpi_to_ltc_error(err);
   }

   /* neither r or s can be null or >q*/
   if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES || mp_cmp(r, &key->q) != MP_LT || mp_cmp(s, &key->q) != MP_LT) {
      err = CRYPT_INVALID_PACKET;
      goto done;
   }
   
   /* w = 1/s mod q */
   if ((err = mp_invmod(s, &key->q, &w)) != MP_OKAY)                                      { goto error; }

   /* u1 = m * w mod q */
   if ((err = mp_read_unsigned_bin(&u1, (unsigned char *)hash, hashlen)) != MP_OKAY)       { goto error; }
   if ((err = mp_mulmod(&u1, &w, &key->q, &u1)) != MP_OKAY)                                { goto error; }

   /* u2 = r*w mod q */
   if ((err = mp_mulmod(r, &w, &key->q, &u2)) != MP_OKAY)                                 { goto error; } 

   /* v = g^u1 * y^u2 mod p mod q */
   if ((err = mp_exptmod(&key->g, &u1, &key->p, &u1)) != MP_OKAY)                          { goto error; }
   if ((err = mp_exptmod(&key->y, &u2, &key->p, &u2)) != MP_OKAY)                          { goto error; }
   if ((err = mp_mulmod(&u1, &u2, &key->p, &v)) != MP_OKAY)                                { goto error; }
   if ((err = mp_mod(&v, &key->q, &v)) != MP_OKAY)                                         { goto error; }

   /* if r = v then we're set */
   if (mp_cmp(r, &v) == MP_EQ) {
      *stat = 1;
   }

   err = CRYPT_OK;
   goto done;

error : err = mpi_to_ltc_error(err);
done  : mp_clear_multi(&w, &v, &u1, &u2, NULL);
   return err;
}
/**
  Verify a DSA signature
  @param r        DSA "r" parameter
  @param s        DSA "s" parameter
  @param hash     The hash that was signed
  @param hashlen  The length of the hash that was signed
  @param stat     [out] The result of the signature verification, 1==valid, 0==invalid
  @param key      The corresponding public DH key
  @return CRYPT_OK if successful (even if the signature is invalid)
*/
int dsa_verify_hash_raw(         void   *r,          void   *s,
                    const unsigned char *hash, unsigned long hashlen, 
                                    int *stat,      dsa_key *key)
{
   void          *w, *v, *u1, *u2;
   int           err;

   LTC_ARGCHK(r    != NULL);
   LTC_ARGCHK(s    != NULL);
   LTC_ARGCHK(stat != NULL);
   LTC_ARGCHK(key  != NULL);

   /* default to invalid signature */
   *stat = 0;

   /* init our variables */
   if ((err = mp_init_multi(&w, &v, &u1, &u2, NULL)) != CRYPT_OK) {
      return err;
   }

   /* neither r or s can be null or >q*/
   if (mp_iszero(r) == LTC_MP_YES || mp_iszero(s) == LTC_MP_YES || mp_cmp(r, key->q) != LTC_MP_LT || mp_cmp(s, key->q) != LTC_MP_LT) {
      err = CRYPT_INVALID_PACKET;
      goto error;
   }
   
   /* w = 1/s mod q */
   if ((err = mp_invmod(s, key->q, w)) != CRYPT_OK)                                       { goto error; }

   /* u1 = m * w mod q */
   if ((err = mp_read_unsigned_bin(u1, (unsigned char *)hash, hashlen)) != CRYPT_OK)      { goto error; }
   if ((err = mp_mulmod(u1, w, key->q, u1)) != CRYPT_OK)                                  { goto error; }

   /* u2 = r*w mod q */
   if ((err = mp_mulmod(r, w, key->q, u2)) != CRYPT_OK)                                   { goto error; } 

   /* v = g^u1 * y^u2 mod p mod q */
   if ((err = mp_exptmod(key->g, u1, key->p, u1)) != CRYPT_OK)                            { goto error; }
   if ((err = mp_exptmod(key->y, u2, key->p, u2)) != CRYPT_OK)                            { goto error; }
   if ((err = mp_mulmod(u1, u2, key->p, v)) != CRYPT_OK)                                  { goto error; }
   if ((err = mp_mod(v, key->q, v)) != CRYPT_OK)                                          { goto error; }

   /* if r = v then we're set */
   if (mp_cmp(r, v) == LTC_MP_EQ) {
      *stat = 1;
   }

   err = CRYPT_OK;
error:
   mp_clear_multi(w, v, u1, u2, NULL);
   return err;
}
예제 #5
0
파일: rsa.c 프로젝트: venkatarajasekhar/Qt
/*
**  RSA Private key operation using CRT.
*/
static SECStatus 
rsa_PrivateKeyOpCRTNoCheck(RSAPrivateKey *key, mp_int *m, mp_int *c)
{
    mp_int p, q, d_p, d_q, qInv;
    mp_int m1, m2, h, ctmp;
    mp_err   err = MP_OKAY;
    SECStatus rv = SECSuccess;
    MP_DIGITS(&p)    = 0;
    MP_DIGITS(&q)    = 0;
    MP_DIGITS(&d_p)  = 0;
    MP_DIGITS(&d_q)  = 0;
    MP_DIGITS(&qInv) = 0;
    MP_DIGITS(&m1)   = 0;
    MP_DIGITS(&m2)   = 0;
    MP_DIGITS(&h)    = 0;
    MP_DIGITS(&ctmp) = 0;
    CHECK_MPI_OK( mp_init(&p)    );
    CHECK_MPI_OK( mp_init(&q)    );
    CHECK_MPI_OK( mp_init(&d_p)  );
    CHECK_MPI_OK( mp_init(&d_q)  );
    CHECK_MPI_OK( mp_init(&qInv) );
    CHECK_MPI_OK( mp_init(&m1)   );
    CHECK_MPI_OK( mp_init(&m2)   );
    CHECK_MPI_OK( mp_init(&h)    );
    CHECK_MPI_OK( mp_init(&ctmp) );
    /* copy private key parameters into mp integers */
    SECITEM_TO_MPINT(key->prime1,      &p);    /* p */
    SECITEM_TO_MPINT(key->prime2,      &q);    /* q */
    SECITEM_TO_MPINT(key->exponent1,   &d_p);  /* d_p  = d mod (p-1) */
    SECITEM_TO_MPINT(key->exponent2,   &d_q);  /* d_q  = d mod (q-1) */
    SECITEM_TO_MPINT(key->coefficient, &qInv); /* qInv = q**-1 mod p */
    /* 1. m1 = c**d_p mod p */
    CHECK_MPI_OK( mp_mod(c, &p, &ctmp) );
    CHECK_MPI_OK( mp_exptmod(&ctmp, &d_p, &p, &m1) );
    /* 2. m2 = c**d_q mod q */
    CHECK_MPI_OK( mp_mod(c, &q, &ctmp) );
    CHECK_MPI_OK( mp_exptmod(&ctmp, &d_q, &q, &m2) );
    /* 3.  h = (m1 - m2) * qInv mod p */
    CHECK_MPI_OK( mp_submod(&m1, &m2, &p, &h) );
    CHECK_MPI_OK( mp_mulmod(&h, &qInv, &p, &h)  );
    /* 4.  m = m2 + h * q */
    CHECK_MPI_OK( mp_mul(&h, &q, m) );
    CHECK_MPI_OK( mp_add(m, &m2, m) );
cleanup:
    mp_clear(&p);
    mp_clear(&q);
    mp_clear(&d_p);
    mp_clear(&d_q);
    mp_clear(&qInv);
    mp_clear(&m1);
    mp_clear(&m2);
    mp_clear(&h);
    mp_clear(&ctmp);
    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }
    return rv;
}
예제 #6
0
static int mulmod(void *a, void *b, void *c, void *d)
{
   LTC_ARGCHK(a != NULL);
   LTC_ARGCHK(b != NULL);
   LTC_ARGCHK(c != NULL);
   LTC_ARGCHK(d != NULL);
   return mpi_to_ltc_error(mp_mulmod(a,b,c,d));
}
예제 #7
0
/**
 * bignum_mulmod - d = a * b (mod c)
 * @a: Bignum from bignum_init()
 * @b: Bignum from bignum_init()
 * @c: Bignum from bignum_init(); modulus
 * @d: Bignum from bignum_init(); used to store the result of a * b (mod c)
 * Returns: 0 on success, -1 on failure
 */
int bignum_mulmod(const struct bignum *a, const struct bignum *b,
        const struct bignum *c, struct bignum *d) {
    if (mp_mulmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d)
            != MP_OKAY) {
        wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
        return -1;
    }
    return 0;
}
예제 #8
0
파일: dsa_utils.cpp 프로젝트: bdbcat/s63_pi
int _dsa_verify_hash (mp_int *r, mp_int *s, mp_int *hash,
                mp_int *keyG, mp_int *keyP, mp_int *keyQ, mp_int *keyY)
{
        mp_int w, v, u1, u2;
        int ret;
        
        MP_OP(mp_init_multi(&w, &v, &u1, &u2, NULL));
        
        // neither r or s can be 0 or >q
        if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES || mp_cmp(r, keyQ) != MP_LT || mp_cmp(s, keyQ) != MP_LT) {
           ret = -1;
           goto error;
        }
        
        // w = 1/s mod q
        MP_OP(mp_invmod(s, keyQ, &w));
        
        // u1 = m * w mod q
        MP_OP(mp_mulmod(hash, &w, keyQ, &u1));
        
        // u2 = r*w mod q
        MP_OP(mp_mulmod(r, &w, keyQ, &u2));
        
        // v = g^u1 * y^u2 mod p mod q
        MP_OP(mp_exptmod(keyG, &u1, keyP, &u1));
        MP_OP(mp_exptmod(keyY, &u2, keyP, &u2));
        MP_OP(mp_mulmod(&u1, &u2, keyP, &v));
        MP_OP(mp_mod(&v, keyQ, &v));
        
        // if r = v then we're set
        ret = 0;
        if (mp_cmp(r, &v) == MP_EQ) ret = 1;
        
error:
        mp_clear_multi(&w, &v, &u1, &u2, NULL);
        return ret;
}
예제 #9
0
int ltc_ecc_is_point(const ltc_ecc_set_type *dp, void *x, void *y)
{
  void *prime, *a, *b, *t1, *t2;
  int err;

  if ((err = mp_init_multi(&prime, &a, &b, &t1, &t2, NULL)) != CRYPT_OK) {
     return err;
  }

  /* load prime, a and b */
  if ((err = mp_read_radix(prime, dp->prime, 16)) != CRYPT_OK)         goto cleanup;
  if ((err = mp_read_radix(b, dp->B, 16)) != CRYPT_OK)                 goto cleanup;
  if ((err = mp_read_radix(a, dp->A, 16)) != CRYPT_OK)                 goto cleanup;

  /* compute y^2 */
  if ((err = mp_sqr(y, t1)) != CRYPT_OK)                               goto cleanup;

  /* compute x^3 */
  if ((err = mp_sqr(x, t2)) != CRYPT_OK)                               goto cleanup;
  if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK)                       goto cleanup;
  if ((err = mp_mul(x, t2, t2)) != CRYPT_OK)                           goto cleanup;

  /* compute y^2 - x^3 */
  if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK)                          goto cleanup;

  /* compute y^2 - x^3 - a*x */
  if ((err = mp_submod(prime, a, prime, t2)) != CRYPT_OK)              goto cleanup;
  if ((err = mp_mulmod(t2, x, prime, t2)) != CRYPT_OK)                 goto cleanup;
  if ((err = mp_addmod(t1, t2, prime, t1)) != CRYPT_OK)                goto cleanup;

  /* adjust range (0, prime) */
  while (mp_cmp_d(t1, 0) == LTC_MP_LT) {
     if ((err = mp_add(t1, prime, t1)) != CRYPT_OK)                    goto cleanup;
  }
  while (mp_cmp(t1, prime) != LTC_MP_LT) {
     if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK)                    goto cleanup;
  }

  /* compare to b */
  if (mp_cmp(t1, b) != LTC_MP_EQ) {
     err = CRYPT_INVALID_PACKET;
  } else {
     err = CRYPT_OK;
  }

cleanup:
  mp_clear_multi(prime, b, t1, t2, NULL);
  return err;
}
예제 #10
0
/* Divides two field elements. If a is NULL, then returns the inverse of
 * b. */
mp_err
ec_GFp_div(const mp_int *a, const mp_int *b, mp_int *r,
           const GFMethod *meth)
{
    mp_err res = MP_OKAY;
    mp_int t;

    /* If a is NULL, then return the inverse of b, otherwise return a/b. */
    if (a == NULL) {
        return mp_invmod(b, &meth->irr, r);
    } else {
        /* MPI doesn't support divmod, so we implement it using invmod and
         * mulmod. */
        MP_CHECKOK(mp_init(&t));
        MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
        MP_CHECKOK(mp_mulmod(a, &t, &meth->irr, r));
    CLEANUP:
        mp_clear(&t);
        return res;
    }
}
예제 #11
0
/* Tests a point p in Modified Jacobian coordinates, comparing against the 
 * expected affine result (x, y). */
mp_err
testJmPoint(ecfp_jm_pt * r, mp_int *x, mp_int *y, ECGroup *ecgroup)
{

	char s[1000];
	mp_int rx, ry, rz, raz4, test;
	mp_err res = MP_OKAY;

	/* Initialization */
	MP_DIGITS(&rx) = 0;
	MP_DIGITS(&ry) = 0;
	MP_DIGITS(&rz) = 0;
	MP_DIGITS(&raz4) = 0;
	MP_DIGITS(&test) = 0;

	MP_CHECKOK(mp_init(&rx));
	MP_CHECKOK(mp_init(&ry));
	MP_CHECKOK(mp_init(&rz));
	MP_CHECKOK(mp_init(&raz4));
	MP_CHECKOK(mp_init(&test));

	/* Convert to integer */
	ecfp_fp2i(&rx, r->x, ecgroup);
	ecfp_fp2i(&ry, r->y, ecgroup);
	ecfp_fp2i(&rz, r->z, ecgroup);
	ecfp_fp2i(&raz4, r->az4, ecgroup);

	/* Verify raz4 = rz^4 * a */
	mp_sqrmod(&rz, &ecgroup->meth->irr, &test);
	mp_sqrmod(&test, &ecgroup->meth->irr, &test);
	mp_mulmod(&test, &ecgroup->curvea, &ecgroup->meth->irr, &test);
	if (mp_cmp(&test, &raz4) != 0) {
		printf("  Error: a*z^4 not valid\n");
		MP_CHECKOK(mp_toradix(&ecgroup->curvea, s, 16));
		printf("a    %s\n", s);
		MP_CHECKOK(mp_toradix(&rz, s, 16));
		printf("rz   %s\n", s);
		MP_CHECKOK(mp_toradix(&raz4, s, 16));
		printf("raz4    %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}

	/* convert result R to affine coordinates */
	ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup);

	/* Compare against expected result */
	if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) {
		printf("  Error: Modified Jacobian Floating Point Incorrect.\n");
		MP_CHECKOK(mp_toradix(&rx, s, 16));
		printf("floating point result\nrx    %s\n", s);
		MP_CHECKOK(mp_toradix(&ry, s, 16));
		printf("ry    %s\n", s);
		MP_CHECKOK(mp_toradix(x, s, 16));
		printf("integer result\nx   %s\n", s);
		MP_CHECKOK(mp_toradix(y, s, 16));
		printf("y   %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}
  CLEANUP:
	mp_clear(&rx);
	mp_clear(&ry);
	mp_clear(&rz);
	mp_clear(&raz4);
	mp_clear(&test);

	return res;
}
예제 #12
0
/* Tests a point p in Chudnovsky Jacobian coordinates, comparing against
 * the expected affine result (x, y). */
mp_err
testChudPoint(ecfp_chud_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup)
{

	char s[1000];
	mp_int rx, ry, rz, rz2, rz3, test;
	mp_err res = MP_OKAY;

	/* Initialization */
	MP_DIGITS(&rx) = 0;
	MP_DIGITS(&ry) = 0;
	MP_DIGITS(&rz) = 0;
	MP_DIGITS(&rz2) = 0;
	MP_DIGITS(&rz3) = 0;
	MP_DIGITS(&test) = 0;

	MP_CHECKOK(mp_init(&rx));
	MP_CHECKOK(mp_init(&ry));
	MP_CHECKOK(mp_init(&rz));
	MP_CHECKOK(mp_init(&rz2));
	MP_CHECKOK(mp_init(&rz3));
	MP_CHECKOK(mp_init(&test));

	/* Convert to integers */
	ecfp_fp2i(&rx, p->x, ecgroup);
	ecfp_fp2i(&ry, p->y, ecgroup);
	ecfp_fp2i(&rz, p->z, ecgroup);
	ecfp_fp2i(&rz2, p->z2, ecgroup);
	ecfp_fp2i(&rz3, p->z3, ecgroup);

	/* Verify z2, z3 are valid */
	mp_sqrmod(&rz, &ecgroup->meth->irr, &test);
	if (mp_cmp(&test, &rz2) != 0) {
		printf("  Error: rzp2 not valid\n");
		res = MP_NO;
		goto CLEANUP;
	}
	mp_mulmod(&test, &rz, &ecgroup->meth->irr, &test);
	if (mp_cmp(&test, &rz3) != 0) {
		printf("  Error: rzp2 not valid\n");
		res = MP_NO;
		goto CLEANUP;
	}

	/* convert result R to affine coordinates */
	ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup);

	/* Compare against expected result */
	if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) {
		printf("  Error: Chudnovsky Floating Point Incorrect.\n");
		MP_CHECKOK(mp_toradix(&rx, s, 16));
		printf("floating point result\nrx    %s\n", s);
		MP_CHECKOK(mp_toradix(&ry, s, 16));
		printf("ry    %s\n", s);
		MP_CHECKOK(mp_toradix(x, s, 16));
		printf("integer result\nx   %s\n", s);
		MP_CHECKOK(mp_toradix(y, s, 16));
		printf("y   %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}

  CLEANUP:
	mp_clear(&rx);
	mp_clear(&ry);
	mp_clear(&rz);
	mp_clear(&rz2);
	mp_clear(&rz3);
	mp_clear(&test);

	return res;
}
예제 #13
0
/**
   Compute an RSA modular exponentiation
   @param in         The input data to send into RSA
   @param inlen      The length of the input (octets)
   @param out        [out] The destination
   @param outlen     [in/out] The max size and resulting size of the output
   @param which      Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC
   @param key        The RSA key to use
   @return CRYPT_OK if successful
*/
int rsa_exptmod(const unsigned char *in,  unsigned long inlen,
                unsigned char *out, unsigned long *outlen, int which,
                rsa_key *key)
{
    void         *tmp, *tmpa, *tmpb;
    unsigned long x;
    int           err;

    LTC_ARGCHK(in     != NULL);
    LTC_ARGCHK(out    != NULL);
    LTC_ARGCHK(outlen != NULL);
    LTC_ARGCHK(key    != NULL);

    /* is the key of the right type for the operation? */
    if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) {
        return CRYPT_PK_NOT_PRIVATE;
    }

    /* must be a private or public operation */
    if (which != PK_PRIVATE && which != PK_PUBLIC) {
        return CRYPT_PK_INVALID_TYPE;
    }

    /* init and copy into tmp */
    if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != CRYPT_OK)                                    {
        return err;
    }
    if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK)                 {
        goto error;
    }

    /* sanity check on the input */
    if (mp_cmp(key->N, tmp) == LTC_MP_LT) {
        err = CRYPT_PK_INVALID_SIZE;
        goto error;
    }

    /* are we using the private exponent and is the key optimized? */
    if (which == PK_PRIVATE) {
        /* tmpa = tmp^dP mod p */
        if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK)                               {
            goto error;
        }

        /* tmpb = tmp^dQ mod q */
        if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK)                               {
            goto error;
        }

        /* tmp = (tmpa - tmpb) * qInv (mod p) */
        if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK)                                              {
            goto error;
        }
        if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK)                                {
            goto error;
        }

        /* tmp = tmpb + q * tmp */
        if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK)                                             {
            goto error;
        }
        if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK)                                               {
            goto error;
        }
    } else {
        /* exptmod it */
        if ((err = mp_exptmod(tmp, key->e, key->N, tmp)) != CRYPT_OK)                                {
            goto error;
        }
    }

    /* read it back */
    x = (unsigned long)mp_unsigned_bin_size(key->N);
    if (x > *outlen) {
        *outlen = x;
        err = CRYPT_BUFFER_OVERFLOW;
        goto error;
    }

    /* this should never happen ... */
    if (mp_unsigned_bin_size(tmp) > mp_unsigned_bin_size(key->N)) {
        err = CRYPT_ERROR;
        goto error;
    }
    *outlen = x;

    /* convert it */
    zeromem(out, x);
    if ((err = mp_to_unsigned_bin(tmp, out+(x-mp_unsigned_bin_size(tmp)))) != CRYPT_OK)               {
        goto error;
    }

    /* clean up and return */
    err = CRYPT_OK;
error:
    mp_clear_multi(tmp, tmpa, tmpb, NULL);
    return err;
}
예제 #14
0
int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
{
  mp_int  M[TAB_SIZE], res;
  mp_digit buf, mp;
  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;

  /* use a pointer to the reduction algorithm.  This allows us to use
   * one of many reduction algorithms without modding the guts of
   * the code with if statements everywhere.
   */
  int     (*redux)(mp_int*,mp_int*,mp_digit);

  /* find window size */
  x = mp_count_bits (X);
  if (x <= 7) {
    winsize = 2;
  } else if (x <= 36) {
    winsize = 3;
  } else if (x <= 140) {
    winsize = 4;
  } else if (x <= 450) {
    winsize = 5;
  } else if (x <= 1303) {
    winsize = 6;
  } else if (x <= 3529) {
    winsize = 7;
  } else {
    winsize = 8;
  }

#ifdef MP_LOW_MEM
  if (winsize > 5) {
     winsize = 5;
  }
#endif

  /* init M array */
  /* init first cell */
  if ((err = mp_init_size(&M[1], P->alloc)) != MP_OKAY) {
     return err;
  }

  /* now init the second half of the array */
  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
    if ((err = mp_init_size(&M[x], P->alloc)) != MP_OKAY) {
      for (y = 1<<(winsize-1); y < x; y++) {
        mp_clear (&M[y]);
      }
      mp_clear(&M[1]);
      return err;
    }
  }

  /* determine and setup reduction code */
  if (redmode == 0) {
#ifdef BN_MP_MONTGOMERY_SETUP_C     
     /* now setup montgomery  */
     if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
        goto LBL_M;
     }
#else
     err = MP_VAL;
     goto LBL_M;
#endif

     /* automatically pick the comba one if available (saves quite a few calls/ifs) */
#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
     if ((((P->used * 2) + 1) < MP_WARRAY) &&
          (P->used < (1 << ((CHAR_BIT * sizeof(mp_word)) - (2 * DIGIT_BIT))))) {
        redux = fast_mp_montgomery_reduce;
     } else 
#endif
     {
#ifdef BN_MP_MONTGOMERY_REDUCE_C
        /* use slower baseline Montgomery method */
        redux = mp_montgomery_reduce;
#else
        err = MP_VAL;
        goto LBL_M;
#endif
     }
  } else if (redmode == 1) {
#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
     /* setup DR reduction for moduli of the form B**k - b */
     mp_dr_setup(P, &mp);
     redux = mp_dr_reduce;
#else
     err = MP_VAL;
     goto LBL_M;
#endif
  } else {
#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
     /* setup DR reduction for moduli of the form 2**k - b */
     if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
        goto LBL_M;
     }
     redux = mp_reduce_2k;
#else
     err = MP_VAL;
     goto LBL_M;
#endif
  }

  /* setup result */
  if ((err = mp_init_size (&res, P->alloc)) != MP_OKAY) {
    goto LBL_M;
  }

  /* create M table
   *

   *
   * The first half of the table is not computed though accept for M[0] and M[1]
   */

  if (redmode == 0) {
#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
     /* now we need R mod m */
     if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
       goto LBL_RES;
     }

     /* now set M[1] to G * R mod m */
     if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
       goto LBL_RES;
     }
#else
     err = MP_VAL;
     goto LBL_RES;
#endif
  } else {
     mp_set(&res, 1);
     if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
        goto LBL_RES;
     }
  }

  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
    goto LBL_RES;
  }

  for (x = 0; x < (winsize - 1); x++) {
    if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
      goto LBL_RES;
    }
    if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
      goto LBL_RES;
    }
  }

  /* create upper table */
  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
      goto LBL_RES;
    }
    if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
      goto LBL_RES;
    }
  }

  /* set initial mode and bit cnt */
  mode   = 0;
  bitcnt = 1;
  buf    = 0;
  digidx = X->used - 1;
  bitcpy = 0;
  bitbuf = 0;

  for (;;) {
    /* grab next digit as required */
    if (--bitcnt == 0) {
      /* if digidx == -1 we are out of digits so break */
      if (digidx == -1) {
        break;
      }
      /* read next digit and reset bitcnt */
      buf    = X->dp[digidx--];
      bitcnt = (int)DIGIT_BIT;
    }

    /* grab the next msb from the exponent */
    y     = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
    buf <<= (mp_digit)1;

    /* if the bit is zero and mode == 0 then we ignore it
     * These represent the leading zero bits before the first 1 bit
     * in the exponent.  Technically this opt is not required but it
     * does lower the # of trivial squaring/reductions used
     */
    if ((mode == 0) && (y == 0)) {
      continue;
    }

    /* if the bit is zero and mode == 1 then we square */
    if ((mode == 1) && (y == 0)) {
      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, mp)) != MP_OKAY) {
        goto LBL_RES;
      }
      continue;
    }

    /* else we add it to the window */
    bitbuf |= (y << (winsize - ++bitcpy));
    mode    = 2;

    if (bitcpy == winsize) {
      /* ok window is filled so square as required and multiply  */
      /* square first */
      for (x = 0; x < winsize; x++) {
        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
          goto LBL_RES;
        }
        if ((err = redux (&res, P, mp)) != MP_OKAY) {
          goto LBL_RES;
        }
      }

      /* then multiply */
      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, mp)) != MP_OKAY) {
        goto LBL_RES;
      }

      /* empty window and reset */
      bitcpy = 0;
      bitbuf = 0;
      mode   = 1;
    }
  }

  /* if bits remain then square/multiply */
  if ((mode == 2) && (bitcpy > 0)) {
    /* square then multiply if the bit is set */
    for (x = 0; x < bitcpy; x++) {
      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, mp)) != MP_OKAY) {
        goto LBL_RES;
      }

      /* get next bit of the window */
      bitbuf <<= 1;
      if ((bitbuf & (1 << winsize)) != 0) {
        /* then multiply */
        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
          goto LBL_RES;
        }
        if ((err = redux (&res, P, mp)) != MP_OKAY) {
          goto LBL_RES;
        }
      }
    }
  }

  if (redmode == 0) {
     /* fixup result if Montgomery reduction is used
      * recall that any value in a Montgomery system is
      * actually multiplied by R mod n.  So we have
      * to reduce one more time to cancel out the factor
      * of R.
      */
     if ((err = redux(&res, P, mp)) != MP_OKAY) {
       goto LBL_RES;
     }
  }

  /* swap res with Y */
  mp_exch (&res, Y);
  err = MP_OKAY;
LBL_RES:mp_clear (&res);
LBL_M:
  mp_clear(&M[1]);
  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
    mp_clear (&M[x]);
  }
  return err;
}
static SECStatus 
dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
               const unsigned char *kb)
{
    mp_int p, q, g;  /* PQG parameters */
    mp_int x, k;     /* private key & pseudo-random integer */
    mp_int r, s;     /* tuple (r, s) is signature) */
    mp_err err   = MP_OKAY;
    SECStatus rv = SECSuccess;
    unsigned int dsa_subprime_len, dsa_signature_len, offset;
    SECItem localDigest;
    unsigned char localDigestData[DSA_MAX_SUBPRIME_LEN];
    

    /* FIPS-compliance dictates that digest is a SHA hash. */
    /* Check args. */
    if (!key || !signature || !digest) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }

    dsa_subprime_len = PQG_GetLength(&key->params.subPrime);
    dsa_signature_len = dsa_subprime_len*2;
    if ((signature->len < dsa_signature_len) ||
	(digest->len > HASH_LENGTH_MAX)  ||
	(digest->len < SHA1_LENGTH)) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }

    /* DSA accepts digests not equal to dsa_subprime_len, if the 
     * digests are greater, then they are truncated to the size of 
     * dsa_subprime_len, using the left most bits. If they are less
     * then they are padded on the left.*/
    PORT_Memset(localDigestData, 0, dsa_subprime_len);
    offset = (digest->len < dsa_subprime_len) ? 
			(dsa_subprime_len - digest->len) : 0;
    PORT_Memcpy(localDigestData+offset, digest->data, 
		dsa_subprime_len - offset);
    localDigest.data = localDigestData;
    localDigest.len = dsa_subprime_len;

    /* Initialize MPI integers. */
    MP_DIGITS(&p) = 0;
    MP_DIGITS(&q) = 0;
    MP_DIGITS(&g) = 0;
    MP_DIGITS(&x) = 0;
    MP_DIGITS(&k) = 0;
    MP_DIGITS(&r) = 0;
    MP_DIGITS(&s) = 0;
    CHECK_MPI_OK( mp_init(&p) );
    CHECK_MPI_OK( mp_init(&q) );
    CHECK_MPI_OK( mp_init(&g) );
    CHECK_MPI_OK( mp_init(&x) );
    CHECK_MPI_OK( mp_init(&k) );
    CHECK_MPI_OK( mp_init(&r) );
    CHECK_MPI_OK( mp_init(&s) );
    /*
    ** Convert stored PQG and private key into MPI integers.
    */
    SECITEM_TO_MPINT(key->params.prime,    &p);
    SECITEM_TO_MPINT(key->params.subPrime, &q);
    SECITEM_TO_MPINT(key->params.base,     &g);
    SECITEM_TO_MPINT(key->privateValue,    &x);
    OCTETS_TO_MPINT(kb, &k, dsa_subprime_len);
    /*
    ** FIPS 186-1, Section 5, Step 1
    **
    ** r = (g**k mod p) mod q
    */
    CHECK_MPI_OK( mp_exptmod(&g, &k, &p, &r) ); /* r = g**k mod p */
    CHECK_MPI_OK(     mp_mod(&r, &q, &r) );     /* r = r mod q    */
    /*                                  
    ** FIPS 186-1, Section 5, Step 2
    **
    ** s = (k**-1 * (HASH(M) + x*r)) mod q
    */
    SECITEM_TO_MPINT(localDigest, &s);          /* s = HASH(M)     */
    CHECK_MPI_OK( mp_invmod(&k, &q, &k) );      /* k = k**-1 mod q */
    CHECK_MPI_OK( mp_mulmod(&x, &r, &q, &x) );  /* x = x * r mod q */
    CHECK_MPI_OK( mp_addmod(&s, &x, &q, &s) );  /* s = s + x mod q */
    CHECK_MPI_OK( mp_mulmod(&s, &k, &q, &s) );  /* s = s * k mod q */
    /*
    ** verify r != 0 and s != 0
    ** mentioned as optional in FIPS 186-1.
    */
    if (mp_cmp_z(&r) == 0 || mp_cmp_z(&s) == 0) {
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	rv = SECFailure;
	goto cleanup;
    }
    /*
    ** Step 4
    **
    ** Signature is tuple (r, s)
    */
    err = mp_to_fixlen_octets(&r, signature->data, dsa_subprime_len);
    if (err < 0) goto cleanup; 
    err = mp_to_fixlen_octets(&s, signature->data + dsa_subprime_len, 
                                  dsa_subprime_len);
    if (err < 0) goto cleanup; 
    err = MP_OKAY;
    signature->len = dsa_signature_len;
cleanup:
    PORT_Memset(localDigestData, 0, DSA_MAX_SUBPRIME_LEN);
    mp_clear(&p);
    mp_clear(&q);
    mp_clear(&g);
    mp_clear(&x);
    mp_clear(&k);
    mp_clear(&r);
    mp_clear(&s);
    if (err) {
	translate_mpi_error(err);
	rv = SECFailure;
    }
    return rv;
}
예제 #16
0
파일: ec.c 프로젝트: venkatarajasekhar/Qt
/*
** Checks the signature on the given digest using the key provided.
*/
SECStatus 
ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, 
                 const SECItem *digest)
{
    SECStatus rv = SECFailure;
#ifndef NSS_DISABLE_ECC
    mp_int r_, s_;           /* tuple (r', s') is received signature) */
    mp_int c, u1, u2, v;     /* intermediate values used in verification */
    mp_int x1;
    mp_int n;
    mp_err err = MP_OKAY;
    ECParams *ecParams = NULL;
    SECItem pointC = { siBuffer, NULL, 0 };
    int slen;       /* length in bytes of a half signature (r or s) */
    int flen;       /* length in bytes of the field size */
    unsigned olen;  /* length in bytes of the base point order */
    unsigned obits; /* length in bits  of the base point order */

#if EC_DEBUG
    char mpstr[256];
    printf("ECDSA verification called\n");
#endif

    /* Initialize MPI integers. */
    /* must happen before the first potential call to cleanup */
    MP_DIGITS(&r_) = 0;
    MP_DIGITS(&s_) = 0;
    MP_DIGITS(&c) = 0;
    MP_DIGITS(&u1) = 0;
    MP_DIGITS(&u2) = 0;
    MP_DIGITS(&x1) = 0;
    MP_DIGITS(&v)  = 0;
    MP_DIGITS(&n)  = 0;

    /* Check args */
    if (!key || !signature || !digest) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	goto cleanup;
    }

    ecParams = &(key->ecParams);
    flen = (ecParams->fieldID.size + 7) >> 3;  
    olen = ecParams->order.len;  
    if (signature->len == 0 || signature->len%2 != 0 ||
	signature->len > 2*olen) {
	PORT_SetError(SEC_ERROR_INPUT_LEN);
	goto cleanup;
    }
    slen = signature->len/2;

    SECITEM_AllocItem(NULL, &pointC, 2*flen + 1);
    if (pointC.data == NULL)
	goto cleanup;

    CHECK_MPI_OK( mp_init(&r_) );
    CHECK_MPI_OK( mp_init(&s_) );
    CHECK_MPI_OK( mp_init(&c)  );
    CHECK_MPI_OK( mp_init(&u1) );
    CHECK_MPI_OK( mp_init(&u2) );
    CHECK_MPI_OK( mp_init(&x1)  );
    CHECK_MPI_OK( mp_init(&v)  );
    CHECK_MPI_OK( mp_init(&n)  );

    /*
    ** Convert received signature (r', s') into MPI integers.
    */
    CHECK_MPI_OK( mp_read_unsigned_octets(&r_, signature->data, slen) );
    CHECK_MPI_OK( mp_read_unsigned_octets(&s_, signature->data + slen, slen) );
                                          
    /* 
    ** ANSI X9.62, Section 5.4.2, Steps 1 and 2
    **
    ** Verify that 0 < r' < n and 0 < s' < n
    */
    SECITEM_TO_MPINT(ecParams->order, &n);
    if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
        mp_cmp(&r_, &n) >= 0 || mp_cmp(&s_, &n) >= 0) {
	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
	goto cleanup; /* will return rv == SECFailure */
    }

    /*
    ** ANSI X9.62, Section 5.4.2, Step 3
    **
    ** c = (s')**-1 mod n
    */
    CHECK_MPI_OK( mp_invmod(&s_, &n, &c) );      /* c = (s')**-1 mod n */

    /*
    ** ANSI X9.62, Section 5.4.2, Step 4
    **
    ** u1 = ((HASH(M')) * c) mod n
    */
    SECITEM_TO_MPINT(*digest, &u1);                  /* u1 = HASH(M)     */

    /* In the definition of EC signing, digests are truncated
     * to the length of n in bits. 
     * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
    CHECK_MPI_OK( (obits = mpl_significant_bits(&n)) );
    if (digest->len*8 > obits) {  /* u1 = HASH(M')     */
	mpl_rsh(&u1,&u1,digest->len*8 - obits);
    }

#if EC_DEBUG
    mp_todecimal(&r_, mpstr);
    printf("r_: %s (dec)\n", mpstr);
    mp_todecimal(&s_, mpstr);
    printf("s_: %s (dec)\n", mpstr);
    mp_todecimal(&c, mpstr);
    printf("c : %s (dec)\n", mpstr);
    mp_todecimal(&u1, mpstr);
    printf("digest: %s (dec)\n", mpstr);
#endif

    CHECK_MPI_OK( mp_mulmod(&u1, &c, &n, &u1) );  /* u1 = u1 * c mod n */

    /*
    ** ANSI X9.62, Section 5.4.2, Step 4
    **
    ** u2 = ((r') * c) mod n
    */
    CHECK_MPI_OK( mp_mulmod(&r_, &c, &n, &u2) );

    /*
    ** ANSI X9.62, Section 5.4.3, Step 1
    **
    ** Compute u1*G + u2*Q
    ** Here, A = u1.G     B = u2.Q    and   C = A + B
    ** If the result, C, is the point at infinity, reject the signature
    */
    if (ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC)
	!= SECSuccess) {
	rv = SECFailure;
	goto cleanup;
    }
    if (ec_point_at_infinity(&pointC)) {
	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
	rv = SECFailure;
	goto cleanup;
    }

    CHECK_MPI_OK( mp_read_unsigned_octets(&x1, pointC.data + 1, flen) );

    /*
    ** ANSI X9.62, Section 5.4.4, Step 2
    **
    ** v = x1 mod n
    */
    CHECK_MPI_OK( mp_mod(&x1, &n, &v) );

#if EC_DEBUG
    mp_todecimal(&r_, mpstr);
    printf("r_: %s (dec)\n", mpstr);
    mp_todecimal(&v, mpstr);
    printf("v : %s (dec)\n", mpstr);
#endif

    /*
    ** ANSI X9.62, Section 5.4.4, Step 3
    **
    ** Verification:  v == r'
    */
    if (mp_cmp(&v, &r_)) {
	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
	rv = SECFailure; /* Signature failed to verify. */
    } else {
	rv = SECSuccess; /* Signature verified. */
    }

#if EC_DEBUG
    mp_todecimal(&u1, mpstr);
    printf("u1: %s (dec)\n", mpstr);
    mp_todecimal(&u2, mpstr);
    printf("u2: %s (dec)\n", mpstr);
    mp_tohex(&x1, mpstr);
    printf("x1: %s\n", mpstr);
    mp_todecimal(&v, mpstr);
    printf("v : %s (dec)\n", mpstr);
#endif

cleanup:
    mp_clear(&r_);
    mp_clear(&s_);
    mp_clear(&c);
    mp_clear(&u1);
    mp_clear(&u2);
    mp_clear(&x1);
    mp_clear(&v);
    mp_clear(&n);

    if (pointC.data) SECITEM_FreeItem(&pointC, PR_FALSE);
    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }

#if EC_DEBUG
    printf("ECDSA verification %s\n",
	(rv == SECSuccess) ? "succeeded" : "failed");
#endif
#else
    PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_DISABLE_ECC */

    return rv;
}
/**
   Verify an ECC signature
   @param sig         The signature to verify
   @param siglen      The length of the signature (octets)
   @param hash        The hash (message digest) that was signed
   @param hashlen     The length of the hash (octets)
   @param stat        Result of signature, 1==valid, 0==invalid
   @param key         The corresponding public ECC key
   @return CRYPT_OK if successful (even if the signature is not valid)
*/
int ecc_verify_hash(const unsigned char *sig,  unsigned long siglen,
                    const unsigned char *hash, unsigned long hashlen, 
                    int *stat, ecc_key *key)
{
   ecc_point    *mG, *mQ;
   void          *r, *s, *v, *w, *u1, *u2, *e, *p, *m;
   void          *mp;
   int           err;

   LTC_ARGCHK(sig  != NULL);
   LTC_ARGCHK(hash != NULL);
   LTC_ARGCHK(stat != NULL);
   LTC_ARGCHK(key  != NULL);

   /* default to invalid signature */
   *stat = 0;
   mp    = NULL;

   /* is the IDX valid ?  */
   if (ltc_ecc_is_valid_idx(key->idx) != 1) {
      return CRYPT_PK_INVALID_TYPE;
   }

   /* allocate ints */
   if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL)) != CRYPT_OK) {
      return CRYPT_MEM;
   }

   /* allocate points */
   mG = ltc_ecc_new_point();
   mQ = ltc_ecc_new_point();
   if (mQ  == NULL || mG == NULL) {
      err = CRYPT_MEM;
      goto error;
   }

   /* parse header */
   if ((err = der_decode_sequence_multi(sig, siglen,
                                  LTC_ASN1_INTEGER, 1UL, r,
                                  LTC_ASN1_INTEGER, 1UL, s,
                                  LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
      goto error;
   }

   /* get the order */
   if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK)                                { goto error; }

   /* get the modulus */
   if ((err = mp_read_radix(m, (char *)key->dp->prime, 16)) != CRYPT_OK)                                { goto error; }

   /* check for zero */
   if (mp_iszero(r) || mp_iszero(s) || mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) {
      err = CRYPT_INVALID_PACKET;
      goto error;
   }

   /* read hash */
   if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, (int)hashlen)) != CRYPT_OK)                { goto error; }

   /*  w  = s^-1 mod n */
   if ((err = mp_invmod(s, p, w)) != CRYPT_OK)                                                          { goto error; }

   /* u1 = ew */
   if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK)                                                      { goto error; }

   /* u2 = rw */
   if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK)                                                      { goto error; }

   /* find mG and mQ */
   if ((err = mp_read_radix(mG->x, (char *)key->dp->Gx, 16)) != CRYPT_OK)                               { goto error; }
   if ((err = mp_read_radix(mG->y, (char *)key->dp->Gy, 16)) != CRYPT_OK)                               { goto error; }
   if ((err = mp_set(mG->z, 1)) != CRYPT_OK)                                                            { goto error; }

   if ((err = mp_copy(key->pubkey.x, mQ->x)) != CRYPT_OK)                                               { goto error; }
   if ((err = mp_copy(key->pubkey.y, mQ->y)) != CRYPT_OK)                                               { goto error; }
   if ((err = mp_copy(key->pubkey.z, mQ->z)) != CRYPT_OK)                                               { goto error; }

   /* compute u1*mG + u2*mQ = mG */
   if (ltc_mp.ecc_mul2add == NULL) {
      if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, m, 0)) != CRYPT_OK)                                       { goto error; }
      if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, m, 0)) != CRYPT_OK)                                       { goto error; }
  
      /* find the montgomery mp */
      if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK)                                              { goto error; }

      /* add them */
      if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, m, mp)) != CRYPT_OK)                                      { goto error; }
   
      /* reduce */
      if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK)                                                { goto error; }
   } else {
      /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
      if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, m)) != CRYPT_OK)                                { goto error; }
   }

   /* v = X_x1 mod n */
   if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK)                                                         { goto error; }

   /* does v == r */
   if (mp_cmp(v, r) == LTC_MP_EQ) {
      *stat = 1;
   }

   /* clear up and return */
   err = CRYPT_OK;
error:
   ltc_ecc_del_point(mG);
   ltc_ecc_del_point(mQ);
   mp_clear_multi(r, s, v, w, u1, u2, p, e, m, NULL);
   if (mp != NULL) { 
      mp_montgomery_free(mp);
   }
   return err;
}
예제 #18
0
/**
  Sign a message digest
  @param in        The message digest to sign
  @param inlen     The length of the digest
  @param out       [out] The destination for the signature
  @param outlen    [in/out] The max size and resulting size of the signature
  @param prng      An active PRNG state
  @param wprng     The index of the PRNG you wish to use
  @param key       A private ECC key
  @return CRYPT_OK if successful
*/
int ecc_sign_hash(const unsigned char *in,  unsigned long inlen, 
                        unsigned char *out, unsigned long *outlen, 
                        prng_state *prng, int wprng, ecc_key *key)
{
   ecc_key       pubkey;
   void          *r, *s, *e, *p;
   int           err;

   LTC_ARGCHK(in     != NULL);
   LTC_ARGCHK(out    != NULL);
   LTC_ARGCHK(outlen != NULL);
   LTC_ARGCHK(key    != NULL);

   /* is this a private key? */
   if (key->type != PK_PRIVATE) {
      return CRYPT_PK_NOT_PRIVATE;
   }
   
   /* is the IDX valid ?  */
   if (ltc_ecc_is_valid_idx(key->idx) != 1) {
      return CRYPT_PK_INVALID_TYPE;
   }
   
   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
      return err;
   }

   /* get the hash and load it as a bignum into 'e' */
   /* init the bignums */
   if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != CRYPT_OK) { 
      ecc_free(&pubkey);
      goto LBL_ERR;
   }
   if ((err = mp_read_radix(p, (char *)ltc_ecc_sets[key->idx].order, 16)) != CRYPT_OK)        { goto error; }
   if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, (int)inlen)) != CRYPT_OK)          { goto error; }

   /* make up a key and export the public copy */
   for (;;) {
      if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
         return err;
      }

      /* find r = x1 mod n */
      if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK)                 { goto error; }

      if (mp_iszero(r)) {
         ecc_free(&pubkey);
      } else { 
        /* find s = (e + xr)/k */
        if ((err = mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK)            { goto error; } /* k = 1/k */
        if ((err = mp_mulmod(key->k, r, p, s)) != CRYPT_OK)                  { goto error; } /* s = xr */
        if ((err = mp_add(e, s, s)) != CRYPT_OK)                             { goto error; } /* s = e +  xr */
        if ((err = mp_mod(s, p, s)) != CRYPT_OK)                             { goto error; } /* s = e +  xr */
        if ((err = mp_mulmod(s, pubkey.k, p, s)) != CRYPT_OK)                { goto error; } /* s = (e + xr)/k */

        if (mp_iszero(s)) {
           ecc_free(&pubkey);
        } else {
           break;
        }
      }
   }

   /* store as SEQUENCE { r, s -- integer } */
   err = der_encode_sequence_multi(out, outlen,
                             LTC_ASN1_INTEGER, 1UL, r,
                             LTC_ASN1_INTEGER, 1UL, s,
                             LTC_ASN1_EOL, 0UL, NULL);
   goto LBL_ERR;
error:
LBL_ERR:
   mp_clear_multi(r, s, p, e, NULL);
   ecc_free(&pubkey);

   return err;   
}
예제 #19
0
파일: ec.c 프로젝트: txazo/hotspot
/* Computes the ECDSA signature (a concatenation of two values r and s)
 * on the digest using the given key and the random value kb (used in
 * computing s).
 */
SECStatus
ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
    const SECItem *digest, const unsigned char *kb, const int kblen, int kmflag)
{
    SECStatus rv = SECFailure;
    mp_int x1;
    mp_int d, k;     /* private key, random integer */
    mp_int r, s;     /* tuple (r, s) is the signature */
    mp_int n;
    mp_err err = MP_OKAY;
    ECParams *ecParams = NULL;
    SECItem kGpoint = { siBuffer, NULL, 0};
    int flen = 0;    /* length in bytes of the field size */
    unsigned olen;   /* length in bytes of the base point order */

#if EC_DEBUG
    char mpstr[256];
#endif

    /* Initialize MPI integers. */
    /* must happen before the first potential call to cleanup */
    MP_DIGITS(&x1) = 0;
    MP_DIGITS(&d) = 0;
    MP_DIGITS(&k) = 0;
    MP_DIGITS(&r) = 0;
    MP_DIGITS(&s) = 0;
    MP_DIGITS(&n) = 0;

    /* Check args */
    if (!key || !signature || !digest || !kb || (kblen < 0)) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        goto cleanup;
    }

    ecParams = &(key->ecParams);
    flen = (ecParams->fieldID.size + 7) >> 3;
    olen = ecParams->order.len;
    if (signature->data == NULL) {
        /* a call to get the signature length only */
        goto finish;
    }
    if (signature->len < 2*olen) {
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
        rv = SECBufferTooSmall;
        goto cleanup;
    }


    CHECK_MPI_OK( mp_init(&x1, kmflag) );
    CHECK_MPI_OK( mp_init(&d, kmflag) );
    CHECK_MPI_OK( mp_init(&k, kmflag) );
    CHECK_MPI_OK( mp_init(&r, kmflag) );
    CHECK_MPI_OK( mp_init(&s, kmflag) );
    CHECK_MPI_OK( mp_init(&n, kmflag) );

    SECITEM_TO_MPINT( ecParams->order, &n );
    SECITEM_TO_MPINT( key->privateValue, &d );
    CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) );
    /* Make sure k is in the interval [1, n-1] */
    if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
#if EC_DEBUG
        printf("k is outside [1, n-1]\n");
        mp_tohex(&k, mpstr);
        printf("k : %s \n", mpstr);
        mp_tohex(&n, mpstr);
        printf("n : %s \n", mpstr);
#endif
        PORT_SetError(SEC_ERROR_NEED_RANDOM);
        goto cleanup;
    }

    /*
     * Using an equivalent exponent of fixed length (same as n or 1 bit less
     * than n) to keep the kG timing relatively constant.
     *
     * Note that this is an extra step on top of the approach defined in
     * ANSI X9.62 so as to make a fixed length K.
     */
    CHECK_MPI_OK( mp_add(&k, &n, &k) );
    CHECK_MPI_OK( mp_div_2(&k, &k) );

    /*
    ** ANSI X9.62, Section 5.3.2, Step 2
    **
    ** Compute kG
    */
    kGpoint.len = 2*flen + 1;
    kGpoint.data = PORT_Alloc(2*flen + 1, kmflag);
    if ((kGpoint.data == NULL) ||
        (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint, kmflag)
            != SECSuccess))
        goto cleanup;

    /*
    ** ANSI X9.62, Section 5.3.3, Step 1
    **
    ** Extract the x co-ordinate of kG into x1
    */
    CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1,
                                          (mp_size) flen) );

    /*
    ** ANSI X9.62, Section 5.3.3, Step 2
    **
    ** r = x1 mod n  NOTE: n is the order of the curve
    */
    CHECK_MPI_OK( mp_mod(&x1, &n, &r) );

    /*
    ** ANSI X9.62, Section 5.3.3, Step 3
    **
    ** verify r != 0
    */
    if (mp_cmp_z(&r) == 0) {
        PORT_SetError(SEC_ERROR_NEED_RANDOM);
        goto cleanup;
    }

    /*
    ** ANSI X9.62, Section 5.3.3, Step 4
    **
    ** s = (k**-1 * (HASH(M) + d*r)) mod n
    */
    SECITEM_TO_MPINT(*digest, &s);        /* s = HASH(M)     */

    /* In the definition of EC signing, digests are truncated
     * to the length of n in bits.
     * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
    if (digest->len*8 > (unsigned int)ecParams->fieldID.size) {
        mpl_rsh(&s,&s,digest->len*8 - ecParams->fieldID.size);
    }

#if EC_DEBUG
    mp_todecimal(&n, mpstr);
    printf("n : %s (dec)\n", mpstr);
    mp_todecimal(&d, mpstr);
    printf("d : %s (dec)\n", mpstr);
    mp_tohex(&x1, mpstr);
    printf("x1: %s\n", mpstr);
    mp_todecimal(&s, mpstr);
    printf("digest: %s (decimal)\n", mpstr);
    mp_todecimal(&r, mpstr);
    printf("r : %s (dec)\n", mpstr);
    mp_tohex(&r, mpstr);
    printf("r : %s\n", mpstr);
#endif

    CHECK_MPI_OK( mp_invmod(&k, &n, &k) );      /* k = k**-1 mod n */
    CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) );  /* d = d * r mod n */
    CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) );  /* s = s + d mod n */
    CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) );  /* s = s * k mod n */

#if EC_DEBUG
    mp_todecimal(&s, mpstr);
    printf("s : %s (dec)\n", mpstr);
    mp_tohex(&s, mpstr);
    printf("s : %s\n", mpstr);
#endif

    /*
    ** ANSI X9.62, Section 5.3.3, Step 5
    **
    ** verify s != 0
    */
    if (mp_cmp_z(&s) == 0) {
        PORT_SetError(SEC_ERROR_NEED_RANDOM);
        goto cleanup;
    }

   /*
    **
    ** Signature is tuple (r, s)
    */
    CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, olen) );
    CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + olen, olen) );
finish:
    signature->len = 2*olen;

    rv = SECSuccess;
    err = MP_OKAY;
cleanup:
    mp_clear(&x1);
    mp_clear(&d);
    mp_clear(&k);
    mp_clear(&r);
    mp_clear(&s);
    mp_clear(&n);

    if (kGpoint.data) {
        PORT_ZFree(kGpoint.data, 2*flen + 1);
    }

    if (err) {
        MP_TO_SEC_ERROR(err);
        rv = SECFailure;
    }

#if EC_DEBUG
    printf("ECDSA signing with seed %s\n",
        (rv == SECSuccess) ? "succeeded" : "failed");
#endif

   return rv;
}
예제 #20
0
파일: rsa.c 프로젝트: venkatarajasekhar/Qt
SECStatus
RSA_PrivateKeyCheck(const RSAPrivateKey *key)
{
    mp_int p, q, n, psub1, qsub1, e, d, d_p, d_q, qInv, res;
    mp_err   err = MP_OKAY;
    SECStatus rv = SECSuccess;
    MP_DIGITS(&p)    = 0;
    MP_DIGITS(&q)    = 0;
    MP_DIGITS(&n)    = 0;
    MP_DIGITS(&psub1)= 0;
    MP_DIGITS(&qsub1)= 0;
    MP_DIGITS(&e)    = 0;
    MP_DIGITS(&d)    = 0;
    MP_DIGITS(&d_p)  = 0;
    MP_DIGITS(&d_q)  = 0;
    MP_DIGITS(&qInv) = 0;
    MP_DIGITS(&res)  = 0;
    CHECK_MPI_OK( mp_init(&p)    );
    CHECK_MPI_OK( mp_init(&q)    );
    CHECK_MPI_OK( mp_init(&n)    );
    CHECK_MPI_OK( mp_init(&psub1));
    CHECK_MPI_OK( mp_init(&qsub1));
    CHECK_MPI_OK( mp_init(&e)    );
    CHECK_MPI_OK( mp_init(&d)    );
    CHECK_MPI_OK( mp_init(&d_p)  );
    CHECK_MPI_OK( mp_init(&d_q)  );
    CHECK_MPI_OK( mp_init(&qInv) );
    CHECK_MPI_OK( mp_init(&res)  );

    if (!key->modulus.data || !key->prime1.data || !key->prime2.data ||
        !key->publicExponent.data || !key->privateExponent.data ||
        !key->exponent1.data || !key->exponent2.data ||
        !key->coefficient.data) {
        /*call RSA_PopulatePrivateKey first, if the application wishes to
         * recover these parameters */
        err = MP_BADARG;
        goto cleanup;
    }

    SECITEM_TO_MPINT(key->modulus,         &n);
    SECITEM_TO_MPINT(key->prime1,          &p);
    SECITEM_TO_MPINT(key->prime2,          &q);
    SECITEM_TO_MPINT(key->publicExponent,  &e);
    SECITEM_TO_MPINT(key->privateExponent, &d);
    SECITEM_TO_MPINT(key->exponent1,       &d_p);
    SECITEM_TO_MPINT(key->exponent2,       &d_q);
    SECITEM_TO_MPINT(key->coefficient,     &qInv);
    /* p > q */
    if (mp_cmp(&p, &q) <= 0) {
	rv = SECFailure;
	goto cleanup;
    }
#define VERIFY_MPI_EQUAL(m1, m2) \
    if (mp_cmp(m1, m2) != 0) {   \
	rv = SECFailure;         \
	goto cleanup;            \
    }
#define VERIFY_MPI_EQUAL_1(m)    \
    if (mp_cmp_d(m, 1) != 0) {   \
	rv = SECFailure;         \
	goto cleanup;            \
    }
    /*
     * The following errors cannot be recovered from.
     */
    /* n == p * q */
    CHECK_MPI_OK( mp_mul(&p, &q, &res) );
    VERIFY_MPI_EQUAL(&res, &n);
    /* gcd(e, p-1) == 1 */
    CHECK_MPI_OK( mp_sub_d(&p, 1, &psub1) );
    CHECK_MPI_OK( mp_gcd(&e, &psub1, &res) );
    VERIFY_MPI_EQUAL_1(&res);
    /* gcd(e, q-1) == 1 */
    CHECK_MPI_OK( mp_sub_d(&q, 1, &qsub1) );
    CHECK_MPI_OK( mp_gcd(&e, &qsub1, &res) );
    VERIFY_MPI_EQUAL_1(&res);
    /* d*e == 1 mod p-1 */
    CHECK_MPI_OK( mp_mulmod(&d, &e, &psub1, &res) );
    VERIFY_MPI_EQUAL_1(&res);
    /* d*e == 1 mod q-1 */
    CHECK_MPI_OK( mp_mulmod(&d, &e, &qsub1, &res) );
    VERIFY_MPI_EQUAL_1(&res);
    /*
     * The following errors can be recovered from. However, the purpose of this
     * function is to check consistency, so they are not.
     */
    /* d_p == d mod p-1 */
    CHECK_MPI_OK( mp_mod(&d, &psub1, &res) );
    VERIFY_MPI_EQUAL(&res, &d_p);
    /* d_q == d mod q-1 */
    CHECK_MPI_OK( mp_mod(&d, &qsub1, &res) );
    VERIFY_MPI_EQUAL(&res, &d_q);
    /* q * q**-1 == 1 mod p */
    CHECK_MPI_OK( mp_mulmod(&q, &qInv, &p, &res) );
    VERIFY_MPI_EQUAL_1(&res);

cleanup:
    mp_clear(&n);
    mp_clear(&p);
    mp_clear(&q);
    mp_clear(&psub1);
    mp_clear(&qsub1);
    mp_clear(&e);
    mp_clear(&d);
    mp_clear(&d_p);
    mp_clear(&d_q);
    mp_clear(&qInv);
    mp_clear(&res);
    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }
    return rv;
}
예제 #21
0
파일: rsa.c 프로젝트: venkatarajasekhar/Qt
/*
** Perform a raw private-key operation 
**	Length of input and output buffers are equal to key's modulus len.
*/
static SECStatus 
rsa_PrivateKeyOp(RSAPrivateKey *key, 
                 unsigned char *output, 
                 const unsigned char *input,
                 PRBool check)
{
    unsigned int modLen;
    unsigned int offset;
    SECStatus rv = SECSuccess;
    mp_err err;
    mp_int n, c, m;
    mp_int f, g;
    if (!key || !output || !input) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }
    /* check input out of range (needs to be in range [0..n-1]) */
    modLen = rsa_modulusLen(&key->modulus);
    offset = (key->modulus.data[0] == 0) ? 1 : 0; /* may be leading 0 */
    if (memcmp(input, key->modulus.data + offset, modLen) >= 0) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }
    MP_DIGITS(&n) = 0;
    MP_DIGITS(&c) = 0;
    MP_DIGITS(&m) = 0;
    MP_DIGITS(&f) = 0;
    MP_DIGITS(&g) = 0;
    CHECK_MPI_OK( mp_init(&n) );
    CHECK_MPI_OK( mp_init(&c) );
    CHECK_MPI_OK( mp_init(&m) );
    CHECK_MPI_OK( mp_init(&f) );
    CHECK_MPI_OK( mp_init(&g) );
    SECITEM_TO_MPINT(key->modulus, &n);
    OCTETS_TO_MPINT(input, &c, modLen);
    /* If blinding, compute pre-image of ciphertext by multiplying by
    ** blinding factor
    */
    if (nssRSAUseBlinding) {
	CHECK_SEC_OK( get_blinding_params(key, &n, modLen, &f, &g) );
	/* c' = c*f mod n */
	CHECK_MPI_OK( mp_mulmod(&c, &f, &n, &c) );
    }
    /* Do the private key operation m = c**d mod n */
    if ( key->prime1.len      == 0 ||
         key->prime2.len      == 0 ||
         key->exponent1.len   == 0 ||
         key->exponent2.len   == 0 ||
         key->coefficient.len == 0) {
	CHECK_SEC_OK( rsa_PrivateKeyOpNoCRT(key, &m, &c, &n, modLen) );
    } else if (check) {
	CHECK_SEC_OK( rsa_PrivateKeyOpCRTCheckedPubKey(key, &m, &c) );
    } else {
	CHECK_SEC_OK( rsa_PrivateKeyOpCRTNoCheck(key, &m, &c) );
    }
    /* If blinding, compute post-image of plaintext by multiplying by
    ** blinding factor
    */
    if (nssRSAUseBlinding) {
	/* m = m'*g mod n */
	CHECK_MPI_OK( mp_mulmod(&m, &g, &n, &m) );
    }
    err = mp_to_fixlen_octets(&m, output, modLen);
    if (err >= 0) err = MP_OKAY;
cleanup:
    mp_clear(&n);
    mp_clear(&c);
    mp_clear(&m);
    mp_clear(&f);
    mp_clear(&g);
    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }
    return rv;
}
int main(int argc, char *argv[])
{
  int      ix;
  mp_int   a, b, c, m;
  mp_digit r;

  if(argc < 4) {
    fprintf(stderr, "Usage: %s <a> <b> <m>\n", argv[0]);
    return 1;
  }

  printf("Test 4: Modular arithmetic\n\n");

  mp_init(&a);
  mp_init(&b);
  mp_init(&m);

  mp_read_radix(&a, argv[1], 10);
  mp_read_radix(&b, argv[2], 10);
  mp_read_radix(&m, argv[3], 10);
  printf("a = "); mp_print(&a, stdout); fputc('\n', stdout);
  printf("b = "); mp_print(&b, stdout); fputc('\n', stdout);
  printf("m = "); mp_print(&m, stdout); fputc('\n', stdout);
  
  mp_init(&c);
  printf("\nc = a (mod m)\n");

  mp_mod(&a, &m, &c);
  printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);

  printf("\nc = b (mod m)\n");

  mp_mod(&b, &m, &c);
  printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);

  printf("\nc = b (mod 1853)\n");

  mp_mod_d(&b, 1853, &r);
  printf("c = %04X\n", r);

  printf("\nc = (a + b) mod m\n");

  mp_addmod(&a, &b, &m, &c);
  printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);

  printf("\nc = (a - b) mod m\n");

  mp_submod(&a, &b, &m, &c);
  printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);

  printf("\nc = (a * b) mod m\n");

  mp_mulmod(&a, &b, &m, &c);
  printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);

  printf("\nc = (a ** b) mod m\n");

  mp_exptmod(&a, &b, &m, &c);
  printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);

  printf("\nIn-place modular squaring test:\n");
  for(ix = 0; ix < 5; ix++) {
    printf("a = (a * a) mod m   a = ");
    mp_sqrmod(&a, &m, &a);
    mp_print(&a, stdout);
    fputc('\n', stdout);
  }
  

  mp_clear(&c);
  mp_clear(&m);
  mp_clear(&b);
  mp_clear(&a);

  return 0;
}
/* signature is caller-supplied buffer of at least 20 bytes.
** On input,  signature->len == size of buffer to hold signature.
**            digest->len    == size of digest.
*/
SECStatus 
DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature, 
                 const SECItem *digest)
{
    /* FIPS-compliance dictates that digest is a SHA hash. */
    mp_int p, q, g;      /* PQG parameters */
    mp_int r_, s_;       /* tuple (r', s') is received signature) */
    mp_int u1, u2, v, w; /* intermediate values used in verification */
    mp_int y;            /* public key */
    mp_err err;
    int dsa_subprime_len, dsa_signature_len, offset;
    SECItem localDigest;
    unsigned char localDigestData[DSA_MAX_SUBPRIME_LEN];
    SECStatus verified = SECFailure;

    /* Check args. */
    if (!key || !signature || !digest ) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }

    dsa_subprime_len = PQG_GetLength(&key->params.subPrime);
    dsa_signature_len = dsa_subprime_len*2;
    if ((signature->len != dsa_signature_len) ||
	(digest->len > HASH_LENGTH_MAX)  ||
	(digest->len < SHA1_LENGTH)) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }

    /* DSA accepts digests not equal to dsa_subprime_len, if the 
     * digests are greater, than they are truncated to the size of 
     * dsa_subprime_len, using the left most bits. If they are less
     * then they are padded on the left.*/
    PORT_Memset(localDigestData, 0, dsa_subprime_len);
    offset = (digest->len < dsa_subprime_len) ? 
			(dsa_subprime_len - digest->len) : 0;
    PORT_Memcpy(localDigestData+offset, digest->data, 
		dsa_subprime_len - offset);
    localDigest.data = localDigestData;
    localDigest.len = dsa_subprime_len;

    /* Initialize MPI integers. */
    MP_DIGITS(&p)  = 0;
    MP_DIGITS(&q)  = 0;
    MP_DIGITS(&g)  = 0;
    MP_DIGITS(&y)  = 0;
    MP_DIGITS(&r_) = 0;
    MP_DIGITS(&s_) = 0;
    MP_DIGITS(&u1) = 0;
    MP_DIGITS(&u2) = 0;
    MP_DIGITS(&v)  = 0;
    MP_DIGITS(&w)  = 0;
    CHECK_MPI_OK( mp_init(&p)  );
    CHECK_MPI_OK( mp_init(&q)  );
    CHECK_MPI_OK( mp_init(&g)  );
    CHECK_MPI_OK( mp_init(&y)  );
    CHECK_MPI_OK( mp_init(&r_) );
    CHECK_MPI_OK( mp_init(&s_) );
    CHECK_MPI_OK( mp_init(&u1) );
    CHECK_MPI_OK( mp_init(&u2) );
    CHECK_MPI_OK( mp_init(&v)  );
    CHECK_MPI_OK( mp_init(&w)  );
    /*
    ** Convert stored PQG and public key into MPI integers.
    */
    SECITEM_TO_MPINT(key->params.prime,    &p);
    SECITEM_TO_MPINT(key->params.subPrime, &q);
    SECITEM_TO_MPINT(key->params.base,     &g);
    SECITEM_TO_MPINT(key->publicValue,     &y);
    /*
    ** Convert received signature (r', s') into MPI integers.
    */
    OCTETS_TO_MPINT(signature->data, &r_, dsa_subprime_len);
    OCTETS_TO_MPINT(signature->data + dsa_subprime_len, &s_, dsa_subprime_len);
    /*
    ** Verify that 0 < r' < q and 0 < s' < q
    */
    if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
        mp_cmp(&r_, &q) >= 0 || mp_cmp(&s_, &q) >= 0) {
	/* err is zero here. */
	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
	goto cleanup; /* will return verified == SECFailure */
    }
    /*
    ** FIPS 186-1, Section 6, Step 1
    **
    ** w = (s')**-1 mod q
    */
    CHECK_MPI_OK( mp_invmod(&s_, &q, &w) );      /* w = (s')**-1 mod q */
    /*
    ** FIPS 186-1, Section 6, Step 2
    **
    ** u1 = ((Hash(M')) * w) mod q
    */
    SECITEM_TO_MPINT(localDigest, &u1);              /* u1 = HASH(M')     */
    CHECK_MPI_OK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */
    /*
    ** FIPS 186-1, Section 6, Step 3
    **
    ** u2 = ((r') * w) mod q
    */
    CHECK_MPI_OK( mp_mulmod(&r_, &w, &q, &u2) );
    /*
    ** FIPS 186-1, Section 6, Step 4
    **
    ** v = ((g**u1 * y**u2) mod p) mod q
    */
    CHECK_MPI_OK( mp_exptmod(&g, &u1, &p, &g) ); /* g = g**u1 mod p */
    CHECK_MPI_OK( mp_exptmod(&y, &u2, &p, &y) ); /* y = y**u2 mod p */
    CHECK_MPI_OK(  mp_mulmod(&g, &y, &p, &v)  ); /* v = g * y mod p */
    CHECK_MPI_OK(     mp_mod(&v, &q, &v)      ); /* v = v mod q     */
    /*
    ** Verification:  v == r'
    */
    if (mp_cmp(&v, &r_)) {
	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
	verified = SECFailure; /* Signature failed to verify. */
    } else {
	verified = SECSuccess; /* Signature verified. */
    }
cleanup:
    mp_clear(&p);
    mp_clear(&q);
    mp_clear(&g);
    mp_clear(&y);
    mp_clear(&r_);
    mp_clear(&s_);
    mp_clear(&u1);
    mp_clear(&u2);
    mp_clear(&v);
    mp_clear(&w);
    if (err) {
	translate_mpi_error(err);
    }
    return verified;
}
예제 #24
0
/* Tests point addition in Modified Jacobian + Chudnovsky Jacobian ->
 * Modified Jacobian coordinates. */
mp_err
testPointAddJmChud(ECGroup *ecgroup)
{
	mp_err res;
	mp_int rx2, ry2, ix, iy, iz, test, pz, paz4, qx, qy, qz;
	ecfp_chud_pt q;
	ecfp_jm_pt p, r;
	EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;

	MP_DIGITS(&qx) = 0;
	MP_DIGITS(&qy) = 0;
	MP_DIGITS(&qz) = 0;
	MP_DIGITS(&pz) = 0;
	MP_DIGITS(&paz4) = 0;
	MP_DIGITS(&iz) = 0;
	MP_DIGITS(&rx2) = 0;
	MP_DIGITS(&ry2) = 0;
	MP_DIGITS(&ix) = 0;
	MP_DIGITS(&iy) = 0;
	MP_DIGITS(&iz) = 0;
	MP_DIGITS(&test) = 0;

	MP_CHECKOK(mp_init(&qx));
	MP_CHECKOK(mp_init(&qy));
	MP_CHECKOK(mp_init(&qz));
	MP_CHECKOK(mp_init(&pz));
	MP_CHECKOK(mp_init(&paz4));
	MP_CHECKOK(mp_init(&rx2));
	MP_CHECKOK(mp_init(&ry2));
	MP_CHECKOK(mp_init(&ix));
	MP_CHECKOK(mp_init(&iy));
	MP_CHECKOK(mp_init(&iz));
	MP_CHECKOK(mp_init(&test));

	/* Test Modified Jacobian form addition */
	/* Set p */
	ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
	ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
	ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
	/* paz4 = az^4 */
	MP_CHECKOK(mp_set_int(&pz, 5));
	mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4);
	mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4);
	mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4);
	ecfp_i2fp(p.z, &pz, ecgroup);
	ecfp_i2fp(p.az4, &paz4, ecgroup);

	/* Set q */
	MP_CHECKOK(mp_set_int(&qz, 105));
	ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
	ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);
	ecfp_i2fp(q.z, &qz, ecgroup);
	mp_sqrmod(&qz, &ecgroup->meth->irr, &test);
	ecfp_i2fp(q.z2, &test, ecgroup);
	mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test);
	ecfp_i2fp(q.z3, &test, ecgroup);

	/* Do calculation */
	group->pt_add_jm_chud(&p, &q, &r, group);

	/* Calculate addition to compare against */
	ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy,
					  ecgroup);
	ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy,
						  &ix, &iy, &iz, ecgroup);
	ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup);

	MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup));

  CLEANUP:
	if (res == MP_OKAY)
		printf
			("  Test Passed - Point Addition - Modified & Chudnovsky Jacobian\n");
	else
		printf
			("TEST FAILED - Point Addition - Modified & Chudnovsky Jacobian\n");

	mp_clear(&qx);
	mp_clear(&qy);
	mp_clear(&qz);
	mp_clear(&pz);
	mp_clear(&paz4);
	mp_clear(&rx2);
	mp_clear(&ry2);
	mp_clear(&ix);
	mp_clear(&iy);
	mp_clear(&iz);
	mp_clear(&test);

	return res;
}
예제 #25
0
/* Tests point doubling in Modified Jacobian coordinates */
mp_err
testPointDoubleJm(ECGroup *ecgroup)
{
	mp_err res;
	mp_int pz, paz4, rx2, ry2, rz2, raz4;
	ecfp_jm_pt p, r;
	EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;

	MP_DIGITS(&pz) = 0;
	MP_DIGITS(&paz4) = 0;
	MP_DIGITS(&rx2) = 0;
	MP_DIGITS(&ry2) = 0;
	MP_DIGITS(&rz2) = 0;
	MP_DIGITS(&raz4) = 0;

	MP_CHECKOK(mp_init(&pz));
	MP_CHECKOK(mp_init(&paz4));
	MP_CHECKOK(mp_init(&rx2));
	MP_CHECKOK(mp_init(&ry2));
	MP_CHECKOK(mp_init(&rz2));
	MP_CHECKOK(mp_init(&raz4));

	/* Set p */
	ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
	ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
	ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);

	/* paz4 = az^4 */
	MP_CHECKOK(mp_set_int(&pz, 5));
	mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4);
	mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4);
	mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4);

	ecfp_i2fp(p.z, &pz, ecgroup);
	ecfp_i2fp(p.az4, &paz4, ecgroup);

	group->pt_dbl_jm(&p, &r, group);

	M_TimeOperation(group->pt_dbl_jm(&p, &r, group), 100000);

	/* Calculate doubling to compare against */
	ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2,
					  &rz2, ecgroup);
	ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);

	/* Do comparison and check az^4 */
	MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup));

  CLEANUP:
	if (res == MP_OKAY)
		printf("  Test Passed - Point Doubling - Modified Jacobian\n");
	else
		printf("TEST FAILED - Point Doubling - Modified Jacobian\n");
	mp_clear(&pz);
	mp_clear(&paz4);
	mp_clear(&rx2);
	mp_clear(&ry2);
	mp_clear(&rz2);
	mp_clear(&raz4);

	return res;

}
예제 #26
0
파일: rsa.c 프로젝트: agoragames/cyassl
static int RsaFunction(const byte* in, word32 inLen, byte* out, word32* outLen,
                       int type, RsaKey* key)
{
    #define ERROR_OUT(x) { ret = x; goto done;}

    mp_int tmp;
    int    ret = 0;
    word32 keyLen, len;

    if (mp_init(&tmp) != MP_OKAY)
        return MP_INIT_E;

    if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY)
        ERROR_OUT(MP_READ_E);

    if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) {
        #ifdef RSA_LOW_MEM      /* half as much memory but twice as slow */
            if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY)
                ERROR_OUT(MP_EXPTMOD_E);
        #else
            #define INNER_ERROR_OUT(x) { ret = x; goto inner_done; }

            mp_int tmpa, tmpb;

            if (mp_init(&tmpa) != MP_OKAY)
                ERROR_OUT(MP_INIT_E);

            if (mp_init(&tmpb) != MP_OKAY) {
                mp_clear(&tmpa);
                ERROR_OUT(MP_INIT_E);
            }

            /* tmpa = tmp^dP mod p */
            if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY)
                INNER_ERROR_OUT(MP_EXPTMOD_E);

            /* tmpb = tmp^dQ mod q */
            if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY)
                INNER_ERROR_OUT(MP_EXPTMOD_E);

            /* tmp = (tmpa - tmpb) * qInv (mod p) */
            if (mp_sub(&tmpa, &tmpb, &tmp) != MP_OKAY)
                INNER_ERROR_OUT(MP_SUB_E);

            if (mp_mulmod(&tmp, &key->u, &key->p, &tmp) != MP_OKAY)
                INNER_ERROR_OUT(MP_MULMOD_E);

            /* tmp = tmpb + q * tmp */
            if (mp_mul(&tmp, &key->q, &tmp) != MP_OKAY)
                INNER_ERROR_OUT(MP_MUL_E);

            if (mp_add(&tmp, &tmpb, &tmp) != MP_OKAY)
                INNER_ERROR_OUT(MP_ADD_E);

        inner_done:
            mp_clear(&tmpa);
            mp_clear(&tmpb);

            if (ret != 0) return ret;

        #endif   /* RSA_LOW_MEM */
    }
    else if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) {
        if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY)
            ERROR_OUT(MP_EXPTMOD_E);
    }
    else
        ERROR_OUT(RSA_WRONG_TYPE_E);

    keyLen = mp_unsigned_bin_size(&key->n);
    if (keyLen > *outLen)
        ERROR_OUT(RSA_BUFFER_E);

    len = mp_unsigned_bin_size(&tmp);

    /* pad front w/ zeros to match key length */
    while (len < keyLen) {
        *out++ = 0x00;
        len++;
    }

    *outLen = keyLen;

    /* convert */
    if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY)
        ERROR_OUT(MP_TO_E);
   
done: 
    mp_clear(&tmp);
    return ret;
}
예제 #27
0
파일: ec.c 프로젝트: venkatarajasekhar/Qt
/* Computes the ECDSA signature (a concatenation of two values r and s)
 * on the digest using the given key and the random value kb (used in
 * computing s).
 */
SECStatus 
ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, 
    const SECItem *digest, const unsigned char *kb, const int kblen)
{
    SECStatus rv = SECFailure;
#ifndef NSS_DISABLE_ECC
    mp_int x1;
    mp_int d, k;     /* private key, random integer */
    mp_int r, s;     /* tuple (r, s) is the signature */
    mp_int n;
    mp_err err = MP_OKAY;
    ECParams *ecParams = NULL;
    SECItem kGpoint = { siBuffer, NULL, 0};
    int flen = 0;    /* length in bytes of the field size */
    unsigned olen;   /* length in bytes of the base point order */
    unsigned obits;  /* length in bits  of the base point order */

#if EC_DEBUG
    char mpstr[256];
#endif

    /* Initialize MPI integers. */
    /* must happen before the first potential call to cleanup */
    MP_DIGITS(&x1) = 0;
    MP_DIGITS(&d) = 0;
    MP_DIGITS(&k) = 0;
    MP_DIGITS(&r) = 0;
    MP_DIGITS(&s) = 0;
    MP_DIGITS(&n) = 0;

    /* Check args */
    if (!key || !signature || !digest || !kb || (kblen < 0)) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	goto cleanup;
    }

    ecParams = &(key->ecParams);
    flen = (ecParams->fieldID.size + 7) >> 3;
    olen = ecParams->order.len;  
    if (signature->data == NULL) {
	/* a call to get the signature length only */
	goto finish;
    }
    if (signature->len < 2*olen) {
	PORT_SetError(SEC_ERROR_OUTPUT_LEN);
	goto cleanup;
    }


    CHECK_MPI_OK( mp_init(&x1) );
    CHECK_MPI_OK( mp_init(&d) );
    CHECK_MPI_OK( mp_init(&k) );
    CHECK_MPI_OK( mp_init(&r) );
    CHECK_MPI_OK( mp_init(&s) );
    CHECK_MPI_OK( mp_init(&n) );

    SECITEM_TO_MPINT( ecParams->order, &n );
    SECITEM_TO_MPINT( key->privateValue, &d );

    CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) );
    /* Make sure k is in the interval [1, n-1] */
    if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
#if EC_DEBUG
        printf("k is outside [1, n-1]\n");
        mp_tohex(&k, mpstr);
	printf("k : %s \n", mpstr);
        mp_tohex(&n, mpstr);
	printf("n : %s \n", mpstr);
#endif
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	goto cleanup;
    }

    /*
    ** We do not want timing information to leak the length of k,
    ** so we compute k*G using an equivalent scalar of fixed
    ** bit-length.
    ** Fix based on patch for ECDSA timing attack in the paper
    ** by Billy Bob Brumley and Nicola Tuveri at
    **   http://eprint.iacr.org/2011/232
    **
    ** How do we convert k to a value of a fixed bit-length?
    ** k starts off as an integer satisfying 0 <= k < n.  Hence,
    ** n <= k+n < 2n, which means k+n has either the same number
    ** of bits as n or one more bit than n.  If k+n has the same
    ** number of bits as n, the second addition ensures that the
    ** final value has exactly one more bit than n.  Thus, we
    ** always end up with a value that exactly one more bit than n.
    */
    CHECK_MPI_OK( mp_add(&k, &n, &k) );
    if (mpl_significant_bits(&k) <= mpl_significant_bits(&n)) {
	CHECK_MPI_OK( mp_add(&k, &n, &k) );
    }

    /* 
    ** ANSI X9.62, Section 5.3.2, Step 2
    **
    ** Compute kG
    */
    kGpoint.len = 2*flen + 1;
    kGpoint.data = PORT_Alloc(2*flen + 1);
    if ((kGpoint.data == NULL) ||
	(ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint)
	    != SECSuccess))
	goto cleanup;

    /* 
    ** ANSI X9.62, Section 5.3.3, Step 1
    **
    ** Extract the x co-ordinate of kG into x1
    */
    CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1, 
	                                  (mp_size) flen) );

    /* 
    ** ANSI X9.62, Section 5.3.3, Step 2
    **
    ** r = x1 mod n  NOTE: n is the order of the curve
    */
    CHECK_MPI_OK( mp_mod(&x1, &n, &r) );

    /*
    ** ANSI X9.62, Section 5.3.3, Step 3
    **
    ** verify r != 0 
    */
    if (mp_cmp_z(&r) == 0) {
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	goto cleanup;
    }

    /*                                  
    ** ANSI X9.62, Section 5.3.3, Step 4
    **
    ** s = (k**-1 * (HASH(M) + d*r)) mod n 
    */
    SECITEM_TO_MPINT(*digest, &s);        /* s = HASH(M)     */

    /* In the definition of EC signing, digests are truncated
     * to the length of n in bits. 
     * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
    CHECK_MPI_OK( (obits = mpl_significant_bits(&n)) );
    if (digest->len*8 > obits) {
	mpl_rsh(&s,&s,digest->len*8 - obits);
    }

#if EC_DEBUG
    mp_todecimal(&n, mpstr);
    printf("n : %s (dec)\n", mpstr);
    mp_todecimal(&d, mpstr);
    printf("d : %s (dec)\n", mpstr);
    mp_tohex(&x1, mpstr);
    printf("x1: %s\n", mpstr);
    mp_todecimal(&s, mpstr);
    printf("digest: %s (decimal)\n", mpstr);
    mp_todecimal(&r, mpstr);
    printf("r : %s (dec)\n", mpstr);
    mp_tohex(&r, mpstr);
    printf("r : %s\n", mpstr);
#endif

    CHECK_MPI_OK( mp_invmod(&k, &n, &k) );      /* k = k**-1 mod n */
    CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) );  /* d = d * r mod n */
    CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) );  /* s = s + d mod n */
    CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) );  /* s = s * k mod n */

#if EC_DEBUG
    mp_todecimal(&s, mpstr);
    printf("s : %s (dec)\n", mpstr);
    mp_tohex(&s, mpstr);
    printf("s : %s\n", mpstr);
#endif

    /*
    ** ANSI X9.62, Section 5.3.3, Step 5
    **
    ** verify s != 0
    */
    if (mp_cmp_z(&s) == 0) {
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	goto cleanup;
    }

   /*
    **
    ** Signature is tuple (r, s)
    */
    CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, olen) );
    CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + olen, olen) );
finish:
    signature->len = 2*olen;

    rv = SECSuccess;
    err = MP_OKAY;
cleanup:
    mp_clear(&x1);
    mp_clear(&d);
    mp_clear(&k);
    mp_clear(&r);
    mp_clear(&s);
    mp_clear(&n);

    if (kGpoint.data) {
	PORT_ZFree(kGpoint.data, 2*flen + 1);
    }

    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }

#if EC_DEBUG
    printf("ECDSA signing with seed %s\n",
	(rv == SECSuccess) ? "succeeded" : "failed");
#endif
#else
    PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_DISABLE_ECC */

   return rv;
}
/**
   Double an ECC point
   @param P   The point to double
   @param R   [out] The destination of the double
   @param a   ECC curve parameter a (if NULL we assume a == -3)
   @param modulus  The modulus of the field the ECC curve is in
   @param mp       The "b" value from montgomery_setup()
   @return CRYPT_OK on success
*/
int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *a, void *modulus, void *mp)
{
    void *t1, *t2;
    int   err;

    LTC_ARGCHK(P       != NULL);
    LTC_ARGCHK(R       != NULL);
    LTC_ARGCHK(modulus != NULL);
    LTC_ARGCHK(mp      != NULL);

    if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {
        return err;
    }

    if (P != R) {
        if ((err = mp_copy(P->x, R->x)) != CRYPT_OK)                                {
            goto done;
        }
        if ((err = mp_copy(P->y, R->y)) != CRYPT_OK)                                {
            goto done;
        }
        if ((err = mp_copy(P->z, R->z)) != CRYPT_OK)                                {
            goto done;
        }
    }

    /* t1 = Z * Z */
    if ((err = mp_sqr(R->z, t1)) != CRYPT_OK)                                      {
        goto done;
    }
    if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK)                 {
        goto done;
    }
    /* Z = Y * Z */
    if ((err = mp_mul(R->z, R->y, R->z)) != CRYPT_OK)                              {
        goto done;
    }
    if ((err = mp_montgomery_reduce(R->z, modulus, mp)) != CRYPT_OK)               {
        goto done;
    }
    /* Z = 2Z */
    if ((err = mp_add(R->z, R->z, R->z)) != CRYPT_OK)                              {
        goto done;
    }
    if (mp_cmp(R->z, modulus) != LTC_MP_LT) {
        if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK)                        {
            goto done;
        }
    }

    if (a == NULL) { /* special case for a == -3 (slightly faster than general case) */
        /* T2 = X - T1 */
        if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK)                               {
            goto done;
        }
        if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
            if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK)                         {
                goto done;
            }
        }
        /* T1 = X + T1 */
        if ((err = mp_add(t1, R->x, t1)) != CRYPT_OK)                               {
            goto done;
        }
        if (mp_cmp(t1, modulus) != LTC_MP_LT) {
            if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                         {
                goto done;
            }
        }
        /* T2 = T1 * T2 */
        if ((err = mp_mul(t1, t2, t2)) != CRYPT_OK)                                 {
            goto done;
        }
        if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK)              {
            goto done;
        }
        /* T1 = 2T2 */
        if ((err = mp_add(t2, t2, t1)) != CRYPT_OK)                                 {
            goto done;
        }
        if (mp_cmp(t1, modulus) != LTC_MP_LT) {
            if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                         {
                goto done;
            }
        }
        /* T1 = T1 + T2 */
        if ((err = mp_add(t1, t2, t1)) != CRYPT_OK)                                 {
            goto done;
        }
        if (mp_cmp(t1, modulus) != LTC_MP_LT) {
            if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                         {
                goto done;
            }
        }
    }
    else {
        /* T2 = T1 * T1 */
        if ((err = mp_sqr(t1, t2)) != CRYPT_OK)                                     {
            goto done;
        }
        if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK)              {
            goto done;
        }
        /* T1 = T2 * a */
        if ((err = mp_mulmod(t2, a, modulus, t1)) != CRYPT_OK)                      {
            goto done;
        }
        /* T2 = X * X */
        if ((err = mp_sqr(R->x, t2)) != CRYPT_OK)                                   {
            goto done;
        }
        if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK)              {
            goto done;
        }
        /* T1 = T2 + T1 */
        if ((err = mp_add(t1, t2, t1)) != CRYPT_OK)                                 {
            goto done;
        }
        if (mp_cmp(t1, modulus) != LTC_MP_LT) {
            if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                         {
                goto done;
            }
        }
        /* T1 = T2 + T1 */
        if ((err = mp_add(t1, t2, t1)) != CRYPT_OK)                                 {
            goto done;
        }
        if (mp_cmp(t1, modulus) != LTC_MP_LT) {
            if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                         {
                goto done;
            }
        }
        /* T1 = T2 + T1 */
        if ((err = mp_add(t1, t2, t1)) != CRYPT_OK)                                 {
            goto done;
        }
        if (mp_cmp(t1, modulus) != LTC_MP_LT) {
            if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                         {
                goto done;
            }
        }
    }

    /* Y = 2Y */
    if ((err = mp_add(R->y, R->y, R->y)) != CRYPT_OK)                              {
        goto done;
    }
    if (mp_cmp(R->y, modulus) != LTC_MP_LT) {
        if ((err = mp_sub(R->y, modulus, R->y)) != CRYPT_OK)                        {
            goto done;
        }
    }
    /* Y = Y * Y */
    if ((err = mp_sqr(R->y, R->y)) != CRYPT_OK)                                    {
        goto done;
    }
    if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK)               {
        goto done;
    }
    /* T2 = Y * Y */
    if ((err = mp_sqr(R->y, t2)) != CRYPT_OK)                                      {
        goto done;
    }
    if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK)                 {
        goto done;
    }
    /* T2 = T2/2 */
    if (mp_isodd(t2)) {
        if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK)                            {
            goto done;
        }
    }
    if ((err = mp_div_2(t2, t2)) != CRYPT_OK)                                      {
        goto done;
    }
    /* Y = Y * X */
    if ((err = mp_mul(R->y, R->x, R->y)) != CRYPT_OK)                              {
        goto done;
    }
    if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK)               {
        goto done;
    }

    /* X  = T1 * T1 */
    if ((err = mp_sqr(t1, R->x)) != CRYPT_OK)                                      {
        goto done;
    }
    if ((err = mp_montgomery_reduce(R->x, modulus, mp)) != CRYPT_OK)               {
        goto done;
    }
    /* X = X - Y */
    if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK)                              {
        goto done;
    }
    if (mp_cmp_d(R->x, 0) == LTC_MP_LT) {
        if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK)                        {
            goto done;
        }
    }
    /* X = X - Y */
    if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK)                              {
        goto done;
    }
    if (mp_cmp_d(R->x, 0) == LTC_MP_LT) {
        if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK)                        {
            goto done;
        }
    }

    /* Y = Y - X */
    if ((err = mp_sub(R->y, R->x, R->y)) != CRYPT_OK)                              {
        goto done;
    }
    if (mp_cmp_d(R->y, 0) == LTC_MP_LT) {
        if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK)                        {
            goto done;
        }
    }
    /* Y = Y * T1 */
    if ((err = mp_mul(R->y, t1, R->y)) != CRYPT_OK)                                {
        goto done;
    }
    if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK)               {
        goto done;
    }
    /* Y = Y - T2 */
    if ((err = mp_sub(R->y, t2, R->y)) != CRYPT_OK)                                {
        goto done;
    }
    if (mp_cmp_d(R->y, 0) == LTC_MP_LT) {
        if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK)                        {
            goto done;
        }
    }

    err = CRYPT_OK;
done:
    mp_clear_multi(t1, t2, NULL);
    return err;
}
예제 #29
0
/**
  Sign a hash with DSA
  @param in       The hash to sign
  @param inlen    The length of the hash to sign
  @param r        The "r" integer of the signature (caller must initialize with mp_init() first)
  @param s        The "s" integer of the signature (caller must initialize with mp_init() first)
  @param prng     An active PRNG state
  @param wprng    The index of the PRNG desired
  @param key      A private DSA key
  @return CRYPT_OK if successful
*/
int dsa_sign_hash_raw(const unsigned char *in,  unsigned long inlen,
                                   void   *r,   void *s,
                               prng_state *prng, int wprng, dsa_key *key)
{
   void         *k, *kinv, *tmp;
   unsigned char *buf;
   int            err;

   LTC_ARGCHK(in  != NULL);
   LTC_ARGCHK(r   != NULL);
   LTC_ARGCHK(s   != NULL);
   LTC_ARGCHK(key != NULL);

   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
      return err;
   }
   if (key->type != PK_PRIVATE) {
      return CRYPT_PK_NOT_PRIVATE;
   }

   /* check group order size  */
   if (key->qord >= MDSA_MAX_GROUP) {
      return CRYPT_INVALID_ARG;
   }

   buf = XMALLOC(MDSA_MAX_GROUP);
   if (buf == NULL) {
      return CRYPT_MEM;
   }

   /* Init our temps */
   if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != CRYPT_OK)                       { goto ERRBUF; }

retry:

   do {
      /* gen random k */
      if (prng_descriptor[wprng].read(buf, key->qord, prng) != (unsigned long)key->qord) {
         err = CRYPT_ERROR_READPRNG;
         goto error;
      }

      /* read k */
      if ((err = mp_read_unsigned_bin(k, buf, key->qord)) != CRYPT_OK)                 { goto error; }

      /* k > 1 ? */
      if (mp_cmp_d(k, 1) != LTC_MP_GT)                                                 { goto retry; }

      /* test gcd */
      if ((err = mp_gcd(k, key->q, tmp)) != CRYPT_OK)                                  { goto error; }
   } while (mp_cmp_d(tmp, 1) != LTC_MP_EQ);

   /* now find 1/k mod q */
   if ((err = mp_invmod(k, key->q, kinv)) != CRYPT_OK)                                 { goto error; }

   /* now find r = g^k mod p mod q */
   if ((err = mp_exptmod(key->g, k, key->p, r)) != CRYPT_OK)                           { goto error; }
   if ((err = mp_mod(r, key->q, r)) != CRYPT_OK)                                       { goto error; }

   if (mp_iszero(r) == LTC_MP_YES)                                                     { goto retry; }

   /* now find s = (in + xr)/k mod q */
   if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, inlen)) != CRYPT_OK)      { goto error; }
   if ((err = mp_mul(key->x, r, s)) != CRYPT_OK)                                       { goto error; }
   if ((err = mp_add(s, tmp, s)) != CRYPT_OK)                                          { goto error; }
   if ((err = mp_mulmod(s, kinv, key->q, s)) != CRYPT_OK)                              { goto error; }

   if (mp_iszero(s) == LTC_MP_YES)                                                     { goto retry; }

   err = CRYPT_OK;
error: 
   mp_clear_multi(k, kinv, tmp, NULL);
ERRBUF:
#ifdef LTC_CLEAN_STACK
   zeromem(buf, MDSA_MAX_GROUP);
#endif
   XFREE(buf);
   return err;
}
예제 #30
0
파일: dsa.c 프로젝트: gygy/asuswrt
int DsaSign(const byte* digest, byte* out, DsaKey* key, RNG* rng)
{
    mp_int k, kInv, r, s, H;
    int    ret = 0, sz;
    byte   buffer[DSA_HALF_SIZE];

    if (mp_init_multi(&k, &kInv, &r, &s, &H, 0) != MP_OKAY)
        return MP_INIT_E;

    sz = min(sizeof(buffer), mp_unsigned_bin_size(&key->q)); 

    /* generate k */
    RNG_GenerateBlock(rng, buffer, sz);
    buffer[0] |= 0x0C;

    if (mp_read_unsigned_bin(&k, buffer, sz) != MP_OKAY)
        ret = MP_READ_E;

    if (mp_cmp_d(&k, 1) != MP_GT)
        ret = MP_CMP_E;

    /* inverse k mod q */
    if (ret == 0 && mp_invmod(&k, &key->q, &kInv) != MP_OKAY)
        ret = MP_INVMOD_E;

    /* generate r, r = (g exp k mod p) mod q */
    if (ret == 0 && mp_exptmod(&key->g, &k, &key->p, &r) != MP_OKAY)
        ret = MP_EXPTMOD_E;

    if (ret == 0 && mp_mod(&r, &key->q, &r) != MP_OKAY)
        ret = MP_MOD_E;

    /* generate H from sha digest */
    if (ret == 0 && mp_read_unsigned_bin(&H, digest,SHA_DIGEST_SIZE) != MP_OKAY)
        ret = MP_READ_E;

    /* generate s, s = (kInv * (H + x*r)) % q */
    if (ret == 0 && mp_mul(&key->x, &r, &s) != MP_OKAY)
        ret = MP_MUL_E;

    if (ret == 0 && mp_add(&s, &H, &s) != MP_OKAY)
        ret = MP_ADD_E;

    if (ret == 0 && mp_mulmod(&s, &kInv, &key->q, &s) != MP_OKAY)
        ret = MP_MULMOD_E;

    /* write out */
    if (ret == 0)  {
        int rSz = mp_unsigned_bin_size(&r);
        int sSz = mp_unsigned_bin_size(&s);

        if (rSz == DSA_HALF_SIZE - 1) {
            out[0] = 0;
            out++;
        }

        if (mp_to_unsigned_bin(&r, out) != MP_OKAY)
            ret = MP_TO_E;
        else {
            if (sSz == DSA_HALF_SIZE - 1) {
                out[rSz] = 0;
                out++;
            }    
            ret = mp_to_unsigned_bin(&s, out + rSz);
        }
    }

    mp_clear(&H);
    mp_clear(&s);
    mp_clear(&r);
    mp_clear(&kInv);
    mp_clear(&k);

    return ret;
}