implement and use new macros BN_get_sign(), BN_set_sign()

Submitted by: Nils Larsch
diff --git a/CHANGES b/CHANGES
index b760b03..a16d78d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,15 @@
 
  Changes between 0.9.7 and 0.9.8  [xx XXX 2002]
 
+  *) Extend the BIGNUM API by creating new macros that behave like
+     functions
+
+          void BN_set_sign(BIGNUM *a, int neg);
+          int BN_get_sign(const BIGNUM *a);
+
+     and avoid the need to access 'a->neg' directly in applications.
+     [Nils Larsch  <nla@trustcenter.de>]
+
   *) Implement fast modular reduction for pseudo-Mersenne primes
      used in NIST curves (crypto/bn/bn_nist.c, crypto/ec/ecp_nist.c).
      EC_GROUP_new_curve_GFp() will now automatically use this
diff --git a/crypto/asn1/a_enum.c b/crypto/asn1/a_enum.c
index ad8f0ff..68a525f 100644
--- a/crypto/asn1/a_enum.c
+++ b/crypto/asn1/a_enum.c
@@ -147,7 +147,7 @@
 		ASN1err(ASN1_F_BN_TO_ASN1_ENUMERATED,ERR_R_NESTED_ASN1_ERROR);
 		goto err;
 		}
-	if(bn->neg) ret->type = V_ASN1_NEG_ENUMERATED;
+	if(BN_get_sign(bn)) ret->type = V_ASN1_NEG_ENUMERATED;
 	else ret->type=V_ASN1_ENUMERATED;
 	j=BN_num_bits(bn);
 	len=((j == 0)?0:((j/8)+1));
@@ -175,6 +175,6 @@
 
 	if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
 		ASN1err(ASN1_F_ASN1_ENUMERATED_TO_BN,ASN1_R_BN_LIB);
-	else if(ai->type == V_ASN1_NEG_ENUMERATED) ret->neg = 1;
+	else if(ai->type == V_ASN1_NEG_ENUMERATED) BN_set_sign(ret,1);
 	return(ret);
 	}
diff --git a/crypto/asn1/a_int.c b/crypto/asn1/a_int.c
index edb243c..78402cd 100644
--- a/crypto/asn1/a_int.c
+++ b/crypto/asn1/a_int.c
@@ -393,7 +393,8 @@
 		ASN1err(ASN1_F_BN_TO_ASN1_INTEGER,ERR_R_NESTED_ASN1_ERROR);
 		goto err;
 		}
-	if(bn->neg) ret->type = V_ASN1_NEG_INTEGER;
+	if (BN_get_sign(bn))
+		ret->type = V_ASN1_NEG_INTEGER;
 	else ret->type=V_ASN1_INTEGER;
 	j=BN_num_bits(bn);
 	len=((j == 0)?0:((j/8)+1));
@@ -426,7 +427,8 @@
 
 	if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
 		ASN1err(ASN1_F_ASN1_INTEGER_TO_BN,ASN1_R_BN_LIB);
-	else if(ai->type == V_ASN1_NEG_INTEGER) ret->neg = 1;
+	else if(ai->type == V_ASN1_NEG_INTEGER)
+		BN_set_sign(ret, 1);
 	return(ret);
 	}
 
diff --git a/crypto/asn1/t_pkey.c b/crypto/asn1/t_pkey.c
index 46fb86a..e3e0739 100644
--- a/crypto/asn1/t_pkey.c
+++ b/crypto/asn1/t_pkey.c
@@ -575,7 +575,7 @@
 	const char *neg;
 
 	if (num == NULL) return(1);
-	neg=(num->neg)?"-":"";
+	neg = (BN_get_sign(num))?"-":"";
 	if (off)
 		{
 		if (off > 128) off=128;
diff --git a/crypto/bn/bn.h b/crypto/bn/bn.h
index 4182dbf..403add9 100644
--- a/crypto/bn/bn.h
+++ b/crypto/bn/bn.h
@@ -320,6 +320,11 @@
 
 #define BN_one(a)	(BN_set_word((a),1))
 #define BN_zero(a)	(BN_set_word((a),0))
+/* BN_set_sign(BIGNUM *, int) sets the sign of a BIGNUM
+ * (0 for a non-negative value, 1 for negative) */
+#define BN_set_sign(a,b) ((a)->neg = (b))
+/* BN_get_sign(BIGNUM *) returns the sign of the BIGNUM */
+#define BN_get_sign(a)   ((a)->neg)
 
 /*#define BN_ascii2bn(a)	BN_hex2bn(a) */
 /*#define BN_bn2ascii(a)	BN_bn2hex(a) */
@@ -470,37 +475,54 @@
 
 /* Functions for arithmetic over binary polynomials represented by BIGNUMs. 
  *
- * The BIGNUM::neg property of BIGNUMs representing binary polynomials is ignored.
+ * The BIGNUM::neg property of BIGNUMs representing binary polynomials is
+ * ignored.
  *
  * Note that input arguments are not const so that their bit arrays can
  * be expanded to the appropriate size if needed.
  */
-int	BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); /* r = a + b */
+
+int	BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); /*r = a + b*/
 #define BN_GF2m_sub(r, a, b) BN_GF2m_add(r, a, b)
-int	BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p); /* r = a mod p */
-int	BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx); /* r = (a * b) mod p */
-int	BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); /* r = (a * a) mod p */
-int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx); /* r = (1 / b) mod p */
-int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx); /* r = (a / b) mod p */
-int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx); /* r = (a ^ b) mod p */
-int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); /* r = sqrt(a) mod p */
-int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); /* r^2 + r = a mod p */
+int	BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p); /*r=a mod p*/
+int	BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+	const BIGNUM *p, BN_CTX *ctx); /* r = (a * b) mod p */
+int	BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+	BN_CTX *ctx); /* r = (a * a) mod p */
+int	BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *b, const BIGNUM *p,
+	BN_CTX *ctx); /* r = (1 / b) mod p */
+int	BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+	const BIGNUM *p, BN_CTX *ctx); /* r = (a / b) mod p */
+int	BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+	const BIGNUM *p, BN_CTX *ctx); /* r = (a ^ b) mod p */
+int	BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+	BN_CTX *ctx); /* r = sqrt(a) mod p */
+int	BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+	BN_CTX *ctx); /* r^2 + r = a mod p */
 #define BN_GF2m_cmp(a, b) BN_ucmp((a), (b))
 /* Some functions allow for representation of the irreducible polynomials
  * as an unsigned int[], say p.  The irreducible f(t) is then of the form:
  *     t^p[0] + t^p[1] + ... + t^p[k]
  * where m = p[0] > p[1] > ... > p[k] = 0.
  */
-int	BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[]); /* r = a mod p */
-int	BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const unsigned int p[], BN_CTX *ctx); /* r = (a * b) mod p */
-int	BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[], BN_CTX *ctx); /* r = (a * a) mod p */
-int BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *b, const unsigned int p[], BN_CTX *ctx); /* r = (1 / b) mod p */
-int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const unsigned int p[], BN_CTX *ctx); /* r = (a / b) mod p */
-int BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const unsigned int p[], BN_CTX *ctx); /* r = (a ^ b) mod p */
-int BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[], BN_CTX *ctx); /* r = sqrt(a) mod p */
-int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[], BN_CTX *ctx); /* r^2 + r = a mod p */
-int BN_GF2m_poly2arr(const BIGNUM *a, unsigned int p[], int max);
-int BN_GF2m_arr2poly(const unsigned int p[], BIGNUM *a);
+int	BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[]);
+	/* r = a mod p */
+int	BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+	const unsigned int p[], BN_CTX *ctx); /* r = (a * b) mod p */
+int	BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[],
+	BN_CTX *ctx); /* r = (a * a) mod p */
+int	BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *b, const unsigned int p[],
+	BN_CTX *ctx); /* r = (1 / b) mod p */
+int	BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+	const unsigned int p[], BN_CTX *ctx); /* r = (a / b) mod p */
+int	BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+	const unsigned int p[], BN_CTX *ctx); /* r = (a ^ b) mod p */
+int	BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a,
+	const unsigned int p[], BN_CTX *ctx); /* r = sqrt(a) mod p */
+int	BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a,
+	const unsigned int p[], BN_CTX *ctx); /* r^2 + r = a mod p */
+int	BN_GF2m_poly2arr(const BIGNUM *a, unsigned int p[], int max);
+int	BN_GF2m_arr2poly(const unsigned int p[], BIGNUM *a);
 
 /* faster mod functions for the 'NIST primes' 
  * 0 <= a < p^2 */
diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c
index 37dd5fc..fc35dfe 100644
--- a/crypto/dsa/dsa_ossl.c
+++ b/crypto/dsa/dsa_ossl.c
@@ -246,12 +246,14 @@
 	BN_init(&u2);
 	BN_init(&t1);
 
-	if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0)
+	if (BN_is_zero(sig->r) || BN_get_sign(sig->r) ||
+	    BN_ucmp(sig->r, dsa->q) >= 0)
 		{
 		ret = 0;
 		goto err;
 		}
-	if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0)
+	if (BN_is_zero(sig->s) || BN_get_sign(sig->s) ||
+	    BN_ucmp(sig->s, dsa->q) >= 0)
 		{
 		ret = 0;
 		goto err;
diff --git a/crypto/ec/ec2_mult.c b/crypto/ec/ec2_mult.c
index 09cf08a..3aef959 100644
--- a/crypto/ec/ec2_mult.c
+++ b/crypto/ec/ec2_mult.c
@@ -297,8 +297,8 @@
 		}
 
 	/* GF(2^m) field elements should always have BIGNUM::neg = 0 */
-	r->X.neg = 0;
-	r->Y.neg = 0;
+	BN_set_sign(&r->X, 0);
+	BN_set_sign(&r->Y, 0);
 
 	ret = 1;
 
@@ -342,14 +342,16 @@
 	if (scalar)
 		{
 		if (!point_multiply(group, p, scalar, group->generator, ctx)) goto err;
-		if (scalar->neg) if (!group->meth->invert(group, p, ctx)) goto err;
+		if (BN_get_sign(scalar)) 
+			if (!group->meth->invert(group, p, ctx)) goto err;
 		if (!group->meth->add(group, r, r, p, ctx)) goto err;
 		}
 
 	for (i = 0; i < num; i++)
 		{
 		if (!point_multiply(group, p, scalars[i], points[i], ctx)) goto err;
-		if (scalars[i]->neg) if (!group->meth->invert(group, p, ctx)) goto err;
+		if (BN_get_sign(scalars[i]))
+			if (!group->meth->invert(group, p, ctx)) goto err;
 		if (!group->meth->add(group, r, r, p, ctx)) goto err;
 		}
 
diff --git a/crypto/ec/ec2_smpl.c b/crypto/ec/ec2_smpl.c
index acf2055..5e37bfa 100644
--- a/crypto/ec/ec2_smpl.c
+++ b/crypto/ec/ec2_smpl.c
@@ -349,11 +349,11 @@
 		}
 
 	if (!BN_copy(&point->X, x)) goto err;
-	point->X.neg = 0;
+	BN_set_sign(&point->X, 0);
 	if (!BN_copy(&point->Y, y)) goto err;
-	point->Y.neg = 0;
+	BN_set_sign(&point->Y, 0);
 	if (!BN_copy(&point->Z, BN_value_one())) goto err;
-	point->Z.neg = 0;
+	BN_set_sign(&point->Z, 0);
 	point->Z_is_one = 1;
 	ret = 1;
 
@@ -384,12 +384,12 @@
 	if (x != NULL)
 		{
 		if (!BN_copy(x, &point->X)) goto err;
-		x->neg = 0;
+		BN_set_sign(x, 0);
 		}
 	if (y != NULL)
 		{
 		if (!BN_copy(y, &point->Y)) goto err;
-		y->neg = 0;
+		BN_set_sign(y, 0);
 		}
 	ret = 1;
 		
diff --git a/crypto/ec/ec_mult.c b/crypto/ec/ec_mult.c
index 4978a54..f5312aa 100644
--- a/crypto/ec/ec_mult.c
+++ b/crypto/ec/ec_mult.c
@@ -102,7 +102,7 @@
 	next_bit = bit << 1; /* at most 256 */
 	mask = next_bit - 1; /* at most 255 */
 
-	if (scalar->neg)
+	if (BN_get_sign(scalar))
 		{
 		sign = -1;
 		}
diff --git a/crypto/ec/ecp_nist.c b/crypto/ec/ecp_nist.c
index 98401fe..156bc54 100644
--- a/crypto/ec/ecp_nist.c
+++ b/crypto/ec/ecp_nist.c
@@ -191,7 +191,7 @@
 
 	/* group->field */
 	if (!BN_copy(&group->field, p)) goto err;
-	group->field.neg = 0;
+	BN_set_sign(&group->field, 0);
 
 	/* group->a */
 	if (!group->field_mod_func(&group->a, a, p, ctx)) goto err;
diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c
index 97ff8eb..ad95b03 100644
--- a/crypto/ec/ecp_smpl.c
+++ b/crypto/ec/ecp_smpl.c
@@ -177,7 +177,7 @@
 
 	/* group->field */
 	if (!BN_copy(&group->field, p)) goto err;
-	group->field.neg = 0;
+	BN_set_sign(&group->field, 0);
 
 	/* group->a */
 	if (!BN_nnmod(tmp_a, a, p, ctx)) goto err;
diff --git a/crypto/ec/ectest.c b/crypto/ec/ectest.c
index e32b231..2553982 100644
--- a/crypto/ec/ectest.c
+++ b/crypto/ec/ectest.c
@@ -603,7 +603,7 @@
 
 		if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT;
 		if (!BN_add(z, z, y)) ABORT;
-		z->neg = 1;
+		BN_set_sign(z, 1);
 		scalars[0] = y;
 		scalars[1] = z; /* z = -(order + y) */
 
@@ -615,7 +615,7 @@
 
 		if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT;
 		if (!BN_add(z, x, y)) ABORT;
-		z->neg = 1;
+		BN_set_sign(z, 1);
 		scalars[0] = x;
 		scalars[1] = y;
 		scalars[2] = z; /* z = -(x+y) */
@@ -1069,7 +1069,7 @@
 
 		if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT;
 		if (!BN_add(z, z, y)) ABORT;
-		z->neg = 1;
+		BN_set_sign(z, 1);
 		scalars[0] = y;
 		scalars[1] = z; /* z = -(order + y) */
 
@@ -1081,7 +1081,7 @@
 
 		if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT;
 		if (!BN_add(z, x, y)) ABORT;
-		z->neg = 1;
+		BN_set_sign(z, 1);
 		scalars[0] = x;
 		scalars[1] = y;
 		scalars[2] = z; /* z = -(x+y) */
diff --git a/crypto/ecdsa/ecs_ossl.c b/crypto/ecdsa/ecs_ossl.c
index a9814af..215da38 100644
--- a/crypto/ecdsa/ecs_ossl.c
+++ b/crypto/ecdsa/ecs_ossl.c
@@ -353,13 +353,15 @@
 		goto err;
 	}
 
-	if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, order) >= 0)
+	if (BN_is_zero(sig->r) || BN_get_sign(sig->r) ||
+	    BN_ucmp(sig->r, order) >= 0)
 	{
 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE);
 		ret = 0;
 		goto err;
 	}
-	if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, order) >= 0)
+	if (BN_is_zero(sig->s) || BN_get_sign(sig->s) ||
+	    BN_ucmp(sig->s, order) >= 0)
 	{
 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE);
 		ret = 0;
diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c
index 0eda816..963c34a 100644
--- a/crypto/rsa/rsa_eay.c
+++ b/crypto/rsa/rsa_eay.c
@@ -546,7 +546,7 @@
 	if (!BN_sub(r0,r0,&m1)) goto err;
 	/* This will help stop the size of r0 increasing, which does
 	 * affect the multiply if it optimised for a power of 2 size */
-	if (r0->neg)
+	if (BN_get_sign(r0))
 		if (!BN_add(r0,r0,rsa->p)) goto err;
 
 	if (!BN_mul(&r1,r0,rsa->iqmp,ctx)) goto err;
@@ -558,7 +558,7 @@
 	 * This will *never* happen with OpenSSL generated keys because
          * they ensure p > q [steve]
          */
-	if (r0->neg)
+	if (BN_get_sign(r0))
 		if (!BN_add(r0,r0,rsa->p)) goto err;
 	if (!BN_mul(&r1,r0,rsa->q,ctx)) goto err;
 	if (!BN_add(r0,&r1,&m1)) goto err;
@@ -572,7 +572,7 @@
 		 * for absolute equality, just congruency. */
 		if (!BN_sub(&vrfy, &vrfy, I)) goto err;
 		if (!BN_mod(&vrfy, &vrfy, rsa->n, ctx)) goto err;
-		if (vrfy.neg)
+		if (BN_get_sign(&vrfy))
 			if (!BN_add(&vrfy, &vrfy, rsa->n)) goto err;
 		if (!BN_is_zero(&vrfy))
 			/* 'I' and 'vrfy' aren't congruent mod n. Don't leak