BouncyCastle in Android devices

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

BouncyCastle in Android devices

Abraham Macias Paredes
Hi everybody,
 I'm programming an Android software that sends and receive lots of data from the server (and I mean LOTS of data). So I used the default SSL implementation of Android (usualy OpenSSL) but the communication was really slow (about 75% of the CPU consumption was due to SSL).

So I tried other options, and I used BouncyCastle and the CPU consumption was about 80%, but that is not the important thing. The important thing is that using a 100% Java implementation I could profile it and discover that the slow part was the AES cipher.

After further investigation I discovered that most of modern CPUs have implemented instructions to accelerate AES cipher, and OpenSSL was supposed to use that hardware acceleration but clearly that is not the case (a 75% of CPU consumption in OpenSSL is clearly not hardware accelerated). But the JVM implementation of javax.crypto.Cipher is also supposed to be hardware accelerated.

So I made a small test and compared Bouncy Castle AES cipher and javax.crypto.Cipher and the difference is incredible (at least in my Xiaomi phone with a Mediatek Helio CPU). By using javax.crypto.Cipher the CPU consumption of SSL is around 5%. In the server side the cipher that I'm using is TLSv1.0 ECDHE-RSA-AES128-SHA.

 Testing 359 ciphers via OpenSSL plus sockets against the server, ordered by encryption strength

Hexcode  Cipher Suite Name (OpenSSL)       KeyExch.   Encryption  Bits     Cipher Suite Name (RFC)
-----------------------------------------------------------------------------------------------------------------------------
 xc014   ECDHE-RSA-AES256-SHA              ECDH 521   AES         256      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA                
 x35     AES256-SHA                        RSA        AES         256      TLS_RSA_WITH_AES_256_CBC_SHA                      
 xc013   ECDHE-RSA-AES128-SHA              ECDH 521   AES         128      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA                
 x2f     AES128-SHA                        RSA        AES         128      TLS_RSA_WITH_AES_128_CBC_SHA                      


 Running client simulations via sockets

 Android 2.3.7                TLSv1.0 AES128-SHA
 Android 4.1.1                TLSv1.0 ECDHE-RSA-AES256-SHA, 521 bit ECDH (P-521)
 Android 4.3                  TLSv1.0 ECDHE-RSA-AES256-SHA, 521 bit ECDH (P-521)
 Android 4.4.2                TLSv1.0 ECDHE-RSA-AES256-SHA, 521 bit ECDH (P-521)
 Android 5.0.0                TLSv1.0 ECDHE-RSA-AES256-SHA, 521 bit ECDH (P-521)
 Android 6.0                  TLSv1.0 ECDHE-RSA-AES256-SHA, 256 bit ECDH (P-256)
 Android 7.0                  TLSv1.0 ECDHE-RSA-AES128-SHA, 253 bit ECDH (X25519)
 Chrome 51 Win 7              TLSv1.0 ECDHE-RSA-AES128-SHA, 253 bit ECDH (X25519)
 Chrome 57 Win 7              TLSv1.0 ECDHE-RSA-AES128-SHA, 253 bit ECDH (X25519)
 Firefox 49 Win 7             TLSv1.0 ECDHE-RSA-AES128-SHA, 256 bit ECDH (P-256)
 Firefox 53 Win 7             TLSv1.0 ECDHE-RSA-AES128-SHA, 253 bit ECDH (X25519)
 IE 6 XP                      No connection
 IE 7 Vista                   TLSv1.0 AES128-SHA
 IE 8 XP                      No connection
 IE 8 Win 7                   TLSv1.0 AES128-SHA
 IE 11 Win 7                  TLSv1.0 ECDHE-RSA-AES256-SHA, 256 bit ECDH (P-256)
 IE 11 Win 8.1                TLSv1.0 ECDHE-RSA-AES256-SHA, 256 bit ECDH (P-256)
 IE 11 Win Phone 8.1 Update   TLSv1.0 ECDHE-RSA-AES256-SHA, 256 bit ECDH (P-256)
 IE 11 Win 10                 TLSv1.0 ECDHE-RSA-AES256-SHA, 256 bit ECDH (P-256)
 Edge 13 Win 10               TLSv1.0 ECDHE-RSA-AES256-SHA, 256 bit ECDH (P-256)
 Edge 13 Win Phone 10         TLSv1.0 ECDHE-RSA-AES256-SHA, 256 bit ECDH (P-256)
 Opera 17 Win 7               TLSv1.0 ECDHE-RSA-AES256-SHA, 256 bit ECDH (P-256)
 Safari 5.1.9 OS X 10.6.8     TLSv1.0 ECDHE-RSA-AES128-SHA, 256 bit ECDH (P-256)
 Safari 7 iOS 7.1             TLSv1.0 ECDHE-RSA-AES256-SHA, 256 bit ECDH (P-256)
 Safari 9 OS X 10.11          TLSv1.0 ECDHE-RSA-AES256-SHA, 256 bit ECDH (P-256)
 Safari 10 OS X 10.12         TLSv1.0 ECDHE-RSA-AES256-SHA, 256 bit ECDH (P-256)
 Apple ATS 9 iOS 9            No connection
 Tor 17.0.9 Win 7             TLSv1.0 ECDHE-RSA-AES256-SHA, 256 bit ECDH (P-256)
 Java 6u45                    TLSv1.0 AES128-SHA
 Java 7u25                    TLSv1.0 ECDHE-RSA-AES128-SHA, 256 bit ECDH (P-256)
 Java 8u31                    TLSv1.0 ECDHE-RSA-AES128-SHA, 256 bit ECDH (P-256)
 OpenSSL 1.0.1l               TLSv1.0 ECDHE-RSA-AES256-SHA, 521 bit ECDH (P-521)
 OpenSSL 1.0.2e               TLSv1.0 ECDHE-RSA-AES256-SHA, 256 bit ECDH (P-256)




Attached to this email is the AESEngineJDK class that I created and I want to share it with you and the community. Maybe you could include it in BouncyCastle. I realize that is not the philosofy of BouncyCastle that aims to be a 100% Java code implementation, but it may be useful for small devices.

To use it, I overrided certaint methods of DefaultTlsCipherFactory:

public class JvmTlsCipherFactory extends DefaultTlsCipherFactory {


@Override
protected TlsBlockCipher createAESCipher(TlsContext context, int cipherKeySize, int macAlgorithm)
throws IOException
{
return new TlsBlockCipher(context, createAESBlockCipher(cipherKeySize),
createAESBlockCipher(cipherKeySize), createHMACDigest(macAlgorithm),
createHMACDigest(macAlgorithm), cipherKeySize);
}


protected BlockCipher createAESEngine(int cipherKeySize)
{
if (cipherKeySize == 16) {
// JDK optimized AES engine
return new AESEngineJDK();
}

return new AESEngine();
}

protected BlockCipher createAESBlockCipher(int cipherKeySize)
{
return new CBCBlockCipher(createAESEngine(cipherKeySize));
}

}
And I used this CipherFactory in my SSLSocket implementation:

public class BouncycastleSocket extends SSLSocket {

private TlsClientProtocol protocol;

public BouncycastleSocket(InetAddress address, int port) throws IOException {
super(address, port);
java.security.SecureRandom secureRandom = new java.security.SecureRandom();

protocol = new TlsClientProtocol(super.getInputStream(), super.getOutputStream(), secureRandom);
DefaultTlsClient client = new DefaultTlsClient(new JvmTlsCipherFactory()) {
public TlsAuthentication getAuthentication() throws IOException {
TlsAuthentication auth = new TlsAuthentication() {
// Capture the server certificate information!
public void notifyServerCertificate(org.bouncycastle.crypto.tls.Certificate serverCertificate) throws IOException {
}

public TlsCredentials getClientCredentials(CertificateRequest certificateRequest) throws IOException {
return null;
}
};
return auth;
}
};
protocol.connect(client);
}

...
}


Thank you and best regards!
 

--
Abraham Macías Pardes
Analista/Programador Departamento de Desarollo y Soluciones
[hidden email] 
Grupo Solutia
Edificio ZZJ / DTM
C/ Camino de los Descubrimientos, 11
41092 Sevilla
T: +34 955 11 11 55
gruposolutia.com

Sus datos personales contenidos en esta comunicación han sido recogidos de los contactos mantenidos por Vd. o por personas de su entorno, con personal de SOLUTIA INNOVAWORLD TECHNOLOGIES, S.L. y han sido incorporados al fichero de GESTIÓN COMERCIAL con la finalidad de realizar la gestión, seguimiento y mantenimiento de nuestra relación comercial, o a otro fichero correspondiente al tipo de relación que mantiene con nosotros, de lo que Vd. fue convenientemente informado al recibir bien el documento contractual entregado al inicio de los contactos bien en una comunicación inmediatamente posterior en que se daba cumplimiento al derecho de información y se le solicitaba consentimiento para tratar sus datos personales, tratamiento que se efectuará de acuerdo a las finalidades allí expresadas.

En el caso en que ésta sea la primera comunicación que recibe por nuestra parte, le solicitamos su consentimiento para proceder al tratamiento de sus datos de acuerdo a las condiciones detalladas al inicio. Entenderemos que nos presta su consentimiento si en el plazo de un mes a contar desde la recepción de esta comunicación no nos expresa su voluntad en contra. Le informamos que puede revocar en cualquier momento su consentimiento respondiendo a este mail indicando que no desea recibir más información acerca de nuestra empresa, supuesto en el que será automáticamente dado de baja de nuestra lista de correo.

Podrá ejercer sus derechos de acceso, rectificación, cancelación y oposición ante el Responsable del fichero, SOLUTIA INNOVAWORLD TECHNOLOGIES, S.L. en la dirección C/ Extremadura, 108 Parque empresarial Los Llanos; 41909 Salteras, SEVILLA, indicando en la comunicación la referencia "LOPD"

AESEngineJDK.java (3K) Download Attachment