Crypt-Bear

 view release on metacpan or  search on metacpan

src/rsa/rsa_i62_priv.c  view on Meta::CPAN

	 * Convert size to 62-bit words.
	 */
	fwlen = (fwlen + 1) >> 1;

	/*
	 * We need to fit at least 6 values in the stack buffer.
	 */
	if (6 * fwlen > TLEN) {
		return 0;
	}

	/*
	 * Compute signature length (in bytes).
	 */
	xlen = (sk->n_bitlen + 7) >> 3;

	/*
	 * Decode q.
	 */
	mq = (uint32_t *)tmp;
	br_i31_decode(mq, q, qlen);

	/*
	 * Decode p.
	 */
	t1 = (uint32_t *)(tmp + fwlen);
	br_i31_decode(t1, p, plen);

	/*
	 * Compute the modulus (product of the two factors), to compare
	 * it with the source value. We use br_i31_mulacc(), since it's
	 * already used later on.
	 */
	t2 = (uint32_t *)(tmp + 2 * fwlen);
	br_i31_zero(t2, mq[0]);
	br_i31_mulacc(t2, mq, t1);

	/*
	 * We encode the modulus into bytes, to perform the comparison
	 * with bytes. We know that the product length, in bytes, is
	 * exactly xlen.
	 * The comparison actually computes the carry when subtracting
	 * the modulus from the source value; that carry must be 1 for
	 * a value in the correct range. We keep it in r, which is our
	 * accumulator for the error code.
	 */
	t3 = (uint32_t *)(tmp + 4 * fwlen);
	br_i31_encode(t3, xlen, t2);
	u = xlen;
	r = 0;
	while (u > 0) {
		uint32_t wn, wx;

		u --;
		wn = ((unsigned char *)t3)[u];
		wx = x[u];
		r = ((wx - (wn + r)) >> 8) & 1;
	}

	/*
	 * Move the decoded p to another temporary buffer.
	 */
	mp = (uint32_t *)(tmp + 2 * fwlen);
	memmove(mp, t1, 2 * fwlen * sizeof *t1);

	/*
	 * Compute s2 = x^dq mod q.
	 */
	q0i = br_i31_ninv31(mq[1]);
	s2 = (uint32_t *)(tmp + fwlen);
	br_i31_decode_reduce(s2, x, xlen, mq);
	r &= br_i62_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
		tmp + 3 * fwlen, TLEN - 3 * fwlen);

	/*
	 * Compute s1 = x^dp mod p.
	 */
	p0i = br_i31_ninv31(mp[1]);
	s1 = (uint32_t *)(tmp + 3 * fwlen);
	br_i31_decode_reduce(s1, x, xlen, mp);
	r &= br_i62_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i,
		tmp + 4 * fwlen, TLEN - 4 * fwlen);

	/*
	 * Compute:
	 *   h = (s1 - s2)*(1/q) mod p
	 * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is
	 * unclear about whether p may be lower than q (some existing,
	 * widely deployed implementations of RSA don't tolerate p < q),
	 * but we want to support that occurrence, so we need to use the
	 * reduction function.
	 *
	 * Since we use br_i31_decode_reduce() for iq (purportedly, the
	 * inverse of q modulo p), we also tolerate improperly large
	 * values for this parameter.
	 */
	t1 = (uint32_t *)(tmp + 4 * fwlen);
	t2 = (uint32_t *)(tmp + 5 * fwlen);
	br_i31_reduce(t2, s2, mp);
	br_i31_add(s1, mp, br_i31_sub(s1, t2, 1));
	br_i31_to_monty(s1, mp);
	br_i31_decode_reduce(t1, sk->iq, sk->iqlen, mp);
	br_i31_montymul(t2, s1, t1, mp, p0i);

	/*
	 * h is now in t2. We compute the final result:
	 *   s = s2 + q*h
	 * All these operations are non-modular.
	 *
	 * We need mq, s2 and t2. We use the t3 buffer as destination.
	 * The buffers mp, s1 and t1 are no longer needed, so we can
	 * reuse them for t3. Moreover, the first step of the computation
	 * is to copy s2 into t3, after which s2 is not needed. Right
	 * now, mq is in slot 0, s2 is in slot 1, and t2 is in slot 5.
	 * Therefore, we have ample room for t3 by simply using s2.
	 */
	t3 = s2;
	br_i31_mulacc(t3, mq, t2);

	/*
	 * Encode the result. Since we already checked the value of xlen,



( run in 2.204 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )