From 50001fd604f0bdea0a20b6adff9cb9f26354a9f9 Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Mon, 18 Aug 2025 17:59:04 -0400 Subject: [PATCH 01/11] fix(sdk): parse the component sizes --- .../io/opentdf/platform/sdk/PolicyInfo.java | 40 +++++++++++++++---- .../java/io/opentdf/platform/sdk/SDK.java | 9 +++++ .../opentdf/platform/sdk/PolicyInfoTest.java | 39 ++++++++++++++++++ 3 files changed, 80 insertions(+), 8 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java b/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java index f181a817..00bf58d3 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java @@ -3,8 +3,8 @@ import java.nio.ByteBuffer; public class PolicyInfo { + private static final int DEFAULT_BINDING_SIZE = 8; private NanoTDFType.PolicyType type; - private boolean hasECDSABinding; private byte[] body; private byte[] binding; @@ -13,7 +13,6 @@ public PolicyInfo() { public PolicyInfo(ByteBuffer buffer, ECCMode eccMode) { this.type = NanoTDFType.PolicyType.values()[buffer.get()]; - this.hasECDSABinding = eccMode.isECDSABindingEnabled(); if (this.type == NanoTDFType.PolicyType.REMOTE_POLICY) { @@ -45,13 +44,39 @@ public PolicyInfo(ByteBuffer buffer, ECCMode eccMode) { } } - int bindingBytesSize = 8; // GMAC length - if (this.hasECDSABinding) { // ECDSA - The size of binding depends on the curve. - bindingBytesSize = ECCMode.getECDSASignatureStructSize(eccMode.getCurve()); + this.binding = readBinding(buffer, eccMode); + } + + static byte[] readBinding(ByteBuffer buffer, ECCMode eccMode) { + byte[] binding; + if (eccMode.isECDSABindingEnabled()) { // ECDSA - The size of binding depends on the curve. + int rSize = getSize(buffer.get(), eccMode.getCurve()); + // don't bother to validate since we can only create an array of size 1024 bytes + byte[] rBytes = new byte[rSize]; + buffer.get(rBytes); + int sSize = getSize(buffer.get(), eccMode.getCurve()); + byte[] sBytes = new byte[sSize]; + buffer.get(sBytes); + int bindingByteSize = eccMode.getCurve().getKeySize(); + binding = new byte[2 * bindingByteSize]; + System.arraycopy(rBytes, 0, binding, bindingByteSize - rSize, rSize); + System.arraycopy(sBytes, 0, binding, bindingByteSize + bindingByteSize - sSize, sSize); + } else { + binding = new byte[DEFAULT_BINDING_SIZE]; + buffer.get(binding); } - this.binding = new byte[bindingBytesSize]; - buffer.get(this.binding); + return binding; + } + + private static int getSize(byte size, NanoTDFType.ECCurve curve) { + int elementSize = Byte.toUnsignedInt(size); + if (elementSize > curve.getKeySize()) { + throw new SDK.MalformedTDFException( + String.format("Invalid ECDSA binding size. Expected signature components to be at most %d bytes but got (%d) bytes for curve %s.", + curve.getKeySize(), elementSize, curve.getCurveName())); + } + return elementSize; } public int getTotalSize() { @@ -64,7 +89,6 @@ public int getTotalSize() { if (type == NanoTDFType.PolicyType.EMBEDDED_POLICY_PLAIN_TEXT || type == NanoTDFType.PolicyType.EMBEDDED_POLICY_ENCRYPTED) { - int policySize = body.length; totalSize = (1 + Short.BYTES + body.length + binding.length); } else { throw new RuntimeException("Embedded policy with key access is not supported."); diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java b/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java index f6009ed6..369a2edf 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java @@ -176,6 +176,15 @@ public String getPlatformUrl() { return platformUrl; } + /** + * {@link MalformedTDFException} indicates that the TDF is malformed in some way + */ + public static class MalformedTDFException extends SDKException { + public MalformedTDFException(String errorMessage) { + super(errorMessage); + } + } + /** * {@link SplitKeyException} is thrown when the SDK encounters an error related to * the inability to reconstruct a split key during decryption. diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java index 8a2c2e31..4b3a13d7 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java @@ -1,7 +1,16 @@ package io.opentdf.platform.sdk; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.DERBitString; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.junit.jupiter.api.Assertions.*; class PolicyInfoTest { @@ -58,4 +67,34 @@ void settingAndGettingPolicyBinding() { policyInfo.setPolicyBinding(binding); assertArrayEquals(binding, policyInfo.getPolicyBinding()); } + + @Test + void testReadingDEREncodedSignature() throws IOException { + var curve = NanoTDFType.ECCurve.SECP384R1; + ByteBuffer buffer = ByteBuffer.allocate(1024); + buffer.put((byte)2); + buffer.put(new BigInteger("200", 10).toByteArray()); + buffer.put((byte)3); + buffer.put(new BigInteger("65536", 10).toByteArray()); + + + ECCMode eccMode = new ECCMode(); + eccMode.setECDSABinding(true); + eccMode.setEllipticCurve(curve); + + buffer.flip(); + + byte[] signature = PolicyInfo.readBinding(buffer, eccMode); + assertThat(signature).hasSize(2 * curve.getKeySize()); + + var rBytes = new byte[curve.getKeySize()]; + System.arraycopy(signature, 0, rBytes, 0, rBytes.length); + var r = new BigInteger(1, rBytes); + assertThat(r).isEqualTo(new BigInteger("200", 10)); + + var sBytes = new byte[curve.getKeySize()]; + System.arraycopy(signature, curve.getKeySize(), sBytes, 0, curve.getKeySize()); + var s = new BigInteger(1, sBytes); + assertThat(s).isEqualTo(new BigInteger("65536", 10)); + } } \ No newline at end of file From daa4651c46c17cbed61a1e9d03a6105d5ca3fffe Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Mon, 18 Aug 2025 18:07:22 -0400 Subject: [PATCH 02/11] Update sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java index 4b3a13d7..15fcf898 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java @@ -69,7 +69,7 @@ void settingAndGettingPolicyBinding() { } @Test - void testReadingDEREncodedSignature() throws IOException { + void testReadingSignatureWithComponentSizes() { var curve = NanoTDFType.ECCurve.SECP384R1; ByteBuffer buffer = ByteBuffer.allocate(1024); buffer.put((byte)2); From db7b6866b452be300b7be26e088bade21e6a6686 Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 19 Aug 2025 13:06:08 -0400 Subject: [PATCH 03/11] update test --- .../io/opentdf/platform/sdk/PolicyInfo.java | 9 +-- .../io/opentdf/platform/sdk/NanoTDFTest.java | 1 + .../opentdf/platform/sdk/PolicyInfoTest.java | 66 ++++++++++--------- 3 files changed, 42 insertions(+), 34 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java b/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java index 00bf58d3..8768895d 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java @@ -57,10 +57,11 @@ static byte[] readBinding(ByteBuffer buffer, ECCMode eccMode) { int sSize = getSize(buffer.get(), eccMode.getCurve()); byte[] sBytes = new byte[sSize]; buffer.get(sBytes); - int bindingByteSize = eccMode.getCurve().getKeySize(); - binding = new byte[2 * bindingByteSize]; - System.arraycopy(rBytes, 0, binding, bindingByteSize - rSize, rSize); - System.arraycopy(sBytes, 0, binding, bindingByteSize + bindingByteSize - sSize, sSize); + binding = new byte[rSize + sSize + 2]; + System.arraycopy(new byte[]{(byte) rSize}, 0, binding, 0, 1); + System.arraycopy(rBytes, 0, binding, 1, rSize); + System.arraycopy(new byte[]{(byte) sSize}, 0, binding, 1 + rSize, 1); + System.arraycopy(sBytes, 0, binding, 2 + rSize, sSize); } else { binding = new byte[DEFAULT_BINDING_SIZE]; buffer.get(binding); diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/NanoTDFTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/NanoTDFTest.java index 599a52a5..7e86169f 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/NanoTDFTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/NanoTDFTest.java @@ -11,6 +11,7 @@ import io.opentdf.platform.sdk.Config.KASInfo; import io.opentdf.platform.sdk.Config.NanoTDFReaderConfig; +import java.io.IOException; import java.nio.charset.StandardCharsets; import io.opentdf.platform.wellknownconfiguration.GetWellKnownConfigurationResponse; diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java index 4b3a13d7..5ffb41fc 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java @@ -1,14 +1,13 @@ package io.opentdf.platform.sdk; -import org.bouncycastle.asn1.ASN1Integer; -import org.bouncycastle.asn1.DERBitString; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Random; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.junit.jupiter.api.Assertions.*; @@ -69,32 +68,39 @@ void settingAndGettingPolicyBinding() { } @Test - void testReadingDEREncodedSignature() throws IOException { - var curve = NanoTDFType.ECCurve.SECP384R1; - ByteBuffer buffer = ByteBuffer.allocate(1024); - buffer.put((byte)2); - buffer.put(new BigInteger("200", 10).toByteArray()); - buffer.put((byte)3); - buffer.put(new BigInteger("65536", 10).toByteArray()); - - - ECCMode eccMode = new ECCMode(); - eccMode.setECDSABinding(true); - eccMode.setEllipticCurve(curve); - - buffer.flip(); - - byte[] signature = PolicyInfo.readBinding(buffer, eccMode); - assertThat(signature).hasSize(2 * curve.getKeySize()); - - var rBytes = new byte[curve.getKeySize()]; - System.arraycopy(signature, 0, rBytes, 0, rBytes.length); - var r = new BigInteger(1, rBytes); - assertThat(r).isEqualTo(new BigInteger("200", 10)); - - var sBytes = new byte[curve.getKeySize()]; - System.arraycopy(signature, curve.getKeySize(), sBytes, 0, curve.getKeySize()); - var s = new BigInteger(1, sBytes); - assertThat(s).isEqualTo(new BigInteger("65536", 10)); + void testReadingEncodedSignature() throws IOException { + var rand = new Random(); + for (var i = 0; i < 100; i++) { + var curve = NanoTDFType.ECCurve.SECP384R1; + ByteBuffer buffer = ByteBuffer.allocate(1024); + var big = 1 + rand.nextInt(Integer.MAX_VALUE - 1); + var small = 1 + rand.nextInt(Integer.MAX_VALUE >>> 10 - 1); + int r; + int s; + if (rand.nextBoolean()) { + r = big; + s = small; + } else { + r = small; + s = big; + } + var rBytes = BigInteger.valueOf(r).toByteArray(); + var sBytes = BigInteger.valueOf(s).toByteArray(); + buffer.put((byte)rBytes.length); + buffer.put(rBytes); + buffer.put((byte) sBytes.length); + buffer.put(sBytes); + + var originalSig = Arrays.copyOf(buffer.array(), buffer.position()); + + buffer.flip(); + + ECCMode eccMode = new ECCMode(); + eccMode.setECDSABinding(true); + eccMode.setEllipticCurve(curve); + + byte[] signature = PolicyInfo.readBinding(buffer, eccMode); + assertThat(signature).containsExactly(originalSig); + } } } \ No newline at end of file From 281fa5207243d668198cacdc3943695513ef2347 Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 19 Aug 2025 13:23:43 -0400 Subject: [PATCH 04/11] simplify test --- .../java/io/opentdf/platform/sdk/ECCMode.java | 6 ----- .../opentdf/platform/sdk/PolicyInfoTest.java | 27 +++++++++---------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/ECCMode.java b/sdk/src/main/java/io/opentdf/platform/sdk/ECCMode.java index 98d89feb..7eeb2775 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/ECCMode.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/ECCMode.java @@ -55,12 +55,6 @@ public byte getECCModeAsByte() { return (byte) value; } - public static int getECDSASignatureStructSize(NanoTDFType.ECCurve curve) { - int keySize = curve.getKeySize(); - return (1 + keySize + 1 + keySize); - } - - @Nonnull public NanoTDFType.ECCurve getCurve() { return NanoTDFType.ECCurve.fromCurveMode(data.curveMode); diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java index a0aad3aa..dbc4f2ca 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java @@ -1,5 +1,6 @@ package io.opentdf.platform.sdk; +import org.assertj.core.api.AbstractIterableAssert; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -66,25 +67,19 @@ void settingAndGettingPolicyBinding() { assertArrayEquals(binding, policyInfo.getPolicyBinding()); } + + BigInteger getRandomBigInteger(Random rand, int bitLength) { + var numBytesForKey = (bitLength + 7) / 8; // Round up to the nearest byte + return new BigInteger(rand.nextInt(numBytesForKey), rand); + } @Test void testReadingSignatureWithComponentSizes() { var rand = new Random(); + var curve = NanoTDFType.ECCurve.SECP256R1; for (var i = 0; i < 100; i++) { - var curve = NanoTDFType.ECCurve.SECP384R1; - ByteBuffer buffer = ByteBuffer.allocate(1024); - var big = 1 + rand.nextInt(Integer.MAX_VALUE - 1); - var small = 1 + rand.nextInt(Integer.MAX_VALUE >>> 10 - 1); - int r; - int s; - if (rand.nextBoolean()) { - r = big; - s = small; - } else { - r = small; - s = big; - } - var rBytes = BigInteger.valueOf(r).toByteArray(); - var sBytes = BigInteger.valueOf(s).toByteArray(); + var rBytes = getRandomBigInteger(rand, curve.getKeySize()).toByteArray(); + var sBytes = getRandomBigInteger(rand, curve.getKeySize()) .toByteArray(); + var buffer = ByteBuffer.allocate(rBytes.length + sBytes.length + 2); buffer.put((byte)rBytes.length); buffer.put(rBytes); buffer.put((byte) sBytes.length); @@ -100,6 +95,8 @@ void testReadingSignatureWithComponentSizes() { byte[] signature = PolicyInfo.readBinding(buffer, eccMode); assertThat(signature).containsExactly(originalSig); + // make sure we read all bytes so that reading continues after us in the TDF + assertThat(buffer.position()).isEqualTo(buffer.capacity()); } } } \ No newline at end of file From a72967812db957ba82a60bce12d2aea0b645b24c Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 19 Aug 2025 13:28:10 -0400 Subject: [PATCH 05/11] fix comment and error message --- sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java b/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java index 8768895d..36223724 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java @@ -51,7 +51,6 @@ static byte[] readBinding(ByteBuffer buffer, ECCMode eccMode) { byte[] binding; if (eccMode.isECDSABindingEnabled()) { // ECDSA - The size of binding depends on the curve. int rSize = getSize(buffer.get(), eccMode.getCurve()); - // don't bother to validate since we can only create an array of size 1024 bytes byte[] rBytes = new byte[rSize]; buffer.get(rBytes); int sSize = getSize(buffer.get(), eccMode.getCurve()); @@ -72,10 +71,11 @@ static byte[] readBinding(ByteBuffer buffer, ECCMode eccMode) { private static int getSize(byte size, NanoTDFType.ECCurve curve) { int elementSize = Byte.toUnsignedInt(size); - if (elementSize > curve.getKeySize()) { + int bytesNeededForCurve = (curve.getKeySize() + 7) / 8; // Round up to the nearest byte + if (elementSize > bytesNeededForCurve) { throw new SDK.MalformedTDFException( String.format("Invalid ECDSA binding size. Expected signature components to be at most %d bytes but got (%d) bytes for curve %s.", - curve.getKeySize(), elementSize, curve.getCurveName())); + bytesNeededForCurve, elementSize, curve.getCurveName())); } return elementSize; } From 8dd1c29cda3cb8d3fb0187c9a4132b8ac5e33da0 Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 19 Aug 2025 13:31:31 -0400 Subject: [PATCH 06/11] docs --- sdk/src/main/java/io/opentdf/platform/sdk/SDK.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java b/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java index 369a2edf..d1c91fcc 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java @@ -166,7 +166,7 @@ public static Manifest readManifest(SeekableByteChannel tdfBytes) throws SDKExce * to get the {@link Manifest} from a TDF. * @param manifest The {@link Manifest} containing the policy. * @return The decoded {@link PolicyObject}. - * @throws SDKException if there is an error during decoding. + * @throws {@link SDKException} if there is an error during decoding. */ public static PolicyObject decodePolicyObject(Manifest manifest) throws SDKException { return Manifest.decodePolicyObject(manifest); @@ -177,7 +177,7 @@ public String getPlatformUrl() { } /** - * {@link MalformedTDFException} indicates that the TDF is malformed in some way + * Indicates that the TDF is malformed in some way */ public static class MalformedTDFException extends SDKException { public MalformedTDFException(String errorMessage) { From 6b1891fe45907bf73731da35cf2d0bb9fdb7ea98 Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 19 Aug 2025 15:56:59 -0400 Subject: [PATCH 07/11] fix check --- sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java b/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java index 36223724..899c2913 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java @@ -71,11 +71,10 @@ static byte[] readBinding(ByteBuffer buffer, ECCMode eccMode) { private static int getSize(byte size, NanoTDFType.ECCurve curve) { int elementSize = Byte.toUnsignedInt(size); - int bytesNeededForCurve = (curve.getKeySize() + 7) / 8; // Round up to the nearest byte - if (elementSize > bytesNeededForCurve) { + if (elementSize > curve.getKeySize()) { throw new SDK.MalformedTDFException( String.format("Invalid ECDSA binding size. Expected signature components to be at most %d bytes but got (%d) bytes for curve %s.", - bytesNeededForCurve, elementSize, curve.getCurveName())); + curve.getKeySize(), elementSize, curve.getCurveName())); } return elementSize; } From a12cac3a27f8b81ea9459f6c405e6a8427e15f68 Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 19 Aug 2025 16:16:15 -0400 Subject: [PATCH 08/11] one more --- .../test/java/io/opentdf/platform/sdk/PolicyInfoTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java index dbc4f2ca..3201d8c2 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java @@ -68,9 +68,8 @@ void settingAndGettingPolicyBinding() { } - BigInteger getRandomBigInteger(Random rand, int bitLength) { - var numBytesForKey = (bitLength + 7) / 8; // Round up to the nearest byte - return new BigInteger(rand.nextInt(numBytesForKey), rand); + BigInteger getRandomBigInteger(Random rand, int byteLength) { + return new BigInteger(1+rand.nextInt(byteLength-1), rand); } @Test void testReadingSignatureWithComponentSizes() { From 8dc34cfbc4792e766c65a55aee849fd928b43c3d Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 19 Aug 2025 16:57:42 -0400 Subject: [PATCH 09/11] coverage --- .../opentdf/platform/sdk/PolicyInfoTest.java | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java index 3201d8c2..f2619e57 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java @@ -69,8 +69,9 @@ void settingAndGettingPolicyBinding() { BigInteger getRandomBigInteger(Random rand, int byteLength) { - return new BigInteger(1+rand.nextInt(byteLength-1), rand); + return new BigInteger((1+rand.nextInt(byteLength-1))*8, rand); } + @Test void testReadingSignatureWithComponentSizes() { var rand = new Random(); @@ -98,4 +99,45 @@ void testReadingSignatureWithComponentSizes() { assertThat(buffer.position()).isEqualTo(buffer.capacity()); } } + + @Test + void testParsingTooBigSignatureComponents() { + { + var rand = new Random(); + var curve = NanoTDFType.ECCurve.SECP256R1; + var rBytes = new BigInteger((curve.getKeySize() + 1) * 8, rand).toByteArray(); + var sBytes = getRandomBigInteger(rand, curve.getKeySize()).toByteArray(); + var buffer = ByteBuffer.allocate(rBytes.length + sBytes.length + 2); + buffer.put((byte) rBytes.length); + buffer.put(rBytes); + buffer.put((byte) sBytes.length); + buffer.put(sBytes); + + buffer.flip(); + + ECCMode eccMode = new ECCMode(); + eccMode.setECDSABinding(true); + eccMode.setEllipticCurve(curve); + assertThrows(SDK.MalformedTDFException.class, () -> PolicyInfo.readBinding(buffer, eccMode)); + } + + { + var rand = new Random(); + var curve = NanoTDFType.ECCurve.SECP256R1; + var rBytes = getRandomBigInteger(rand, curve.getKeySize()).toByteArray(); + var sBytes = new BigInteger((curve.getKeySize() + 1) * 8, rand).toByteArray(); + var buffer = ByteBuffer.allocate(rBytes.length + sBytes.length + 2); + buffer.put((byte) rBytes.length); + buffer.put(rBytes); + buffer.put((byte) sBytes.length); + buffer.put(sBytes); + + buffer.flip(); + + ECCMode eccMode = new ECCMode(); + eccMode.setECDSABinding(true); + eccMode.setEllipticCurve(curve); + assertThrows(SDK.MalformedTDFException.class, () -> PolicyInfo.readBinding(buffer, eccMode)); + } + } } \ No newline at end of file From 496f1a9299747c0bd10a28aededf353c14ab411b Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 19 Aug 2025 17:54:52 -0400 Subject: [PATCH 10/11] sonar --- sdk/src/test/java/io/opentdf/platform/sdk/NanoTDFTest.java | 1 - sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java | 1 - 2 files changed, 2 deletions(-) diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/NanoTDFTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/NanoTDFTest.java index 7e86169f..599a52a5 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/NanoTDFTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/NanoTDFTest.java @@ -11,7 +11,6 @@ import io.opentdf.platform.sdk.Config.KASInfo; import io.opentdf.platform.sdk.Config.NanoTDFReaderConfig; -import java.io.IOException; import java.nio.charset.StandardCharsets; import io.opentdf.platform.wellknownconfiguration.GetWellKnownConfigurationResponse; diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java index f2619e57..8df3a0e7 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/PolicyInfoTest.java @@ -1,6 +1,5 @@ package io.opentdf.platform.sdk; -import org.assertj.core.api.AbstractIterableAssert; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; From 364b89a0258559e8a6799ada507a9125807c634d Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Wed, 20 Aug 2025 09:48:26 -0400 Subject: [PATCH 11/11] Apply suggestion from @gemini-code-assist[bot] Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../main/java/io/opentdf/platform/sdk/PolicyInfo.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java b/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java index 899c2913..d09a8f3c 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/PolicyInfo.java @@ -56,11 +56,12 @@ static byte[] readBinding(ByteBuffer buffer, ECCMode eccMode) { int sSize = getSize(buffer.get(), eccMode.getCurve()); byte[] sBytes = new byte[sSize]; buffer.get(sBytes); - binding = new byte[rSize + sSize + 2]; - System.arraycopy(new byte[]{(byte) rSize}, 0, binding, 0, 1); - System.arraycopy(rBytes, 0, binding, 1, rSize); - System.arraycopy(new byte[]{(byte) sSize}, 0, binding, 1 + rSize, 1); - System.arraycopy(sBytes, 0, binding, 2 + rSize, sSize); + binding = ByteBuffer.allocate(rSize + sSize + 2) + .put((byte) rSize) + .put(rBytes) + .put((byte) sSize) + .put(sBytes) + .array(); } else { binding = new byte[DEFAULT_BINDING_SIZE]; buffer.get(binding);