/** * TLS-Attacker - A Modular Penetration Testing Framework for TLS * * Copyright 2014-2016 Ruhr University Bochum / Hackmanit GmbH * * Licensed under Apache License 2.0 * http://www.apache.org/licenses/LICENSE-2.0 */ package de.rub.nds.tlsattacker.tls.crypto.ec; import java.math.BigInteger; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * * @author Juraj Somorovsky - juraj.somorovsky@rub.de */ public class ECComputer { static Logger LOGGER = LogManager.getLogger(ECComputer.class); private static BigInteger TWO = BigInteger.valueOf(2); private static BigInteger THREE = BigInteger.valueOf(3); /** * curve with its parameters */ private Curve curve; /** * secret we use to multiply a given point */ private BigInteger secret; public ECComputer() { } public ECComputer(Curve c, BigInteger s) { this.curve = c; this.secret = s; } /** * Doubles point, does not check for infinity * * @param p * @return * @throws DivisionException * exception occurs if y coordinate is zero */ public Point dbl(Point p) throws DivisionException { BigInteger x = p.getX(); BigInteger y = p.getY(); if (y.equals(BigInteger.ZERO)) { throw new DivisionException("y was equal to zero"); } BigInteger l1 = ((THREE.multiply(x.pow(2))).add(curve.getA())); BigInteger l2 = TWO.multiply(y).modInverse(curve.getP()); BigInteger l = l1.multiply(l2).mod(curve.getP()); BigInteger xr = l.pow(2).subtract(TWO.multiply(x)).mod(curve.getP()); BigInteger yr = l.multiply(x.subtract(xr)).subtract(y).mod(curve.getP()); Point ret = new Point(xr, yr); return ret; } /** * Doubles point, checks for infinity if checkInfinity set * * @param p * @param checkInfinity * @return * @throws DivisionException */ public Point dbl(Point p, boolean checkInfinity) throws DivisionException { if (checkInfinity) { if (p.isInfinity()) { return p; } if (p.getY().signum() == 0) { return new Point(true); } } return dbl(p); } /** * Provides point addition, without infinity check * * @param p * @param q * @return * @throws DivisionException * exception thrown if xq=xp, since then we divide with zero */ public Point add(Point p, Point q) throws DivisionException { BigInteger xp = p.getX(); BigInteger yp = p.getY(); BigInteger xq = q.getX(); BigInteger yq = q.getY(); if (xq.subtract(xp).mod(curve.getP()).equals(BigInteger.ZERO)) { throw new DivisionException("xq was equal to xp (mod p)"); } BigInteger l = ((yq.subtract(yp)).multiply((xq.subtract(xp)).modInverse(curve.getP()))).mod(curve.getP()); BigInteger xr = l.pow(2).subtract(xp).subtract(xq).mod(curve.getP()); BigInteger yr = (l.multiply(xp.subtract(xr))).subtract(yp).mod(curve.getP()); Point ret = new Point(xr, yr); return ret; } /** * Provides point addition, checks for infinity in case checkInfinity is set * * @param p * @param q * @param checkInfinity * @return * @throws DivisionException */ public Point add(Point p, Point q, boolean checkInfinity) throws DivisionException { if (checkInfinity) { if (p == null || p.isInfinity()) { return q; } if (q == null || q.isInfinity()) { return p; } if (p.getX().equals(q.getX())) { if (p.getY().equals(q.getY())) { return dbl(p, true); } else { return new Point(true); } } } return add(p, q); } /** * Simple point multiplication * * @param p * @param checkInfinity * @return * @throws DivisionException */ public Point mul(Point p, boolean checkInfinity) throws DivisionException { Point r = new Point(p.getX(), p.getY()); for (int i = 1; i < secret.bitLength(); i++) { try { r = dbl(r, checkInfinity); if (secret.testBit(secret.bitLength() - 1 - i)) { r = add(r, p, checkInfinity); } } catch (DivisionException e) { throw new DivisionException(e.getLocalizedMessage(), i); } } return r; } /** * * @param p * @return * @throws DivisionException */ public Point mul(Point p) throws DivisionException { return mul(p, true); } public Curve getCurve() { return curve; } public void setCurve(Curve curve) { this.curve = curve; } public BigInteger getSecret() { return secret; } public void setSecret(BigInteger secret) { this.secret = secret; } }