Beispiel #1
0
term_t bignum_to_term(bignum_t *a, xpool_t *xp)
{
	if (bn_size(a) == 0)
		return intnum(0);
	if (bn_sign(a) == 0 && bn_size(a) == 1 && a->digits[0] <= MAX_INT_VALUE)
		return intnum(a->digits[0]);
	if (bn_sign(a) == 1 && bn_size(a) == 1 && a->digits[0] <= MAX_INT_VALUE+1)
		return intnum(-(int_value_t)a->digits[0]);
	if (bn_sign(a) == 0 && bn_size(a) == 2)
	{
		apr_uint64_t v = (apr_uint64_t)a->digits[0] << 32;
		v += a->digits[1];	// somehow it doesn't work if combined with previous line
		
		if (v <= MAX_INT_VALUE)
			return intnum(v);
	}
	if (bn_sign(a) == 1 && bn_size(a) == 2)
	{
		apr_uint64_t v = (apr_uint64_t)a->digits[0] << 32;
		v += a->digits[1];
		
		if (v <= MAX_INT_VALUE+1)
			return intnum(-(int_value_t)v);
	}

	return bignum(a);
}
static int check_modulus_params(const struct BIGNUM *N, uint32_t *out_len)
{
	if (bn_size(N) > RSA_MAX_BYTES)
		return 0;                      /* Unsupported key size. */
	if (!bn_check_topbit(N))               /* Check that top bit is set. */
		return 0;
	if (out_len && *out_len < bn_size(N))
		return 0;                      /* Output buffer too small. */
	return 1;
}
int DCRYPTO_rsa_decrypt(struct RSA *rsa, uint8_t *out, uint32_t *out_len,
			const uint8_t *in, const uint32_t in_len,
			enum padding_mode padding, enum hashing_mode hashing,
			const char *label)
{
	uint32_t encrypted_buf[RSA_MAX_WORDS];
	uint32_t padded_buf[RSA_MAX_WORDS];

	struct BIGNUM encrypted;
	struct BIGNUM padded;
	int ret = 1;

	if (!check_modulus_params(&rsa->N, out_len))
		return 0;
	if (in_len != bn_size(&rsa->N))
		return 0;                      /* Invalid input length. */

	/* TODO(ngm): this copy can be eliminated if input may be modified. */
	bn_init(&encrypted, encrypted_buf, in_len);
	memcpy(encrypted_buf, in, in_len);
	bn_init(&padded, padded_buf, in_len);

	/* Reverse from big-endian to little-endian notation. */
	reverse((uint8_t *) encrypted.d, encrypted.dmax * BN_BYTES);
	bn_mont_modexp(&padded, &encrypted, &rsa->d, &rsa->N);
	/* Back to big-endian notation. */
	reverse((uint8_t *) padded.d, padded.dmax * BN_BYTES);

	switch (padding) {
	case PADDING_MODE_OAEP:
		if (!check_oaep_pad(out, out_len, (uint8_t *) padded.d,
					bn_size(&padded), hashing, label))
			ret = 0;
		break;
	case PADDING_MODE_PKCS1:
		if (!check_pkcs1_type2_pad(
				out, out_len, (const uint8_t *) padded.d,
				bn_size(&padded)))
			ret = 0;
		break;
	default:
		/* Unsupported padding mode. */
		ret = 0;
		break;
	}

	dcrypto_memset(encrypted_buf, 0, sizeof(encrypted_buf));
	dcrypto_memset(padded_buf, 0, sizeof(padded_buf));
	return ret;
}
int DCRYPTO_rsa_verify(struct RSA *rsa, const uint8_t *digest,
		uint32_t digest_len, const uint8_t *sig,
		const uint32_t sig_len,	enum padding_mode padding,
		enum hashing_mode hashing)
{
	uint32_t padded_buf[RSA_MAX_WORDS];
	uint32_t signature_buf[RSA_MAX_WORDS];
	uint32_t e_buf[BN_BYTES / sizeof(uint32_t)];

	struct BIGNUM padded;
	struct BIGNUM signature;
	struct BIGNUM e;
	int ret = 1;

	if (!check_modulus_params(&rsa->N, NULL))
		return 0;
	if (sig_len != bn_size(&rsa->N))
		return 0;                      /* Invalid input length. */

	bn_init(&signature, signature_buf, bn_size(&rsa->N));
	memcpy(signature_buf, sig, bn_size(&rsa->N));
	bn_init(&padded, padded_buf, bn_size(&rsa->N));
	bn_init(&e, e_buf, sizeof(e_buf));
	*e.d = rsa->e;

	/* Reverse from big-endian to little-endian notation. */
	reverse((uint8_t *) signature.d, signature.dmax * BN_BYTES);
	bn_mont_modexp(&padded, &signature, &e, &rsa->N);
	/* Back to big-endian notation. */
	reverse((uint8_t *) padded.d, padded.dmax * BN_BYTES);

	switch (padding) {
	case PADDING_MODE_PKCS1:
		if (!check_pkcs1_type1_pad(
				digest, digest_len, (uint8_t *) padded.d,
				bn_size(&padded), hashing))
			ret = 0;
		break;
	default:
		/* Unsupported padding mode. */
		ret = 0;
		break;
	}

	dcrypto_memset(padded_buf, 0, sizeof(padded_buf));
	dcrypto_memset(signature_buf, 0, sizeof(signature_buf));
	return ret;
}
int DCRYPTO_rsa_encrypt(struct RSA *rsa, uint8_t *out, uint32_t *out_len,
			const uint8_t *in, const uint32_t in_len,
			enum padding_mode padding, enum hashing_mode hashing,
			const char *label)
{
	uint32_t padded_buf[RSA_MAX_WORDS];
	uint32_t e_buf[BN_BYTES / sizeof(uint32_t)];

	struct BIGNUM padded;
	struct BIGNUM e;
	struct BIGNUM encrypted;

	if (!check_modulus_params(&rsa->N, out_len))
		return 0;

	bn_init(&padded, padded_buf, bn_size(&rsa->N));
	bn_init(&encrypted, out, bn_size(&rsa->N));
	bn_init(&e, e_buf, sizeof(e_buf));
	*e.d = rsa->e;

	switch (padding) {
	case PADDING_MODE_OAEP:
		if (!oaep_pad((uint8_t *) padded.d, bn_size(&padded),
				(const uint8_t *) in, in_len, hashing, label))
			return 0;
		break;
	case PADDING_MODE_PKCS1:
		if (!pkcs1_type2_pad((uint8_t *) padded.d, bn_size(&padded),
					(const uint8_t *) in, in_len))
			return 0;
		break;
	default:
		return 0;                       /* Unsupported padding mode. */
	}

	/* Reverse from big-endian to little-endian notation. */
	reverse((uint8_t *) padded.d, bn_size(&padded));
	bn_mont_modexp(&encrypted, &padded, &e, &rsa->N);
	/* Back to big-endian notation. */
	reverse((uint8_t *) encrypted.d, bn_size(&encrypted));
	*out_len = bn_size(&encrypted);

	dcrypto_memset(padded_buf, 0, sizeof(padded_buf));
	dcrypto_memset(e_buf, 0, sizeof(e_buf));
	return 1;
}
int DCRYPTO_rsa_sign(struct RSA *rsa, uint8_t *out, uint32_t *out_len,
		const uint8_t *in, const uint32_t in_len,
		enum padding_mode padding, enum hashing_mode hashing)
{
	uint32_t padded_buf[RSA_MAX_WORDS];

	struct BIGNUM padded;
	struct BIGNUM signature;

	if (!check_modulus_params(&rsa->N, out_len))
		return 0;

	bn_init(&padded, padded_buf, bn_size(&rsa->N));
	bn_init(&signature, out, bn_size(&rsa->N));

	/* TODO(ngm): add support for PSS. */
	switch (padding) {
	case PADDING_MODE_PKCS1:
		if (!pkcs1_type1_pad((uint8_t *) padded.d, bn_size(&padded),
					(const uint8_t *) in, in_len, hashing))
			return 0;
		break;
	default:
		return 0;
	}

	/* Reverse from big-endian to little-endian notation. */
	reverse((uint8_t *) padded.d, bn_size(&padded));
	bn_mont_modexp(&signature, &padded, &rsa->d, &rsa->N);
	/* Back to big-endian notation. */
	reverse((uint8_t *) signature.d, bn_size(&signature));
	*out_len = bn_size(&rsa->N);

	dcrypto_memset(padded_buf, 0, sizeof(padded_buf));
	return 1;
}