Пример #1
0
int cp_phpe_enc(uint8_t *out, int *out_len, uint8_t *in, int in_len, bn_t n) {
	bn_t g, m, r, s;
	int size, result = STS_OK;

	bn_null(g);
	bn_null(m);
	bn_null(r);
	bn_null(s);

	size = bn_size_bin(n);

	if (n == NULL || in_len <= 0 || in_len > size) {
		return STS_ERR;
	}

	TRY {
		bn_new(g);
		bn_new(m);
		bn_new(r);
		bn_new(s);

		/* Represent m as a padded element of Z_n. */
		bn_read_bin(m, in, in_len);

		/* Generate r in Z_n^*. */
		bn_rand_mod(r, n);

		/* Compute c = (g^m)(r^n) mod n^2. */
		bn_add_dig(g, n, 1);
		bn_sqr(s, n);
		bn_mxp(m, g, m, s);
		bn_mxp(r, r, n, s);
		bn_mul(m, m, r);
		bn_mod(m, m, s);
		if (2 * size <= *out_len) {
			*out_len = 2 * size;
			memset(out, 0, *out_len);
			bn_write_bin(out, *out_len, m);
		} else {
			result = STS_ERR;
		}
	}
	CATCH_ANY {
		result = STS_ERR;
	}
	FINALLY {
		bn_free(g);
		bn_free(m);
		bn_free(r);
		bn_free(s);		
	}

	return result;
}
Пример #2
0
int cp_bdpe_dec(dig_t *out, uint8_t *in, int in_len, bdpe_t prv) {
	bn_t m, t, z;
	unsigned i;
	int size, result = STS_OK;

	size = bn_size_bin(prv->n);

	if (in_len < 0 || in_len != size) {
		return STS_ERR;
	}

	bn_null(m);
	bn_null(t);
	bn_null(z);

	TRY {
		bn_new(m);
		bn_new(t);
		bn_new(z);

		/* Compute t = (p-1)(q-1)/block. */
		bn_mul(t, prv->p, prv->q);
		bn_sub(t, t, prv->p);
		bn_sub(t, t, prv->q);
		bn_add_dig(t, t, 1);
		bn_div_dig(t, t, prv->t);
		bn_read_bin(m, in, in_len);
		bn_mxp(m, m, t, prv->n);
		bn_mxp(t, prv->y, t, prv->n);

		for (i = 0; i < prv->t; i++) {
			bn_mxp_dig(z, t, i, prv->n);
			if (bn_cmp(z, m) == CMP_EQ) {
				*out = i;
				break;
			}
		}

		if (i == prv->t) {
			result = STS_ERR;
		}
	} CATCH_ANY {
		result = STS_ERR;
	}
	FINALLY {
		bn_free(m);
		bn_free(t);
		bn_free(z);
	}

	return result;
}
Пример #3
0
status_t element_pow_int(element_t c, element_t a, integer_t b)
{
	GroupType type = a->type;
	// TODO: c (type) = a (type) ^ b (ZR)
	LEAVE_IF( c->isInitialized != TRUE || a->isInitialized != TRUE, "uninitialized argument.");
	EXIT_IF_NOT_SAME(c, a);
	LEAVE_IF(b == NULL, "uninitialized integer.");

	status_t result = ELEMENT_OK;
	LEAVE_IF( c->type != type, "result initialized but invalid type.");

	switch(type) {
		case ZR: bn_mxp(c->bn, a->bn, b, a->order);
				 break;
		case G1: g1_mul(c->g1, a->g1, b);
				 break;
		case G2: g2_mul(c->g2, a->g2, b);
				 break;
		case GT: gt_exp(c->gt, a->gt, b);
				 break;
		default:
				 result = ELEMENT_INVALID_TYPES;
				 break;
	}

	return result;

}
Пример #4
0
status_t element_pow_zr(element_t c, element_t a, element_t b)
{
	GroupType type = a->type;
	// c (type) = a (type) ^ b (ZR)
	LEAVE_IF( c->isInitialized != TRUE || a->isInitialized != TRUE, "uninitialized argument.");
	EXIT_IF_NOT_SAME(c, a);
	LEAVE_IF(a->isInitialized != TRUE, "invalid argument.");
	LEAVE_IF(b->isInitialized != TRUE || b->type != ZR, "invalid type.");

	if(type == ZR) {
		bn_mxp(c->bn, a->bn, b->bn, a->order);
	}
	else if(type == G1) {
		g1_mul(c->g1, a->g1, b->bn);
	}
	else if(type == G2) {
		g2_mul(c->g2, a->g2, b->bn);
	}
	else if(type == GT) {
		gt_exp(c->gt, a->gt, b->bn);
	}
	else {
		return ELEMENT_INVALID_TYPES;
	}

	return ELEMENT_OK;
}
Пример #5
0
int cp_phpe_dec(uint8_t *out, int out_len, uint8_t *in, int in_len, bn_t n,
	bn_t l) {
	bn_t c, u, s;
	int size, result = STS_OK;

	size = bn_size_bin(n);

	if (in_len < 0 || in_len != 2 * size) {
		return STS_ERR;
	}

	bn_null(c);
	bn_null(u);
	bn_null(s);

	TRY {
		bn_new(c);
		bn_new(u);
		bn_new(s);

		/* Compute (c^l mod n^2) * u mod n. */
		bn_sqr(s, n);
		bn_read_bin(c, in, in_len);
		bn_mxp(c, c, l, s);
		bn_sub_dig(c, c, 1);
		bn_div(c, c, n);
		bn_gcd_ext(s, u, NULL, l, n);
		if (bn_sign(u) == BN_NEG) {
			bn_add(u, u, n);
		}
		bn_mul(c, c, u);
		bn_mod(c, c, n);

		size = bn_size_bin(c);
		if (size <= out_len) {
			memset(out, 0, out_len);
			bn_write_bin(out + (out_len - size), size, c);
		} else {
			result = STS_ERR;
		}
	} CATCH_ANY {
		result = STS_ERR;
	}
	FINALLY {
		bn_free(c);
		bn_free(u);
		bn_free(s);
	}

	return result;
}
Пример #6
0
int cp_bdpe_enc(uint8_t *out, int *out_len, dig_t in, bdpe_t pub) {
	bn_t m, u;
	int size, result = STS_OK;

	bn_null(m);
	bn_null(u);

	size = bn_size_bin(pub->n);

	if (in > pub->t) {
		return STS_ERR;
	}

	TRY {
		bn_new(m);
		bn_new(u);

		bn_set_dig(m, in);

		do {
			bn_rand(u, BN_POS, bn_bits(pub->n));
			bn_mod(u, u, pub->n);
		} while (bn_is_zero(u));

		bn_mxp(m, pub->y, m, pub->n);
		bn_mxp_dig(u, u, pub->t, pub->n);
		bn_mul(m, m, u);
		bn_mod(m, m, pub->n);

		if (size <= *out_len) {
			*out_len = size;
			memset(out, 0, *out_len);
			bn_write_bin(out, size, m);
		} else {
			result = STS_ERR;
		}
	}
	CATCH_ANY {
		result = STS_ERR;
	}
	FINALLY {
		bn_free(m);
		bn_free(u);
	}

	return result;
}
Пример #7
0
int bn_factor(bn_t c, const bn_t a) {
    bn_t t0, t1;
    int result;
    unsigned int i, tests;

    bn_null(t0);
    bn_null(t1);

    result = 1;

    if (bn_is_even(a)) {
        bn_set_dig(c, 2);
        return 1;
    }

    TRY {
        bn_new(t0);
        bn_new(t1);

        bn_set_dig(t0, 2);

#if WORD == 8
        tests = 255;
#else
        tests = 65535;
#endif
        for (i = 2; i < tests; i++) {
            bn_set_dig(t1, i);
            bn_mxp(t0, t0, t1, a);
        }

        bn_sub_dig(t0, t0, 1);
        bn_gcd(t1, t0, a);
        if (bn_cmp_dig(t1, 1) == CMP_GT && bn_cmp(t1, a) == CMP_LT) {
            bn_copy(c, t1);
        } else {
            result = 0;
        }
    } CATCH_ANY {
        THROW(ERR_CAUGHT);
    } FINALLY {
        bn_free(t0);
        bn_free(t1);
    }
    return result;
}
Пример #8
0
int cp_rsa_enc(uint8_t *out, int *out_len, uint8_t *in, int in_len, rsa_t pub) {
	bn_t m, eb;
	int size, pad_len, result = STS_OK;

	bn_null(m);
	bn_null(eb);

	size = bn_size_bin(pub->n);

	if (pub == NULL || in_len <= 0 || in_len > (size - RSA_PAD_LEN)) {
		return STS_ERR;
	}

	TRY {
		bn_new(m);
		bn_new(eb);

		bn_zero(m);
		bn_zero(eb);

#if CP_RSAPD == BASIC
		if (pad_basic(eb, &pad_len, in_len, size, RSA_ENC) == STS_OK) {
#elif CP_RSAPD == PKCS1
		if (pad_pkcs1(eb, &pad_len, in_len, size, RSA_ENC) == STS_OK) {
#elif CP_RSAPD == PKCS2
		if (pad_pkcs2(eb, &pad_len, in_len, size, RSA_ENC) == STS_OK) {
#endif
			bn_read_bin(m, in, in_len);
			bn_add(eb, eb, m);

#if CP_RSAPD == PKCS2
			pad_pkcs2(eb, &pad_len, in_len, size, RSA_ENC_FIN);
#endif
			bn_mxp(eb, eb, pub->e, pub->n);

			if (size <= *out_len) {
				*out_len = size;
				memset(out, 0, *out_len);
				bn_write_bin(out, size, eb);
			} else {
				result = STS_ERR;
			}
		} else {
			result = STS_ERR;
		}
	}
	CATCH_ANY {
		result = STS_ERR;
	}
	FINALLY {
		bn_free(m);
		bn_free(eb);
	}

	return result;
}

#if CP_RSA == BASIC || !defined(STRIP)

int cp_rsa_dec_basic(uint8_t *out, int *out_len, uint8_t *in, int in_len, rsa_t prv) {
	bn_t m, eb;
	int size, pad_len, result = STS_OK;

	size = bn_size_bin(prv->n);

	if (prv == NULL || in_len != size || in_len < RSA_PAD_LEN) {
		return STS_ERR;
	}

	bn_null(m);
	bn_null(eb);

	TRY {
		bn_new(m);
		bn_new(eb);

		bn_read_bin(eb, in, in_len);
		bn_mxp(eb, eb, prv->d, prv->n);

		if (bn_cmp(eb, prv->n) != CMP_LT) {
			result = STS_ERR;
		}
#if CP_RSAPD == BASIC
		if (pad_basic(eb, &pad_len, in_len, size, RSA_DEC) == STS_OK) {
#elif CP_RSAPD == PKCS1
		if (pad_pkcs1(eb, &pad_len, in_len, size, RSA_DEC) == STS_OK) {
#elif CP_RSAPD == PKCS2
		if (pad_pkcs2(eb, &pad_len, in_len, size, RSA_DEC) == STS_OK) {
#endif
			size = size - pad_len;

			if (size <= *out_len) {
				memset(out, 0, size);
				bn_write_bin(out, size, eb);
				*out_len = size;
			} else {
				result = STS_ERR;
			}
		} else {
			result = STS_ERR;
		}
	}
	CATCH_ANY {
		result = STS_ERR;
	}
	FINALLY {
		bn_free(m);
		bn_free(eb);
	}

	return result;
}

#endif

#if CP_RSA == QUICK || !defined(STRIP)

int cp_rsa_dec_quick(uint8_t *out, int *out_len, uint8_t *in, int in_len, rsa_t prv) {
	bn_t m, eb;
	int size, pad_len, result = STS_OK;

	bn_null(m);
	bn_null(eb);

	size = bn_size_bin(prv->n);

	if (prv == NULL || in_len != size || in_len < RSA_PAD_LEN) {
		return STS_ERR;
	}

	TRY {
		bn_new(m);
		bn_new(eb);

		bn_read_bin(eb, in, in_len);

		bn_copy(m, eb);

		/* m1 = c^dP mod p. */
		bn_mxp(eb, eb, prv->dp, prv->p);

		/* m2 = c^dQ mod q. */
		bn_mxp(m, m, prv->dq, prv->q);

		/* m1 = m1 - m2 mod p. */
		bn_sub(eb, eb, m);
		while (bn_sign(eb) == BN_NEG) {
			bn_add(eb, eb, prv->p);
		}
		bn_mod(eb, eb, prv->p);
		/* m1 = qInv(m1 - m2) mod p. */
		bn_mul(eb, eb, prv->qi);
		bn_mod(eb, eb, prv->p);
		/* m = m2 + m1 * q. */
		bn_mul(eb, eb, prv->q);
		bn_add(eb, eb, m);

		if (bn_cmp(eb, prv->n) != CMP_LT) {
			result = STS_ERR;
		}
#if CP_RSAPD == BASIC
		if (pad_basic(eb, &pad_len, in_len, size, RSA_DEC) == STS_OK) {
#elif CP_RSAPD == PKCS1
		if (pad_pkcs1(eb, &pad_len, in_len, size, RSA_DEC) == STS_OK) {
#elif CP_RSAPD == PKCS2
		if (pad_pkcs2(eb, &pad_len, in_len, size, RSA_DEC) == STS_OK) {
#endif
			size = size - pad_len;

			if (size <= *out_len) {
				memset(out, 0, size);
				bn_write_bin(out, size, eb);
				*out_len = size;
			} else {
				result = STS_ERR;
			}
		} else {
			result = STS_ERR;
		}
	}
	CATCH_ANY {
		result = STS_ERR;
	}
	FINALLY {
		bn_free(m);
		bn_free(eb);
	}

	return result;
}

#endif

#if CP_RSA == BASIC || !defined(STRIP)

int cp_rsa_sig_basic(uint8_t *sig, int *sig_len, uint8_t *msg, int msg_len, int hash, rsa_t prv) {
	bn_t m, eb;
	int size, pad_len, result = STS_OK;
	uint8_t h[MD_LEN];

	if (prv == NULL || msg_len < 0) {
		return STS_ERR;
	}

	pad_len = (!hash ? MD_LEN : msg_len);

#if CP_RSAPD == PKCS2
	size = bn_bits(prv->n) - 1;
	size = (size / 8) + (size % 8 > 0);
	if (pad_len > (size - 2)) {
		return STS_ERR;
	}
#else
	size = bn_size_bin(prv->n);
	if (pad_len > (size - RSA_PAD_LEN)) {
		return STS_ERR;
	}
#endif

	bn_null(m);
	bn_null(eb);

	TRY {
		bn_new(m);
		bn_new(eb);

		bn_zero(m);
		bn_zero(eb);

		int operation = (!hash ? RSA_SIG : RSA_SIG_HASH);

#if CP_RSAPD == BASIC
		if (pad_basic(eb, &pad_len, pad_len, size, operation) == STS_OK) {
#elif CP_RSAPD == PKCS1
		if (pad_pkcs1(eb, &pad_len, pad_len, size, operation) == STS_OK) {
#elif CP_RSAPD == PKCS2
		if (pad_pkcs2(eb, &pad_len, pad_len, size, operation) == STS_OK) {
#endif
			if (!hash) {
				md_map(h, msg, msg_len);
				bn_read_bin(m, h, MD_LEN);
				bn_add(eb, eb, m);
			} else {
				bn_read_bin(m, msg, msg_len);
				bn_add(eb, eb, m);
			}

#if CP_RSAPD == PKCS2
			pad_pkcs2(eb, &pad_len, bn_bits(prv->n), size, RSA_SIG_FIN);
#endif

			bn_mxp(eb, eb, prv->d, prv->n);

			size = bn_size_bin(prv->n);

			if (size <= *sig_len) {
				memset(sig, 0, size);
				bn_write_bin(sig, size, eb);
				*sig_len = size;
			} else {
				result = STS_ERR;
			}
		} else {
			result = STS_ERR;
		}
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(m);
		bn_free(eb);
	}

	return result;
}

#endif

#if CP_RSA == QUICK || !defined(STRIP)

int cp_rsa_sig_quick(uint8_t *sig, int *sig_len, uint8_t *msg, int msg_len, int hash, rsa_t prv) {
	bn_t m, eb;
	int pad_len, size, result = STS_OK;
	uint8_t h[MD_LEN];

	if (prv == NULL || msg_len < 0) {
		return STS_ERR;
	}

	pad_len = (!hash ? MD_LEN : msg_len);

#if CP_RSAPD == PKCS2
	size = bn_bits(prv->n) - 1;
	size = (size / 8) + (size % 8 > 0);
	if (pad_len > (size - 2)) {
		return STS_ERR;
	}
#else
	size = bn_size_bin(prv->n);
	if (pad_len > (size - RSA_PAD_LEN)) {
		return STS_ERR;
	}
#endif

	bn_null(m);
	bn_null(eb);

	TRY {
		bn_new(m);
		bn_new(eb);

		bn_zero(m);
		bn_zero(eb);

		int operation = (!hash ? RSA_SIG : RSA_SIG_HASH);

#if CP_RSAPD == BASIC
		if (pad_basic(eb, &pad_len, pad_len, size, operation) == STS_OK) {
#elif CP_RSAPD == PKCS1
		if (pad_pkcs1(eb, &pad_len, pad_len, size, operation) == STS_OK) {
#elif CP_RSAPD == PKCS2
		if (pad_pkcs2(eb, &pad_len, pad_len, size, operation) == STS_OK) {
#endif
			if (!hash) {
				md_map(h, msg, msg_len);
				bn_read_bin(m, h, MD_LEN);
				bn_add(eb, eb, m);
			} else {
				bn_read_bin(m, msg, msg_len);
				bn_add(eb, eb, m);
			}

#if CP_RSAPD == PKCS2
			pad_pkcs2(eb, &pad_len, bn_bits(prv->n), size, RSA_SIG_FIN);
#endif

			bn_copy(m, eb);

			/* m1 = c^dP mod p. */
			bn_mxp(eb, eb, prv->dp, prv->p);

			/* m2 = c^dQ mod q. */
			bn_mxp(m, m, prv->dq, prv->q);

			/* m1 = m1 - m2 mod p. */
			bn_sub(eb, eb, m);
			while (bn_sign(eb) == BN_NEG) {
				bn_add(eb, eb, prv->p);
			}
			bn_mod(eb, eb, prv->p);
			/* m1 = qInv(m1 - m2) mod p. */
			bn_mul(eb, eb, prv->qi);
			bn_mod(eb, eb, prv->p);
			/* m = m2 + m1 * q. */
			bn_mul(eb, eb, prv->q);
			bn_add(eb, eb, m);
			bn_mod(eb, eb, prv->n);

			size = bn_size_bin(prv->n);

			if (size <= *sig_len) {
				memset(sig, 0, size);
				bn_write_bin(sig, size, eb);
				*sig_len = size;
			} else {
				result = STS_ERR;
			}
		} else {
			result = STS_ERR;
		}
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(m);
		bn_free(eb);
	}

	return result;
}

#endif

int cp_rsa_ver(uint8_t *sig, int sig_len, uint8_t *msg, int msg_len, int hash, rsa_t pub) {
	bn_t m, eb;
	int size, pad_len, result;
	uint8_t h1[MAX(msg_len, MD_LEN) + 8], h2[MAX(msg_len, MD_LEN)];

	/* We suppose that the signature is invalid. */
	result = 0;

	if (pub == NULL || msg_len < 0) {
		return 0;
	}

	pad_len = (!hash ? MD_LEN : msg_len);

#if CP_RSAPD == PKCS2
	size = bn_bits(pub->n) - 1;
	if (size % 8 == 0) {
		size = size / 8 - 1;
	} else {
		size = bn_size_bin(pub->n);
	}
	if (pad_len > (size - 2)) {
		return 0;
	}
#else
	size = bn_size_bin(pub->n);
	if (pad_len > (size - RSA_PAD_LEN)) {
		return 0;
	}
#endif

	bn_null(m);
	bn_null(eb);

	TRY {
		bn_new(m);
		bn_new(eb);

		bn_read_bin(eb, sig, sig_len);

		bn_mxp(eb, eb, pub->e, pub->n);

		int operation = (!hash ? RSA_VER : RSA_VER_HASH);

#if CP_RSAPD == BASIC
		if (pad_basic(eb, &pad_len, MD_LEN, size, operation) == STS_OK) {
#elif CP_RSAPD == PKCS1
		if (pad_pkcs1(eb, &pad_len, MD_LEN, size, operation) == STS_OK) {
#elif CP_RSAPD == PKCS2
		if (pad_pkcs2(eb, &pad_len, bn_bits(pub->n), size, operation) == STS_OK) {
#endif

#if CP_RSAPD == PKCS2
			memset(h1, 0, 8);

			if (!hash) {
				md_map(h1 + 8, msg, msg_len);
				md_map(h2, h1, MD_LEN + 8);

				memset(h1, 0, MD_LEN);
				bn_write_bin(h1, size - pad_len, eb);
				/* Everything went ok, so signature status is changed. */
				result = util_cmp_const(h1, h2, MD_LEN);
			} else {
				memcpy(h1 + 8, msg, msg_len);
				md_map(h2, h1, MD_LEN + 8);

				memset(h1, 0, msg_len);
				bn_write_bin(h1, size - pad_len, eb);

				/* Everything went ok, so signature status is changed. */
				result = util_cmp_const(h1, h2, msg_len);
			}
#else
			memset(h1, 0, MAX(msg_len, MD_LEN));
			bn_write_bin(h1, size - pad_len, eb);

			if (!hash) {
				md_map(h2, msg, msg_len);
				/* Everything went ok, so signature status is changed. */
				result = util_cmp_const(h1, h2, MD_LEN);
			} else {
				/* Everything went ok, so signature status is changed. */
				result = util_cmp_const(h1, msg, msg_len);
			}
#endif
			result = (result == CMP_EQ ? 1 : 0);
		} else {
			result = 0;
		}
	}
	CATCH_ANY {
		result = 0;
	}
	FINALLY {
		bn_free(m);
		bn_free(eb);
	}

	return result;
}
Пример #9
0
int cp_bdpe_gen(bdpe_t pub, bdpe_t prv, dig_t block, int bits) {
	bn_t t, r;
	int result = STS_OK;

	bn_null(t);
	bn_null(r);

	TRY {
		bn_new(t);
		bn_new(r);

		prv->t = pub->t = block;

		/* Make sure that block size is prime. */
		bn_set_dig(t, block);
		if (bn_is_prime_basic(t) == 0) {
			THROW(ERR_NO_VALID);
		}

		/* Generate prime q such that gcd(block, (q - 1)) = 1. */
		do {
			bn_gen_prime(prv->q, bits / 2);
			bn_sub_dig(prv->q, prv->q, 1);
			bn_gcd_dig(t, prv->q, block);
			bn_add_dig(prv->q, prv->q, 1);
		} while (bn_cmp_dig(t, 1) != CMP_EQ);

		/* Generate different primes p and q. */
		do {
			/* Compute p = block * (x * block + b) + 1, 0 < b < block random. */
			bn_rand(prv->p, BN_POS, bits / 2 - 2 * util_bits_dig(block));
			bn_mul_dig(prv->p, prv->p, block);
			bn_rand(t, BN_POS, util_bits_dig(block));
			bn_add_dig(prv->p, prv->p, t->dp[0]);

			/* We know that block divides (p-1). */
			bn_gcd_dig(t, prv->p, block);
			bn_mul_dig(prv->p, prv->p, block);
			bn_add_dig(prv->p, prv->p, 1);
		} while (bn_cmp_dig(t, 1) != CMP_EQ || bn_is_prime(prv->p) == 0);

		/* Compute t = (p-1)*(q-1). */
		bn_sub_dig(prv->q, prv->q, 1);
		bn_sub_dig(prv->p, prv->p, 1);
		bn_mul(t, prv->p, prv->q);
		bn_div_dig(t, t, block);

		/* Restore factors p and q and compute n = p * q. */
		bn_add_dig(prv->p, prv->p, 1);
		bn_add_dig(prv->q, prv->q, 1);
		bn_mul(pub->n, prv->p, prv->q);
		bn_copy(prv->n, pub->n);

		/* Select random y such that y^{(p-1)(q-1)}/block \neq 1 mod N. */
		do {
			bn_rand(pub->y, BN_POS, bits);
			bn_mxp(r, pub->y, t, pub->n);
		} while (bn_cmp_dig(r, 1) == CMP_EQ);

		bn_copy(prv->y, pub->y);
	}
	CATCH_ANY {
		result = STS_ERR;
	}
	FINALLY {
		bn_free(t);
		bn_free(r);
	}

	return result;
}
Пример #10
0
void bn_gen_prime_stron(bn_t a, int bits) {
	dig_t i, j;
	int found, k;
	bn_t r, s, t;

	bn_null(r);
	bn_null(s);
	bn_null(t);

	TRY {
		bn_new(r);
		bn_new(s);
		bn_new(t);

		do {
			do {
				/* Generate two large primes r and s. */
				bn_rand(s, BN_POS, bits / 2 - BN_DIGIT / 2);
				bn_rand(t, BN_POS, bits / 2 - BN_DIGIT / 2);
			} while (!bn_is_prime(s) || !bn_is_prime(t));
			found = 1;
			bn_rand(a, BN_POS, bits / 2 - bn_bits(t) - 1);
			i = a->dp[0];
			bn_dbl(t, t);
			do {
				/* Find first prime r = 2 * i * t + 1. */
				bn_mul_dig(r, t, i);
				bn_add_dig(r, r, 1);
				i++;
				if (bn_bits(r) > bits / 2 - 1) {
					found = 0;
					break;
				}
			} while (!bn_is_prime(r));
			if (found == 0) {
				continue;
			}
			/* Compute t = 2 * (s^(r-2) mod r) * s - 1. */
			bn_sub_dig(t, r, 2);
#if BN_MOD != PMERS
			bn_mxp(t, s, t, r);
#else
			bn_exp(t, s, t, r);
#endif

			bn_mul(t, t, s);
			bn_dbl(t, t);
			bn_sub_dig(t, t, 1);

			k = bits - bn_bits(r);
			k -= bn_bits(s);
			bn_rand(a, BN_POS, k);
			j = a->dp[0];
			do {
				/* Find first prime a = t + 2 * j * r * s. */
				bn_mul(a, r, s);
				bn_mul_dig(a, a, j);
				bn_dbl(a, a);
				bn_add(a, a, t);
				j++;
				if (bn_bits(a) > bits) {
					found = 0;
					break;
				}
			} while (!bn_is_prime(a));
		} while (found == 0 && bn_bits(a) != bits);
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(r);
		bn_free(s);
		bn_free(t);
	}
}
Пример #11
0
int bn_is_prime_solov(const bn_t a) {
	bn_t t0, t1, t2;
	int i, result;

	bn_null(t0);
	bn_null(t1);
	bn_null(t2);

	result = 1;

	TRY {
		bn_new(t0);
		bn_new(t1);
		bn_new(t2);

		for (i = 0; i < 100; i++) {
			/* Generate t0, 2 <= t0, <= a - 2. */
			do {
				bn_rand(t0, BN_POS, bn_bits(a));
				bn_mod(t0, t0, a);
			} while (bn_cmp_dig(t0, 2) == CMP_LT);
			/* t2 = a - 1. */
			bn_copy(t2, a);
			bn_sub_dig(t2, t2, 1);
			/* t1 = (a - 1)/2. */
			bn_rsh(t1, t2, 1);
			/* t1 = t0^(a - 1)/2 mod a. */
#if BN_MOD != PMERS
			bn_mxp(t1, t0, t1, a);
#else
			bn_exp(t1, t0, t1, a);
#endif
			/* If t1 != 1 and t1 != n - 1 return 0 */
			if (bn_cmp_dig(t1, 1) != CMP_EQ && bn_cmp(t1, t2) != CMP_EQ) {
				result = 0;
				break;
			}

			/* t2 = (t0|a). */
			bn_smb_jac(t2, t0, a);
			if (bn_sign(t2) == BN_NEG) {
				bn_add(t2, t2, a);
			}
			/* If t1 != t2 (mod a) return 0. */
			bn_mod(t1, t1, a);
			bn_mod(t2, t2, a);
			if (bn_cmp(t1, t2) != CMP_EQ) {
				result = 0;
				break;
			}
		}
	}
	CATCH_ANY {
		result = 0;
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(t0);
		bn_free(t1);
		bn_free(t2);
	}
	return result;
}
Пример #12
0
int bn_is_prime_rabin(const bn_t a) {
	bn_t t, n1, y, r;
	int i, s, j, result, b, tests = 0;

	tests = 0;
	result = 1;

	bn_null(t);
	bn_null(n1);
	bn_null(y);
	bn_null(r);

	if (bn_cmp_dig(a, 1) == CMP_EQ) {
		return 0;
	}

	TRY {
		/*
		 * These values are taken from Table 4.4 inside Handbook of Applied
		 * Cryptography.
		 */
		b = bn_bits(a);
		if (b >= 1300) {
			tests = 2;
		} else if (b >= 850) {
			tests = 3;
		} else if (b >= 650) {
			tests = 4;
		} else if (b >= 550) {
			tests = 5;
		} else if (b >= 450) {
			tests = 6;
		} else if (b >= 400) {
			tests = 7;
		} else if (b >= 350) {
			tests = 8;
		} else if (b >= 300) {
			tests = 9;
		} else if (b >= 250) {
			tests = 12;
		} else if (b >= 200) {
			tests = 15;
		} else if (b >= 150) {
			tests = 18;
		} else {
			tests = 27;
		}

		bn_new(t);
		bn_new(n1);
		bn_new(y);
		bn_new(r);

		/* r = (n - 1)/2^s. */
		bn_sub_dig(n1, a, 1);
		s = 0;
		while (bn_is_even(n1)) {
			s++;
			bn_rsh(n1, n1, 1);
		}
		bn_lsh(r, n1, s);

		for (i = 0; i < tests; i++) {
			/* Fix the basis as the first few primes. */
			bn_set_dig(t, primes[i]);

			/* y = b^r mod a. */
#if BN_MOD != PMERS
			bn_mxp(y, t, r, a);
#else
			bn_exp(y, t, r, a);
#endif

			if (bn_cmp_dig(y, 1) != CMP_EQ && bn_cmp(y, n1) != CMP_EQ) {
				j = 1;
				while ((j <= (s - 1)) && bn_cmp(y, n1) != CMP_EQ) {
					bn_sqr(y, y);
					bn_mod(y, y, a);

					/* If y == 1 then composite. */
					if (bn_cmp_dig(y, 1) == CMP_EQ) {
						result = 0;
						break;
					}
					++j;
				}

				/* If y != n1 then composite. */
				if (bn_cmp(y, n1) != CMP_EQ) {
					result = 0;
					break;
				}
			}
		}
	}
	CATCH_ANY {
		result = 0;
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(r);
		bn_free(y);
		bn_free(n1);
		bn_free(t);
	}
	return result;
}