summaryrefslogtreecommitdiff
path: root/src/main/javatest/com/google/security/cryptauth/lib/securegcm/Ukey2HandshakeTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/javatest/com/google/security/cryptauth/lib/securegcm/Ukey2HandshakeTest.java')
-rw-r--r--src/main/javatest/com/google/security/cryptauth/lib/securegcm/Ukey2HandshakeTest.java818
1 files changed, 0 insertions, 818 deletions
diff --git a/src/main/javatest/com/google/security/cryptauth/lib/securegcm/Ukey2HandshakeTest.java b/src/main/javatest/com/google/security/cryptauth/lib/securegcm/Ukey2HandshakeTest.java
deleted file mode 100644
index f5d0e1a..0000000
--- a/src/main/javatest/com/google/security/cryptauth/lib/securegcm/Ukey2HandshakeTest.java
+++ /dev/null
@@ -1,818 +0,0 @@
-// Copyright 2020 Google LLC
-//
-// 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
-//
-// https://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 com.google.security.cryptauth.lib.securegcm;
-
-import com.google.protobuf.ByteString;
-import com.google.security.cryptauth.lib.securegcm.Ukey2Handshake.AlertException;
-import com.google.security.cryptauth.lib.securegcm.Ukey2Handshake.HandshakeCipher;
-import com.google.security.cryptauth.lib.securegcm.Ukey2Handshake.State;
-import com.google.security.cryptauth.lib.securegcm.UkeyProto.Ukey2ClientFinished;
-import com.google.security.cryptauth.lib.securegcm.UkeyProto.Ukey2ClientInit;
-import com.google.security.cryptauth.lib.securegcm.UkeyProto.Ukey2ClientInit.CipherCommitment;
-import com.google.security.cryptauth.lib.securegcm.UkeyProto.Ukey2Message;
-import com.google.security.cryptauth.lib.securegcm.UkeyProto.Ukey2ServerInit;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-import junit.framework.TestCase;
-import org.junit.Assert;
-
-/**
- * Android compatible tests for the {@link Ukey2Handshake} class.
- */
-public class Ukey2HandshakeTest extends TestCase {
-
- private static final int MAX_AUTH_STRING_LENGTH = 32;
-
- @Override
- protected void setUp() throws Exception {
- KeyEncodingTest.installSunEcSecurityProviderIfNecessary();
- super.setUp();
- }
-
- /**
- * Tests correct use
- */
- public void testHandshake() throws Exception {
- if (KeyEncoding.isLegacyCryptoRequired()) {
- // this means we're running on an old SDK, which doesn't support the
- // necessary crypto. Let's not test anything in this case.
- return;
- }
-
- Ukey2Handshake client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- byte[] handshakeMessage;
-
- assertEquals(State.IN_PROGRESS, client.getHandshakeState());
- assertEquals(State.IN_PROGRESS, server.getHandshakeState());
-
- // Message 1 (Client Init)
- handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
- assertEquals(State.IN_PROGRESS, client.getHandshakeState());
- assertEquals(State.IN_PROGRESS, server.getHandshakeState());
-
- // Message 2 (Server Init)
- handshakeMessage = server.getNextHandshakeMessage();
- client.parseHandshakeMessage(handshakeMessage);
- assertEquals(State.IN_PROGRESS, client.getHandshakeState());
- assertEquals(State.IN_PROGRESS, server.getHandshakeState());
-
- // Message 3 (Client Finish)
- handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
- assertEquals(State.VERIFICATION_NEEDED, client.getHandshakeState());
- assertEquals(State.VERIFICATION_NEEDED, server.getHandshakeState());
-
- // Get the auth string
- byte[] clientAuthString = client.getVerificationString(MAX_AUTH_STRING_LENGTH);
- byte[] serverAuthString = server.getVerificationString(MAX_AUTH_STRING_LENGTH);
- Assert.assertArrayEquals(clientAuthString, serverAuthString);
- assertEquals(State.VERIFICATION_IN_PROGRESS, client.getHandshakeState());
- assertEquals(State.VERIFICATION_IN_PROGRESS, server.getHandshakeState());
-
- // Verify the auth string
- client.verifyHandshake();
- server.verifyHandshake();
- assertEquals(State.FINISHED, client.getHandshakeState());
- assertEquals(State.FINISHED, server.getHandshakeState());
-
- // Make a context
- D2DConnectionContext clientContext = client.toConnectionContext();
- D2DConnectionContext serverContext = server.toConnectionContext();
- assertContextsCompatible(clientContext, serverContext);
- assertEquals(State.ALREADY_USED, client.getHandshakeState());
- assertEquals(State.ALREADY_USED, server.getHandshakeState());
- }
-
- /**
- * Verify enums for ciphers match the proto values
- */
- public void testCipherEnumValuesCorrect() {
- assertEquals(
- "You added a cipher, but forgot to change the test", 1, HandshakeCipher.values().length);
-
- assertEquals(UkeyProto.Ukey2HandshakeCipher.P256_SHA512,
- HandshakeCipher.P256_SHA512.getValue());
- }
-
- /**
- * Tests incorrect use by callers (client and servers accidentally sending the wrong message at
- * the wrong time)
- */
- public void testHandshakeClientAndServerSendRepeatedOutOfOrderMessages() throws Exception {
- if (KeyEncoding.isLegacyCryptoRequired()) {
- // this means we're running on an old SDK, which doesn't support the
- // necessary crypto. Let's not test anything in this case.
- return;
- }
-
- // Client sends ClientInit (again) instead of ClientFinished
- Ukey2Handshake client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- byte[] handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
- server.getNextHandshakeMessage(); // do this to avoid illegal state
- try {
- server.parseHandshakeMessage(handshakeMessage);
- fail("Expected Alert for client sending ClientInit twice");
- } catch (HandshakeException e) {
- // success
- }
- assertEquals(State.ERROR, server.getHandshakeState());
-
- // Server sends ClientInit back to client instead of ServerInit
- client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- handshakeMessage = client.getNextHandshakeMessage();
- try {
- client.parseHandshakeMessage(handshakeMessage);
- fail("Expected Alert for server sending ClientInit back to client");
- } catch (AlertException e) {
- // success
- }
- assertEquals(State.ERROR, client.getHandshakeState());
-
- // Clients sends ServerInit back to client instead of ClientFinished
- client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server.getNextHandshakeMessage();
- try {
- server.parseHandshakeMessage(handshakeMessage);
- fail("Expected Alert for client sending ServerInit back to server");
- } catch (HandshakeException e) {
- // success
- }
- assertEquals(State.ERROR, server.getHandshakeState());
- }
-
- /**
- * Tests that verification codes are different for different handshake runs. Also tests a full
- * man-in-the-middle attack.
- */
- public void testVerificationCodeUniqueToSession() throws Exception {
- if (KeyEncoding.isLegacyCryptoRequired()) {
- // this means we're running on an old SDK, which doesn't support the
- // necessary crypto. Let's not test anything in this case.
- return;
- }
-
- // Client 1 and Server 1
- Ukey2Handshake client1 = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server1 = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- byte[] handshakeMessage = client1.getNextHandshakeMessage();
- server1.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server1.getNextHandshakeMessage();
- client1.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = client1.getNextHandshakeMessage();
- server1.parseHandshakeMessage(handshakeMessage);
- byte[] client1AuthString = client1.getVerificationString(MAX_AUTH_STRING_LENGTH);
- byte[] server1AuthString = server1.getVerificationString(MAX_AUTH_STRING_LENGTH);
- Assert.assertArrayEquals(client1AuthString, server1AuthString);
-
- // Client 2 and Server 2
- Ukey2Handshake client2 = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server2 = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- handshakeMessage = client2.getNextHandshakeMessage();
- server2.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server2.getNextHandshakeMessage();
- client2.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = client2.getNextHandshakeMessage();
- server2.parseHandshakeMessage(handshakeMessage);
- byte[] client2AuthString = client2.getVerificationString(MAX_AUTH_STRING_LENGTH);
- byte[] server2AuthString = server2.getVerificationString(MAX_AUTH_STRING_LENGTH);
- Assert.assertArrayEquals(client2AuthString, server2AuthString);
-
- // Make sure the verification strings differ
- assertFalse(Arrays.equals(client1AuthString, client2AuthString));
- }
-
- /**
- * Test an attack where the adversary swaps out the public key in the final message (i.e.,
- * commitment doesn't match public key)
- */
- public void testPublicKeyDoesntMatchCommitment() throws Exception {
- if (KeyEncoding.isLegacyCryptoRequired()) {
- // this means we're running on an old SDK, which doesn't support the
- // necessary crypto. Let's not test anything in this case.
- return;
- }
-
- // Run handshake as usual, but stop before sending client finished
- Ukey2Handshake client1 = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server1 = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- byte[] handshakeMessage = client1.getNextHandshakeMessage();
- server1.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server1.getNextHandshakeMessage();
-
- // Run another handshake and get the final client finished
- Ukey2Handshake client2 = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server2 = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- handshakeMessage = client2.getNextHandshakeMessage();
- server2.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server2.getNextHandshakeMessage();
- client2.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = client2.getNextHandshakeMessage();
-
- // Now use the client finished from second handshake in first handshake (simulates where an
- // attacker switches out the last message).
- try {
- server1.parseHandshakeMessage(handshakeMessage);
- fail("Expected server to catch mismatched ClientFinished");
- } catch (HandshakeException e) {
- // success
- }
- assertEquals(State.ERROR, server1.getHandshakeState());
-
- // Make sure caller can't actually do anything with the server now that an error has occurred
- try {
- server1.getVerificationString(MAX_AUTH_STRING_LENGTH);
- fail("Server allows operations post error");
- } catch (IllegalStateException e) {
- // success
- }
- try {
- server1.verifyHandshake();
- fail("Server allows operations post error");
- } catch (IllegalStateException e) {
- // success
- }
- try {
- server1.toConnectionContext();
- fail("Server allows operations post error");
- } catch (IllegalStateException e) {
- // success
- }
- }
-
- /**
- * Test commitment having unsupported version
- */
- public void testClientInitUnsupportedVersion() throws Exception {
- if (KeyEncoding.isLegacyCryptoRequired()) {
- // this means we're running on an old SDK, which doesn't support the
- // necessary crypto. Let's not test anything in this case.
- return;
- }
-
- // Get ClientInit and modify the version to be too big
- Ukey2Handshake client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- byte[] handshakeMessage = client.getNextHandshakeMessage();
-
- Ukey2Message.Builder message = Ukey2Message.newBuilder(
- Ukey2Message.parseFrom(handshakeMessage));
- Ukey2ClientInit.Builder clientInit =
- Ukey2ClientInit.newBuilder(Ukey2ClientInit.parseFrom(message.getMessageData()));
- clientInit.setVersion(Ukey2Handshake.VERSION + 1);
- message.setMessageData(ByteString.copyFrom(clientInit.build().toByteArray()));
- handshakeMessage = message.build().toByteArray();
-
- try {
- server.parseHandshakeMessage(handshakeMessage);
- fail("Server did not catch unsupported version (too big) in ClientInit");
- } catch (AlertException e) {
- // success
- }
- assertEquals(State.ERROR, server.getHandshakeState());
-
- // Get ClientInit and modify the version to be too big
- client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- handshakeMessage = client.getNextHandshakeMessage();
-
- message = Ukey2Message.newBuilder(
- Ukey2Message.parseFrom(handshakeMessage));
- clientInit = Ukey2ClientInit.newBuilder(Ukey2ClientInit.parseFrom(message.getMessageData()));
- clientInit.setVersion(0 /* minimum version is 1 */);
- message.setMessageData(ByteString.copyFrom(clientInit.build().toByteArray()));
- handshakeMessage = message.build().toByteArray();
-
- try {
- server.parseHandshakeMessage(handshakeMessage);
- fail("Server did not catch unsupported version (too small) in ClientInit");
- } catch (AlertException e) {
- // success
- }
- assertEquals(State.ERROR, server.getHandshakeState());
- }
-
- /**
- * Tests that server catches wrong number of random bytes in ClientInit
- */
- public void testWrongNonceLengthInClientInit() throws Exception {
- if (KeyEncoding.isLegacyCryptoRequired()) {
- // this means we're running on an old SDK, which doesn't support the
- // necessary crypto. Let's not test anything in this case.
- return;
- }
-
- // Get ClientInit and modify the nonce
- Ukey2Handshake client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- byte[] handshakeMessage = client.getNextHandshakeMessage();
-
- Ukey2Message.Builder message = Ukey2Message.newBuilder(
- Ukey2Message.parseFrom(handshakeMessage));
- Ukey2ClientInit.Builder clientInit =
- Ukey2ClientInit.newBuilder(Ukey2ClientInit.parseFrom(message.getMessageData()));
- clientInit.setRandom(
- ByteString.copyFrom(
- Arrays.copyOf(
- clientInit.getRandom().toByteArray(),
- 31 /* as per go/ukey2, nonces must be 32 bytes long */)));
- message.setMessageData(ByteString.copyFrom(clientInit.build().toByteArray()));
- handshakeMessage = message.build().toByteArray();
-
- try {
- server.parseHandshakeMessage(handshakeMessage);
- fail("Server did not catch nonce being too short in ClientInit");
- } catch (AlertException e) {
- // success
- }
- assertEquals(State.ERROR, server.getHandshakeState());
- }
-
- /**
- * Test that server catches missing commitment in ClientInit message
- */
- public void testServerCatchesMissingCommitmentInClientInit() throws Exception {
- if (KeyEncoding.isLegacyCryptoRequired()) {
- // this means we're running on an old SDK, which doesn't support the
- // necessary crypto. Let's not test anything in this case.
- return;
- }
-
- // Get ClientInit and modify the commitment
- Ukey2Handshake client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- byte[] handshakeMessage = client.getNextHandshakeMessage();
-
- Ukey2Message.Builder message = Ukey2Message.newBuilder(
- Ukey2Message.parseFrom(handshakeMessage));
- Ukey2ClientInit clientInit =
- Ukey2ClientInit.newBuilder(Ukey2ClientInit.parseFrom(message.getMessageData()))
- .build();
- Ukey2ClientInit.Builder badClientInit = Ukey2ClientInit.newBuilder()
- .setVersion(clientInit.getVersion())
- .setRandom(clientInit.getRandom());
- for (CipherCommitment commitment : clientInit.getCipherCommitmentsList()) {
- badClientInit.addCipherCommitments(commitment);
- }
-
- message.setMessageData(ByteString.copyFrom(badClientInit.build().toByteArray()));
- handshakeMessage = message.build().toByteArray();
-
- try {
- server.parseHandshakeMessage(handshakeMessage);
- fail("Server did not catch missing commitment in ClientInit");
- } catch (AlertException e) {
- // success
- }
- }
-
- /**
- * Test that client catches invalid version in ServerInit
- */
- public void testServerInitUnsupportedVersion() throws Exception {
- if (KeyEncoding.isLegacyCryptoRequired()) {
- // this means we're running on an old SDK, which doesn't support the
- // necessary crypto. Let's not test anything in this case.
- return;
- }
-
- // Get ServerInit and modify the version to be too big
- Ukey2Handshake client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- byte[] handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server.getNextHandshakeMessage();
-
- Ukey2Message.Builder message = Ukey2Message.newBuilder(
- Ukey2Message.parseFrom(handshakeMessage));
- Ukey2ServerInit serverInit =
- Ukey2ServerInit.newBuilder(Ukey2ServerInit.parseFrom(message.getMessageData()))
- .setVersion(Ukey2Handshake.VERSION + 1)
- .build();
- message.setMessageData(ByteString.copyFrom(serverInit.toByteArray()));
- handshakeMessage = message.build().toByteArray();
-
- try {
- client.parseHandshakeMessage(handshakeMessage);
- fail("Client did not catch unsupported version (too big) in ServerInit");
- } catch (AlertException e) {
- // success
- }
- assertEquals(State.ERROR, client.getHandshakeState());
-
- // Get ServerInit and modify the version to be too big
- client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server.getNextHandshakeMessage();
-
- message = Ukey2Message.newBuilder(Ukey2Message.parseFrom(handshakeMessage));
- serverInit =
- Ukey2ServerInit.newBuilder(Ukey2ServerInit.parseFrom(message.getMessageData()))
- .setVersion(0 /* minimum version is 1 */)
- .build();
- message.setMessageData(ByteString.copyFrom(serverInit.toByteArray()));
- handshakeMessage = message.build().toByteArray();
-
- try {
- client.parseHandshakeMessage(handshakeMessage);
- fail("Client did not catch unsupported version (too small) in ServerInit");
- } catch (AlertException e) {
- // success
- }
- assertEquals(State.ERROR, client.getHandshakeState());
- }
-
- /**
- * Tests that client catches wrong number of random bytes in ServerInit
- */
- public void testWrongNonceLengthInServerInit() throws Exception {
- if (KeyEncoding.isLegacyCryptoRequired()) {
- // this means we're running on an old SDK, which doesn't support the
- // necessary crypto. Let's not test anything in this case.
- return;
- }
-
- // Get ServerInit and modify the nonce
- Ukey2Handshake client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- byte[] handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server.getNextHandshakeMessage();
-
- Ukey2Message.Builder message = Ukey2Message.newBuilder(
- Ukey2Message.parseFrom(handshakeMessage));
- Ukey2ServerInit.Builder serverInitBuilder =
- Ukey2ServerInit.newBuilder(Ukey2ServerInit.parseFrom(message.getMessageData()));
- Ukey2ServerInit serverInit = serverInitBuilder.setRandom(ByteString.copyFrom(Arrays.copyOf(
- serverInitBuilder.getRandom().toByteArray(),
- 31 /* as per go/ukey2, nonces must be 32 bytes long */)))
- .build();
- message.setMessageData(ByteString.copyFrom(serverInit.toByteArray()));
- handshakeMessage = message.build().toByteArray();
-
- try {
- client.parseHandshakeMessage(handshakeMessage);
- fail("Client did not catch nonce being too short in ServerInit");
- } catch (AlertException e) {
- // success
- }
- assertEquals(State.ERROR, client.getHandshakeState());
- }
-
- /**
- * Test that client catches missing or incorrect handshake cipher in serverInit
- */
- public void testMissingOrIncorrectHandshakeCipherInServerInit() throws Exception {
- if (KeyEncoding.isLegacyCryptoRequired()) {
- // this means we're running on an old SDK, which doesn't support the
- // necessary crypto. Let's not test anything in this case.
- return;
- }
-
- // Get ServerInit
- Ukey2Handshake client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- byte[] handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server.getNextHandshakeMessage();
- Ukey2Message.Builder message = Ukey2Message.newBuilder(
- Ukey2Message.parseFrom(handshakeMessage));
- Ukey2ServerInit serverInit = Ukey2ServerInit.parseFrom(message.getMessageData());
-
- // remove handshake cipher
- Ukey2ServerInit badServerInit = Ukey2ServerInit.newBuilder()
- .setPublicKey(serverInit.getPublicKey())
- .setRandom(serverInit.getRandom())
- .setVersion(serverInit.getVersion())
- .build();
-
- message.setMessageData(ByteString.copyFrom(badServerInit.toByteArray()));
- handshakeMessage = message.build().toByteArray();
-
- try {
- client.parseHandshakeMessage(handshakeMessage);
- fail("Client did not catch missing handshake cipher in ServerInit");
- } catch (AlertException e) {
- // success
- }
- assertEquals(State.ERROR, client.getHandshakeState());
-
- // Get ServerInit
- client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server.getNextHandshakeMessage();
- message = Ukey2Message.newBuilder(Ukey2Message.parseFrom(handshakeMessage));
- serverInit = Ukey2ServerInit.parseFrom(message.getMessageData());
-
- // put in a bad handshake cipher
- badServerInit = Ukey2ServerInit.newBuilder()
- .setPublicKey(serverInit.getPublicKey())
- .setRandom(serverInit.getRandom())
- .setVersion(serverInit.getVersion())
- .setHandshakeCipher(UkeyProto.Ukey2HandshakeCipher.RESERVED)
- .build();
-
- message.setMessageData(ByteString.copyFrom(badServerInit.toByteArray()));
- handshakeMessage = message.build().toByteArray();
-
- try {
- client.parseHandshakeMessage(handshakeMessage);
- fail("Client did not catch bad handshake cipher in ServerInit");
- } catch (AlertException e) {
- // success
- }
- assertEquals(State.ERROR, client.getHandshakeState());
- }
-
- /**
- * Test that client catches missing or incorrect public key in serverInit
- */
- public void testMissingOrIncorrectPublicKeyInServerInit() throws Exception {
- if (KeyEncoding.isLegacyCryptoRequired()) {
- // this means we're running on an old SDK, which doesn't support the
- // necessary crypto. Let's not test anything in this case.
- return;
- }
-
- // Get ServerInit
- Ukey2Handshake client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- byte[] handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server.getNextHandshakeMessage();
- Ukey2Message.Builder message = Ukey2Message.newBuilder(
- Ukey2Message.parseFrom(handshakeMessage));
- Ukey2ServerInit serverInit = Ukey2ServerInit.parseFrom(message.getMessageData());
-
- // remove public key
- Ukey2ServerInit badServerInit = Ukey2ServerInit.newBuilder()
- .setRandom(serverInit.getRandom())
- .setVersion(serverInit.getVersion())
- .setHandshakeCipher(serverInit.getHandshakeCipher())
- .build();
-
- message.setMessageData(ByteString.copyFrom(badServerInit.toByteArray()));
- handshakeMessage = message.build().toByteArray();
-
- try {
- client.parseHandshakeMessage(handshakeMessage);
- fail("Client did not catch missing public key in ServerInit");
- } catch (AlertException e) {
- // success
- }
- assertEquals(State.ERROR, client.getHandshakeState());
-
- // Get ServerInit
- client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server.getNextHandshakeMessage();
- message = Ukey2Message.newBuilder(
- Ukey2Message.parseFrom(handshakeMessage));
- serverInit = Ukey2ServerInit.parseFrom(message.getMessageData());
-
- // put in a bad public key
- badServerInit = Ukey2ServerInit.newBuilder()
- .setPublicKey(ByteString.copyFrom(new byte[] {42, 12, 1}))
- .setRandom(serverInit.getRandom())
- .setVersion(serverInit.getVersion())
- .setHandshakeCipher(serverInit.getHandshakeCipher())
- .build();
-
- message.setMessageData(ByteString.copyFrom(badServerInit.toByteArray()));
- handshakeMessage = message.build().toByteArray();
-
- try {
- client.parseHandshakeMessage(handshakeMessage);
- fail("Client did not catch bad public key in ServerInit");
- } catch (AlertException e) {
- // success
- }
- assertEquals(State.ERROR, client.getHandshakeState());
- }
-
- /**
- * Test that client catches missing or incorrect public key in clientFinished
- */
- public void testMissingOrIncorrectPublicKeyInClientFinished() throws Exception {
- if (KeyEncoding.isLegacyCryptoRequired()) {
- // this means we're running on an old SDK, which doesn't support the
- // necessary crypto. Let's not test anything in this case.
- return;
- }
-
- // Get ClientFinished
- Ukey2Handshake client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- byte[] handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server.getNextHandshakeMessage();
- client.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = client.getNextHandshakeMessage();
- Ukey2Message.Builder message = Ukey2Message.newBuilder(
- Ukey2Message.parseFrom(handshakeMessage));
-
- // remove public key
- Ukey2ClientFinished.Builder badClientFinished = Ukey2ClientFinished.newBuilder();
-
- message.setMessageData(ByteString.copyFrom(badClientFinished.build().toByteArray()));
- handshakeMessage = message.build().toByteArray();
-
- try {
- server.parseHandshakeMessage(handshakeMessage);
- fail("Server did not catch missing public key in ClientFinished");
- } catch (HandshakeException e) {
- // success
- }
- assertEquals(State.ERROR, server.getHandshakeState());
-
- // Get ClientFinished
- client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server.getNextHandshakeMessage();
- client.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = client.getNextHandshakeMessage();
- message = Ukey2Message.newBuilder(Ukey2Message.parseFrom(handshakeMessage));
-
- // remove public key
- badClientFinished = Ukey2ClientFinished.newBuilder()
- .setPublicKey(ByteString.copyFrom(new byte[] {42, 12, 1}));
-
- message.setMessageData(ByteString.copyFrom(badClientFinished.build().toByteArray()));
- handshakeMessage = message.build().toByteArray();
-
- try {
- server.parseHandshakeMessage(handshakeMessage);
- fail("Server did not catch bad public key in ClientFinished");
- } catch (HandshakeException e) {
- // success
- }
- assertEquals(State.ERROR, server.getHandshakeState());
- }
-
- /**
- * Tests that items (nonces, commitments, public keys) that should be random are at least
- * different on every run.
- */
- public void testRandomItemsDifferentOnEveryRun() throws Exception {
- if (KeyEncoding.isLegacyCryptoRequired()) {
- // this means we're running on an old SDK, which doesn't support the
- // necessary crypto. Let's not test anything in this case.
- return;
- }
-
- int numberOfRuns = 50;
-
- // Search for collisions
- Set<Integer> commitments = new HashSet<>(numberOfRuns);
- Set<Integer> clientNonces = new HashSet<>(numberOfRuns);
- Set<Integer> serverNonces = new HashSet<>(numberOfRuns);
- Set<Integer> serverPublicKeys = new HashSet<>(numberOfRuns);
- Set<Integer> clientPublicKeys = new HashSet<>(numberOfRuns);
-
- for (int i = 0; i < numberOfRuns; i++) {
- Ukey2Handshake client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- byte[] handshakeMessage = client.getNextHandshakeMessage();
- Ukey2Message message = Ukey2Message.parseFrom(handshakeMessage);
- Ukey2ClientInit clientInit = Ukey2ClientInit.parseFrom(message.getMessageData());
-
- server.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server.getNextHandshakeMessage();
- message = Ukey2Message.parseFrom(handshakeMessage);
- Ukey2ServerInit serverInit = Ukey2ServerInit.parseFrom(message.getMessageData());
-
- client.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = client.getNextHandshakeMessage();
- message = Ukey2Message.parseFrom(handshakeMessage);
- Ukey2ClientFinished clientFinished = Ukey2ClientFinished.parseFrom(message.getMessageData());
-
- // Clean up to save some memory (b/32054837)
- client = null;
- server = null;
- handshakeMessage = null;
- message = null;
- System.gc();
-
- // ClientInit randomness
- Integer nonceHash = Integer.valueOf(Arrays.hashCode(clientInit.getRandom().toByteArray()));
- if (clientNonces.contains(nonceHash) || serverNonces.contains(nonceHash)) {
- fail("Nonce in ClientINit has repeated!");
- }
- clientNonces.add(nonceHash);
-
- Integer commitmentHash = 0;
- for (CipherCommitment commitement : clientInit.getCipherCommitmentsList()) {
- commitmentHash += Arrays.hashCode(commitement.toByteArray());
- }
- if (commitments.contains(nonceHash)) {
- fail("Commitment has repeated!");
- }
- commitments.add(commitmentHash);
-
- // ServerInit randomness
- nonceHash = Integer.valueOf(Arrays.hashCode(serverInit.getRandom().toByteArray()));
- if (serverNonces.contains(nonceHash) || clientNonces.contains(nonceHash)) {
- fail("Nonce in ServerInit repeated!");
- }
- serverNonces.add(nonceHash);
-
- Integer publicKeyHash =
- Integer.valueOf(Arrays.hashCode(serverInit.getPublicKey().toByteArray()));
- if (serverPublicKeys.contains(publicKeyHash) || clientPublicKeys.contains(publicKeyHash)) {
- fail("Public Key in ServerInit repeated!");
- }
- serverPublicKeys.add(publicKeyHash);
-
- // Client Finished randomness
- publicKeyHash = Integer.valueOf(Arrays.hashCode(clientFinished.getPublicKey().toByteArray()));
- if (serverPublicKeys.contains(publicKeyHash) || clientPublicKeys.contains(publicKeyHash)) {
- fail("Public Key in ClientFinished repeated!");
- }
- clientPublicKeys.add(publicKeyHash);
- }
- }
-
- /**
- * Tests that {@link Ukey2Handshake#getVerificationString(int)} enforces sane verification string
- * lengths.
- */
- public void testGetVerificationEnforcesSaneLengths() throws Exception {
- if (KeyEncoding.isLegacyCryptoRequired()) {
- // this means we're running on an old SDK, which doesn't support the
- // necessary crypto. Let's not test anything in this case.
- return;
- }
-
- // Run the protocol
- Ukey2Handshake client = Ukey2Handshake.forInitiator(HandshakeCipher.P256_SHA512);
- Ukey2Handshake server = Ukey2Handshake.forResponder(HandshakeCipher.P256_SHA512);
- byte[] handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = server.getNextHandshakeMessage();
- client.parseHandshakeMessage(handshakeMessage);
- handshakeMessage = client.getNextHandshakeMessage();
- server.parseHandshakeMessage(handshakeMessage);
-
- // Try to get too short verification string
- try {
- client.getVerificationString(0);
- fail("Too short verification string allowed");
- } catch (IllegalArgumentException e) {
- // success
- }
-
- // Try to get too long verification string
- try {
- server.getVerificationString(MAX_AUTH_STRING_LENGTH + 1);
- fail("Too long verification string allowed");
- } catch (IllegalArgumentException e) {
- // success
- }
- }
-
- /**
- * Asserts that the given client and server contexts are compatible
- */
- private void assertContextsCompatible(
- D2DConnectionContext clientContext, D2DConnectionContext serverContext) {
- assertNotNull(clientContext);
- assertNotNull(serverContext);
- assertEquals(D2DConnectionContextV1.PROTOCOL_VERSION, clientContext.getProtocolVersion());
- assertEquals(D2DConnectionContextV1.PROTOCOL_VERSION, serverContext.getProtocolVersion());
- assertEquals(clientContext.getEncodeKey(), serverContext.getDecodeKey());
- assertEquals(clientContext.getDecodeKey(), serverContext.getEncodeKey());
- assertFalse(clientContext.getEncodeKey().equals(clientContext.getDecodeKey()));
- assertEquals(0, clientContext.getSequenceNumberForEncoding());
- assertEquals(0, clientContext.getSequenceNumberForDecoding());
- assertEquals(0, serverContext.getSequenceNumberForEncoding());
- assertEquals(0, serverContext.getSequenceNumberForDecoding());
- }
-}