int bdModInv(T x, T a, T m)
	/* Compute x = a^-1 mod m */
{
	size_t n;
	int status;

	assert(x && a && m);
	/* Make sure all variables are the same size */
	n = max(a->ndigits, m->ndigits);

	bd_resize(x, n);
	bd_resize(a, n);
	bd_resize(m, n);

	/* Do the business */
	status = mpModInv(x->digits, a->digits, m->digits, n);

	x->ndigits = mpSizeof(x->digits, n);

	return status;
}
Пример #2
0
/* --------------------------------------------------------------------------
 * EcdsaSignerDoFinal
 * -------------------------------------------------------------------------- */
VLT_STS EcdsaSignerDoFinal(
    VLT_PU8 pu8Message, 
    VLT_U32 u32MessageLen, 
    VLT_U32 u32MessageCapacity, 
    VLT_PU8 pu8Signature, 
    VLT_PU32 pu32SignatureLen, 
    VLT_U32 u32SignatureCapacity )
{
	E2n_Point P;
	E2n_Point R;
	E2n_Point Q;

	/* intermediate calculation storage */
	DIGIT_T k[MAX_DIGITS];
	DIGIT_T k1[MAX_DIGITS]; 
	DIGIT_T	tmp[MAX_DIGITS];
	DIGIT_T r[MAX_DIGITS]; 
	DIGIT_T s[MAX_DIGITS]; 
	DIGIT_T u1[MAX_DIGITS];
	DIGIT_T u2[MAX_DIGITS]; 
	DIGIT_T v[MAX_DIGITS]; 
	DIGIT_T yy[MAX_DIGITS];

	DIGIT_T Px[MAX_DIGITS];
	DIGIT_T Py[MAX_DIGITS];

	DIGIT_T Rx[MAX_DIGITS];
	DIGIT_T Ry[MAX_DIGITS];

	DIGIT_T Qx[MAX_DIGITS];
	DIGIT_T Qy[MAX_DIGITS];

	/* SHA-256 storage */
	DIGIT_T	bdHash[MAX_DIGITS];
	VLT_U8 bHash[HASH_BYTE_SIZE];

	UINT len;
	UINT hashLen;

	sha256_ctx ctx; // context holder

    VLT_STS status = VLT_FAIL;

	if((ST_INITIALISED_SIGN != signerState) &&
	   (ST_INITIALISED_VERIFY != signerState))
	{
		/* not initialised */
		return EECDSAEXECUTIONERROR;
	}

	/* Initialise Point variables */
	P.x = Px;
	P.y = Py;
	R.x = Rx;
	R.y = Ry;
	Q.x = Qx;
	Q.y = Qy;

    if ( ( NULL == pu8Message ) ||
         ( NULL == pu8Signature ) ||
         ( NULL == pu32SignatureLen ) )
    {
        return ( EECDSAINUPNULLPARAM );
    }

	/* hash of message used by both signing and verify */

	/* e or e1 = SHA-256(M) */
	sha256_begin(&ctx);
    sha256_hash(pu8Message, u32MessageLen, &ctx);
    sha256_end(bHash, &ctx);

	/* convert hash to big digits, 
	same size as base point order if > hash size */
	if (sNumBpOrderDigits > HASH_DIGIT_SIZE)
		hashLen = sNumBpOrderDigits;
	else
		hashLen = HASH_DIGIT_SIZE;
	mpConvFromOctets(bdHash, hashLen, bHash, HASH_BYTE_SIZE);

	/* ANS X9.62-2005 7.3.e
	// if bit length of hash is > bit length of base point order
	// then truncate hash by removing LSBs until bit length
	// equals the length of the base point order
	*/
	len = mpBitLength(E.r, E.rlen);
	if (len < HASH_SIZE)
	{	
		/* take leftmost bits of message by shifting right */
		mpShiftRight(tmp, bdHash, HASH_SIZE - len, hashLen);
		/* truncate to base point order size */
		mpSetEqual(bdHash, tmp, E.rlen);
	}

	if (ST_INITIALISED_SIGN == signerState)
	{
		/* signing process as per ANS X9.62 Section 7.3 */
		*pu32SignatureLen = 0;

		/* generate ephemeral private key k such that 0 < k < n */			 
		if (VLT_OK != GenerateRandomDigits(tmp, E.rlen))
			return EECDSAEXECUTIONERROR;
		mpModulo(k, tmp, E.rlen, E.r, E.rlen);
		if (mpIsZero(k, E.rlen))
		{
			/* probability of a zero is 1/n */
			if (VLT_OK != GenerateRandomDigits(tmp, E.rlen))
				return EECDSAEXECUTIONERROR;
			mpModulo(k, tmp, E.rlen, E.r, E.rlen);
			if (mpIsZero(k, E.rlen))
			{
				return EECDSAEXECUTIONERROR;
			}
		}

		/* generate ephemeral public key: P = kG */
		e2n_point_mul(&E, &P, &E.G, k, E.rlen);

		/* convert P.x to integer j	*/
		/* conversion is implicit for polynomial basis */

		/*
		// r = j mod n, n = base point oder (E.r)
		*/
		mpModulo(r, P.x, E.rlen, E.r, E.rlen);

		/*
		// calculate s = k^-1 (e + dr) mod n
		*/

		/* Compute k' = k^-1 mod n */
		mpModInv(k1, k, E.r, E.rlen);

		/* Compute s = (k^-1(SHA-xxx(M) + dr)) mod n */

		/* d * r */
		mpModMult(tmp, sPrivateKey, r, E.r, E.rlen);
		/* M + d * r */
		mpModAdd(yy, tmp, bdHash, E.r, E.rlen);
		/* s = (k^-1)(M + dr) */
		mpModMult(s, k1, yy, E.r, E.rlen);
	
		/* signing: convert back to byte format and construct r || s */
		mpConvToOctets(r, sNumBpOrderDigits, pu8Signature, sNumBpOrderBytes);
		mpConvToOctets(s, sNumBpOrderDigits, pu8Signature + sNumBpOrderBytes, 
			sNumBpOrderBytes);

		/* set the byte length of the output signature */
		*pu32SignatureLen = sNumBpOrderBytes * 2;

		status = VLT_OK;
	}
	else
	{
	    /* ANS X9.62-2005 Section 7.4.1: Verification with Public Key */;

		/* extract r & s and format as big digits */
		mpConvFromOctets(r, E.rlen, pu8Signature, (*pu32SignatureLen) / 2);
		mpConvFromOctets(s, E.rlen, pu8Signature + (*pu32SignatureLen / 2), 
			(*pu32SignatureLen) / 2);

		/* Compute u1 = e1(s1^-1) mod n */
		mpModInv(tmp, s, E.r, E.rlen);
		mpModMult(u1, tmp, bdHash, E.r, E.rlen);

		/* Compute u2 = r1(s1^-1) mod n */
		mpModMult(u2, tmp, r, E.r, E.rlen);

		/* use supplied public key */
		mpSetEqual(Q.x, sPublicKeyQx, E.len);
		mpSetEqual(Q.y, sPublicKeyQy, E.len);

		/* compute R = u1G */
		e2n_point_mul(&E, &R, &E.G, u1, E.rlen);

		/* P = u2Q */
		e2n_point_mul(&E, &P, &Q, u2, E.rlen);

		/* R = R + P */
		e2n_point_add(&E, &R, &R, &P);

		/* compute v = j mod n */
		mpModulo(v, R.x, E.rlen, E.r, E.rlen);

		/* verify v == r */
		if (mpEqual(v, r, E.rlen))
		{	
			status = VLT_OK;
		}
		else
		{
			status = VLT_FAIL;
		}
	}

    return ( status );
}