From f6198c1513edcb44e7edb96fc82e3a5549a4bdc3 Mon Sep 17 00:00:00 2001
From: Paul Bakker
Date: Wed, 16 May 2012 08:02:29 +0000
Subject: [PATCH] - mpi_exp_mod() now correctly handles negative base numbers
(Closes ticket #52)
---
ChangeLog | 2 ++
include/polarssl/bignum.h | 3 ++-
library/bignum.c | 27 +++++++++++++++++++++++++--
tests/suites/test_suite_mpi.data | 21 ++++++++++++++++++---
4 files changed, 47 insertions(+), 6 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index eebc39e48..c8ec678d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -32,6 +32,8 @@ Bugfix
Hui Dong)
* Fixed potential heap corruption in x509_name allocation
* Fixed single RSA test that failed on Big Endian systems (Closes ticket #54)
+ * mpi_exp_mod() now correctly handles negative base numbers (Closes ticket
+ #52)
Security
* Fixed potential memory corruption on miscrafted client messages (found by
diff --git a/include/polarssl/bignum.h b/include/polarssl/bignum.h
index 898e37daf..ce6ca86c0 100644
--- a/include/polarssl/bignum.h
+++ b/include/polarssl/bignum.h
@@ -543,7 +543,8 @@ int mpi_mod_int( t_uint *r, const mpi *A, t_sint b );
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
- * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even or if
+ * E is negative
*
* \note _RR is used to avoid re-computing R*R mod N across
* multiple calls, which speeds up things a bit. It can
diff --git a/library/bignum.c b/library/bignum.c
index 5c0d6220d..e73a810b3 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -1387,11 +1387,28 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
size_t i, j, nblimbs;
size_t bufsize, nbits;
t_uint ei, mm, state;
- mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ];
+ mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
+ int neg;
if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+ if( mpi_cmp_int( E, 0 ) < 0 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ /*
+ * Compensate for negative A (and correct at the end)
+ */
+ neg = ( A->s == -1 );
+
+ mpi_init( &Apos );
+ if( neg )
+ {
+ MPI_CHK( mpi_copy( &Apos, A ) );
+ Apos.s = 1;
+ A = &Apos;
+ }
+
/*
* Init temps and window size
*/
@@ -1547,12 +1564,18 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
*/
mpi_montred( X, N, mm, &T );
+ if( neg )
+ {
+ X->s = -1;
+ mpi_add_mpi( X, N, X );
+ }
+
cleanup:
for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
mpi_free( &W[i] );
- mpi_free( &W[1] ); mpi_free( &T );
+ mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
if( _RR == NULL )
mpi_free( &RR );
diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data
index 089c7477e..192edb013 100644
--- a/tests/suites/test_suite_mpi.data
+++ b/tests/suites/test_suite_mpi.data
@@ -408,15 +408,30 @@ mpi_mod_int:10:"1000":2:0:0
Base test mpi_exp_mod #1
mpi_exp_mod:10:"23":10:"13":10:"29":10:"":10:"24":0
-Base test mpi_exp_mod #2
+Base test mpi_exp_mod #2 (Even N)
mpi_exp_mod:10:"23":10:"13":10:"30":10:"":10:"0":POLARSSL_ERR_MPI_BAD_INPUT_DATA
-Base test mpi_exp_mod #3
-mpi_exp_mod:10:"23":10:"13":10:"-29":10:"":10:"24":POLARSSL_ERR_MPI_BAD_INPUT_DATA
+Base test mpi_exp_mod #3 (Negative N)
+mpi_exp_mod:10:"23":10:"13":10:"-29":10:"":10:"0":POLARSSL_ERR_MPI_BAD_INPUT_DATA
+
+Base test mpi_exp_mod #4 (Negative base)
+mpi_exp_mod:10:"-23":10:"13":10:"29":10:"":10:"5":0
+
+Base test mpi_exp_mod #5 (Negative exponent)
+mpi_exp_mod:10:"23":10:"-13":10:"29":10:"":10:"0":POLARSSL_ERR_MPI_BAD_INPUT_DATA
+
+Base test mpi_exp_mod #7 (Negative base + exponent)
+mpi_exp_mod:10:"-23":10:"-13":10:"29":10:"":10:"0":POLARSSL_ERR_MPI_BAD_INPUT_DATA
Test mpi_exp_mod #1
mpi_exp_mod:10:"433019240910377478217373572959560109819648647016096560523769010881172869083338285573756574557395862965095016483867813043663981946477698466501451832407592327356331263124555137732393938242285782144928753919588632679050799198937132922145084847":10:"5781538327977828897150909166778407659250458379645823062042492461576758526757490910073628008613977550546382774775570888130029763571528699574717583228939535960234464230882573615930384979100379102915657483866755371559811718767760594919456971354184113721":10:"583137007797276923956891216216022144052044091311388601652961409557516421612874571554415606746479105795833145583959622117418531166391184939066520869800857530421873250114773204354963864729386957427276448683092491947566992077136553066273207777134303397724679138833126700957":10:"":10:"114597449276684355144920670007147953232659436380163461553186940113929777196018164149703566472936578890991049344459204199888254907113495794730452699842273939581048142004834330369483813876618772578869083248061616444392091693787039636316845512292127097865026290173004860736":0
+Test mpi_exp_mod (Negative base)
+mpi_exp_mod:10:"-10000000000":10:"10000000000":10:"99999":10:"":10:"99998":0
+
+Test mpi_exp_mod (Negative base)
+mpi_exp_mod:16:"-9f13012cd92aa72fb86ac8879d2fde4f7fd661aaae43a00971f081cc60ca277059d5c37e89652e2af2585d281d66ef6a9d38a117e9608e9e7574cd142dc55278838a2161dd56db9470d4c1da2d5df15a908ee2eb886aaa890f23be16de59386663a12f1afbb325431a3e835e3fd89b98b96a6f77382f458ef9a37e1f84a03045c8676ab55291a94c2228ea15448ee96b626b998":16:"40a54d1b9e86789f06d9607fb158672d64867665c73ee9abb545fc7a785634b354c7bae5b962ce8040cf45f2c1f3d3659b2ee5ede17534c8fc2ec85c815e8df1fe7048d12c90ee31b88a68a081f17f0d8ce5f4030521e9400083bcea73a429031d4ca7949c2000d597088e0c39a6014d8bf962b73bb2e8083bd0390a4e00b9b3":16:"eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3":16:"":16:"21acc7199e1b90f9b4844ffe12c19f00ec548c5d32b21c647d48b6015d8eb9ec9db05b4f3d44db4227a2b5659c1a7cceb9d5fa8fa60376047953ce7397d90aaeb7465e14e820734f84aa52ad0fc66701bcbb991d57715806a11531268e1e83dd48288c72b424a6287e9ce4e5cc4db0dd67614aecc23b0124a5776d36e5c89483":0
+
Base test GCD #1
mpi_gcd:10:"693":10:"609":10:"21"