I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit 8d9790fd authored by zzz's avatar zzz
Browse files

* CPUID:

   - Add hasAES()
   - Fix bugs in unused hasSSE3(), hasSSE41(), hasSSE42()
 * Crypto: Use JVM AES when faster
 * SystemVersion: Add isJava7() and isX86()
parent cd91a6b2
No related branches found
No related tags found
No related merge requests found
...@@ -2,9 +2,10 @@ package freenet.support.CPUInformation; ...@@ -2,9 +2,10 @@ package freenet.support.CPUInformation;
/** /**
* Moved out of CPUID.java * Moved out of CPUID.java
* Ref: http://en.wikipedia.org/wiki/CPUID
* @since 0.8.7 * @since 0.8.7
*/ */
abstract class CPUIDCPUInfo abstract class CPUIDCPUInfo implements CPUInfo
{ {
protected static boolean isX64 = false; protected static boolean isX64 = false;
...@@ -12,33 +13,48 @@ abstract class CPUIDCPUInfo ...@@ -12,33 +13,48 @@ abstract class CPUIDCPUInfo
{ {
return CPUID.getCPUVendorID(); return CPUID.getCPUVendorID();
} }
public boolean hasMMX() public boolean hasMMX()
{ {
return (CPUID.getEDXCPUFlags() & 0x800000) != 0; //EDX Bit 23 return (CPUID.getEDXCPUFlags() & 0x800000) != 0; //EDX Bit 23
} }
public boolean hasSSE(){ public boolean hasSSE(){
return (CPUID.getEDXCPUFlags() & 0x2000000) != 0; //EDX Bit 25 return (CPUID.getEDXCPUFlags() & 0x2000000) != 0; //EDX Bit 25
} }
public boolean hasSSE2() public boolean hasSSE2()
{ {
return (CPUID.getEDXCPUFlags() & 0x4000000) != 0; //EDX Bit 26 return (CPUID.getEDXCPUFlags() & 0x4000000) != 0; //EDX Bit 26
} }
public boolean hasSSE3() public boolean hasSSE3()
{ {
return (CPUID.getEDXCPUFlags() & 0x1) != 0; //ECX Bit 0 return (CPUID.getECXCPUFlags() & 0x1) != 0; //ECX Bit 0
} }
public boolean hasSSE41() public boolean hasSSE41()
{ {
return (CPUID.getEDXCPUFlags() & 0x80000) != 0; //ECX Bit 19 return (CPUID.getECXCPUFlags() & 0x80000) != 0; //ECX Bit 19
} }
public boolean hasSSE42() public boolean hasSSE42()
{ {
return (CPUID.getEDXCPUFlags() & 0x100000) != 0; //ECX Bit 20 return (CPUID.getECXCPUFlags() & 0x100000) != 0; //ECX Bit 20
} }
public boolean hasSSE4A() public boolean hasSSE4A()
{ {
return (CPUID.getExtendedECXCPUFlags() & 0x40) != 0; //Extended ECX Bit 6 return (CPUID.getExtendedECXCPUFlags() & 0x40) != 0; //Extended ECX Bit 6
} }
/**
* @return true iff the CPU supports the AES-NI instruction set.
* @since 0.9.14
*/
public boolean hasAES() {
return (CPUID.getECXCPUFlags() & 0x2000000) != 0; //ECX Bit 25
}
public abstract boolean hasX64(); public abstract boolean hasX64();
} }
...@@ -62,4 +62,10 @@ public interface CPUInfo ...@@ -62,4 +62,10 @@ public interface CPUInfo
* @return true iff the CPU support the SSE4A instruction set. * @return true iff the CPU support the SSE4A instruction set.
*/ */
public boolean hasSSE4A(); public boolean hasSSE4A();
/**
* @return true iff the CPU supports the AES-NI instruction set.
* @since 0.9.14
*/
public boolean hasAES();
} }
...@@ -12,16 +12,21 @@ package net.i2p.crypto; ...@@ -12,16 +12,21 @@ package net.i2p.crypto;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
// for using system version // for using system version
//import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
//import javax.crypto.Cipher; import javax.crypto.Cipher;
//import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
//import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import freenet.support.CPUInformation.CPUID;
import freenet.support.CPUInformation.CPUInfo;
import freenet.support.CPUInformation.UnknownCPUException;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.data.SessionKey; import net.i2p.data.SessionKey;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.SimpleByteCache; import net.i2p.util.SimpleByteCache;
import net.i2p.util.SystemVersion;
/** /**
* Wrapper for AES cypher operation using Cryptix's Rijndael implementation. Implements * Wrapper for AES cypher operation using Cryptix's Rijndael implementation. Implements
...@@ -37,28 +42,47 @@ public class CryptixAESEngine extends AESEngine { ...@@ -37,28 +42,47 @@ public class CryptixAESEngine extends AESEngine {
// keys are now cached in the SessionKey objects // keys are now cached in the SessionKey objects
//private CryptixAESKeyCache _cache; //private CryptixAESKeyCache _cache;
/**** see comments for main() below
private static final boolean USE_SYSTEM_AES; private static final boolean USE_SYSTEM_AES;
static { static {
boolean systemOK = false; boolean systemOK = false;
try { if (hasAESNI()) {
systemOK = Cipher.getMaxAllowedKeyLength("AES") >= 256;
} catch (GeneralSecurityException gse) {
// a NoSuchAlgorithmException
} catch (NoSuchMethodError nsme) {
// JamVM, gij
try { try {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); systemOK = Cipher.getMaxAllowedKeyLength("AES") >= 256;
SecretKeySpec key = new SecretKeySpec(new byte[32], "AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
systemOK = true;
} catch (GeneralSecurityException gse) { } catch (GeneralSecurityException gse) {
// a NoSuchAlgorithmException
} catch (NoSuchMethodError nsme) {
// JamVM, gij
try {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec key = new SecretKeySpec(new byte[32], "AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
systemOK = true;
} catch (GeneralSecurityException gse) {
}
} }
} }
USE_SYSTEM_AES = systemOK; USE_SYSTEM_AES = systemOK;
//System.out.println("Using system AES? " + systemOK); //System.out.println("Using system AES? " + systemOK);
} }
****/
/**
* Do we have AES-NI support in the processor and JVM?
* Only on 64-bit x86 Java 7 fast JVMs, with AES-NI support.
* See comments in main() below.
* @since 0.9.14
*/
private static boolean hasAESNI() {
if (SystemVersion.isX86() && SystemVersion.is64Bit() && SystemVersion.isJava7() &&
!SystemVersion.isApache() && !SystemVersion.isGNU()) {
try {
return CPUID.getInfo().hasAES();
} catch (UnknownCPUException e) {
return false;
}
} else {
return false;
}
}
/** */ /** */
public CryptixAESEngine(I2PAppContext context) { public CryptixAESEngine(I2PAppContext context) {
...@@ -104,7 +128,6 @@ public class CryptixAESEngine extends AESEngine { ...@@ -104,7 +128,6 @@ public class CryptixAESEngine extends AESEngine {
return; return;
} }
/****
if (USE_SYSTEM_AES) { if (USE_SYSTEM_AES) {
try { try {
SecretKeySpec key = new SecretKeySpec(sessionKey.getData(), "AES"); SecretKeySpec key = new SecretKeySpec(sessionKey.getData(), "AES");
...@@ -118,7 +141,6 @@ public class CryptixAESEngine extends AESEngine { ...@@ -118,7 +141,6 @@ public class CryptixAESEngine extends AESEngine {
_log.warn("Java encrypt fail", gse); _log.warn("Java encrypt fail", gse);
} }
} }
****/
int numblock = length / 16; int numblock = length / 16;
...@@ -159,7 +181,6 @@ public class CryptixAESEngine extends AESEngine { ...@@ -159,7 +181,6 @@ public class CryptixAESEngine extends AESEngine {
return ; return ;
} }
/****
if (USE_SYSTEM_AES) { if (USE_SYSTEM_AES) {
try { try {
SecretKeySpec key = new SecretKeySpec(sessionKey.getData(), "AES"); SecretKeySpec key = new SecretKeySpec(sessionKey.getData(), "AES");
...@@ -173,7 +194,6 @@ public class CryptixAESEngine extends AESEngine { ...@@ -173,7 +194,6 @@ public class CryptixAESEngine extends AESEngine {
_log.warn("Java decrypt fail", gse); _log.warn("Java decrypt fail", gse);
} }
} }
****/
int numblock = length / 16; int numblock = length / 16;
if (length % 16 != 0) { if (length % 16 != 0) {
...@@ -261,8 +281,8 @@ public class CryptixAESEngine extends AESEngine { ...@@ -261,8 +281,8 @@ public class CryptixAESEngine extends AESEngine {
} }
/****** /******
private static final int MATCH_RUNS = 5000; private static final int MATCH_RUNS = 11000;
private static final int TIMING_RUNS = 10000; private static final int TIMING_RUNS = 100000;
******/ ******/
/** /**
...@@ -282,6 +302,15 @@ public class CryptixAESEngine extends AESEngine { ...@@ -282,6 +302,15 @@ public class CryptixAESEngine extends AESEngine {
* jrockit 9780 n/a * jrockit 9780 n/a
*</pre> *</pre>
* *
* Speed ups with AES-NI:
* May 2014 AMD Hexcore 100K runs:
*<pre>
* JVM Cryptix (ms) System (ms)
* OpenJDK 6 3314 5030
* OpenJDK 7 3285 2476
*</pre>
*
*
*/ */
/******* /*******
public static void main(String args[]) { public static void main(String args[]) {
......
...@@ -181,8 +181,7 @@ public class NativeBigInteger extends BigInteger { ...@@ -181,8 +181,7 @@ public class NativeBigInteger extends BigInteger {
*/ */
private static final boolean _is64 = SystemVersion.is64Bit(); private static final boolean _is64 = SystemVersion.is64Bit();
private static final boolean _isX86 = System.getProperty("os.arch").contains("86") || private static final boolean _isX86 = SystemVersion.isX86();
System.getProperty("os.arch").equals("amd64");
private static final boolean _isArm = SystemVersion.isARM(); private static final boolean _isArm = SystemVersion.isARM();
......
...@@ -16,6 +16,8 @@ public abstract class SystemVersion { ...@@ -16,6 +16,8 @@ public abstract class SystemVersion {
private static final boolean _isWin = System.getProperty("os.name").startsWith("Win"); private static final boolean _isWin = System.getProperty("os.name").startsWith("Win");
private static final boolean _isMac = System.getProperty("os.name").startsWith("Mac"); private static final boolean _isMac = System.getProperty("os.name").startsWith("Mac");
private static final boolean _isArm = System.getProperty("os.arch").startsWith("arm"); private static final boolean _isArm = System.getProperty("os.arch").startsWith("arm");
private static final boolean _isX86 = System.getProperty("os.arch").contains("86") ||
System.getProperty("os.arch").equals("amd64");
private static final boolean _isAndroid; private static final boolean _isAndroid;
private static final boolean _isApache; private static final boolean _isApache;
private static final boolean _isGNU; private static final boolean _isGNU;
...@@ -23,6 +25,7 @@ public abstract class SystemVersion { ...@@ -23,6 +25,7 @@ public abstract class SystemVersion {
private static final boolean _hasWrapper = System.getProperty("wrapper.version") != null; private static final boolean _hasWrapper = System.getProperty("wrapper.version") != null;
private static final boolean _oneDotSix; private static final boolean _oneDotSix;
private static final boolean _oneDotSeven;
private static final int _androidSDK; private static final int _androidSDK;
static { static {
...@@ -56,8 +59,10 @@ public abstract class SystemVersion { ...@@ -56,8 +59,10 @@ public abstract class SystemVersion {
if (_isAndroid) { if (_isAndroid) {
_oneDotSix = _androidSDK >= 9; _oneDotSix = _androidSDK >= 9;
_oneDotSeven = _androidSDK >= 19;
} else { } else {
_oneDotSix = VersionComparator.comp(System.getProperty("java.version"), "1.6") >= 0; _oneDotSix = VersionComparator.comp(System.getProperty("java.version"), "1.6") >= 0;
_oneDotSeven = VersionComparator.comp(System.getProperty("java.version"), "1.7") >= 0;
} }
} }
...@@ -94,6 +99,13 @@ public abstract class SystemVersion { ...@@ -94,6 +99,13 @@ public abstract class SystemVersion {
return _isArm; return _isArm;
} }
/**
* @since 0.9.14
*/
public static boolean isX86() {
return _isX86;
}
/** /**
* Better than (new VersionComparator()).compare(System.getProperty("java.version"), "1.6") >= 0 * Better than (new VersionComparator()).compare(System.getProperty("java.version"), "1.6") >= 0
* as it handles Android also, where java.version = "0". * as it handles Android also, where java.version = "0".
...@@ -104,6 +116,17 @@ public abstract class SystemVersion { ...@@ -104,6 +116,17 @@ public abstract class SystemVersion {
return _oneDotSix; return _oneDotSix;
} }
/**
* Better than (new VersionComparator()).compare(System.getProperty("java.version"), "1.7") >= 0
* as it handles Android also, where java.version = "0".
*
* @return true if Java 1.7 or higher, or Android API 19 or higher
* @since 0.9.14
*/
public static boolean isJava7() {
return _oneDotSeven;
}
/** /**
* This isn't always correct. * This isn't always correct.
* http://stackoverflow.com/questions/807263/how-do-i-detect-which-kind-of-jre-is-installed-32bit-vs-64bit * http://stackoverflow.com/questions/807263/how-do-i-detect-which-kind-of-jre-is-installed-32bit-vs-64bit
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment