forked from I2P_Developers/i2p.i2p
* CPUID:
- Add hasAES() - Fix bugs in unused hasSSE3(), hasSSE41(), hasSSE42() * Crypto: Use JVM AES when faster * SystemVersion: Add isJava7() and isX86()
This commit is contained in:
@ -2,9 +2,10 @@ package freenet.support.CPUInformation;
|
||||
|
||||
/**
|
||||
* Moved out of CPUID.java
|
||||
* Ref: http://en.wikipedia.org/wiki/CPUID
|
||||
* @since 0.8.7
|
||||
*/
|
||||
abstract class CPUIDCPUInfo
|
||||
abstract class CPUIDCPUInfo implements CPUInfo
|
||||
{
|
||||
protected static boolean isX64 = false;
|
||||
|
||||
@ -12,33 +13,48 @@ abstract class CPUIDCPUInfo
|
||||
{
|
||||
return CPUID.getCPUVendorID();
|
||||
}
|
||||
|
||||
public boolean hasMMX()
|
||||
{
|
||||
return (CPUID.getEDXCPUFlags() & 0x800000) != 0; //EDX Bit 23
|
||||
}
|
||||
|
||||
public boolean hasSSE(){
|
||||
return (CPUID.getEDXCPUFlags() & 0x2000000) != 0; //EDX Bit 25
|
||||
}
|
||||
|
||||
public boolean hasSSE2()
|
||||
{
|
||||
return (CPUID.getEDXCPUFlags() & 0x4000000) != 0; //EDX Bit 26
|
||||
}
|
||||
|
||||
public boolean hasSSE3()
|
||||
{
|
||||
return (CPUID.getEDXCPUFlags() & 0x1) != 0; //ECX Bit 0
|
||||
return (CPUID.getECXCPUFlags() & 0x1) != 0; //ECX Bit 0
|
||||
}
|
||||
|
||||
public boolean hasSSE41()
|
||||
{
|
||||
return (CPUID.getEDXCPUFlags() & 0x80000) != 0; //ECX Bit 19
|
||||
return (CPUID.getECXCPUFlags() & 0x80000) != 0; //ECX Bit 19
|
||||
}
|
||||
|
||||
public boolean hasSSE42()
|
||||
{
|
||||
return (CPUID.getEDXCPUFlags() & 0x100000) != 0; //ECX Bit 20
|
||||
return (CPUID.getECXCPUFlags() & 0x100000) != 0; //ECX Bit 20
|
||||
}
|
||||
|
||||
public boolean hasSSE4A()
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
@ -62,4 +62,10 @@ public interface CPUInfo
|
||||
* @return true iff the CPU support the SSE4A instruction set.
|
||||
*/
|
||||
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;
|
||||
import java.security.InvalidKeyException;
|
||||
|
||||
// for using system version
|
||||
//import java.security.GeneralSecurityException;
|
||||
//import javax.crypto.Cipher;
|
||||
//import javax.crypto.spec.IvParameterSpec;
|
||||
//import javax.crypto.spec.SecretKeySpec;
|
||||
import java.security.GeneralSecurityException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
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.data.DataHelper;
|
||||
import net.i2p.data.SessionKey;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.SimpleByteCache;
|
||||
import net.i2p.util.SystemVersion;
|
||||
|
||||
/**
|
||||
* Wrapper for AES cypher operation using Cryptix's Rijndael implementation. Implements
|
||||
@ -37,28 +42,47 @@ public class CryptixAESEngine extends AESEngine {
|
||||
// keys are now cached in the SessionKey objects
|
||||
//private CryptixAESKeyCache _cache;
|
||||
|
||||
/**** see comments for main() below
|
||||
private static final boolean USE_SYSTEM_AES;
|
||||
static {
|
||||
boolean systemOK = false;
|
||||
try {
|
||||
systemOK = Cipher.getMaxAllowedKeyLength("AES") >= 256;
|
||||
} catch (GeneralSecurityException gse) {
|
||||
// a NoSuchAlgorithmException
|
||||
} catch (NoSuchMethodError nsme) {
|
||||
// JamVM, gij
|
||||
if (hasAESNI()) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||
SecretKeySpec key = new SecretKeySpec(new byte[32], "AES");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key);
|
||||
systemOK = true;
|
||||
systemOK = Cipher.getMaxAllowedKeyLength("AES") >= 256;
|
||||
} 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;
|
||||
//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) {
|
||||
@ -104,7 +128,6 @@ public class CryptixAESEngine extends AESEngine {
|
||||
return;
|
||||
}
|
||||
|
||||
/****
|
||||
if (USE_SYSTEM_AES) {
|
||||
try {
|
||||
SecretKeySpec key = new SecretKeySpec(sessionKey.getData(), "AES");
|
||||
@ -118,7 +141,6 @@ public class CryptixAESEngine extends AESEngine {
|
||||
_log.warn("Java encrypt fail", gse);
|
||||
}
|
||||
}
|
||||
****/
|
||||
|
||||
int numblock = length / 16;
|
||||
|
||||
@ -159,7 +181,6 @@ public class CryptixAESEngine extends AESEngine {
|
||||
return ;
|
||||
}
|
||||
|
||||
/****
|
||||
if (USE_SYSTEM_AES) {
|
||||
try {
|
||||
SecretKeySpec key = new SecretKeySpec(sessionKey.getData(), "AES");
|
||||
@ -173,7 +194,6 @@ public class CryptixAESEngine extends AESEngine {
|
||||
_log.warn("Java decrypt fail", gse);
|
||||
}
|
||||
}
|
||||
****/
|
||||
|
||||
int numblock = length / 16;
|
||||
if (length % 16 != 0) {
|
||||
@ -261,8 +281,8 @@ public class CryptixAESEngine extends AESEngine {
|
||||
}
|
||||
|
||||
/******
|
||||
private static final int MATCH_RUNS = 5000;
|
||||
private static final int TIMING_RUNS = 10000;
|
||||
private static final int MATCH_RUNS = 11000;
|
||||
private static final int TIMING_RUNS = 100000;
|
||||
******/
|
||||
|
||||
/**
|
||||
@ -282,6 +302,15 @@ public class CryptixAESEngine extends AESEngine {
|
||||
* jrockit 9780 n/a
|
||||
*</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[]) {
|
||||
|
@ -181,8 +181,7 @@ public class NativeBigInteger extends BigInteger {
|
||||
*/
|
||||
private static final boolean _is64 = SystemVersion.is64Bit();
|
||||
|
||||
private static final boolean _isX86 = System.getProperty("os.arch").contains("86") ||
|
||||
System.getProperty("os.arch").equals("amd64");
|
||||
private static final boolean _isX86 = SystemVersion.isX86();
|
||||
|
||||
private static final boolean _isArm = SystemVersion.isARM();
|
||||
|
||||
|
@ -16,6 +16,8 @@ public abstract class SystemVersion {
|
||||
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 _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 _isApache;
|
||||
private static final boolean _isGNU;
|
||||
@ -23,6 +25,7 @@ public abstract class SystemVersion {
|
||||
private static final boolean _hasWrapper = System.getProperty("wrapper.version") != null;
|
||||
|
||||
private static final boolean _oneDotSix;
|
||||
private static final boolean _oneDotSeven;
|
||||
private static final int _androidSDK;
|
||||
|
||||
static {
|
||||
@ -56,8 +59,10 @@ public abstract class SystemVersion {
|
||||
|
||||
if (_isAndroid) {
|
||||
_oneDotSix = _androidSDK >= 9;
|
||||
_oneDotSeven = _androidSDK >= 19;
|
||||
} else {
|
||||
_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 {
|
||||
return _isArm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.14
|
||||
*/
|
||||
public static boolean isX86() {
|
||||
return _isX86;
|
||||
}
|
||||
|
||||
/**
|
||||
* Better than (new VersionComparator()).compare(System.getProperty("java.version"), "1.6") >= 0
|
||||
* as it handles Android also, where java.version = "0".
|
||||
@ -104,6 +116,17 @@ public abstract class SystemVersion {
|
||||
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.
|
||||
* http://stackoverflow.com/questions/807263/how-do-i-detect-which-kind-of-jre-is-installed-32bit-vs-64bit
|
||||
|
Reference in New Issue
Block a user