> rules() {
return Stream.of(
JcaDetectionRules.rules().stream(),
BouncyCastleDetectionRules.rules().stream(),
- SSLDetectionRules.rules().stream())
+ SSLDetectionRules.rules().stream(),
+ TinkDetectionRules.rules().stream())
.flatMap(i -> i)
.toList();
}
diff --git a/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkAead.java b/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkAead.java
new file mode 100644
index 000000000..8af2a06b1
--- /dev/null
+++ b/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkAead.java
@@ -0,0 +1,133 @@
+/*
+ * Sonar Cryptography Plugin
+ * Copyright (C) 2024 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.plugin.rules.detection.tink;
+
+import com.ibm.engine.detection.MethodMatcher;
+import com.ibm.engine.model.context.CipherContext;
+import com.ibm.engine.model.factory.ValueActionFactory;
+import com.ibm.engine.rule.IDetectionRule;
+import com.ibm.engine.rule.builder.DetectionRuleBuilder;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.sonar.plugins.java.api.tree.Tree;
+
+/**
+ * Detection rules for Google Tink AEAD.
+ *
+ * Detects key generation and encrypt/decrypt operations:
+ *
+ *
+ * - {@code KeysetHandle.generateNew(AeadKeyTemplates.AES128_GCM)}
+ *
- {@code KeysetHandle.generateNew(AeadKeyTemplates.AES256_GCM)}
+ *
- {@code KeysetHandle.generateNew(AeadKeyTemplates.AES128_CTR_HMAC_SHA256)}
+ *
- {@code KeysetHandle.generateNew(AeadKeyTemplates.AES256_CTR_HMAC_SHA256)}
+ *
- {@code aead.encrypt(plaintext, aad)}
+ *
- {@code aead.decrypt(ciphertext, aad)}
+ *
+ */
+@SuppressWarnings("java:S1192")
+public final class TinkAead {
+
+ private TinkAead() {
+ // nothing
+ }
+
+ // aead.encrypt(plaintext, aad)
+ private static final IDetectionRule AEAD_ENCRYPT =
+ new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.Aead")
+ .forMethods("encrypt")
+ .shouldBeDetectedAs(new ValueActionFactory<>("ENCRYPT"))
+ .withMethodParameter(MethodMatcher.ANY)
+ .withMethodParameter(MethodMatcher.ANY)
+ .buildForContext(new CipherContext())
+ .inBundle(() -> "Tink")
+ .withoutDependingDetectionRules();
+
+ // aead.decrypt(ciphertext, aad)
+ private static final IDetectionRule AEAD_DECRYPT =
+ new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.Aead")
+ .forMethods("decrypt")
+ .shouldBeDetectedAs(new ValueActionFactory<>("DECRYPT"))
+ .withMethodParameter(MethodMatcher.ANY)
+ .withMethodParameter(MethodMatcher.ANY)
+ .buildForContext(new CipherContext())
+ .inBundle(() -> "Tink")
+ .withoutDependingDetectionRules();
+
+ private static final List> AEAD_OP_RULES =
+ List.of(AEAD_ENCRYPT, AEAD_DECRYPT);
+
+ // KeysetHandle.generateNew(AeadKeyTemplates.AES128_GCM)
+ private static final IDetectionRule AES128_GCM =
+ new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.KeysetHandle")
+ .forMethods("generateNew")
+ .shouldBeDetectedAs(new ValueActionFactory<>("AES128_GCM"))
+ .withAnyParameters()
+ .buildForContext(new CipherContext())
+ .inBundle(() -> "Tink")
+ .withDependingDetectionRules(AEAD_OP_RULES);
+
+ // KeysetHandle.generateNew(AeadKeyTemplates.AES256_GCM)
+ private static final IDetectionRule AES256_GCM =
+ new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.KeysetHandle")
+ .forMethods("generateNew")
+ .shouldBeDetectedAs(new ValueActionFactory<>("AES256_GCM"))
+ .withAnyParameters()
+ .buildForContext(new CipherContext())
+ .inBundle(() -> "Tink")
+ .withDependingDetectionRules(AEAD_OP_RULES);
+
+ // KeysetHandle.generateNew(AeadKeyTemplates.AES128_CTR_HMAC_SHA256)
+ private static final IDetectionRule AES128_CTR_HMAC_SHA256 =
+ new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.KeysetHandle")
+ .forMethods("generateNew")
+ .shouldBeDetectedAs(new ValueActionFactory<>("AES128_CTR_HMAC_SHA256"))
+ .withAnyParameters()
+ .buildForContext(new CipherContext())
+ .inBundle(() -> "Tink")
+ .withDependingDetectionRules(AEAD_OP_RULES);
+
+ // KeysetHandle.generateNew(AeadKeyTemplates.AES256_CTR_HMAC_SHA256)
+ private static final IDetectionRule AES256_CTR_HMAC_SHA256 =
+ new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.KeysetHandle")
+ .forMethods("generateNew")
+ .shouldBeDetectedAs(new ValueActionFactory<>("AES256_CTR_HMAC_SHA256"))
+ .withAnyParameters()
+ .buildForContext(new CipherContext())
+ .inBundle(() -> "Tink")
+ .withDependingDetectionRules(AEAD_OP_RULES);
+
+ @Nonnull
+ public static List> rules() {
+ return List.of(AES128_GCM, AES256_GCM, AES128_CTR_HMAC_SHA256, AES256_CTR_HMAC_SHA256);
+ }
+}
diff --git a/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkDetectionRules.java b/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkDetectionRules.java
new file mode 100644
index 000000000..c144bef97
--- /dev/null
+++ b/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkDetectionRules.java
@@ -0,0 +1,45 @@
+/*
+ * Sonar Cryptography Plugin
+ * Copyright (C) 2024 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.plugin.rules.detection.tink;
+
+import com.ibm.engine.rule.IDetectionRule;
+import java.util.List;
+import java.util.stream.Stream;
+import javax.annotation.Nonnull;
+import org.sonar.plugins.java.api.tree.Tree;
+
+/** Aggregates all Google Tink detection rule lists. */
+public final class TinkDetectionRules {
+
+ private TinkDetectionRules() {
+ // nothing
+ }
+
+ @Nonnull
+ public static List> rules() {
+ return Stream.of(
+ TinkAead.rules().stream(),
+ TinkMac.rules().stream(),
+ TinkSignature.rules().stream(),
+ TinkHybrid.rules().stream())
+ .flatMap(i -> i)
+ .toList();
+ }
+}
diff --git a/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkHybrid.java b/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkHybrid.java
new file mode 100644
index 000000000..459d61460
--- /dev/null
+++ b/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkHybrid.java
@@ -0,0 +1,99 @@
+/*
+ * Sonar Cryptography Plugin
+ * Copyright (C) 2024 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.plugin.rules.detection.tink;
+
+import com.ibm.engine.detection.MethodMatcher;
+import com.ibm.engine.model.context.CipherContext;
+import com.ibm.engine.model.factory.ValueActionFactory;
+import com.ibm.engine.rule.IDetectionRule;
+import com.ibm.engine.rule.builder.DetectionRuleBuilder;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.sonar.plugins.java.api.tree.Tree;
+
+/**
+ * Detection rules for Google Tink hybrid encryption primitive.
+ *
+ *
+ * - {@code KeysetHandle.generateNew(HybridKeyTemplates.ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM)}
+ *
- {@code hybridEncrypt.encrypt(plaintext, contextInfo)}
+ *
- {@code hybridDecrypt.decrypt(ciphertext, contextInfo)}
+ *
+ */
+@SuppressWarnings("java:S1192")
+public final class TinkHybrid {
+
+ private TinkHybrid() {
+ // nothing
+ }
+
+ // hybridEncrypt.encrypt(byte[] plaintext, byte[] contextInfo)
+ private static final IDetectionRule HYBRID_ENCRYPT =
+ new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.HybridEncrypt")
+ .forMethods("encrypt")
+ .shouldBeDetectedAs(new ValueActionFactory<>("ENCRYPT"))
+ .withMethodParameter(MethodMatcher.ANY)
+ .withMethodParameter(MethodMatcher.ANY)
+ .buildForContext(new CipherContext())
+ .inBundle(() -> "Tink")
+ .withoutDependingDetectionRules();
+
+ // hybridDecrypt.decrypt(byte[] ciphertext, byte[] contextInfo)
+ private static final IDetectionRule HYBRID_DECRYPT =
+ new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.HybridDecrypt")
+ .forMethods("decrypt")
+ .shouldBeDetectedAs(new ValueActionFactory<>("DECRYPT"))
+ .withMethodParameter(MethodMatcher.ANY)
+ .withMethodParameter(MethodMatcher.ANY)
+ .buildForContext(new CipherContext())
+ .inBundle(() -> "Tink")
+ .withoutDependingDetectionRules();
+
+ private static final List> HYBRID_OP_RULES =
+ List.of(HYBRID_ENCRYPT, HYBRID_DECRYPT);
+
+ private static IDetectionRule hybridKeyRule(String value) {
+ return new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.KeysetHandle")
+ .forMethods("generateNew")
+ .shouldBeDetectedAs(new ValueActionFactory<>(value))
+ .withAnyParameters()
+ .buildForContext(new CipherContext())
+ .inBundle(() -> "Tink")
+ .withDependingDetectionRules(HYBRID_OP_RULES);
+ }
+
+ private static final IDetectionRule ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM =
+ hybridKeyRule("ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM");
+ private static final IDetectionRule ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256 =
+ hybridKeyRule("ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256");
+
+ @Nonnull
+ public static List> rules() {
+ return List.of(
+ ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM,
+ ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256);
+ }
+}
diff --git a/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkMac.java b/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkMac.java
new file mode 100644
index 000000000..bcc469f60
--- /dev/null
+++ b/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkMac.java
@@ -0,0 +1,111 @@
+/*
+ * Sonar Cryptography Plugin
+ * Copyright (C) 2024 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.plugin.rules.detection.tink;
+
+import com.ibm.engine.detection.MethodMatcher;
+import com.ibm.engine.model.context.MacContext;
+import com.ibm.engine.model.factory.ValueActionFactory;
+import com.ibm.engine.rule.IDetectionRule;
+import com.ibm.engine.rule.builder.DetectionRuleBuilder;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.sonar.plugins.java.api.tree.Tree;
+
+/**
+ * Detection rules for Google Tink MAC primitive.
+ *
+ * Detects key generation and MAC operations:
+ *
+ *
+ * - {@code KeysetHandle.generateNew(MacKeyTemplates.HMAC_SHA256_128BITTAG)}
+ *
- {@code KeysetHandle.generateNew(MacKeyTemplates.HMAC_SHA256_256BITTAG)}
+ *
- {@code KeysetHandle.generateNew(MacKeyTemplates.HMAC_SHA512_256BITTAG)}
+ *
- {@code KeysetHandle.generateNew(MacKeyTemplates.HMAC_SHA512_512BITTAG)}
+ *
- {@code KeysetHandle.generateNew(MacKeyTemplates.AES_CMAC)}
+ *
- {@code mac.computeMac(data)}
+ *
- {@code mac.verifyMac(tag, data)}
+ *
+ */
+@SuppressWarnings("java:S1192")
+public final class TinkMac {
+
+ private TinkMac() {
+ // nothing
+ }
+
+ // mac.computeMac(byte[] data)
+ private static final IDetectionRule MAC_COMPUTE =
+ new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.Mac")
+ .forMethods("computeMac")
+ .shouldBeDetectedAs(new ValueActionFactory<>("COMPUTE"))
+ .withMethodParameter(MethodMatcher.ANY)
+ .buildForContext(new MacContext())
+ .inBundle(() -> "Tink")
+ .withoutDependingDetectionRules();
+
+ // mac.verifyMac(byte[] tag, byte[] data)
+ private static final IDetectionRule MAC_VERIFY =
+ new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.Mac")
+ .forMethods("verifyMac")
+ .shouldBeDetectedAs(new ValueActionFactory<>("VERIFY"))
+ .withMethodParameter(MethodMatcher.ANY)
+ .withMethodParameter(MethodMatcher.ANY)
+ .buildForContext(new MacContext())
+ .inBundle(() -> "Tink")
+ .withoutDependingDetectionRules();
+
+ private static final List> MAC_OP_RULES = List.of(MAC_COMPUTE, MAC_VERIFY);
+
+ private static IDetectionRule macKeyRule(String value) {
+ return new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.KeysetHandle")
+ .forMethods("generateNew")
+ .shouldBeDetectedAs(new ValueActionFactory<>(value))
+ .withAnyParameters()
+ .buildForContext(new MacContext())
+ .inBundle(() -> "Tink")
+ .withDependingDetectionRules(MAC_OP_RULES);
+ }
+
+ private static final IDetectionRule HMAC_SHA256_128BITTAG =
+ macKeyRule("HMAC_SHA256_128BITTAG");
+ private static final IDetectionRule HMAC_SHA256_256BITTAG =
+ macKeyRule("HMAC_SHA256_256BITTAG");
+ private static final IDetectionRule HMAC_SHA512_256BITTAG =
+ macKeyRule("HMAC_SHA512_256BITTAG");
+ private static final IDetectionRule HMAC_SHA512_512BITTAG =
+ macKeyRule("HMAC_SHA512_512BITTAG");
+ private static final IDetectionRule AES_CMAC = macKeyRule("AES_CMAC");
+
+ @Nonnull
+ public static List> rules() {
+ return List.of(
+ HMAC_SHA256_128BITTAG,
+ HMAC_SHA256_256BITTAG,
+ HMAC_SHA512_256BITTAG,
+ HMAC_SHA512_512BITTAG,
+ AES_CMAC);
+ }
+}
diff --git a/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkSignature.java b/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkSignature.java
new file mode 100644
index 000000000..2c95ada9b
--- /dev/null
+++ b/java/src/main/java/com/ibm/plugin/rules/detection/tink/TinkSignature.java
@@ -0,0 +1,98 @@
+/*
+ * Sonar Cryptography Plugin
+ * Copyright (C) 2024 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.plugin.rules.detection.tink;
+
+import com.ibm.engine.detection.MethodMatcher;
+import com.ibm.engine.model.context.SignatureContext;
+import com.ibm.engine.model.factory.ValueActionFactory;
+import com.ibm.engine.rule.IDetectionRule;
+import com.ibm.engine.rule.builder.DetectionRuleBuilder;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.sonar.plugins.java.api.tree.Tree;
+
+/**
+ * Detection rules for Google Tink digital signature primitive.
+ *
+ *
+ * - {@code KeysetHandle.generateNew(SignatureKeyTemplates.ECDSA_P256)}
+ *
- {@code KeysetHandle.generateNew(SignatureKeyTemplates.ED25519)}
+ *
- {@code signer.sign(data)}
+ *
- {@code verifier.verify(signature, data)}
+ *
+ */
+@SuppressWarnings("java:S1192")
+public final class TinkSignature {
+
+ private TinkSignature() {
+ // nothing
+ }
+
+ // signer.sign(byte[] data)
+ private static final IDetectionRule SIGN =
+ new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.PublicKeySign")
+ .forMethods("sign")
+ .shouldBeDetectedAs(new ValueActionFactory<>("SIGN"))
+ .withMethodParameter(MethodMatcher.ANY)
+ .buildForContext(new SignatureContext())
+ .inBundle(() -> "Tink")
+ .withoutDependingDetectionRules();
+
+ // verifier.verify(byte[] signature, byte[] data)
+ private static final IDetectionRule VERIFY =
+ new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.PublicKeyVerify")
+ .forMethods("verify")
+ .shouldBeDetectedAs(new ValueActionFactory<>("VERIFY"))
+ .withMethodParameter(MethodMatcher.ANY)
+ .withMethodParameter(MethodMatcher.ANY)
+ .buildForContext(new SignatureContext())
+ .inBundle(() -> "Tink")
+ .withoutDependingDetectionRules();
+
+ private static final List> SIGN_OP_RULES = List.of(SIGN, VERIFY);
+
+ private static IDetectionRule signKeyRule(String value) {
+ return new DetectionRuleBuilder()
+ .createDetectionRule()
+ .forObjectTypes("com.google.crypto.tink.KeysetHandle")
+ .forMethods("generateNew")
+ .shouldBeDetectedAs(new ValueActionFactory<>(value))
+ .withAnyParameters()
+ .buildForContext(new SignatureContext())
+ .inBundle(() -> "Tink")
+ .withDependingDetectionRules(SIGN_OP_RULES);
+ }
+
+ private static final IDetectionRule ECDSA_P256 = signKeyRule("ECDSA_P256");
+ private static final IDetectionRule ECDSA_P384 = signKeyRule("ECDSA_P384");
+ private static final IDetectionRule ECDSA_P521 = signKeyRule("ECDSA_P521");
+ private static final IDetectionRule ED25519 = signKeyRule("ED25519");
+ private static final IDetectionRule RSA_SSA_PKCS1_3072_SHA256_F4 =
+ signKeyRule("RSA_SSA_PKCS1_3072_SHA256_F4");
+
+ @Nonnull
+ public static List> rules() {
+ return List.of(ECDSA_P256, ECDSA_P384, ECDSA_P521, ED25519, RSA_SSA_PKCS1_3072_SHA256_F4);
+ }
+}
diff --git a/java/src/main/java/com/ibm/plugin/translation/translator/contexts/JavaAbstractLibraryTranslator.java b/java/src/main/java/com/ibm/plugin/translation/translator/contexts/JavaAbstractLibraryTranslator.java
index 9246b8765..dadb381d6 100644
--- a/java/src/main/java/com/ibm/plugin/translation/translator/contexts/JavaAbstractLibraryTranslator.java
+++ b/java/src/main/java/com/ibm/plugin/translation/translator/contexts/JavaAbstractLibraryTranslator.java
@@ -42,6 +42,7 @@ public Optional translate(
return switch (bundleIdentifier.getIdentifier()) {
case "Jca" -> translateJCA(value, detectionContext, detectionLocation);
case "Bc" -> translateBC(value, detectionContext, detectionLocation);
+ case "Tink" -> translateTink(value, detectionContext, detectionLocation);
default -> Optional.of(new Unknown(detectionLocation));
};
}
@@ -57,4 +58,12 @@ protected abstract Optional translateBC(
@Nonnull IValue value,
@Nonnull IDetectionContext detectionContext,
@Nonnull DetectionLocation detectionLocation);
+
+ @Nonnull
+ protected Optional translateTink(
+ @Nonnull IValue value,
+ @Nonnull IDetectionContext detectionContext,
+ @Nonnull DetectionLocation detectionLocation) {
+ return Optional.empty();
+ }
}
diff --git a/java/src/main/java/com/ibm/plugin/translation/translator/contexts/JavaCipherContextTranslator.java b/java/src/main/java/com/ibm/plugin/translation/translator/contexts/JavaCipherContextTranslator.java
index 7bfed2e84..92e362915 100644
--- a/java/src/main/java/com/ibm/plugin/translation/translator/contexts/JavaCipherContextTranslator.java
+++ b/java/src/main/java/com/ibm/plugin/translation/translator/contexts/JavaCipherContextTranslator.java
@@ -202,4 +202,24 @@ public Optional translateBC(
}
return Optional.empty();
}
+
+ @Nonnull
+ @Override
+ protected Optional translateTink(
+ @Nonnull IValue value,
+ @Nonnull IDetectionContext detectionContext,
+ @Nonnull DetectionLocation detectionLocation) {
+ if (value instanceof ValueAction>) {
+ return switch (value.asString()) {
+ case "AES128_GCM", "AES256_GCM" ->
+ Optional.of(
+ new com.ibm.mapper.model.algorithms.AES(
+ AuthenticatedEncryption.class, detectionLocation));
+ case "AES128_CTR_HMAC_SHA256", "AES256_CTR_HMAC_SHA256" ->
+ Optional.of(new com.ibm.mapper.model.algorithms.AES(detectionLocation));
+ default -> Optional.empty();
+ };
+ }
+ return Optional.empty();
+ }
}
diff --git a/java/src/test/files/rules/detection/tink/TinkAeadTestFile.java b/java/src/test/files/rules/detection/tink/TinkAeadTestFile.java
new file mode 100644
index 000000000..821d31071
--- /dev/null
+++ b/java/src/test/files/rules/detection/tink/TinkAeadTestFile.java
@@ -0,0 +1,21 @@
+import com.google.crypto.tink.Aead;
+import com.google.crypto.tink.KeysetHandle;
+import com.google.crypto.tink.aead.AeadConfig;
+import com.google.crypto.tink.aead.AeadKeyTemplates;
+
+public class TinkAeadTestFile {
+
+ public void testAes128Gcm() throws Exception {
+ AeadConfig.register();
+ KeysetHandle keysetHandle =
+ KeysetHandle.generateNew(AeadKeyTemplates.AES128_GCM); // Noncompliant 4
+ Aead aead = keysetHandle.getPrimitive(Aead.class);
+ }
+
+ public void testAes256Gcm() throws Exception {
+ AeadConfig.register();
+ KeysetHandle keysetHandle =
+ KeysetHandle.generateNew(AeadKeyTemplates.AES256_GCM); // Noncompliant 4
+ Aead aead = keysetHandle.getPrimitive(Aead.class);
+ }
+}
\ No newline at end of file
diff --git a/java/src/test/files/rules/detection/tink/TinkHybridTestFile.java b/java/src/test/files/rules/detection/tink/TinkHybridTestFile.java
new file mode 100644
index 000000000..2ddaac349
--- /dev/null
+++ b/java/src/test/files/rules/detection/tink/TinkHybridTestFile.java
@@ -0,0 +1,18 @@
+import com.google.crypto.tink.HybridDecrypt;
+import com.google.crypto.tink.HybridEncrypt;
+import com.google.crypto.tink.KeysetHandle;
+import com.google.crypto.tink.hybrid.HybridConfig;
+import com.google.crypto.tink.hybrid.HybridKeyTemplates;
+
+public class TinkHybridTestFile {
+
+ public void testEciesP256() throws Exception {
+ HybridConfig.register();
+ KeysetHandle keysetHandle = KeysetHandle.generateNew(HybridKeyTemplates.ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM); // Noncompliant 4
+ }
+
+ public void testEciesP256Ctr() throws Exception {
+ HybridConfig.register();
+ KeysetHandle keysetHandle = KeysetHandle.generateNew(HybridKeyTemplates.ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256); // Noncompliant 4
+ }
+}
diff --git a/java/src/test/files/rules/detection/tink/TinkMacTestFile.java b/java/src/test/files/rules/detection/tink/TinkMacTestFile.java
new file mode 100644
index 000000000..b535c4304
--- /dev/null
+++ b/java/src/test/files/rules/detection/tink/TinkMacTestFile.java
@@ -0,0 +1,19 @@
+import com.google.crypto.tink.KeysetHandle;
+import com.google.crypto.tink.Mac;
+import com.google.crypto.tink.mac.MacConfig;
+import com.google.crypto.tink.mac.MacKeyTemplates;
+
+public class TinkMacTestFile {
+
+ public void testHmacSha256() throws Exception {
+ MacConfig.register();
+ KeysetHandle keysetHandle =
+ KeysetHandle.generateNew(MacKeyTemplates.HMAC_SHA256_128BITTAG); // Noncompliant 4
+ }
+
+ public void testHmacSha512() throws Exception {
+ MacConfig.register();
+ KeysetHandle keysetHandle =
+ KeysetHandle.generateNew(MacKeyTemplates.HMAC_SHA512_256BITTAG); // Noncompliant 4
+ }
+}
\ No newline at end of file
diff --git a/java/src/test/files/rules/detection/tink/TinkSignatureTestFile.java b/java/src/test/files/rules/detection/tink/TinkSignatureTestFile.java
new file mode 100644
index 000000000..580b42bbc
--- /dev/null
+++ b/java/src/test/files/rules/detection/tink/TinkSignatureTestFile.java
@@ -0,0 +1,19 @@
+import com.google.crypto.tink.KeysetHandle;
+import com.google.crypto.tink.PublicKeySign;
+import com.google.crypto.tink.signature.SignatureConfig;
+import com.google.crypto.tink.signature.SignatureKeyTemplates;
+
+public class TinkSignatureTestFile {
+
+ public void testEcdsaP256() throws Exception {
+ SignatureConfig.register();
+ KeysetHandle keysetHandle =
+ KeysetHandle.generateNew(SignatureKeyTemplates.ECDSA_P256); // Noncompliant 4
+ }
+
+ public void testEd25519() throws Exception {
+ SignatureConfig.register();
+ KeysetHandle keysetHandle =
+ KeysetHandle.generateNew(SignatureKeyTemplates.ED25519); // Noncompliant 4
+ }
+}
\ No newline at end of file
diff --git a/java/src/test/java/com/ibm/plugin/rules/detection/tink/TinkAeadTest.java b/java/src/test/java/com/ibm/plugin/rules/detection/tink/TinkAeadTest.java
new file mode 100644
index 000000000..681bc5f84
--- /dev/null
+++ b/java/src/test/java/com/ibm/plugin/rules/detection/tink/TinkAeadTest.java
@@ -0,0 +1,98 @@
+/*
+ * Sonar Cryptography Plugin
+ * Copyright (C) 2024 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.plugin.rules.detection.tink;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.ibm.engine.detection.DetectionStore;
+import com.ibm.engine.model.IValue;
+import com.ibm.engine.model.ValueAction;
+import com.ibm.engine.model.context.CipherContext;
+import com.ibm.engine.model.context.MacContext;
+import com.ibm.engine.model.context.SignatureContext;
+import com.ibm.mapper.model.AuthenticatedEncryption;
+import com.ibm.mapper.model.BlockCipher;
+import com.ibm.mapper.model.INode;
+import com.ibm.plugin.TestBase;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.junit.jupiter.api.Test;
+import org.sonar.java.checks.verifier.CheckVerifier;
+import org.sonar.plugins.java.api.JavaCheck;
+import org.sonar.plugins.java.api.JavaFileScannerContext;
+import org.sonar.plugins.java.api.semantic.Symbol;
+import org.sonar.plugins.java.api.tree.Tree;
+
+class TinkAeadTest extends TestBase {
+
+ @Test
+ void test() {
+ CheckVerifier.newVerifier()
+ .onFile("src/test/files/rules/detection/tink/TinkAeadTestFile.java")
+ .withChecks(this)
+ .withClassPath(
+ com.google.common.collect.ImmutableList.of(
+ new java.io.File(
+ System.getProperty("user.home")
+ + "/.m2/repository/com/google/crypto/tink/tink/1.21.0/tink-1.21.0.jar")))
+ .verifyIssues();
+ }
+
+ @Override
+ public void asserts(
+ int findingId,
+ @Nonnull DetectionStore detectionStore,
+ @Nonnull List nodes) {
+
+ /*
+ * Detection Store
+ */
+ assertThat(detectionStore.getDetectionValues()).hasSize(1);
+ assertThat(detectionStore.getDetectionValueContext())
+ .isInstanceOfAny(CipherContext.class, MacContext.class, SignatureContext.class);
+ IValue value = detectionStore.getDetectionValues().get(0);
+ assertThat(value).isInstanceOf(ValueAction.class);
+ assertThat(value.asString())
+ .isIn(
+ "AES128_GCM",
+ "AES256_GCM",
+ "AES128_CTR_HMAC_SHA256",
+ "AES256_CTR_HMAC_SHA256",
+ "HMAC_SHA256_128BITTAG",
+ "HMAC_SHA256_256BITTAG",
+ "HMAC_SHA512_256BITTAG",
+ "HMAC_SHA512_512BITTAG",
+ "AES_CMAC",
+ "ECDSA_P256",
+ "ECDSA_P384",
+ "ECDSA_P521",
+ "ED25519",
+ "RSA_SSA_PKCS1_3072_SHA256_F4",
+ "ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM",
+ "ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256");
+
+ // Translation only implemented for AEAD templates — Mac/Hybrid/Signature return empty nodes
+ if (!nodes.isEmpty()) {
+ INode node = nodes.get(0);
+ assertThat(node.getKind()).isIn(AuthenticatedEncryption.class, BlockCipher.class);
+ assertThat(node.asString()).isEqualTo("AES");
+ }
+ }
+}
diff --git a/java/src/test/java/com/ibm/plugin/rules/detection/tink/TinkHybridTest.java b/java/src/test/java/com/ibm/plugin/rules/detection/tink/TinkHybridTest.java
new file mode 100644
index 000000000..dd7158d77
--- /dev/null
+++ b/java/src/test/java/com/ibm/plugin/rules/detection/tink/TinkHybridTest.java
@@ -0,0 +1,89 @@
+/*
+ * Sonar Cryptography Plugin
+ * Copyright (C) 2024 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.plugin.rules.detection.tink;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.ibm.engine.detection.DetectionStore;
+import com.ibm.engine.model.IValue;
+import com.ibm.engine.model.ValueAction;
+import com.ibm.engine.model.context.CipherContext;
+import com.ibm.engine.model.context.MacContext;
+import com.ibm.engine.model.context.SignatureContext;
+import com.ibm.mapper.model.INode;
+import com.ibm.plugin.TestBase;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.junit.jupiter.api.Test;
+import org.sonar.java.checks.verifier.CheckVerifier;
+import org.sonar.plugins.java.api.JavaCheck;
+import org.sonar.plugins.java.api.JavaFileScannerContext;
+import org.sonar.plugins.java.api.semantic.Symbol;
+import org.sonar.plugins.java.api.tree.Tree;
+
+class TinkHybridTest extends TestBase {
+
+ @Test
+ void test() {
+ CheckVerifier.newVerifier()
+ .onFile("src/test/files/rules/detection/tink/TinkHybridTestFile.java")
+ .withChecks(this)
+ .withClassPath(
+ com.google.common.collect.ImmutableList.of(
+ new java.io.File(
+ System.getProperty("user.home")
+ + "/.m2/repository/com/google/crypto/tink/tink/1.21.0/tink-1.21.0.jar")))
+ .verifyIssues();
+ }
+
+ @Override
+ public void asserts(
+ int findingId,
+ @Nonnull DetectionStore detectionStore,
+ @Nonnull List nodes) {
+
+ /*
+ * Detection Store
+ */
+ assertThat(detectionStore.getDetectionValues()).hasSize(1);
+ assertThat(detectionStore.getDetectionValueContext())
+ .isInstanceOfAny(CipherContext.class, MacContext.class, SignatureContext.class);
+ IValue value = detectionStore.getDetectionValues().get(0);
+ assertThat(value).isInstanceOf(ValueAction.class);
+ assertThat(value.asString())
+ .isIn(
+ "AES128_GCM",
+ "AES256_GCM",
+ "AES128_CTR_HMAC_SHA256",
+ "AES256_CTR_HMAC_SHA256",
+ "HMAC_SHA256_128BITTAG",
+ "HMAC_SHA256_256BITTAG",
+ "HMAC_SHA512_256BITTAG",
+ "HMAC_SHA512_512BITTAG",
+ "AES_CMAC",
+ "ECDSA_P256",
+ "ECDSA_P384",
+ "ECDSA_P521",
+ "ED25519",
+ "RSA_SSA_PKCS1_3072_SHA256_F4",
+ "ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM",
+ "ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256");
+ }
+}
diff --git a/java/src/test/java/com/ibm/plugin/rules/detection/tink/TinkMacTest.java b/java/src/test/java/com/ibm/plugin/rules/detection/tink/TinkMacTest.java
new file mode 100644
index 000000000..abef704f9
--- /dev/null
+++ b/java/src/test/java/com/ibm/plugin/rules/detection/tink/TinkMacTest.java
@@ -0,0 +1,89 @@
+/*
+ * Sonar Cryptography Plugin
+ * Copyright (C) 2024 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.plugin.rules.detection.tink;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.ibm.engine.detection.DetectionStore;
+import com.ibm.engine.model.IValue;
+import com.ibm.engine.model.ValueAction;
+import com.ibm.engine.model.context.CipherContext;
+import com.ibm.engine.model.context.MacContext;
+import com.ibm.engine.model.context.SignatureContext;
+import com.ibm.mapper.model.INode;
+import com.ibm.plugin.TestBase;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.junit.jupiter.api.Test;
+import org.sonar.java.checks.verifier.CheckVerifier;
+import org.sonar.plugins.java.api.JavaCheck;
+import org.sonar.plugins.java.api.JavaFileScannerContext;
+import org.sonar.plugins.java.api.semantic.Symbol;
+import org.sonar.plugins.java.api.tree.Tree;
+
+class TinkMacTest extends TestBase {
+
+ @Test
+ void test() {
+ CheckVerifier.newVerifier()
+ .onFile("src/test/files/rules/detection/tink/TinkMacTestFile.java")
+ .withChecks(this)
+ .withClassPath(
+ com.google.common.collect.ImmutableList.of(
+ new java.io.File(
+ System.getProperty("user.home")
+ + "/.m2/repository/com/google/crypto/tink/tink/1.21.0/tink-1.21.0.jar")))
+ .verifyIssues();
+ }
+
+ @Override
+ public void asserts(
+ int findingId,
+ @Nonnull DetectionStore detectionStore,
+ @Nonnull List nodes) {
+
+ /*
+ * Detection Store
+ */
+ assertThat(detectionStore.getDetectionValues()).hasSize(1);
+ assertThat(detectionStore.getDetectionValueContext())
+ .isInstanceOfAny(CipherContext.class, MacContext.class, SignatureContext.class);
+ IValue value = detectionStore.getDetectionValues().get(0);
+ assertThat(value).isInstanceOf(ValueAction.class);
+ assertThat(value.asString())
+ .isIn(
+ "AES128_GCM",
+ "AES256_GCM",
+ "AES128_CTR_HMAC_SHA256",
+ "AES256_CTR_HMAC_SHA256",
+ "HMAC_SHA256_128BITTAG",
+ "HMAC_SHA256_256BITTAG",
+ "HMAC_SHA512_256BITTAG",
+ "HMAC_SHA512_512BITTAG",
+ "AES_CMAC",
+ "ECDSA_P256",
+ "ECDSA_P384",
+ "ECDSA_P521",
+ "ED25519",
+ "RSA_SSA_PKCS1_3072_SHA256_F4",
+ "ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM",
+ "ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256");
+ }
+}
diff --git a/java/src/test/java/com/ibm/plugin/rules/detection/tink/TinkSignatureTest.java b/java/src/test/java/com/ibm/plugin/rules/detection/tink/TinkSignatureTest.java
new file mode 100644
index 000000000..8d428cb85
--- /dev/null
+++ b/java/src/test/java/com/ibm/plugin/rules/detection/tink/TinkSignatureTest.java
@@ -0,0 +1,89 @@
+/*
+ * Sonar Cryptography Plugin
+ * Copyright (C) 2024 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.plugin.rules.detection.tink;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.ibm.engine.detection.DetectionStore;
+import com.ibm.engine.model.IValue;
+import com.ibm.engine.model.ValueAction;
+import com.ibm.engine.model.context.CipherContext;
+import com.ibm.engine.model.context.MacContext;
+import com.ibm.engine.model.context.SignatureContext;
+import com.ibm.mapper.model.INode;
+import com.ibm.plugin.TestBase;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.junit.jupiter.api.Test;
+import org.sonar.java.checks.verifier.CheckVerifier;
+import org.sonar.plugins.java.api.JavaCheck;
+import org.sonar.plugins.java.api.JavaFileScannerContext;
+import org.sonar.plugins.java.api.semantic.Symbol;
+import org.sonar.plugins.java.api.tree.Tree;
+
+class TinkSignatureTest extends TestBase {
+
+ @Test
+ void test() {
+ CheckVerifier.newVerifier()
+ .onFile("src/test/files/rules/detection/tink/TinkSignatureTestFile.java")
+ .withChecks(this)
+ .withClassPath(
+ com.google.common.collect.ImmutableList.of(
+ new java.io.File(
+ System.getProperty("user.home")
+ + "/.m2/repository/com/google/crypto/tink/tink/1.21.0/tink-1.21.0.jar")))
+ .verifyIssues();
+ }
+
+ @Override
+ public void asserts(
+ int findingId,
+ @Nonnull DetectionStore detectionStore,
+ @Nonnull List nodes) {
+
+ /*
+ * Detection Store
+ */
+ assertThat(detectionStore.getDetectionValues()).hasSize(1);
+ assertThat(detectionStore.getDetectionValueContext())
+ .isInstanceOfAny(CipherContext.class, MacContext.class, SignatureContext.class);
+ IValue value = detectionStore.getDetectionValues().get(0);
+ assertThat(value).isInstanceOf(ValueAction.class);
+ assertThat(value.asString())
+ .isIn(
+ "AES128_GCM",
+ "AES256_GCM",
+ "AES128_CTR_HMAC_SHA256",
+ "AES256_CTR_HMAC_SHA256",
+ "HMAC_SHA256_128BITTAG",
+ "HMAC_SHA256_256BITTAG",
+ "HMAC_SHA512_256BITTAG",
+ "HMAC_SHA512_512BITTAG",
+ "AES_CMAC",
+ "ECDSA_P256",
+ "ECDSA_P384",
+ "ECDSA_P521",
+ "ED25519",
+ "RSA_SSA_PKCS1_3072_SHA256_F4",
+ "ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM",
+ "ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256");
+ }
+}