Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions common/src/test/java/org/conscrypt/javax/net/ssl/SSLEngineTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,116 @@ private void assertWrapSucceeds(ByteBuffer[] buffers, int offset, int length) th
}
}

/*
* The preconditions for the unwrap() methods of SSLEngine have a relatively
* complex mapping from precondition to the exception thrown on failure. This method
* checks that all the failure cases throw the correct exception and that
* corner cases which should not throw are also handled correctly.
*/
@Test
public void unwrapPreconditions() throws Exception {
int bufferSize = 128;
int arrayLength = 5;
ByteBuffer srcBuffer = BufferType.HEAP.newRandomBuffer(bufferSize);
ByteBuffer dstBuffer = ByteBuffer.allocate(bufferSize);
ByteBuffer readOnlyDestBuffer = dstBuffer.asReadOnlyBuffer();

ByteBuffer[] dsts = BufferType.HEAP.newBufferArray(arrayLength, bufferSize);
ByteBuffer[] dstsWithNullEntry = Arrays.copyOf(dsts, dsts.length);
int nullBufferIndex = 2;
dstsWithNullEntry[nullBufferIndex] = null;
ByteBuffer[] dstsWithReadOnlyEntry = Arrays.copyOf(dsts, dsts.length);
int readOnlyBufferIndex = 2;
dstsWithReadOnlyEntry[readOnlyBufferIndex] =
dstsWithReadOnlyEntry[readOnlyBufferIndex].asReadOnlyBuffer();

// Failure cases
// Client/server mode not set => IllegalStateException
assertThrows(IllegalStateException.class,
() -> newUnconnectedEngine().unwrap(srcBuffer, dstBuffer));
assertThrows(IllegalStateException.class,
() -> newUnconnectedEngine().unwrap(srcBuffer, dsts));
assertThrows(IllegalStateException.class,
() -> newUnconnectedEngine().unwrap(srcBuffer, dsts, 0, 1));

// Read-only destination => ReadOnlyBufferException
assertThrows(ReadOnlyBufferException.class,
() -> newConnectedEngine().unwrap(srcBuffer, readOnlyDestBuffer));
assertThrows(ReadOnlyBufferException.class,
() -> newConnectedEngine().unwrap(srcBuffer, dstsWithReadOnlyEntry));
assertThrows(ReadOnlyBufferException.class,
() -> newConnectedEngine().unwrap(
srcBuffer, dstsWithReadOnlyEntry, 0, arrayLength));

// Null destination => IllegalArgumentException
assertThrows(IllegalArgumentException.class,
() -> newConnectedEngine().unwrap(srcBuffer, (ByteBuffer) null));
assertThrows(IllegalArgumentException.class,
() -> newConnectedEngine().unwrap(srcBuffer, (ByteBuffer[]) null));
assertThrows(IllegalArgumentException.class,
() -> newConnectedEngine().unwrap(srcBuffer, null, 0, 1));

// Null source => IllegalArgumentException
assertThrows(IllegalArgumentException.class,
() -> newConnectedEngine().unwrap(null, dstBuffer));
assertThrows(IllegalArgumentException.class,
() -> newConnectedEngine().unwrap(null, dsts));
assertThrows(IllegalArgumentException.class,
() -> newConnectedEngine().unwrap(null, dsts, 0, 1));

// Null entries in destination buffer array => IllegalArgumentException
assertThrows(IllegalArgumentException.class,
() -> newConnectedEngine().unwrap(srcBuffer, dstsWithNullEntry));
assertThrows(IllegalArgumentException.class,
() -> newConnectedEngine().unwrap(
srcBuffer, dstsWithNullEntry, 0, arrayLength));

// Bad offset or length => IndexOutOfBoundsException
assertThrows(IndexOutOfBoundsException.class,
() -> newConnectedEngine().unwrap(srcBuffer, dsts, 0, arrayLength + 1));
assertThrows(IndexOutOfBoundsException.class,
() -> newConnectedEngine().unwrap(srcBuffer, dsts, arrayLength, 1));
assertThrows(IndexOutOfBoundsException.class,
() -> newConnectedEngine().unwrap(srcBuffer, dsts, arrayLength - 1, 2));

// Corner cases which should not throw
// Zero length arrays of output buffers should never throw
assertUnwrapDoesNotThrow(dsts, 0, 0);
assertUnwrapDoesNotThrow(dsts, arrayLength, 0);

// TODO(prb): Add tests for null/read-only entries outside the selected offset and length
// after https://github.com/google/conscrypt/issues/1372 is fixed.
}

// Asserts that an unwrap call with the given arguments does not throw a precondition
// exception. Note that the unwrap call itself may not produce plaintext if the selected
// destination buffers don't have enough capacity, but this is purely a precondition test
// and actual unwrap functionality is tested elsewhere.
private void assertUnwrapDoesNotThrow(ByteBuffer[] dsts, int offset, int length) throws Exception {
try (TestSSLEnginePair pair = TestSSLEnginePair.create()) {
assertConnected(pair);

// Wrap some plaintext to get TLS ciphertext to unwrap.
ByteBuffer plaintext = BufferType.HEAP.newRandomBuffer(128);
ByteBuffer ciphertext =
ByteBuffer.allocate(pair.client.getSession().getPacketBufferSize());
SSLEngineResult wrapResult = pair.client.wrap(plaintext, ciphertext);
assertEquals(Status.OK, wrapResult.getStatus());
ciphertext.flip();

// Reset the selected destination buffers to their initial (empty) state.
for (int i = offset; i < offset + length; i++) {
dsts[i].clear();
}

// Unwrap: may return BUFFER_OVERFLOW if the selected buffers don't have enough capacity but that's
// fine for this *precondition* test.
SSLEngineResult result = pair.server.unwrap(ciphertext, dsts, offset, length);
assertTrue(result.getStatus() == Status.OK
|| result.getStatus() == Status.BUFFER_OVERFLOW);
}
}

@Test
public void bufferArrayOffsets() throws Exception {
TestSSLEnginePair pair = TestSSLEnginePair.create();
Expand Down
8 changes: 8 additions & 0 deletions testing/src/main/java/org/conscrypt/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ ByteBuffer newBuffer(int size) {
private static final Random random = new Random(System.currentTimeMillis());
abstract ByteBuffer newBuffer(int size);

public ByteBuffer[] newBufferArray(int arrayLength, int bufferSize) {
ByteBuffer[] result = new ByteBuffer[arrayLength];
for (int i = 0; i < arrayLength; i++) {
result[i] = newBuffer(bufferSize);
}
return result;
}

public ByteBuffer[] newRandomBuffers(int... sizes) {
int numBuffers = sizes.length;
ByteBuffer[] result = new ByteBuffer[numBuffers];
Expand Down
Loading