From a0b4a14150e26ee5feed60365e335b0953b28b04 Mon Sep 17 00:00:00 2001
From: Adam Langley <agl@chromium.org>
Date: Tue, 23 Apr 2013 12:13:51 -0400
Subject: [PATCH 07/11] exp_zero_mod_one

Ensure that x**0 mod 1 = 0.
---
 crypto/bn/bn_exp.c  |  9 ++++++++-
 crypto/bn/exptest.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c
index 8441994..d26b0ca 100644
--- a/crypto/bn/bn_exp.c
+++ b/crypto/bn/bn_exp.c
@@ -980,7 +980,14 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
 	bits = BN_num_bits(p);
 	if (bits == 0)
 		{
-		ret = BN_one(rr);
+		/* x**0 mod 1 is still zero. */
+		if (BN_is_one(m))
+			{
+			ret = 1;
+			BN_zero(rr);
+			}
+		else
+			ret = BN_one(rr);
 		return ret;
 		}
 	if (a == 0)
diff --git a/crypto/bn/exptest.c b/crypto/bn/exptest.c
index 074a8e8..5fa02a1 100644
--- a/crypto/bn/exptest.c
+++ b/crypto/bn/exptest.c
@@ -71,6 +71,43 @@
 
 static const char rnd_seed[] = "string to make the random number generator think it has entropy";
 
+/* test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success. */
+static int test_exp_mod_zero() {
+	BIGNUM a, p, m;
+	BIGNUM r;
+	BN_CTX *ctx = BN_CTX_new();
+	int ret = 1;
+
+	BN_init(&m);
+	BN_one(&m);
+
+	BN_init(&a);
+	BN_one(&a);
+
+	BN_init(&p);
+	BN_zero(&p);
+
+	BN_init(&r);
+	BN_mod_exp(&r, &a, &p, &m, ctx);
+	BN_CTX_free(ctx);
+
+	if (BN_is_zero(&r))
+		ret = 0;
+	else
+		{
+		printf("1**0 mod 1 = ");
+		BN_print_fp(stdout, &r);
+		printf(", should be 0\n");
+		}
+
+	BN_free(&r);
+	BN_free(&a);
+	BN_free(&p);
+	BN_free(&m);
+
+	return ret;
+}
+
 int main(int argc, char *argv[])
 	{
 	BN_CTX *ctx;
@@ -190,7 +227,13 @@ int main(int argc, char *argv[])
 	ERR_remove_thread_state(NULL);
 	CRYPTO_mem_leaks(out);
 	BIO_free(out);
-	printf(" done\n");
+	printf("\n");
+
+	if (test_exp_mod_zero() != 0)
+		goto err;
+
+	printf("done\n");
+
 	EXIT(0);
 err:
 	ERR_load_crypto_strings();
-- 
1.8.2.1

