Skip to content

fix: Merge mainline into keyrings, reverting the keyring reverts #209

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 6, 2020
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,17 @@ calls to `AwsCrypto.encrypt(EncryptRequest)` and `AwsCrypto.decrypt(DecryptReque
[#165](https://github.com/aws/aws-encryption-sdk-java/pull/165),
[#168](https://github.com/aws/aws-encryption-sdk-java/pull/168),
and [#170](https://github.com/aws/aws-encryption-sdk-java/pull/170).


## 1.6.2 -- 2020-05-26

### Patches
* Validate final frame length does not exceed the frame size in the message header [PR #166](https://github.com/aws/aws-encryption-sdk-java/pull/166)
* Validate entire ciphertext has been processed before returning [PR #191](https://github.com/aws/aws-encryption-sdk-java/pull/191)

### Maintenance
* Update AWS Java SDK version from 1.11.561 to 1.11.704. [PR #186](https://github.com/aws/aws-encryption-sdk-java/pull/186)
* Upgrade Bouncy Castle from 1.61 to 1.65 [PR #179](https://github.com/aws/aws-encryption-sdk-java/pull/179)

## 1.6.1 -- 2019-10-29

### Deprecation Warnings
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ You can get the latest release from Maven:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-encryption-sdk-java</artifactId>
<version>1.6.1</version>
<version>1.6.2</version>
</dependency>
```

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>com.amazonaws</groupId>
<artifactId>aws-encryption-sdk-java</artifactId>
<version>1.6.1</version>
<version>1.6.2</version>
<packaging>jar</packaging>

<name>aws-encryption-sdk-java</name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,15 @@

package com.amazonaws.encryptionsdk.internal;

import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;

import com.amazonaws.encryptionsdk.CryptoAlgorithm;
import com.amazonaws.encryptionsdk.exception.AwsCryptoException;
import com.amazonaws.encryptionsdk.exception.BadCiphertextException;
import com.amazonaws.encryptionsdk.model.CipherBlockHeaders;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import java.util.Arrays;

/**
* The block decryption handler is an implementation of CryptoHandler that
* provides methods to decrypt content encrypted and stored in a single block.
Expand Down Expand Up @@ -97,6 +96,11 @@ public BlockDecryptionHandler(final SecretKey decryptionKey, final short nonceLe
synchronized public ProcessingSummary processBytes(final byte[] in, final int off, final int len,
final byte[] out,
final int outOff) throws AwsCryptoException {

if (complete_) {
throw new AwsCryptoException("Ciphertext has already been processed.");
}

final byte[] bytesToParse = new byte[unparsedBytes_.length + len];
// If there were previously unparsed bytes, add them as the first
// set of bytes to be parsed in this call.
Expand Down Expand Up @@ -166,6 +170,9 @@ synchronized public ProcessingSummary processBytes(final byte[] in, final int of
*/
@Override
synchronized public int doFinal(final byte[] out, final int outOff) throws BadCiphertextException {
if (!complete_) {
throw new BadCiphertextException("Unable to process entire ciphertext.");
}
return 0;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,10 @@ public int doFinal(final byte[] out, final int outOff) throws BadCiphertextExcep
} else {
int result = contentCryptoHandler_.doFinal(out, outOff);

if (!ciphertextHeaders_.isComplete() || !contentCryptoHandler_.isComplete()) {
throw new BadCiphertextException("Unable to process entire ciphertext.");
}

return result;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,16 @@ public FrameDecryptionHandler(final SecretKey decryptionKey, final short nonceLe
*
* @param in
* the input byte array.
* @param inOff
* @param off
* the offset into the in array where the data to be decrypted starts.
* @param inLen
* @param len
* the number of bytes to be decrypted.
* @param out
* the output buffer the decrypted plaintext bytes go into.
* @param outOff
* the offset into the output byte array the decrypted data starts at.
* @return the number of bytes written to out and processed
* @throws InvalidCiphertextException
* @throws BadCiphertextException
* if frame number is invalid/out-of-order or if the bytes do not decrypt correctly.
* @throws AwsCryptoException
* if the content type found in the headers is not of frame type.
Expand All @@ -96,6 +96,11 @@ public FrameDecryptionHandler(final SecretKey decryptionKey, final short nonceLe
public ProcessingSummary processBytes(final byte[] in, final int off, final int len, final byte[] out,
final int outOff)
throws BadCiphertextException, AwsCryptoException {

if (complete_) {
throw new AwsCryptoException("Ciphertext has already been processed.");
}

final long totalBytesToParse = unparsedBytes_.length + (long) len;
if (totalBytesToParse > Integer.MAX_VALUE) {
throw new AwsCryptoException(
Expand Down Expand Up @@ -200,6 +205,10 @@ public ProcessingSummary processBytes(final byte[] in, final int off, final int
*/
@Override
public int doFinal(final byte[] out, final int outOff) {
if (!complete_) {
throw new BadCiphertextException("Unable to process entire ciphertext.");
}

return 0;
}

Expand Down
51 changes: 51 additions & 0 deletions src/test/java/com/amazonaws/encryptionsdk/AwsCryptoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
Expand Down Expand Up @@ -150,6 +151,31 @@ private void doTamperedEncryptDecryptWithKeyring(final CryptoAlgorithm cryptoAlg
.ciphertext(cipherText).build()));
}

private void doTruncatedEncryptDecrypt(final CryptoAlgorithm cryptoAlg, final int byteSize, final int frameSize) {
final byte[] plaintextBytes = new byte[byteSize];

final Map<String, String> encryptionContext = new HashMap<>(1);
encryptionContext.put("ENC1", "Encrypt-decrypt test with %d" + byteSize);

encryptionClient_.setEncryptionAlgorithm(cryptoAlg);
encryptionClient_.setEncryptionFrameSize(frameSize);

final byte[] cipherText = encryptionClient_.encryptData(
masterKeyProvider,
plaintextBytes,
encryptionContext).getResult();
final byte[] truncatedCipherText = Arrays.copyOf(cipherText, cipherText.length - 1);
try {
encryptionClient_.decryptData(
masterKeyProvider,
truncatedCipherText
).getResult();
Assert.fail("Expected BadCiphertextException");
} catch (final BadCiphertextException ex) {
// Expected exception
}
}

private void doEncryptDecryptWithParsedCiphertext(final int byteSize, final int frameSize) {
final byte[] plaintextBytes = new byte[byteSize];

Expand Down Expand Up @@ -235,6 +261,31 @@ public void encryptDecryptWithBadSignature() {
}
}

@Test
public void encryptDecryptWithTruncatedCiphertext() {
for (final CryptoAlgorithm cryptoAlg : EnumSet.allOf(CryptoAlgorithm.class)) {
final int[] frameSizeToTest = TestUtils.getFrameSizesToTest(cryptoAlg);

for (int i = 0; i < frameSizeToTest.length; i++) {
final int frameSize = frameSizeToTest[i];
int[] bytesToTest = { 0, 1, frameSize - 1, frameSize, frameSize + 1, (int) (frameSize * 1.5),
frameSize * 2, 1000000 };

for (int j = 0; j < bytesToTest.length; j++) {
final int byteSize = bytesToTest[j];

if (byteSize > 500_000) {
continue;
}

if (byteSize >= 0) {
doTruncatedEncryptDecrypt(cryptoAlg, byteSize, frameSize);
}
}
}
}
}

@Test
public void encryptDecryptWithParsedCiphertext() {
for (final CryptoAlgorithm cryptoAlg : EnumSet.allOf(CryptoAlgorithm.class)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

package com.amazonaws.encryptionsdk.internal;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.nio.ByteBuffer;
Expand All @@ -22,6 +21,7 @@
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import com.amazonaws.encryptionsdk.exception.BadCiphertextException;
import org.junit.Before;
import org.junit.Test;

Expand Down Expand Up @@ -58,11 +58,9 @@ public void estimateOutputSize() {
assertTrue(outSize >= inLen);
}

@Test
public void decryptWithoutHeaders() {
final byte[] out = new byte[1];
final int returnedLen = blockDecryptionHandler_.doFinal(out, 0);
assertEquals(0, returnedLen);
@Test(expected= BadCiphertextException.class)
public void doFinalCalledWhileNotComplete() {
blockDecryptionHandler_.doFinal(new byte[1], 0);
}

@Test(expected = AwsCryptoException.class)
Expand Down Expand Up @@ -90,4 +88,23 @@ public void decryptMaxContentLength() {
final byte[] decryptedOut = new byte[decryptedOutLen];
blockDecryptionHandler_.processBytes(outBuff.array(), 0, outBuff.array().length, decryptedOut, 0);
}
}

@Test(expected = AwsCryptoException.class)
public void processBytesCalledWhileComplete() {
final BlockEncryptionHandler blockEncryptionHandler = new BlockEncryptionHandler(
dataKey_,
nonceLen_,
cryptoAlgorithm_,
messageId_);
final byte[] in = new byte[0];
final int outLen = blockEncryptionHandler.estimateOutputSize(in.length);
final byte[] out = new byte[outLen];

blockEncryptionHandler.processBytes(in, 0, in.length, out, 0);
blockEncryptionHandler.doFinal(out, 0);

final byte[] decryptedOut = new byte[outLen];
blockDecryptionHandler_.processBytes(out, 0, outLen, decryptedOut, 0);
blockDecryptionHandler_.processBytes(out, 0, outLen, decryptedOut, 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.Collections;
import java.util.Map;

import com.amazonaws.encryptionsdk.model.CiphertextHeaders;
import com.amazonaws.encryptionsdk.keyrings.Keyring;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -146,6 +147,20 @@ public void invalidOffsetProcessBytes() {
decryptionHandler.processBytes(in, -1, in.length, out, 0);
}

@Test(expected = BadCiphertextException.class)
public void incompleteCiphertext() {
byte[] ciphertext = getTestHeaders();

CiphertextHeaders h = new CiphertextHeaders();
h.deserialize(ciphertext, 0);

final DecryptionHandler<StaticMasterKey> decryptionHandler = DecryptionHandler.create(masterKeyProvider_);
final byte[] out = new byte[1];

decryptionHandler.processBytes(ciphertext, 0, ciphertext.length - 1, out, 0);
decryptionHandler.doFinal(out, 0);
}

@Test
public void testNullMasterKey() {
final DecryptionHandler decryptionHandler = DecryptionHandler.create(new DefaultCryptoMaterialsManager(keyring));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,30 @@ public void finalFrameLengthTooLarge() {

frameDecryptionHandler_.processBytes(in, 0, in.length, out, 0);
}

@Test(expected = BadCiphertextException.class)
public void doFinalCalledWhileNotComplete() {
frameDecryptionHandler_.doFinal(new byte[1], 0);
}

@Test(expected = AwsCryptoException.class)
public void processBytesCalledWhileComplete() {
final FrameEncryptionHandler frameEncryptionHandler = new FrameEncryptionHandler(
dataKey_,
nonceLen_,
cryptoAlgorithm_,
messageId_,
frameSize_);
final byte[] in = new byte[0];
final int outLen = frameEncryptionHandler.estimateOutputSize(in.length);
final byte[] out = new byte[outLen];

frameEncryptionHandler.processBytes(in, 0, in.length, out, 0);
frameEncryptionHandler.doFinal(out, 0);

final byte[] decryptedOut = new byte[outLen];

frameDecryptionHandler_.processBytes(out, 0, out.length, decryptedOut, 0);
frameDecryptionHandler_.processBytes(out, 0, out.length, decryptedOut, 0);
}
}