diff options
author | Brian Carlstrom <bdc@google.com> | 2011-02-01 15:57:13 -0800 |
---|---|---|
committer | Brian Carlstrom <bdc@google.com> | 2011-02-01 20:58:35 -0800 |
commit | 4155a2498a57fb09e92815f8993a70c216ddc5ec (patch) | |
tree | 18508b14968d422c1d766ee8bf80b70c3b36c47d /support/src | |
parent | 54db500a1f77652e25d2789eb40dc46abc8ea8ea (diff) | |
download | libcore-4155a2498a57fb09e92815f8993a70c216ddc5ec.zip libcore-4155a2498a57fb09e92815f8993a70c216ddc5ec.tar.gz libcore-4155a2498a57fb09e92815f8993a70c216ddc5ec.tar.bz2 |
Performance improvements to NativeCrypto based MessageDigest API
NativeCrypto API improvements:
- Move to using EVP_MD related native methods, some of which are derived
from the EVP_MD_CTX versions with similar name. The new
EVP_get_digestbyname allows one time lookup of the EVP_MD from the
string name, avoiding doing it on every call to EVP_DigestInit.
- EVP_MD_CTX_create is now removed, it is just done as part of
EVP_DigestInit and EVP_VerifyInit to an extra JNI call.
- EVP_DigestFinal now destroys the EVP_MD_CTX to avoid needing to make
another call JNI call to EVP_MD_CTX_destroy. EVP_MD_CTX_destroy is
kept for cases when EVP_DigestFinal is never called.
luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
In addition to the improved NativeCrypto API to allow better
performance for callers, the implementations use of
throwExceptionIfNecessary was made conditional based on the status
code from various operations, which had a noticeable impact on
performance compared to android.security.MessageDigest
luni/src/main/native/NativeCrypto.cpp
Updated MessageDigest.getInstance default implementation to use new
NativeCrypto API. An EVP_MD instance is looked up at class load time
for a specific digest type and then used to call
NativeCrypto.EVP_DigestInit as needed, avoiding a lookup of EVP_MD for
each new digest. The EVP_MD is also for a one-time lookup the digest
output size in bytes, to avoid native calls for
engineGetDigestLength. Finally, the creation of the EVP_MD_CTX is now
lazy, only created when needed, avoiding unnecessarily create/free in
reset cases such as engineDigest. See also external/bouncycastle's
OpenSSLDigest implementation which had similar optimizations.
luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMessageDigestJDK.java
OpenSSLSignature also used EVP_MD_CTX_create, and its EVP_VerifyInit
was changed similar to EVP_DigestInit to internally allocate the
EVP_MD_CTX on the call to init.
luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignature.java
Fix test to work with arbitrary provider order
luni/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java
Fix CloseGuard warnings
luni/src/test/java/tests/security/MessageDigestTest.java
Bug: 3392028
Change-Id: Idb266ebc0918ffd5550e0f457784256400cd2ff0
Diffstat (limited to 'support/src')
-rw-r--r-- | support/src/test/java/tests/security/MessageDigestTest.java | 182 |
1 files changed, 39 insertions, 143 deletions
diff --git a/support/src/test/java/tests/security/MessageDigestTest.java b/support/src/test/java/tests/security/MessageDigestTest.java index 9ae4881..5457688 100644 --- a/support/src/test/java/tests/security/MessageDigestTest.java +++ b/support/src/test/java/tests/security/MessageDigestTest.java @@ -15,16 +15,12 @@ */ package tests.security; -import dalvik.annotation.TestLevel; -import dalvik.annotation.TestTargetNew; -import dalvik.annotation.TestTargets; - -import junit.framework.TestCase; - import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import junit.framework.TestCase; + public abstract class MessageDigestTest extends TestCase { private String digestAlgorithmName; @@ -65,14 +61,14 @@ public abstract class MessageDigestTest extends TestCase { expected3 = null; digest = null; + sourceData.close(); sourceData = null; checkDigest = null; System.gc(); } - MessageDigest getMessageDigest() - { + MessageDigest getMessageDigest() { try { return MessageDigest.getInstance(digestAlgorithmName); } catch (NoSuchAlgorithmException e) { @@ -81,59 +77,37 @@ public abstract class MessageDigestTest extends TestCase { } } - InputStream getSourceData() - { - InputStream sourceStream = getClass().getResourceAsStream( - digestAlgorithmName + ".data"); - assertNotNull("digest source data not found: " + digestAlgorithmName, - sourceStream); + InputStream getSourceData() { + InputStream sourceStream = getClass().getResourceAsStream(digestAlgorithmName + ".data"); + assertNotNull("digest source data not found: " + digestAlgorithmName, sourceStream); return sourceStream; } - byte[] getCheckDigest() - { - InputStream checkDigestStream = getClass().getResourceAsStream( - digestAlgorithmName + ".check"); + byte[] getCheckDigest() { + InputStream checkDigestStream = + getClass().getResourceAsStream(digestAlgorithmName + ".check"); byte[] checkDigest = new byte[digest.getDigestLength()]; int read = 0; int index = 0; try { - while ((read = checkDigestStream.read()) != -1) - { + while ((read = checkDigestStream.read()) != -1) { checkDigest[index++] = (byte)read; } + checkDigestStream.close(); } catch (IOException e) { fail("failed to read digest golden data: " + digestAlgorithmName); } return checkDigest; } - @TestTargets({ - @TestTargetNew( - level = TestLevel.ADDITIONAL, - method = "update", - args = {byte[].class,int.class,int.class} - ), - @TestTargetNew( - level = TestLevel.ADDITIONAL, - method = "digest", - args = {} - ), - @TestTargetNew( - level = TestLevel.COMPLETE, - method = "method", - args = {} - ) - }) - public void testMessageDigest1() - { + public void testMessageDigest1() { byte[] buf = new byte[128]; int read = 0; try { - while ((read = sourceData.read(buf)) != -1) - { + while ((read = sourceData.read(buf)) != -1) { digest.update(buf, 0, read); } + sourceData.close(); } catch (IOException e) { fail("failed to read digest data"); } @@ -141,42 +115,22 @@ public abstract class MessageDigestTest extends TestCase { byte[] computedDigest = digest.digest(); assertNotNull("computed digest is is null", computedDigest); - assertEquals("digest length mismatch", checkDigest.length, - computedDigest.length); + assertEquals("digest length mismatch", checkDigest.length, computedDigest.length); - for (int i = 0; i < checkDigest.length; i++) - { + for (int i = 0; i < checkDigest.length; i++) { assertEquals("byte " + i + " of computed and check digest differ", - checkDigest[i], computedDigest[i]); + checkDigest[i], computedDigest[i]); } } - @TestTargets({ - @TestTargetNew( - level = TestLevel.ADDITIONAL, - method = "update", - args = {byte.class} - ), - @TestTargetNew( - level = TestLevel.ADDITIONAL, - method = "digest", - args = {} - ), - @TestTargetNew( - level = TestLevel.COMPLETE, - method = "method", - args = {} - ) - }) - public void testMessageDigest2() - { + public void testMessageDigest2() { int val; try { - while ((val = sourceData.read()) != -1) - { + while ((val = sourceData.read()) != -1) { digest.update((byte)val); } + sourceData.close(); } catch (IOException e) { fail("failed to read digest data"); } @@ -184,12 +138,10 @@ public abstract class MessageDigestTest extends TestCase { byte[] computedDigest = digest.digest(); assertNotNull("computed digest is is null", computedDigest); - assertEquals("digest length mismatch", checkDigest.length, - computedDigest.length); - for (int i = 0; i < checkDigest.length; i++) - { + assertEquals("digest length mismatch", checkDigest.length, computedDigest.length); + for (int i = 0; i < checkDigest.length; i++) { assertEquals("byte " + i + " of computed and check digest differ", - checkDigest[i], computedDigest[i]); + checkDigest[i], computedDigest[i]); } } @@ -199,8 +151,12 @@ public abstract class MessageDigestTest extends TestCase { * Official FIPS180-2 testcases */ - protected String source1, source2, source3; - protected String expected1, expected2, expected3; + protected String source1; + protected String source2; + protected String source3; + protected String expected1; + protected String expected2; + protected String expected3; String getLongMessage(int length) { StringBuilder sourceBuilder = new StringBuilder(length); @@ -210,23 +166,6 @@ public abstract class MessageDigestTest extends TestCase { return sourceBuilder.toString(); } - @TestTargets({ - @TestTargetNew( - level = TestLevel.ADDITIONAL, - method = "update", - args = {byte.class} - ), - @TestTargetNew( - level = TestLevel.ADDITIONAL, - method = "digest", - args = {} - ), - @TestTargetNew( - level = TestLevel.COMPLETE, - method = "method", - args = {} - ) - }) public void testfips180_2_singleblock() { digest.update(source1.getBytes(), 0, source1.length()); @@ -236,33 +175,13 @@ public abstract class MessageDigestTest extends TestCase { assertNotNull("computed digest is null", computedDigest); StringBuilder sb = new StringBuilder(); - String res; - for (int i = 0; i < computedDigest.length; i++) - { - res = Integer.toHexString(computedDigest[i] & 0xFF); + for (int i = 0; i < computedDigest.length; i++) { + String res = Integer.toHexString(computedDigest[i] & 0xFF); sb.append((res.length() == 1 ? "0" : "") + res); } - assertEquals("computed and check digest differ", expected1, - sb.toString()); + assertEquals("computed and check digest differ", expected1, sb.toString()); } - @TestTargets({ - @TestTargetNew( - level = TestLevel.ADDITIONAL, - method = "update", - args = {byte.class} - ), - @TestTargetNew( - level = TestLevel.ADDITIONAL, - method = "digest", - args = {} - ), - @TestTargetNew( - level = TestLevel.COMPLETE, - method = "method", - args = {} - ) - }) public void testfips180_2_multiblock() { digest.update(source2.getBytes(), 0, source2.length()); @@ -272,33 +191,13 @@ public abstract class MessageDigestTest extends TestCase { assertNotNull("computed digest is null", computedDigest); StringBuilder sb = new StringBuilder(); - String res; - for (int i = 0; i < computedDigest.length; i++) - { - res = Integer.toHexString(computedDigest[i] & 0xFF); + for (int i = 0; i < computedDigest.length; i++) { + String res = Integer.toHexString(computedDigest[i] & 0xFF); sb.append((res.length() == 1 ? "0" : "") + res); } - assertEquals("computed and check digest differ", expected2, - sb.toString()); + assertEquals("computed and check digest differ", expected2, sb.toString()); } - @TestTargets({ - @TestTargetNew( - level = TestLevel.ADDITIONAL, - method = "update", - args = {byte.class} - ), - @TestTargetNew( - level = TestLevel.ADDITIONAL, - method = "digest", - args = {} - ), - @TestTargetNew( - level = TestLevel.COMPLETE, - method = "method", - args = {} - ) - }) public void testfips180_2_longMessage() { digest.update(source3.getBytes(), 0, source3.length()); @@ -308,13 +207,10 @@ public abstract class MessageDigestTest extends TestCase { assertNotNull("computed digest is null", computedDigest); StringBuilder sb = new StringBuilder(); - String res; - for (int i = 0; i < computedDigest.length; i++) - { - res = Integer.toHexString(computedDigest[i] & 0xFF); + for (int i = 0; i < computedDigest.length; i++) { + String res = Integer.toHexString(computedDigest[i] & 0xFF); sb.append((res.length() == 1 ? "0" : "") + res); } - assertEquals("computed and check digest differ", expected3, - sb.toString()); + assertEquals("computed and check digest differ", expected3, sb.toString()); } } |