|
|
@@ -0,0 +1,175 @@ |
|
|
package org.bouncycastle.math.ec.custom.sec.test; |
|
|
|
|
|
import java.math.BigInteger; |
|
|
import java.security.SecureRandom; |
|
|
|
|
|
import org.bouncycastle.asn1.sec.SECObjectIdentifiers; |
|
|
import org.bouncycastle.asn1.x9.X9ECParameters; |
|
|
import org.bouncycastle.crypto.ec.CustomNamedCurves; |
|
|
import org.bouncycastle.math.ec.ECFieldElement; |
|
|
import org.bouncycastle.math.raw.Nat256; |
|
|
|
|
|
import junit.framework.TestCase; |
|
|
|
|
|
public class SecP256R1FieldTest extends TestCase |
|
|
{ |
|
|
private static final SecureRandom RANDOM = new SecureRandom(); |
|
|
|
|
|
private static final X9ECParameters DP = CustomNamedCurves |
|
|
.getByOID(SECObjectIdentifiers.secp256r1); |
|
|
private static final BigInteger Q = DP.getCurve().getField().getCharacteristic(); |
|
|
|
|
|
public void testMultiply1() |
|
|
{ |
|
|
int COUNT = 1000; |
|
|
|
|
|
for (int i = 0; i < COUNT; ++i) |
|
|
{ |
|
|
ECFieldElement x = generateMultiplyInput_Random(); |
|
|
ECFieldElement y = generateMultiplyInput_Random(); |
|
|
|
|
|
BigInteger X = x.toBigInteger(), Y = y.toBigInteger(); |
|
|
BigInteger R = X.multiply(Y).mod(Q); |
|
|
|
|
|
ECFieldElement z = x.multiply(y); |
|
|
BigInteger Z = z.toBigInteger(); |
|
|
|
|
|
assertEquals(R, Z); |
|
|
} |
|
|
} |
|
|
|
|
|
public void testMultiply2() |
|
|
{ |
|
|
int COUNT = 100; |
|
|
ECFieldElement[] inputs = new ECFieldElement[COUNT]; |
|
|
BigInteger[] INPUTS = new BigInteger[COUNT]; |
|
|
|
|
|
for (int i = 0; i < inputs.length; ++i) |
|
|
{ |
|
|
inputs[i] = generateMultiplyInput_Random(); |
|
|
INPUTS[i] = inputs[i].toBigInteger(); |
|
|
} |
|
|
|
|
|
for (int j = 0; j < inputs.length; ++j) |
|
|
{ |
|
|
for (int k = 0; k < inputs.length; ++k) |
|
|
{ |
|
|
BigInteger R = INPUTS[j].multiply(INPUTS[k]).mod(Q); |
|
|
|
|
|
ECFieldElement z = inputs[j].multiply(inputs[k]); |
|
|
BigInteger Z = z.toBigInteger(); |
|
|
|
|
|
assertEquals(R, Z); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
public void testSquare() |
|
|
{ |
|
|
int COUNT = 1000; |
|
|
|
|
|
for (int i = 0; i < COUNT; ++i) |
|
|
{ |
|
|
ECFieldElement x = generateMultiplyInput_Random(); |
|
|
|
|
|
BigInteger X = x.toBigInteger(); |
|
|
BigInteger R = X.multiply(X).mod(Q); |
|
|
|
|
|
ECFieldElement z = x.square(); |
|
|
BigInteger Z = z.toBigInteger(); |
|
|
|
|
|
assertEquals(R, Z); |
|
|
} |
|
|
} |
|
|
|
|
|
/** |
|
|
* Test multiplication with specifically selected values that triggered a bug in the modular |
|
|
* reduction in OpenSSL (last affected version 0.9.8g). |
|
|
* |
|
|
* See "Practical realisation and elimination of an ECC-related software bug attack", B. B. |
|
|
* Brumley, M. Barbarosa, D. Page, F. Vercauteren. |
|
|
*/ |
|
|
public void testMultiply_OpenSSLBug() |
|
|
{ |
|
|
int COUNT = 100; |
|
|
|
|
|
for (int i = 0; i < COUNT; ++i) |
|
|
{ |
|
|
ECFieldElement x = generateMultiplyInputA_OpenSSLBug(); |
|
|
ECFieldElement y = generateMultiplyInputB_OpenSSLBug(); |
|
|
|
|
|
BigInteger X = x.toBigInteger(), Y = y.toBigInteger(); |
|
|
BigInteger R = X.multiply(Y).mod(Q); |
|
|
|
|
|
ECFieldElement z = x.multiply(y); |
|
|
BigInteger Z = z.toBigInteger(); |
|
|
|
|
|
assertEquals(R, Z); |
|
|
} |
|
|
} |
|
|
|
|
|
/** |
|
|
* Test squaring with specifically selected values that triggered a bug in the modular reduction |
|
|
* in OpenSSL (last affected version 0.9.8g). |
|
|
* |
|
|
* See "Practical realisation and elimination of an ECC-related software bug attack", B. B. |
|
|
* Brumley, M. Barbarosa, D. Page, F. Vercauteren. |
|
|
*/ |
|
|
public void testSquare_OpenSSLBug() |
|
|
{ |
|
|
int COUNT = 100; |
|
|
|
|
|
for (int i = 0; i < COUNT; ++i) |
|
|
{ |
|
|
ECFieldElement x = generateSquareInput_OpenSSLBug(); |
|
|
|
|
|
BigInteger X = x.toBigInteger(); |
|
|
BigInteger R = X.multiply(X).mod(Q); |
|
|
|
|
|
ECFieldElement z = x.square(); |
|
|
BigInteger Z = z.toBigInteger(); |
|
|
|
|
|
assertEquals(R, Z); |
|
|
} |
|
|
} |
|
|
|
|
|
private ECFieldElement fe(BigInteger x) |
|
|
{ |
|
|
return DP.getCurve().fromBigInteger(x); |
|
|
} |
|
|
|
|
|
private ECFieldElement generateMultiplyInput_Random() |
|
|
{ |
|
|
return fe(new BigInteger(DP.getCurve().getFieldSize() + 32, RANDOM).mod(Q)); |
|
|
} |
|
|
|
|
|
private ECFieldElement generateMultiplyInputA_OpenSSLBug() |
|
|
{ |
|
|
int[] x = Nat256.create(); |
|
|
x[0] = RANDOM.nextInt() >>> 1; |
|
|
x[4] = 3; |
|
|
x[7] = -1; |
|
|
|
|
|
return fe(Nat256.toBigInteger(x)); |
|
|
} |
|
|
|
|
|
private ECFieldElement generateMultiplyInputB_OpenSSLBug() |
|
|
{ |
|
|
int[] x = Nat256.create(); |
|
|
x[0] = RANDOM.nextInt() >>> 1; |
|
|
x[3] = 1; |
|
|
x[7] = -1; |
|
|
|
|
|
return fe(Nat256.toBigInteger(x)); |
|
|
} |
|
|
|
|
|
private ECFieldElement generateSquareInput_OpenSSLBug() |
|
|
{ |
|
|
int[] x = Nat256.create(); |
|
|
x[0] = RANDOM.nextInt() >>> 1; |
|
|
x[4] = 2; |
|
|
x[7] = -1; |
|
|
|
|
|
return fe(Nat256.toBigInteger(x)); |
|
|
} |
|
|
} |