From dd303ca9af64bda1a503d9918ec17a61e9b06e6d Mon Sep 17 00:00:00 2001 From: Neil Fuller Date: Wed, 23 Sep 2015 17:01:32 +0100 Subject: Patch for awaitNanos() for coarse-grained clocks If System.nanoTime() returns the same value twice in awaitNanos() then (remaining == initialNanos) will be true but the code will conclude that a (less likely) overflow occurred. Bug: 24284239 (cherry-picked from commit 8fc2ac0fa8eb47ce607f8412e469d4f680b6ef85) Change-Id: I3b9d573ea822e18f4c1849c8ab66071e66274a50 --- .../java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java | 5 ++++- .../java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java index 47a02a9..a74fb24 100644 --- a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java +++ b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java @@ -1838,7 +1838,10 @@ public abstract class AbstractQueuedLongSynchronizer if (interruptMode != 0) reportInterruptAfterWait(interruptMode); long remaining = deadline - System.nanoTime(); // avoid overflow - return (remaining < initialNanos) ? remaining : Long.MIN_VALUE; + // BEGIN android-note Changed from < to <= http://b/24284239 + // return (remaining < initialNanos) ? remaining : Long.MIN_VALUE; + return (remaining <= initialNanos) ? remaining : Long.MIN_VALUE; + // END android-note } /** diff --git a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java index bfe88e5..8823b6f 100644 --- a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java +++ b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java @@ -2062,7 +2062,10 @@ public abstract class AbstractQueuedSynchronizer if (interruptMode != 0) reportInterruptAfterWait(interruptMode); long remaining = deadline - System.nanoTime(); // avoid overflow - return (remaining < initialNanos) ? remaining : Long.MIN_VALUE; + // BEGIN android-note Changed from < to <= http://b/24284239 + // return (remaining < initialNanos) ? remaining : Long.MIN_VALUE; + return (remaining <= initialNanos) ? remaining : Long.MIN_VALUE; + // END android-note } /** -- cgit v1.1 From ef2d585bdcf12e6ba1aa1ded6a5cf80e4a79b568 Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Mon, 14 Sep 2015 03:35:13 -0700 Subject: Add more debugging to the DigestTest This test sometimes fails, but we don't know what the coefficient of variation is on the test results. Add this to the debug output so we can see if there is just some wild swing during testing. Also add a few rounds of warm-up as well. Bug: 24011092 Change-Id: Ic58f106f68eb93976e3f030e2f23e0156fe84be8 (cherry picked from commit 5fe1cd001f38fba460ac0ce5c15b85250e400f25) --- .../bouncycastle/crypto/digests/DigestTest.java | 33 +++++---- .../test/java/tests/util/SummaryStatistics.java | 82 ++++++++++++++++++++++ 2 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 support/src/test/java/tests/util/SummaryStatistics.java diff --git a/luni/src/test/java/com/android/org/bouncycastle/crypto/digests/DigestTest.java b/luni/src/test/java/com/android/org/bouncycastle/crypto/digests/DigestTest.java index 8708214..fce8507 100644 --- a/luni/src/test/java/com/android/org/bouncycastle/crypto/digests/DigestTest.java +++ b/luni/src/test/java/com/android/org/bouncycastle/crypto/digests/DigestTest.java @@ -19,6 +19,7 @@ package com.android.org.bouncycastle.crypto.digests; import junit.framework.TestCase; import com.android.org.bouncycastle.crypto.Digest; import com.android.org.bouncycastle.crypto.ExtendedDigest; +import tests.util.SummaryStatistics; /** * Implements unit tests for our JNI wrapper around OpenSSL. We use the @@ -36,6 +37,7 @@ public class DigestTest extends TestCase { * @param newDigest The new digest implementation, provided by OpenSSL */ public void doTestMessageDigest(Digest oldDigest, Digest newDigest) { + final int WARMUP = 10; final int ITERATIONS = 100; byte[] data = new byte[1024]; @@ -54,27 +56,31 @@ public class DigestTest extends TestCase { data[i] = (byte)i; } - long oldTime = 0; - long newTime = 0; + SummaryStatistics oldTime = new SummaryStatistics(); + SummaryStatistics newTime = new SummaryStatistics(); - for (int j = 0; j < ITERATIONS; j++) { - long t0 = System.currentTimeMillis(); + for (int j = 0; j < ITERATIONS + WARMUP; j++) { + long t0 = System.nanoTime(); for (int i = 0; i < 4; i++) { oldDigest.update(data, 0, data.length); } int oldLength = oldDigest.doFinal(oldHash, 0); - long t1 = System.currentTimeMillis(); + long t1 = System.nanoTime(); - oldTime = oldTime + (t1 - t0); + if (j >= WARMUP) { + oldTime.add(t1 - t0); + } - long t2 = System.currentTimeMillis(); + long t2 = System.nanoTime(); for (int i = 0; i < 4; i++) { newDigest.update(data, 0, data.length); } int newLength = newDigest.doFinal(newHash, 0); - long t3 = System.currentTimeMillis(); + long t3 = System.nanoTime(); - newTime = newTime + (t3 - t2); + if (j >= WARMUP) { + newTime.add(t3 - t2); + } assertEquals("Hash sizes must be equal", oldLength, newLength); @@ -83,10 +89,13 @@ public class DigestTest extends TestCase { } } - System.out.println("Time for " + ITERATIONS + " x old hash processing: " + oldTime + " ms"); - System.out.println("Time for " + ITERATIONS + " x new hash processing: " + newTime + " ms"); + System.out.println("Time for " + ITERATIONS + " x old hash processing: " + + oldTime.toString()); + System.out.println("Time for " + ITERATIONS + " x new hash processing: " + + newTime.toString()); - assertTrue("New hash should be faster", newTime < oldTime); + assertTrue("New hash should be faster:\nold=" + oldTime.toString() + "\nnew=" + + newTime.toString(), newTime.mean() < oldTime.mean()); } /** diff --git a/support/src/test/java/tests/util/SummaryStatistics.java b/support/src/test/java/tests/util/SummaryStatistics.java new file mode 100644 index 0000000..4ce0a04 --- /dev/null +++ b/support/src/test/java/tests/util/SummaryStatistics.java @@ -0,0 +1,82 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.util; + +public class SummaryStatistics { + /** The number of values seen. */ + private int numValues; + + /** Sum of the values. */ + private double sum; + + /** Sum of the squares of the values added. */ + private double squaresSum; + + /** The previously added value. */ + private double lastValue; + + public SummaryStatistics() { + } + + private double square(double value) { + return value * value; + } + + /** Add a new value to the values seen. */ + public void add(double value) { + sum += value - lastValue; + squaresSum += square(value) - square(lastValue); + numValues++; + lastValue = value; + } + + /** Mean of the values seen. */ + public double mean() { + return sum / numValues; + } + + /** Variance of the values seen. */ + public double var() { + return (squaresSum / numValues) - square(mean()); + } + + /** Standard deviation of the values seen. */ + public double stddev() { + return Math.sqrt(var()); + } + + /** Coefficient of variation of the values seen. */ + public double coeffVar() { + return stddev() / mean(); + } + + public String toString() { + StringBuilder sb = new StringBuilder("SummaryStatistics{"); + sb.append("n="); + sb.append(numValues); + sb.append(",mean="); + sb.append(mean()); + sb.append(",var="); + sb.append(var()); + sb.append(",stddev="); + sb.append(stddev()); + sb.append(",coeffVar="); + sb.append(coeffVar()); + sb.append('}'); + return sb.toString(); + } +} -- cgit v1.1 From 36363b0d43f12432837ab936b85973f08e74a299 Mon Sep 17 00:00:00 2001 From: zhulin0910 Date: Thu, 24 Sep 2015 14:21:45 +0800 Subject: Fix time calculation in test_SSLSession_getLastAccessedTime [root cause] Time precision in NativeCrypto SSL_SESSION_get_time is second, ignore millisecond. Then, assertTrue( Math.abs(s.server.getLastAccessedTime() - s.client.getLastAccessedTime()) < 1 * 1000); is not rigorous. [changes] modify diff time of s.server.getLastAccessedTime() and s.client.getLastAccessedTime() <= 1*1000 Bug: https://code.google.com/p/android/issues/detail?id=183898 (cherry picked from commit 3f49882b1d3316e37d8312d707c29261d14ece65) Change-Id: Ib0d5eb512f717f1fd88818eac5bf8ef0e5cbac6b --- luni/src/test/java/libcore/javax/net/ssl/SSLSessionTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSessionTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSessionTest.java index a434d94..bc2b626 100644 --- a/luni/src/test/java/libcore/javax/net/ssl/SSLSessionTest.java +++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSessionTest.java @@ -99,7 +99,7 @@ public class SSLSessionTest extends TestCase { assertTrue("s.server.getLastAccessedTime()=" + s.server.getLastAccessedTime() + " " + "s.client.getLastAccessedTime()=" + s.client.getLastAccessedTime(), Math.abs(s.server.getLastAccessedTime() - - s.client.getLastAccessedTime()) < 1 * 1000); + - s.client.getLastAccessedTime()) <= 1 * 1000); assertTrue(s.server.getLastAccessedTime() >= s.server.getCreationTime()); assertTrue(s.client.getLastAccessedTime() >= -- cgit v1.1 From 161ab7af0434978ad3a9512293a032861a18e16e Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Wed, 2 Dec 2015 13:53:46 -0800 Subject: Change FinalizeTest to use helper function Old way kept the object live in a vreg. Bug: 25851249 (cherry picked from commit cf3d432790a78b7d81da656f9a666f3d1ce4962c) Change-Id: I3cefd317e23c602c6c74dd866f0831161ef10962 (cherry picked from commit 8210c23a598b363e89d6cd32dedeeae673bf9212) --- luni/src/test/java/libcore/java/lang/ref/FinalizeTest.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/luni/src/test/java/libcore/java/lang/ref/FinalizeTest.java b/luni/src/test/java/libcore/java/lang/ref/FinalizeTest.java index ef303bd..d71b5b0 100644 --- a/luni/src/test/java/libcore/java/lang/ref/FinalizeTest.java +++ b/luni/src/test/java/libcore/java/lang/ref/FinalizeTest.java @@ -69,13 +69,18 @@ public final class FinalizeTest extends TestCase { static class X {} - // http://b/issue?id=2136462 - public void testBackFromTheDead() throws Exception { + // Helper function since we do not want a vreg to keep the allocated object live. + // For b/25851249 + private void exceptionInConstructor() { try { new ConstructionFails(); } catch (AssertionError expected) { } + } + // http://b/issue?id=2136462 + public void testBackFromTheDead() throws Exception { + exceptionInConstructor(); FinalizationTester.induceFinalization(); assertTrue("object whose constructor threw was not finalized", ConstructionFails.finalized); } -- cgit v1.1 From e7bdc26218b2f0fa323778de1ff1449f4c5f5a52 Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Wed, 6 Jan 2016 10:02:28 -0800 Subject: Check for RFC 5746 TLS extension RFC 5746 allows you to either include a signaling cipher suite or a TLS extension. However, since TLS API has no way to indicate or check that a certain TLS extension is used, we insert it into the cipher suites we see to check against the enabled cipher suites. (cherry picked from commit 81885494e46596c796cdcb5037b91d92915b65a7) Bug: 24602368 Change-Id: I06422b9a90f47bb5ffa10ef614233d856773d336 --- .../test/java/libcore/javax/net/ssl/SSLSocketTest.java | 18 +++++++++++++++++- .../java/libcore/tlswire/handshake/HelloExtension.java | 3 ++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java index bf2d0f8..11dfb3d 100644 --- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java +++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java @@ -1559,7 +1559,23 @@ public class SSLSocketTest extends TestCase { @Override public void run(SSLSocketFactory sslSocketFactory) throws Exception { ClientHello clientHello = captureTlsHandshakeClientHello(sslSocketFactory); - String[] cipherSuites = new String[clientHello.cipherSuites.size()]; + final String[] cipherSuites; + + // RFC 5746 allows you to send an empty "renegotiation_info" extension *or* + // a special signaling cipher suite. The TLS API has no way to check or + // indicate that a certain TLS extension should be used. + HelloExtension renegotiationInfoExtension = clientHello.findExtensionByType( + HelloExtension.TYPE_RENEGOTIATION_INFO); + if (renegotiationInfoExtension != null && + renegotiationInfoExtension.data.length == 1 && + renegotiationInfoExtension.data[0] == 0) { + cipherSuites = new String[clientHello.cipherSuites.size() + 1]; + cipherSuites[clientHello.cipherSuites.size()] = + StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION; + } else { + cipherSuites = new String[clientHello.cipherSuites.size()]; + } + for (int i = 0; i < clientHello.cipherSuites.size(); i++) { CipherSuite cipherSuite = clientHello.cipherSuites.get(i); cipherSuites[i] = cipherSuite.getAndroidName(); diff --git a/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java b/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java index 5741072..a648cdf 100644 --- a/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java +++ b/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java @@ -31,6 +31,7 @@ public class HelloExtension { public static final int TYPE_SERVER_NAME = 0; public static final int TYPE_PADDING = 21; public static final int TYPE_SESSION_TICKET = 35; + public static final int TYPE_RENEGOTIATION_INFO = 65281; private static final Map TYPE_TO_NAME = new HashMap(); static { @@ -60,7 +61,7 @@ public class HelloExtension { TYPE_TO_NAME.put(13172, "next_protocol_negotiation"); TYPE_TO_NAME.put(30031, "Channel ID (old)"); TYPE_TO_NAME.put(30032, "Channel ID (new)"); - TYPE_TO_NAME.put(65281, "renegotiation_info"); + TYPE_TO_NAME.put(TYPE_RENEGOTIATION_INFO, "renegotiation_info"); } public int type; -- cgit v1.1 From 4e6f59996fae4f9a2de077b113be46cd461e4b4d Mon Sep 17 00:00:00 2001 From: Sergio Giro Date: Tue, 23 Feb 2016 18:53:33 +0000 Subject: GCMParameters: check that the default tag size is secure (16 bits) Note: port of cr/110497945 Bug: 26231099 Bug: 26234568 Change-Id: I3eef233b15ded9553c3cdfd1c51ffef306276f7d --- .../test/java/libcore/javax/crypto/CipherTest.java | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java index dd7d6e7..38d6d8d 100644 --- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java +++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java @@ -3203,6 +3203,28 @@ public final class CipherTest extends TestCase { } } + public void test_DefaultGCMTagSizeAlgorithmParameterSpec() throws Exception { + final String AES = "AES"; + final String AES_GCM = "AES/GCM/NoPadding"; + byte[] input = new byte[16]; + byte[] key = new byte[16]; + Cipher cipher = Cipher.getInstance(AES_GCM, "BC"); + AlgorithmParameters param = AlgorithmParameters.getInstance("GCM"); + param.init(new byte[] { + (byte) 48, // DER encoding : tag_Sequence + (byte) 14, // DER encoding : total length + (byte) 4, // DER encoding : tag_OctetString + (byte) 12, // DER encoding : counter length + // Note that IV's size 12 bytes is recommended, but authentication tag size should be 16 + // bytes. + (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, + (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 }); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, AES), param); + byte[] ciphertext = cipher.update(input); + byte[] tag = cipher.doFinal(); + assertEquals(16, tag.length); + } + public void testAES_ECB_PKCS5Padding_ShortBuffer_Failure() throws Exception { for (String provider : AES_PROVIDERS) { testAES_ECB_PKCS5Padding_ShortBuffer_Failure(provider); -- cgit v1.1 From b307d3520ae526e437fa1ede12ff6f113fe9e8f9 Mon Sep 17 00:00:00 2001 From: Sergio Giro Date: Tue, 23 Feb 2016 18:53:33 +0000 Subject: GCMParameters: check that the default tag size is secure (16 bits) Note: port of cr/110497945 Bug: 26231099 Bug: 26234568 Change-Id: I3eef233b15ded9553c3cdfd1c51ffef306276f7d --- .../test/java/libcore/javax/crypto/CipherTest.java | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java index dd7d6e7..38d6d8d 100644 --- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java +++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java @@ -3203,6 +3203,28 @@ public final class CipherTest extends TestCase { } } + public void test_DefaultGCMTagSizeAlgorithmParameterSpec() throws Exception { + final String AES = "AES"; + final String AES_GCM = "AES/GCM/NoPadding"; + byte[] input = new byte[16]; + byte[] key = new byte[16]; + Cipher cipher = Cipher.getInstance(AES_GCM, "BC"); + AlgorithmParameters param = AlgorithmParameters.getInstance("GCM"); + param.init(new byte[] { + (byte) 48, // DER encoding : tag_Sequence + (byte) 14, // DER encoding : total length + (byte) 4, // DER encoding : tag_OctetString + (byte) 12, // DER encoding : counter length + // Note that IV's size 12 bytes is recommended, but authentication tag size should be 16 + // bytes. + (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, + (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 }); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, AES), param); + byte[] ciphertext = cipher.update(input); + byte[] tag = cipher.doFinal(); + assertEquals(16, tag.length); + } + public void testAES_ECB_PKCS5Padding_ShortBuffer_Failure() throws Exception { for (String provider : AES_PROVIDERS) { testAES_ECB_PKCS5Padding_ShortBuffer_Failure(provider); -- cgit v1.1 From 156bf0a0237c98bfca6826ac9030b1444c391a50 Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Thu, 25 Feb 2016 23:15:47 -0800 Subject: CipherTest: test instance reuse with updateAAD AAD was not being reset on each Cipher init or doFinal call, so add regression tests to make sure that is now the case. (cherry picked from commit d90a44bf4956d335e2a876015cf258dc46e226ea) Bug: 27324690 Change-Id: I5f7606efb6dfcd412166eed2bd5f417097a97f1f --- .../test/java/libcore/javax/crypto/CipherTest.java | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java index 38d6d8d..7cd6133 100644 --- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java +++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java @@ -3537,4 +3537,45 @@ public final class CipherTest extends TestCase { cipher.init(Cipher.ENCRYPT_MODE, keyGen.generateKeyPair().getPublic()); cipher.doFinal(new byte[] {1,2,3,4}); } + + /* + * Check that GCM encryption with old and new instances update correctly. + * http://b/26694388 + */ + public void test_AESGCMNoPadding_Reuse_Success() throws Exception { + SecretKeySpec key = new SecretKeySpec(new byte[16], "AES"); + GCMParameterSpec spec = new GCMParameterSpec(128, new byte[12]); + Cipher c1 = Cipher.getInstance("AES/GCM/NoPadding"); + Cipher c2 = Cipher.getInstance("AES/GCM/NoPadding"); + + // Pollute the c1 cipher with AAD + c1.init(Cipher.ENCRYPT_MODE, key, spec); + c1.updateAAD(new byte[] { + 0x01, 0x02, 0x03, 0x04, 0x05, + }); + + // Now init each again and make sure the outputs are the same + c1.init(Cipher.ENCRYPT_MODE, key, spec); + c2.init(Cipher.ENCRYPT_MODE, key, spec); + + byte[] aad = new byte[] { + 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, + }; + c1.updateAAD(aad); + c2.updateAAD(aad); + + assertEquals(Arrays.toString(c1.doFinal()), Arrays.toString(c2.doFinal())); + + // .doFinal should also reset the state, so check that as well. + byte[] aad2 = new byte[] { + 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, + }; + + Cipher c3 = Cipher.getInstance("AES/GCM/NoPadding"); + c3.init(Cipher.ENCRYPT_MODE, key, spec); + + c1.updateAAD(aad2); + c3.updateAAD(aad2); + assertEquals(Arrays.toString(c1.doFinal()), Arrays.toString(c3.doFinal())); + } } -- cgit v1.1 From e565176fedcadcb6d1256a106bdb93d206d62043 Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Thu, 25 Feb 2016 23:17:43 -0800 Subject: CipherTest: add test for multiple updateAAD calls Make sure that multiple updateAAD calls are equivalent to other calls to updateAAD with the same data. (cherry picked from commit 67ee3c5c2dad218e497035de5100e9036d140fdd) Bug: 27371173 Change-Id: Ie69df0906438ad26c566daed3f55b07ba60fe468 --- .../test/java/libcore/javax/crypto/CipherTest.java | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java index 7cd6133..0f642cf 100644 --- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java +++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java @@ -3539,6 +3539,33 @@ public final class CipherTest extends TestCase { } /* + * Check that two AAD updates are equivalent to one. + * http://b/27371173 + */ + public void test_AESGCMNoPadding_UpdateAADTwice_Success() throws Exception { + SecretKeySpec key = new SecretKeySpec(new byte[16], "AES"); + GCMParameterSpec spec = new GCMParameterSpec(128, new byte[12]); + Cipher c1 = Cipher.getInstance("AES/GCM/NoPadding"); + Cipher c2 = Cipher.getInstance("AES/GCM/NoPadding"); + + c1.init(Cipher.ENCRYPT_MODE, key, spec); + c1.updateAAD(new byte[] { + 0x01, 0x02, 0x03, 0x04, 0x05, + }); + c1.updateAAD(new byte[] { + 0x06, 0x07, 0x08, 0x09, 0x10, + }); + + c2.init(Cipher.ENCRYPT_MODE, key, spec); + c2.updateAAD(new byte[] { + 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x10, + }); + + assertEquals(Arrays.toString(c1.doFinal()), Arrays.toString(c2.doFinal())); + } + + /* * Check that GCM encryption with old and new instances update correctly. * http://b/26694388 */ -- cgit v1.1 From 3a5c4a7f6a52c6e6f71616940920cb647aafff2b Mon Sep 17 00:00:00 2001 From: Kevin Hart Date: Thu, 11 Feb 2016 12:04:26 -0800 Subject: XML Pull Parser optimizations This patch includes three improvements to the pull parser. 1. readValue now only uses the stringPool for all-whitespace strings. Values are generally not repeated, and this function can thrash the string pool in some cases 2. Added a fast path for the normal, correct, end-tag case. This avoids a hash and lookup in the stringPool 3. While parsing an element (not attribute) name, the namespace and post-namespace strings are generated using the stringPool. This saves the cost of calling String.substring in adjustNsp. Change-Id: I69482a49bf52cb72d48bcbecd30fb56effe6a4ef --- xml/src/main/java/org/kxml2/io/KXmlParser.java | 74 +++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/xml/src/main/java/org/kxml2/io/KXmlParser.java b/xml/src/main/java/org/kxml2/io/KXmlParser.java index a90db3b..a75cc72 100644 --- a/xml/src/main/java/org/kxml2/io/KXmlParser.java +++ b/xml/src/main/java/org/kxml2/io/KXmlParser.java @@ -157,6 +157,8 @@ public class KXmlParser implements XmlPullParser, Closeable { private boolean isWhitespace; private String namespace; private String prefix; + private String foundPrefix = null; + private String foundName = null; private String name; private String text; @@ -268,15 +270,21 @@ public class KXmlParser implements XmlPullParser, Closeable { } } - int cut = name.indexOf(':'); + if (foundPrefix != null && foundName != null) { + prefix = foundPrefix; + name = foundName; + } + else { + int cut = name.indexOf(':'); if (cut == 0) { checkRelaxed("illegal tag name: " + name); } - if (cut != -1) { - prefix = name.substring(0, cut); - name = name.substring(cut + 1); + if (cut != -1) { + prefix = name.substring(0, cut); + name = name.substring(cut + 1); + } } this.namespace = getNamespace(prefix); @@ -961,13 +969,19 @@ public class KXmlParser implements XmlPullParser, Closeable { } private void readEndTag() throws IOException, XmlPullParserException { + int sp = (depth - 1) * 4; read('<'); read('/'); - name = readName(); // TODO: pass the expected name in as a hint? + if (depth == 0) { + name = readName(); + } + else { + // Pass the expected name in as a hint. + name = readExpectedName(elementStack[sp + 3]); + } skip(); read('>'); - int sp = (depth - 1) * 4; if (depth == 0) { checkRelaxed("read end tag " + name + " with no tags open"); @@ -1055,7 +1069,7 @@ public class KXmlParser implements XmlPullParser, Closeable { if (!xmldecl) { read('<'); } - name = readName(); + name = readName(true); attributeCount = 0; while (true) { @@ -1429,7 +1443,12 @@ public class KXmlParser implements XmlPullParser, Closeable { } if (result == null) { - return stringPool.get(buffer, start, position - start); + if (isWhitespace) { + return stringPool.get(buffer, start, position - start); + } + else { + return new String(buffer, start, position - start); + } } else { result.append(buffer, start, position - start); return result.toString(); @@ -1525,13 +1544,44 @@ public class KXmlParser implements XmlPullParser, Closeable { * Returns an element or attribute name. This is always non-empty for * non-relaxed parsers. */ + private String readExpectedName(String expected) throws IOException, XmlPullParserException { + int length = expected.length(); + int end = position + length; + if (end < limit) { + // Fast path for normal case. + boolean match = true; + for (int i = 0; i < length; i++) { + if (buffer[position+i] != expected.charAt(i)) { + match = false; + break; + } + } + if (match) { + position += length; + return expected; + } + } + return readName(); + } + private String readName() throws IOException, XmlPullParserException { + return readName(false); + } + + /** + * Returns an element or attribute name. This is always non-empty for + * non-relaxed parsers. findPrefix should only be true for element names + */ + private String readName(boolean findPrefix) throws IOException, XmlPullParserException { if (position >= limit && !fillBuffer(1)) { checkRelaxed("name expected"); return ""; } int start = position; + int nameStart = -1; + foundPrefix = null; + foundName = null; StringBuilder result = null; // read the first character @@ -1575,12 +1625,20 @@ public class KXmlParser implements XmlPullParser, Closeable { || c == ':' || c == '.' || c >= '\u00b7') { // TODO: check the XML spec + // Fast path for common case + if (c == ':' && findPrefix && foundPrefix == null) { + foundPrefix = stringPool.get(buffer, start, position - start); + nameStart = position+1; + } position++; continue; } // we encountered a non-name character. done! if (result == null) { + if (foundPrefix != null && position != nameStart) { + foundName = stringPool.get(buffer, nameStart, position - nameStart); + } return stringPool.get(buffer, start, position - start); } else { result.append(buffer, start, position - start); -- cgit v1.1 From c95c72ec796254f98e12d108d6f6d0e06d01bcd3 Mon Sep 17 00:00:00 2001 From: Sergio Giro Date: Tue, 19 Jul 2016 14:40:40 +0100 Subject: CipherTest: in ASN1 encoding for GCM, no value for tag size means 12 Bug: 26231099 Bug: 26234568 Bug: 29876633 Change-Id: I44c0c68f1e92caf6547c9e3b494ec5b82b8cff5f --- luni/src/test/java/libcore/javax/crypto/CipherTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java index 0f642cf..398c688 100644 --- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java +++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java @@ -3203,6 +3203,9 @@ public final class CipherTest extends TestCase { } } + // Test that when reading GCM parameters encoded using ASN1, a value for the tag size + // not present indicates a value of 12. + // https://b/29876633 public void test_DefaultGCMTagSizeAlgorithmParameterSpec() throws Exception { final String AES = "AES"; final String AES_GCM = "AES/GCM/NoPadding"; @@ -3215,14 +3218,12 @@ public final class CipherTest extends TestCase { (byte) 14, // DER encoding : total length (byte) 4, // DER encoding : tag_OctetString (byte) 12, // DER encoding : counter length - // Note that IV's size 12 bytes is recommended, but authentication tag size should be 16 - // bytes. (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 }); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, AES), param); byte[] ciphertext = cipher.update(input); byte[] tag = cipher.doFinal(); - assertEquals(16, tag.length); + assertEquals(12, tag.length); } public void testAES_ECB_PKCS5Padding_ShortBuffer_Failure() throws Exception { -- cgit v1.1 From 0cfcb79a5cf22eacd814b1c37b65a1b6398d90ab Mon Sep 17 00:00:00 2001 From: Sergio Giro Date: Tue, 19 Jul 2016 14:40:40 +0100 Subject: CipherTest: in ASN1 encoding for GCM, no value for tag size means 12 Bug: 26231099 Bug: 26234568 Bug: 29876633 Change-Id: I44c0c68f1e92caf6547c9e3b494ec5b82b8cff5f --- luni/src/test/java/libcore/javax/crypto/CipherTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java index 0f642cf..398c688 100644 --- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java +++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java @@ -3203,6 +3203,9 @@ public final class CipherTest extends TestCase { } } + // Test that when reading GCM parameters encoded using ASN1, a value for the tag size + // not present indicates a value of 12. + // https://b/29876633 public void test_DefaultGCMTagSizeAlgorithmParameterSpec() throws Exception { final String AES = "AES"; final String AES_GCM = "AES/GCM/NoPadding"; @@ -3215,14 +3218,12 @@ public final class CipherTest extends TestCase { (byte) 14, // DER encoding : total length (byte) 4, // DER encoding : tag_OctetString (byte) 12, // DER encoding : counter length - // Note that IV's size 12 bytes is recommended, but authentication tag size should be 16 - // bytes. (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 }); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, AES), param); byte[] ciphertext = cipher.update(input); byte[] tag = cipher.doFinal(); - assertEquals(16, tag.length); + assertEquals(12, tag.length); } public void testAES_ECB_PKCS5Padding_ShortBuffer_Failure() throws Exception { -- cgit v1.1 From a1e0873bd8ab79f64296d1103a4e9e7ee6a5bbb7 Mon Sep 17 00:00:00 2001 From: Narayan Kamath Date: Fri, 19 Aug 2016 15:26:24 +0100 Subject: IDN: Fix handling of long domain names. Fix merge conflict into mnc-mr2-release We were incorrectly using sizeof() to calculate the size of the output array. Note that this change also changes the output size to 512 to minimize behavioural differences (especially wrt. ICU checks on sizes). bug: 30765246 Change-Id: I5d28ddc45d2d6d2bed3e479ca195ed2779b906ed --- luni/src/main/native/libcore_icu_NativeIDN.cpp | 9 +++++---- luni/src/test/java/libcore/java/net/IDNTest.java | 11 +++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/luni/src/main/native/libcore_icu_NativeIDN.cpp b/luni/src/main/native/libcore_icu_NativeIDN.cpp index 43f3ce5..9786b9d 100644 --- a/luni/src/main/native/libcore_icu_NativeIDN.cpp +++ b/luni/src/main/native/libcore_icu_NativeIDN.cpp @@ -37,7 +37,8 @@ static jstring NativeIDN_convertImpl(JNIEnv* env, jclass, jstring javaSrc, jint if (src.get() == NULL) { return NULL; } - UChar dst[256]; + static const size_t kDstSize = 512; + UChar dst[kDstSize]; UErrorCode status = U_ZERO_ERROR; // We're stuck implementing IDNA-2003 for now since that's what we specify. @@ -47,10 +48,10 @@ static jstring NativeIDN_convertImpl(JNIEnv* env, jclass, jstring javaSrc, jint #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" size_t resultLength = toAscii - ? uidna_IDNToASCII(src.get(), src.size(), &dst[0], sizeof(dst), flags, NULL, &status) - : uidna_IDNToUnicode(src.get(), src.size(), &dst[0], sizeof(dst), flags, NULL, &status); + ? uidna_IDNToASCII(src.get(), src.size(), &dst[0], kDstSize, flags, NULL, &status) + : uidna_IDNToUnicode(src.get(), src.size(), &dst[0], kDstSize, flags, NULL, &status); #pragma GCC diagnostic pop - + if (U_FAILURE(status)) { jniThrowException(env, "java/lang/IllegalArgumentException", u_errorName(status)); return NULL; diff --git a/luni/src/test/java/libcore/java/net/IDNTest.java b/luni/src/test/java/libcore/java/net/IDNTest.java index f01eca3..37f3505 100644 --- a/luni/src/test/java/libcore/java/net/IDNTest.java +++ b/luni/src/test/java/libcore/java/net/IDNTest.java @@ -37,4 +37,15 @@ public class IDNTest extends TestCase { String longInput = makePunyString(512); assertEquals(longInput, IDN.toUnicode(longInput)); } + + // http://b/30765246 + public void testLongDomainName() { + String label63 = "123456789-123456789-123456789-123456789-123456789-123456789-123"; + String host255 = label63 + "." + label63 + "." + label63 + "." + label63; + try { + IDN.toASCII(host255.substring(3) + ".com"); + fail(); + } catch (IllegalArgumentException expected) { + } + } } -- cgit v1.1