bn_gf2m.c 29 KB
Newer Older
			} while (BN_is_zero(w) && (count < MAX_ITERATIONS));
		if (BN_is_zero(w))
			{
			BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR,BN_R_TOO_MANY_ITERATIONS);
			goto err;
			}
		}
	
	if (!BN_GF2m_mod_sqr_arr(w, z, p, ctx)) goto err;
	if (!BN_GF2m_add(w, z, w)) goto err;
	if (BN_GF2m_cmp(w, a))
		{
		BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, BN_R_NO_SOLUTION);
		goto err;
		}

	if (!BN_copy(r, z)) goto err;
	bn_check_top(r);

	ret = 1;

err:
	BN_CTX_end(ctx);
	return ret;
	}

/* Find r such that r^2 + r = a mod p.  r could be a. If no r exists returns 0.
 *
 * This function calls down to the BN_GF2m_mod_solve_quad_arr implementation; this wrapper
 * function is only provided for convenience; for best performance, use the 
 * BN_GF2m_mod_solve_quad_arr function.
 */
int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
	{
	int ret = 0;
	const int max = BN_num_bits(p) + 1;
	int *arr=NULL;
	bn_check_top(a);
	bn_check_top(p);
	if ((arr = (int *)OPENSSL_malloc(sizeof(int) *
						max)) == NULL) goto err;
	ret = BN_GF2m_poly2arr(p, arr, max);
	if (!ret || ret > max)
		{
		BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD,BN_R_INVALID_LENGTH);
		goto err;
		}
	ret = BN_GF2m_mod_solve_quad_arr(r, a, arr, ctx);
	bn_check_top(r);
err:
	if (arr) OPENSSL_free(arr);
	return ret;
	}

/* Convert the bit-string representation of a polynomial
 * ( \sum_{i=0}^n a_i * x^i) into an array of integers corresponding 
 * to the bits with non-zero coefficient.  Array is terminated with -1.
 * Up to max elements of the array will be filled.  Return value is total
 * number of array elements that would be filled if array was large enough.
 */
int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max)
	{
	int i, j, k = 0;
	BN_ULONG mask;

	if (BN_is_zero(a))
		return 0;

	for (i = a->top - 1; i >= 0; i--)
		{
		if (!a->d[i])
			/* skip word if a->d[i] == 0 */
			continue;
		mask = BN_TBIT;
		for (j = BN_BITS2 - 1; j >= 0; j--)
			{
			if (a->d[i] & mask) 
				{
				if (k < max) p[k] = BN_BITS2 * i + j;
				k++;
				}
			mask >>= 1;
			}
		}

	if (k < max) {
		p[k] = -1;
		k++;
	}

	return k;
	}

/* Convert the coefficient array representation of a polynomial to a 
 * bit-string.  The array must be terminated by -1.
 */
int BN_GF2m_arr2poly(const int p[], BIGNUM *a)
	{
	int i;

	bn_check_top(a);
	BN_zero(a);
	for (i = 0; p[i] != -1; i++)
		{
		if (BN_set_bit(a, p[i]) == 0)
			return 0;
		}
	bn_check_top(a);

	return 1;
	}

#endif