Skip to content

Commit c6d5d8a

Browse files
authored
Merge branch 'main' into imabhichow/update-releaserc
2 parents 1a54cb6 + 2b13cf2 commit c6d5d8a

File tree

82 files changed

+11793
-6498
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+11793
-6498
lines changed

.gitmodules

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[submodule "specification"]
22
path = specification
3-
url = [email protected]:awslabs/aws-encryption-sdk-specification.git
4-
branch = kessplas/s3-ec-v3
3+
url = [email protected]:awslabs/private-aws-encryption-sdk-specification-staging.git
4+
branch = fire-egg-staging

specification

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package software.amazon.encryption.s3;
4+
5+
/**
6+
* Defines the S3 Encryption Client's key commitment behavior during encryption and decryption operations.
7+
* Key commitment ensures each encrypted object can be decrypted to only a single plaintext by cryptographically binding the data key to the encrypted object.
8+
* <p>
9+
* For more information, refer to the <a href=https://docs.aws.amazon.com/amazon-s3-encryption-client/latest/developerguide/concepts.html)>Developer Guide.</a>
10+
*/
11+
public enum CommitmentPolicy {
12+
13+
//= specification/s3-encryption/key-commitment.md#commitment-policy
14+
//# When the commitment policy is FORBID_ENCRYPT_ALLOW_DECRYPT, the S3EC MUST allow decryption using algorithm suites which do not support key commitment.
15+
/**
16+
* This policy forbids the client from encrypting objects with an algorithm suite which supports key commitment.
17+
* This policy allows decryption of objects using algorithm suites which do not support key commitment. Objects encrypted with key commitment may be decrypted as well.
18+
* <p>
19+
* This client will write objects that any v3 client can read and any v4 client can read.
20+
* This client can read objects written by any v3 or v4 client.
21+
* This is the default (and only) policy for v3 clients.
22+
*/
23+
FORBID_ENCRYPT_ALLOW_DECRYPT(false, false),
24+
25+
//= specification/s3-encryption/key-commitment.md#commitment-policy
26+
//# When the commitment policy is REQUIRE_ENCRYPT_ALLOW_DECRYPT, the S3EC MUST only encrypt using an algorithm suite which supports key commitment.
27+
//= specification/s3-encryption/key-commitment.md#commitment-policy
28+
//# When the commitment policy is REQUIRE_ENCRYPT_ALLOW_DECRYPT, the S3EC MUST allow decryption using algorithm suites which do not support key commitment.
29+
/**
30+
* This policy requires the client to encrypt objects using an algorithm suite which supports key commitment.
31+
* This policy allows decryption of objects using algorithm suites which do not support key commitment. Objects encrypted with key commitment may be decrypted as well.
32+
* <p>
33+
* This client will write objects that any v4 client can read.
34+
* Only V4 clients and the latest V3 client can read objects written by a client using this policy.
35+
* This client can read objects written by any V3 or V4 client.
36+
*/
37+
REQUIRE_ENCRYPT_ALLOW_DECRYPT(true, false),
38+
39+
//= specification/s3-encryption/key-commitment.md#commitment-policy
40+
//# When the commitment policy is REQUIRE_ENCRYPT_REQUIRE_DECRYPT, the S3EC MUST only encrypt using an algorithm suite which supports key commitment.
41+
//= specification/s3-encryption/key-commitment.md#commitment-policy
42+
//# When the commitment policy is REQUIRE_ENCRYPT_REQUIRE_DECRYPT, the S3EC MUST NOT allow decryption using algorithm suites which do not support key commitment.
43+
/**
44+
* This policy requires the client to encrypt objects using an algorithm suite which supports key commitment.
45+
* This policy requires that objects have been encrypted using an algorithm suite which supports key commitment.
46+
* <p>
47+
* This client will write objects that any v4 client can read.
48+
* Only V4 clients and the latest V3 clients can read objects written by a client using this policy.
49+
* This client can only read objects written by v4 clients with key commitment enabled.
50+
* This is the most secure policy and should be used when all objects are encrypted with key commitment.
51+
*/
52+
REQUIRE_ENCRYPT_REQUIRE_DECRYPT(true, true);
53+
54+
private final boolean _requiresEncrypt;
55+
private final boolean _requiresDecrypt;
56+
57+
CommitmentPolicy(boolean requiresEncrypt, boolean requiresDecrypt) {
58+
_requiresEncrypt = requiresEncrypt;
59+
_requiresDecrypt = requiresDecrypt;
60+
}
61+
62+
/**
63+
* Indicates whether this commitment policy requires key commitment for encryption operations.
64+
*
65+
* @return {@code true} if encryption must use algorithm suites that support key commitment
66+
*/
67+
public boolean requiresEncrypt() {
68+
return _requiresEncrypt;
69+
}
70+
71+
/**
72+
* Indicates whether this commitment policy requires key commitment for decryption operations.
73+
*
74+
* @return {@code true} if decryption can only succeed for messages with valid key commitment
75+
*/
76+
public boolean requiresDecrypt() {
77+
return _requiresDecrypt;
78+
}
79+
}

src/main/java/software/amazon/encryption/s3/S3AsyncEncryptionClient.java

Lines changed: 105 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,24 @@
22
// SPDX-License-Identifier: Apache-2.0
33
package software.amazon.encryption.s3;
44

5+
import static software.amazon.encryption.s3.S3EncryptionClientUtilities.DEFAULT_BUFFER_SIZE_BYTES;
6+
import static software.amazon.encryption.s3.S3EncryptionClientUtilities.MAX_ALLOWED_BUFFER_SIZE_BYTES;
7+
import static software.amazon.encryption.s3.S3EncryptionClientUtilities.MIN_ALLOWED_BUFFER_SIZE_BYTES;
8+
import static software.amazon.encryption.s3.internal.ApiNameVersion.API_NAME_INTERCEPTOR;
9+
10+
import java.net.URI;
11+
import java.security.KeyPair;
12+
import java.security.Provider;
13+
import java.security.SecureRandom;
14+
import java.util.List;
15+
import java.util.Map;
16+
import java.util.Optional;
17+
import java.util.concurrent.CompletableFuture;
18+
import java.util.function.Consumer;
19+
import java.util.function.Function;
20+
21+
import javax.crypto.SecretKey;
22+
523
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
624
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
725
import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration;
@@ -37,6 +55,7 @@
3755
import software.amazon.awssdk.services.s3.model.UploadPartRequest;
3856
import software.amazon.awssdk.services.s3.model.UploadPartResponse;
3957
import software.amazon.awssdk.services.s3.multipart.MultipartConfiguration;
58+
import software.amazon.encryption.s3.algorithms.AlgorithmSuite;
4059
import software.amazon.encryption.s3.internal.GetEncryptedObjectPipeline;
4160
import software.amazon.encryption.s3.internal.InstructionFileConfig;
4261
import software.amazon.encryption.s3.internal.NoRetriesAsyncRequestBody;
@@ -49,26 +68,12 @@
4968
import software.amazon.encryption.s3.materials.PartialRsaKeyPair;
5069
import software.amazon.encryption.s3.materials.RsaKeyring;
5170

52-
import javax.crypto.SecretKey;
53-
import java.net.URI;
54-
import java.security.KeyPair;
55-
import java.security.Provider;
56-
import java.security.SecureRandom;
57-
import java.util.List;
58-
import java.util.Map;
59-
import java.util.Optional;
60-
import java.util.concurrent.CompletableFuture;
61-
import java.util.function.Consumer;
62-
import java.util.function.Function;
63-
64-
import static software.amazon.encryption.s3.S3EncryptionClientUtilities.DEFAULT_BUFFER_SIZE_BYTES;
65-
import static software.amazon.encryption.s3.S3EncryptionClientUtilities.MAX_ALLOWED_BUFFER_SIZE_BYTES;
66-
import static software.amazon.encryption.s3.S3EncryptionClientUtilities.MIN_ALLOWED_BUFFER_SIZE_BYTES;
67-
import static software.amazon.encryption.s3.internal.ApiNameVersion.API_NAME_INTERCEPTOR;
68-
6971
/**
7072
* This client is a drop-in replacement for the S3 Async client. It will automatically encrypt objects
7173
* on putObject and decrypt objects on getObject using the provided encryption key(s).
74+
*
75+
* This major version uses AES_GCM_HKDF_SHA512_COMMIT_KEY by default and only recent minor versions
76+
* of the previous major version can decrypt these objects.
7277
*/
7378
public class S3AsyncEncryptionClient extends DelegatingS3AsyncClient {
7479

@@ -80,6 +85,7 @@ public class S3AsyncEncryptionClient extends DelegatingS3AsyncClient {
8085
private final boolean _enableMultipartPutObject;
8186
private final long _bufferSize;
8287
private final InstructionFileConfig _instructionFileConfig;
88+
private final CommitmentPolicy _commitmentPolicy;
8389

8490
private S3AsyncEncryptionClient(Builder builder) {
8591
super(builder._wrappedClient);
@@ -91,16 +97,29 @@ private S3AsyncEncryptionClient(Builder builder) {
9197
_enableMultipartPutObject = builder._enableMultipartPutObject;
9298
_bufferSize = builder._bufferSize;
9399
_instructionFileConfig = builder._instructionFileConfig;
100+
_commitmentPolicy = builder._commitmentPolicy;
94101
}
95102

96103
/**
97104
* Creates a builder that can be used to configure and create a {@link S3AsyncEncryptionClient}.
98105
*/
106+
@Deprecated
99107
public static Builder builder() {
100-
return new Builder();
108+
// Defaults to ForbidEncryptAllowDecrypt and ALG_AES_256_GCM_IV12_TAG16_NO_KDF
109+
return new Builder(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT, AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF);
101110
}
102111

103112

113+
114+
/**
115+
* Creates a V4 Transition builder that can be used to configure and create a {@link S3AsyncEncryptionClient}.
116+
*/
117+
public static Builder builderV4() {
118+
// NewBuilder introduced which REQUIRES commitmentPolicy and encryptionAlgorithm
119+
// to be set and is V4 compatible
120+
return new Builder();
121+
}
122+
104123
/**
105124
* Attaches encryption context to a request. Must be used as a parameter to
106125
* {@link S3Request#overrideConfiguration()} in the request.
@@ -211,6 +230,7 @@ public <T> CompletableFuture<T> getObject(GetObjectRequest getObjectRequest,
211230
.enableDelayedAuthentication(_enableDelayedAuthenticationMode)
212231
.bufferSize(_bufferSize)
213232
.instructionFileConfig(_instructionFileConfig)
233+
.commitmentPolicy(_commitmentPolicy)
214234
.build();
215235

216236
return pipeline.getObject(getObjectRequest, asyncResponseTransformer);
@@ -309,6 +329,8 @@ public static class Builder implements S3AsyncClientBuilder {
309329
private SecureRandom _secureRandom = new SecureRandom();
310330
private long _bufferSize = -1L;
311331
private InstructionFileConfig _instructionFileConfig = null;
332+
private AlgorithmSuite _encryptionAlgorithm = null;
333+
private CommitmentPolicy _commitmentPolicy = null;
312334

313335
// generic AwsClient configuration to be shared by default clients
314336
private AwsCredentialsProvider _awsCredentialsProvider = null;
@@ -335,6 +357,11 @@ public static class Builder implements S3AsyncClientBuilder {
335357
private Builder() {
336358
}
337359

360+
private Builder(CommitmentPolicy commitmentPolicy, AlgorithmSuite algorithmSuite) {
361+
_commitmentPolicy = commitmentPolicy;
362+
_encryptionAlgorithm = algorithmSuite;
363+
}
364+
338365
/**
339366
* Specifies the wrapped client to use for the actual S3 request.
340367
* This client will be used for all async operations.
@@ -568,6 +595,42 @@ public Builder instructionFileConfig(InstructionFileConfig instructionFileConfig
568595
return this;
569596
}
570597

598+
//= specification/s3-encryption/client.md#encryption-algorithm
599+
//# The S3EC MUST support configuration of the encryption algorithm (or algorithm suite) during its initialization.
600+
/**
601+
* Sets the {@link AlgorithmSuite} to encrypt with.
602+
* <p>
603+
* Defaults to AlgorithmSuite.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY which provides key commitment.
604+
* Objects encrypted with this default algorithm can only be decrypted by version 3.6.0 or later.
605+
*
606+
* @param encryptionAlgorithm The {@link AlgorithmSuite}
607+
* @return The Builder, for method chaining
608+
*/
609+
public Builder encryptionAlgorithm(AlgorithmSuite encryptionAlgorithm) {
610+
_encryptionAlgorithm = encryptionAlgorithm;
611+
return this;
612+
}
613+
614+
//= specification/s3-encryption/client.md#key-commitment
615+
//# The S3EC MUST support configuration of the [Key Commitment policy](./key-commitment.md) during its initialization.
616+
/**
617+
* Sets the commitment policy for this S3 encryption client.
618+
* The commitment policy determines whether the client requires, forbids, or allows
619+
* key commitment during encryption and decryption operations.
620+
* <p>
621+
* Defaults to REQUIRE_ENCRYPT_REQUIRE_DECRYPT which provides the highest security.
622+
* This policy will reject messages encrypted without key commitment, so it should be only used when all the objects expected to succeed decryption have been encrypted using key commitment.
623+
*
624+
* @param commitmentPolicy the commitment policy to use
625+
* @return this builder instance for method chaining
626+
* @see CommitmentPolicy
627+
*/
628+
629+
public Builder commitmentPolicy(CommitmentPolicy commitmentPolicy) {
630+
_commitmentPolicy = commitmentPolicy;
631+
return this;
632+
}
633+
571634
/**
572635
* The credentials provider to use for all inner clients, including KMS, if a KMS key ID is provided.
573636
* Note that if a wrapped client is configured, the wrapped client will take precedence over this option.
@@ -896,6 +959,30 @@ public S3AsyncEncryptionClient build() {
896959
.build();
897960
}
898961

962+
//= specification/s3-encryption/client.md#encryption-algorithm
963+
//# The S3EC MUST validate that the configured encryption algorithm is not legacy.
964+
//= specification/s3-encryption/client.md#key-commitment
965+
//# The S3EC MUST validate the configured Encryption Algorithm against the provided key commitment policy.
966+
//= specification/s3-encryption/key-commitment.md#commitment-policy
967+
//# When the commitment policy is FORBID_ENCRYPT_ALLOW_DECRYPT, the S3EC MUST NOT encrypt using an algorithm suite which supports key commitment.
968+
if (_encryptionAlgorithm == null || _commitmentPolicy == null) {
969+
throw new S3EncryptionClientException(
970+
"Both encryption algorithm and commitment policy must be configured."
971+
);
972+
}
973+
if (!(_encryptionAlgorithm.id() == AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF.id()
974+
&& _commitmentPolicy.equals(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT))) {
975+
//= specification/s3-encryption/client.md#encryption-algorithm
976+
//# If the configured encryption algorithm is legacy, then the S3EC MUST throw an exception.
977+
//= specification/s3-encryption/client.md#key-commitment
978+
//# If the configured Encryption Algorithm is incompatible with the key commitment policy, then it MUST throw an exception.
979+
throw new S3EncryptionClientException(
980+
"This client can ONLY be built with these Settings: Commitment Policy: FORBID_ENCRYPT_ALLOW_DECRYPT; Encryption Algorithm: ALG_AES_256_GCM_IV12_TAG16_NO_KDF. "
981+
+ "Note that the Encryption Algorithm does NOT effect Decryption; See: https://docs.aws.amazon.com/amazon-s3-encryption-client/latest/developerguide/encryption-algorithms.html#decryption-modes. "
982+
+ "Please update your configuration. Provided algorithm: " + _encryptionAlgorithm.name() + " and commitment policy: " + _commitmentPolicy.name()
983+
);
984+
}
985+
899986
return new S3AsyncEncryptionClient(this);
900987
}
901988

0 commit comments

Comments
 (0)