diff --git a/test-server/feature-config.json b/test-server/feature-config.json index 644bf2e6..dbdd2014 100644 --- a/test-server/feature-config.json +++ b/test-server/feature-config.json @@ -1,7 +1,6 @@ { "supportedFeatures": [ "streaming", - "MPL", "hierarchical", "raw-aes", "raw-rsa", diff --git a/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/handler/DecryptHandler.java b/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/handler/DecryptHandler.java index 3f865a2e..1ee75a25 100644 --- a/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/handler/DecryptHandler.java +++ b/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/handler/DecryptHandler.java @@ -3,6 +3,9 @@ import aws.cryptography.esdk.testserver.server.error.OperationWrapper; import aws.cryptography.esdk.testserver.server.model.DecryptInput; import aws.cryptography.esdk.testserver.server.model.DecryptOutput; +import aws.cryptography.esdk.testserver.server.model.ESDKAlgorithmSuiteId; +import aws.cryptography.esdk.testserver.server.registry.DecryptMetadata; +import aws.cryptography.esdk.testserver.server.registry.DecryptResult; import aws.cryptography.esdk.testserver.server.registry.EsdkClient; import aws.cryptography.esdk.testserver.server.service.DecryptOperation; import java.nio.ByteBuffer; @@ -30,10 +33,15 @@ public DecryptHandler(ClientIdGuard guard, OperationWrapper wrapper) { public DecryptOutput decrypt(DecryptInput input, RequestContext context) { return wrapper.invoke("Decrypt", () -> { EsdkClient client = guard.resolve(input.getClientId()); - byte[] plaintext = client.decrypt( + DecryptResult result = client.decrypt( Blobs.toArray(input.getCiphertext()), input.getEncryptionContext()); - return DecryptOutput.builder().plaintext(ByteBuffer.wrap(plaintext)).build(); + DecryptMetadata metadata = result.metadata(); + return DecryptOutput.builder() + .plaintext(ByteBuffer.wrap(result.plaintext())) + .encryptionContext(metadata.encryptionContext()) + .algorithmSuiteId(ESDKAlgorithmSuiteId.from(metadata.algorithmSuiteId())) + .build(); }); } } diff --git a/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/handler/DecryptStreamHandler.java b/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/handler/DecryptStreamHandler.java index c9ac2931..f54314a1 100644 --- a/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/handler/DecryptStreamHandler.java +++ b/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/handler/DecryptStreamHandler.java @@ -3,6 +3,8 @@ import aws.cryptography.esdk.testserver.server.error.OperationWrapper; import aws.cryptography.esdk.testserver.server.model.DecryptStreamInput; import aws.cryptography.esdk.testserver.server.model.DecryptStreamOutput; +import aws.cryptography.esdk.testserver.server.model.ESDKAlgorithmSuiteId; +import aws.cryptography.esdk.testserver.server.registry.DecryptMetadata; import aws.cryptography.esdk.testserver.server.registry.EsdkClient; import aws.cryptography.esdk.testserver.server.service.DecryptStreamOperation; import java.io.ByteArrayInputStream; @@ -41,12 +43,15 @@ public DecryptStreamOutput decryptStream(DecryptStreamInput input, RequestContex // Drive the ESDK STREAMING API even though the payload rides as a blob: // wrap the received bytes in a stream, stream-decrypt, collect the bytes. ByteArrayOutputStream plaintext = new ByteArrayOutputStream(); + DecryptMetadata metadata; try (InputStream ciphertext = new ByteArrayInputStream(Blobs.toArray(input.getCiphertext()))) { - client.decryptStream(ciphertext, plaintext, input.getEncryptionContext()); + metadata = client.decryptStream(ciphertext, plaintext, input.getEncryptionContext()); } return DecryptStreamOutput.builder() .plaintext(ByteBuffer.wrap(plaintext.toByteArray())) + .encryptionContext(metadata.encryptionContext()) + .algorithmSuiteId(ESDKAlgorithmSuiteId.from(metadata.algorithmSuiteId())) .build(); }); } diff --git a/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/registry/DecryptMetadata.java b/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/registry/DecryptMetadata.java new file mode 100644 index 00000000..f95d84d0 --- /dev/null +++ b/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/registry/DecryptMetadata.java @@ -0,0 +1,14 @@ +package aws.cryptography.esdk.testserver.server.registry; + +import java.util.Map; + +/** + * What the ESDK read from a message it decrypted: the authenticated encryption + * context and the algorithm suite, which the decrypt responses expose. + * + * @param encryptionContext the message's encryption context. + * @param algorithmSuiteId the suite's {@code CryptoAlgorithm} name, which matches + * the modeled {@code ESDKAlgorithmSuiteId} value. + */ +public record DecryptMetadata(Map encryptionContext, String algorithmSuiteId) { +} diff --git a/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/registry/DecryptResult.java b/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/registry/DecryptResult.java new file mode 100644 index 00000000..382edf6a --- /dev/null +++ b/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/registry/DecryptResult.java @@ -0,0 +1,10 @@ +package aws.cryptography.esdk.testserver.server.registry; + +/** + * The result of a blob decrypt. + * + * @param plaintext the plaintext bytes. + * @param metadata the encryption context and suite of the decrypted message. + */ +public record DecryptResult(byte[] plaintext, DecryptMetadata metadata) { +} diff --git a/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/registry/EsdkClient.java b/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/registry/EsdkClient.java index f12dbcaf..01ceedfb 100644 --- a/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/registry/EsdkClient.java +++ b/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/registry/EsdkClient.java @@ -41,10 +41,10 @@ byte[] encrypt(byte[] plaintext, Map encryptionContext, * @param ciphertext the ciphertext bytes. * @param encryptionContext optional encryption context to require on decrypt; * may be empty but not {@code null}. - * @return the plaintext bytes. + * @return the plaintext bytes and the message's encryption context and suite. * @throws EsdkClientException if the ESDK client fails (Requirement 4.10). */ - byte[] decrypt(byte[] ciphertext, Map encryptionContext) + DecryptResult decrypt(byte[] ciphertext, Map encryptionContext) throws EsdkClientException; /** @@ -61,10 +61,11 @@ void encryptStream(InputStream plaintext, OutputStream ciphertext, * Decrypt a ciphertext stream into a plaintext stream (Stream_Variant, * Requirement 4.6). Only meaningful when {@link #isStreamingCapable()}. * + * @return the message's encryption context and suite. * @throws EsdkClientException if the ESDK client fails (Requirement 4.10). */ - void decryptStream(InputStream ciphertext, OutputStream plaintext, - Map encryptionContext) throws EsdkClientException; + DecryptMetadata decryptStream(InputStream ciphertext, OutputStream plaintext, + Map encryptionContext) throws EsdkClientException; /** * @return whether the backing ESDK implementation supports the Stream_Variant. diff --git a/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/registry/RealEsdkClient.java b/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/registry/RealEsdkClient.java index fd78c429..e07a3c91 100644 --- a/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/registry/RealEsdkClient.java +++ b/test-server/server/src/main/java/aws/cryptography/esdk/testserver/server/registry/RealEsdkClient.java @@ -70,7 +70,7 @@ public byte[] encrypt(byte[] plaintext, Map encryptionContext, } @Override - public byte[] decrypt(byte[] ciphertext, Map encryptionContext) + public DecryptResult decrypt(byte[] ciphertext, Map encryptionContext) throws EsdkClientException { try { AwsCrypto crypto = buildCrypto(null, null); @@ -78,12 +78,12 @@ public byte[] decrypt(byte[] ciphertext, Map encryptionContext) if (legacyCmm != null) { CryptoResult result = crypto.decryptData(legacyCmm, ciphertext); requireReproducedContext(ec, result.getEncryptionContext()); - return result.getResult(); + return new DecryptResult(result.getResult(), metadata(result)); } CryptoResult result = ec.isEmpty() ? crypto.decryptData(cmm, ciphertext) : crypto.decryptData(cmm, ciphertext, ec); - return result.getResult(); + return new DecryptResult(result.getResult(), metadata(result)); } catch (Exception esdkFailure) { throw new EsdkClientException(esdkFailure); } @@ -113,8 +113,8 @@ public void encryptStream(InputStream plaintext, OutputStream ciphertext, } @Override - public void decryptStream(InputStream ciphertext, OutputStream plaintext, - Map encryptionContext) throws EsdkClientException { + public DecryptMetadata decryptStream(InputStream ciphertext, OutputStream plaintext, + Map encryptionContext) throws EsdkClientException { try { AwsCrypto crypto = buildCrypto(null, null); Map ec = nonNull(encryptionContext); @@ -132,6 +132,7 @@ public void decryptStream(InputStream ciphertext, OutputStream plaintext, requireReproducedContext(ec, decrypting.getCryptoResult().getEncryptionContext()); } decrypting.transferTo(plaintext); + return metadata(decrypting.getCryptoResult()); } } catch (Exception esdkFailure) { throw new EsdkClientException(esdkFailure); @@ -179,6 +180,10 @@ private static void requireReproducedContext(Map reproduced, } } + private static DecryptMetadata metadata(CryptoResult result) { + return new DecryptMetadata(result.getEncryptionContext(), result.getCryptoAlgorithm().name()); + } + private static Map nonNull(Map encryptionContext) { return encryptionContext == null ? Collections.emptyMap() : encryptionContext; } diff --git a/test-server/server/src/test/java/aws/cryptography/esdk/testserver/server/handler/ControllableEsdkClient.java b/test-server/server/src/test/java/aws/cryptography/esdk/testserver/server/handler/ControllableEsdkClient.java index 5ea5f32d..76a5fda6 100644 --- a/test-server/server/src/test/java/aws/cryptography/esdk/testserver/server/handler/ControllableEsdkClient.java +++ b/test-server/server/src/test/java/aws/cryptography/esdk/testserver/server/handler/ControllableEsdkClient.java @@ -1,6 +1,8 @@ package aws.cryptography.esdk.testserver.server.handler; import aws.cryptography.esdk.testserver.server.error.EsdkClientException; +import aws.cryptography.esdk.testserver.server.registry.DecryptMetadata; +import aws.cryptography.esdk.testserver.server.registry.DecryptResult; import java.io.InputStream; import java.io.OutputStream; import java.util.Map; @@ -18,6 +20,9 @@ final class ControllableEsdkClient implements aws.cryptography.esdk.testserver.s enum Mode { SUCCEED, FAIL_ESDK, FAIL_FRAMEWORK } + private static final DecryptMetadata METADATA = + new DecryptMetadata(Map.of(), "ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY"); + private final Mode mode; private final String failureMessage; private final AtomicInteger cryptoCalls = new AtomicInteger(); @@ -63,9 +68,9 @@ public byte[] encrypt(byte[] plaintext, Map encryptionContext, } @Override - public byte[] decrypt(byte[] ciphertext, Map encryptionContext) + public DecryptResult decrypt(byte[] ciphertext, Map encryptionContext) throws EsdkClientException { - return act(ciphertext); + return new DecryptResult(act(ciphertext), METADATA); } @Override @@ -76,9 +81,10 @@ public void encryptStream(InputStream plaintext, OutputStream ciphertext, } @Override - public void decryptStream(InputStream ciphertext, OutputStream plaintext, - Map encryptionContext) throws EsdkClientException { + public DecryptMetadata decryptStream(InputStream ciphertext, OutputStream plaintext, + Map encryptionContext) throws EsdkClientException { act(new byte[0]); + return METADATA; } @Override diff --git a/test-server/server/src/test/java/aws/cryptography/esdk/testserver/server/registry/StubEsdkClient.java b/test-server/server/src/test/java/aws/cryptography/esdk/testserver/server/registry/StubEsdkClient.java index a4b1b520..f667a1de 100644 --- a/test-server/server/src/test/java/aws/cryptography/esdk/testserver/server/registry/StubEsdkClient.java +++ b/test-server/server/src/test/java/aws/cryptography/esdk/testserver/server/registry/StubEsdkClient.java @@ -23,7 +23,7 @@ public byte[] encrypt(byte[] plaintext, Map encryptionContext, } @Override - public byte[] decrypt(byte[] ciphertext, Map encryptionContext) { + public DecryptResult decrypt(byte[] ciphertext, Map encryptionContext) { throw new UnsupportedOperationException("StubEsdkClient does not decrypt"); } @@ -35,8 +35,8 @@ public void encryptStream(InputStream plaintext, OutputStream ciphertext, } @Override - public void decryptStream(InputStream ciphertext, OutputStream plaintext, - Map encryptionContext) throws EsdkClientException { + public DecryptMetadata decryptStream(InputStream ciphertext, OutputStream plaintext, + Map encryptionContext) throws EsdkClientException { throw new UnsupportedOperationException("StubEsdkClient does not stream"); }