Skip to content

Commit 2cdb8b3

Browse files
committed
chore: add client specification and Duvet annotations
1 parent 59027c4 commit 2cdb8b3

File tree

7 files changed

+127
-6
lines changed

7 files changed

+127
-6
lines changed

.gitmodules

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

Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Used for misc supporting functions like Duvet and prettier. Builds, tests, etc. should use the usual Java/Maven tooling.
2+
3+
duvet: | duvet_extract duvet_report
4+
5+
duvet_extract:
6+
rm -rf compliance
7+
$(foreach file, $(shell find specification/s3-encryption -name '*.md'), duvet extract -o compliance -f MARKDOWN $(file);)
8+
9+
duvet_report:
10+
duvet \
11+
report \
12+
--spec-pattern "compliance/**/*.toml" \
13+
--source-pattern "src/**/*.java" \
14+
--html specification_compliance_report.html

specification

Submodule specification added at c5a78bc

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

Lines changed: 82 additions & 4 deletions
Large diffs are not rendered by default.

src/main/java/software/amazon/encryption/s3/internal/GetEncryptedObjectPipeline.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,11 @@ private DecryptionMaterials prepareMaterialsFromRequest(final GetObjectRequest g
7575
}
7676

7777
AlgorithmSuite algorithmSuite = contentMetadata.algorithmSuite();
78+
//= specification/s3-encryption/client.md#enable-legacy-unauthenticated-modes
79+
//# When enabled, the S3EC MUST be able to decrypt objects encrypted with all content encryption algorithms (both legacy and fully supported).
7880
if (!_enableLegacyUnauthenticatedModes && algorithmSuite.isLegacy()) {
81+
//= specification/s3-encryption/client.md#enable-legacy-unauthenticated-modes
82+
//# When disabled, the S3EC MUST NOT decrypt objects encrypted using legacy content encryption algorithms.
7983
throw new S3EncryptionClientException("Enable legacy unauthenticated modes to use legacy content decryption: " + algorithmSuite.cipherName());
8084
}
8185

@@ -146,11 +150,15 @@ public void onStream(SdkPublisher<ByteBuffer> ciphertextPublisher) {
146150
if (algorithmSuite.equals(AlgorithmSuite.ALG_AES_256_CBC_IV16_NO_KDF)
147151
|| algorithmSuite.equals(AlgorithmSuite.ALG_AES_256_CTR_IV16_TAG16_NO_KDF)
148152
|| _enableDelayedAuthentication) {
153+
//= specification/s3-encryption/client.md#enable-delayed-authentication
154+
//# When enabled, the S3EC MAY release plaintext from a stream which has not been authenticated.
149155
// CBC and GCM with delayed auth enabled use a standard publisher
150156
CipherPublisher plaintextPublisher = new CipherPublisher(ciphertextPublisher,
151157
getObjectResponse.contentLength(), desiredRange, contentMetadata.contentRange(), algorithmSuite.cipherTagLengthBits(), materials, iv);
152158
wrappedAsyncResponseTransformer.onStream(plaintextPublisher);
153159
} else {
160+
//= specification/s3-encryption/client.md#enable-delayed-authentication
161+
//# When disabled the S3EC MUST NOT release plaintext from a stream which has not been authenticated.
154162
// Use buffered publisher for GCM when delayed auth is not enabled
155163
BufferedCipherPublisher plaintextPublisher = new BufferedCipherPublisher(ciphertextPublisher,
156164
getObjectResponse.contentLength(), materials, iv, _bufferSize);

src/main/java/software/amazon/encryption/s3/internal/MultipartUploadObjectPipeline.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ public CreateMultipartUploadResponse createMultipartUpload(CreateMultipartUpload
7474
.overrideConfiguration(API_NAME_INTERCEPTOR)
7575
.build();
7676

77+
//= specification/s3-encryption/client.md#api-operations
78+
//# If implemented, CreateMultipartUpload MUST initiate a multipart upload.
7779
CreateMultipartUploadResponse response = _s3AsyncClient.createMultipartUpload(request).join();
7880

7981
MultipartUploadMaterials mpuMaterials = MultipartUploadMaterials.builder()
@@ -133,13 +135,18 @@ public UploadPartResponse uploadPart(UploadPartRequest request, RequestBody requ
133135
throw new S3EncryptionClientException("No client-side information available on upload ID " + uploadId);
134136
}
135137
final UploadPartResponse response;
136-
// Checks the parts are uploaded in series
138+
//= specification/s3-encryption/client.md#api-operations
139+
//# Each part MUST be encrypted in sequence.
137140
materials.beginPartUpload(actualRequest.partNumber(), partContentLength);
141+
//= specification/s3-encryption/client.md#api-operations
142+
//# Each part MUST be encrypted using the same cipher instance for each part.
138143
Cipher cipher = materials.getCipher(materials.getIv());
139144

140145
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
141146

142147
try {
148+
//= specification/s3-encryption/client.md#api-operations
149+
//# UploadPart MUST encrypt each part.
143150
final AsyncRequestBody cipherAsyncRequestBody = new CipherAsyncRequestBody(
144151
AsyncRequestBody.fromInputStream(
145152
requestBody.contentStreamProvider().newStream(),
@@ -159,6 +166,7 @@ public UploadPartResponse uploadPart(UploadPartRequest request, RequestBody requ
159166
}
160167
// Ensures parts are not retried to avoid corrupting ciphertext
161168
AsyncRequestBody noRetryBody = new NoRetriesAsyncRequestBody(cipherAsyncRequestBody);
169+
//= specification/s3-encryption/client.md#api-operations
162170
response = _s3AsyncClient.uploadPart(actualRequest, noRetryBody).join();
163171
} finally {
164172
materials.endPartUpload();
@@ -187,6 +195,8 @@ public CompleteMultipartUploadResponse completeMultipartUpload(CompleteMultipart
187195
.overrideConfiguration(API_NAME_INTERCEPTOR)
188196
.build();
189197

198+
//= specification/s3-encryption/client.md#api-operations
199+
//# CompleteMultipartUpload MUST complete the multipart upload.
190200
CompleteMultipartUploadResponse response = _s3AsyncClient.completeMultipartUpload(actualRequest).join();
191201

192202
_multipartUploadMaterials.remove(uploadId);
@@ -198,6 +208,8 @@ public AbortMultipartUploadResponse abortMultipartUpload(AbortMultipartUploadReq
198208
AbortMultipartUploadRequest actualRequest = request.toBuilder()
199209
.overrideConfiguration(API_NAME_INTERCEPTOR)
200210
.build();
211+
//= specification/s3-encryption/client.md#api-operations
212+
//# AbortMultipartUpload MUST abort the multipart upload.
201213
return _s3AsyncClient.abortMultipartUpload(actualRequest).join();
202214
}
203215

src/main/java/software/amazon/encryption/s3/materials/S3Keyring.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
66
import software.amazon.encryption.s3.S3EncryptionClientException;
77

8+
import javax.crypto.SecretKey;
89
import java.nio.charset.StandardCharsets;
910
import java.security.GeneralSecurityException;
1011
import java.security.SecureRandom;
1112
import java.util.ArrayList;
1213
import java.util.List;
1314
import java.util.Map;
14-
import javax.crypto.SecretKey;
1515

1616
/**
1717
* This serves as the base class for all the keyrings in the S3 encryption client.
@@ -115,7 +115,11 @@ public DecryptionMaterials onDecrypt(final DecryptionMaterials materials, List<E
115115
throw new S3EncryptionClientException("The keyring does not support the object's key wrapping algorithm: " + keyProviderInfo);
116116
}
117117

118+
//= specification/s3-encryption/client.md#enable-legacy-wrapping-algorithms
119+
//# When enabled, the S3EC MUST be able to decrypt objects encrypted with all supported wrapping algorithms (both legacy and fully supported).
118120
if (decryptStrategy.isLegacy() && !_enableLegacyWrappingAlgorithms) {
121+
//= specification/s3-encryption/client.md#enable-legacy-wrapping-algorithms
122+
//# When disabled, the S3EC MUST NOT decrypt objects encrypted using legacy wrapping algorithms.
119123
throw new S3EncryptionClientException("Enable legacy wrapping algorithms to use legacy key wrapping algorithm: " + keyProviderInfo);
120124
}
121125

0 commit comments

Comments
 (0)