From d864bff7b15e637439fcca891b38444b09841b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicklas=20K=C3=B6rtge?= Date: Thu, 29 Aug 2024 09:13:35 +0200 Subject: [PATCH] update tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nicklas Körtge --- .../main/java/com/ibm/enricher/Enricher.java | 4 + .../enricher/algorithm/RSAoaepEnricher.java | 49 +++ .../main/java/com/ibm/mapper/ITranslator.java | 6 +- .../mapper/mapper/pyca/PycaCipherMapper.java | 2 - .../com/ibm/mapper/model/algorithms/RSA.java | 4 + .../reorganizer/rules/PaddingReorganizer.java | 86 +++++ .../rules/detection/asymmetric/PycaRSA.java | 4 +- .../reorganizer/PythonReorganizerRules.java | 4 +- .../contexts/PycaDigestContextTranslator.java | 9 +- .../PycaSignatureContextTranslator.java | 19 +- ....py => PycaEllipticCurveVerifyTestFile.py} | 2 +- ...tTestFile.py => PycaRSADecryptTestFile.py} | 2 +- .../PycaEllipticCurveVerifyTest.java | 14 +- .../asymmetric/RSA/PycaRSADecryptTest.java | 358 ++++++++++-------- 14 files changed, 376 insertions(+), 187 deletions(-) create mode 100644 enricher/src/main/java/com/ibm/enricher/algorithm/RSAoaepEnricher.java create mode 100644 mapper/src/main/java/com/ibm/mapper/reorganizer/rules/PaddingReorganizer.java rename python/src/test/files/rules/detection/asymmetric/EllipticCurve/{CryptographyEllipticCurveVerifyTestFile.py => PycaEllipticCurveVerifyTestFile.py} (80%) rename python/src/test/files/rules/detection/asymmetric/RSA/{CryptographyRSADecryptTestFile.py => PycaRSADecryptTestFile.py} (95%) diff --git a/enricher/src/main/java/com/ibm/enricher/Enricher.java b/enricher/src/main/java/com/ibm/enricher/Enricher.java index 23c99281..bfe1fae5 100644 --- a/enricher/src/main/java/com/ibm/enricher/Enricher.java +++ b/enricher/src/main/java/com/ibm/enricher/Enricher.java @@ -26,6 +26,7 @@ import com.ibm.enricher.algorithm.MacOrDigestEnricher; import com.ibm.enricher.algorithm.PBKDF2Enricher; import com.ibm.enricher.algorithm.RSAEnricher; +import com.ibm.enricher.algorithm.RSAoaepEnricher; import com.ibm.enricher.algorithm.RSAssaPSSEnricher; import com.ibm.enricher.algorithm.SHA2Enricher; import com.ibm.enricher.algorithm.SHA3Enricher; @@ -120,6 +121,9 @@ public INode enrich(@Nonnull INode node) { if (node instanceof RSAssaPSS) { node = new RSAssaPSSEnricher().enrich(node); } + if (node instanceof RSA) { + node = new RSAoaepEnricher().enrich(node); + } if (node instanceof Signature) { node = new SignatureEnricher().enrich(node); diff --git a/enricher/src/main/java/com/ibm/enricher/algorithm/RSAoaepEnricher.java b/enricher/src/main/java/com/ibm/enricher/algorithm/RSAoaepEnricher.java new file mode 100644 index 00000000..9f663c77 --- /dev/null +++ b/enricher/src/main/java/com/ibm/enricher/algorithm/RSAoaepEnricher.java @@ -0,0 +1,49 @@ +/* + * SonarQube Cryptography Plugin + * Copyright (C) 2024 IBM + * + * 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.enricher.algorithm; + +import com.ibm.enricher.IEnricher; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.Padding; +import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.algorithms.RSA; +import com.ibm.mapper.model.padding.OAEP; +import java.util.Optional; +import org.jetbrains.annotations.NotNull; + +public class RSAoaepEnricher implements IEnricher { + + @Override + public @NotNull INode enrich(@NotNull INode node) { + if (node instanceof RSA rsa) { + final Optional padding = rsa.hasChildOfType(Padding.class); + if (padding.isEmpty()) { + return node; + } + if (padding.get() instanceof OAEP) { + final RSA newRSA = new RSA(Signature.class, rsa); + newRSA.put(new Oid("1.2.840.113549.1.1.7", rsa.getDetectionContext())); + return newRSA; + } + } + return node; + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/ITranslator.java b/mapper/src/main/java/com/ibm/mapper/ITranslator.java index 70f5de85..73313711 100644 --- a/mapper/src/main/java/com/ibm/mapper/ITranslator.java +++ b/mapper/src/main/java/com/ibm/mapper/ITranslator.java @@ -113,7 +113,7 @@ protected abstract Optional translate( */ static class Traverser { @Nonnull final DetectionStore rootDetectionStore; - @Nonnull final List newParents = new ArrayList<>(); + @Nonnull final List newRoots = new ArrayList<>(); @Nonnull final Function, Map>> translator; public Traverser( @@ -131,7 +131,7 @@ public List translate() { travers(rootDetectionStore, rootNodes); final List translatedRootNodes = new ArrayList<>(rootNodes.values().stream().flatMap(List::stream).toList()); - translatedRootNodes.addAll(newParents); + translatedRootNodes.addAll(newRoots); return translatedRootNodes; } @@ -196,7 +196,7 @@ private void append( if (parentNode.hasChildOfType(childNode.getKind()).isPresent()) { final INode newParent = parentNode.deepCopy(); newParent.put(childNode); - newParents.add(newParent); + newRoots.add(newParent); } else { parentNode.put(childNode); } diff --git a/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaCipherMapper.java b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaCipherMapper.java index e617ab09..25d01fce 100644 --- a/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaCipherMapper.java +++ b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaCipherMapper.java @@ -27,7 +27,6 @@ import com.ibm.mapper.model.algorithms.ChaCha20; import com.ibm.mapper.model.algorithms.ChaCha20Poly1305; import com.ibm.mapper.model.algorithms.IDEA; -import com.ibm.mapper.model.algorithms.MGF1; import com.ibm.mapper.model.algorithms.RC4; import com.ibm.mapper.model.algorithms.RSA; import com.ibm.mapper.model.algorithms.SEED; @@ -48,7 +47,6 @@ public final class PycaCipherMapper implements IMapper { } return switch (str.toUpperCase().trim()) { - case "MGF1" -> Optional.of(new MGF1(detectionLocation)); case "AES" -> Optional.of(new AES(detectionLocation)); case "AES128" -> Optional.of(new AES(128, detectionLocation)); case "AES256" -> Optional.of(new AES(256, detectionLocation)); diff --git a/mapper/src/main/java/com/ibm/mapper/model/algorithms/RSA.java b/mapper/src/main/java/com/ibm/mapper/model/algorithms/RSA.java index fadbf7b0..4c2ed8b9 100644 --- a/mapper/src/main/java/com/ibm/mapper/model/algorithms/RSA.java +++ b/mapper/src/main/java/com/ibm/mapper/model/algorithms/RSA.java @@ -51,4 +51,8 @@ public RSA( super(NAME, asKind, detectionLocation); this.put(new Oid(OID, detectionLocation)); } + + public RSA(@Nonnull final Class asKind, @NotNull RSA rsa) { + super(rsa, asKind); + } } diff --git a/mapper/src/main/java/com/ibm/mapper/reorganizer/rules/PaddingReorganizer.java b/mapper/src/main/java/com/ibm/mapper/reorganizer/rules/PaddingReorganizer.java new file mode 100644 index 00000000..0f2adb7b --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/reorganizer/rules/PaddingReorganizer.java @@ -0,0 +1,86 @@ +/* + * SonarQube Cryptography Plugin + * Copyright (C) 2024 IBM + * + * 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.mapper.reorganizer.rules; + +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Padding; +import com.ibm.mapper.model.PrivateKey; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.functionality.Decrypt; +import com.ibm.mapper.model.padding.OAEP; +import com.ibm.mapper.reorganizer.IReorganizerRule; +import com.ibm.mapper.reorganizer.builder.ReorganizerRuleBuilder; +import java.util.Optional; + +public final class PaddingReorganizer { + + private PaddingReorganizer() { + // nothing + } + + public static final IReorganizerRule MOVE_OAEP_UNDER_ALGORITHM = + new ReorganizerRuleBuilder() + .createReorganizerRule() + .forNodeKind(PrivateKey.class) + .withDetectionCondition( + (node, parent, roots) -> { + final Optional functionality = + node.hasChildOfType(Decrypt.class); + final Optional pke = + node.hasChildOfType(PublicKeyEncryption.class); + if (functionality.isEmpty()) { + return false; + } + if (pke.isEmpty()) { + return false; + } + + return functionality + .get() + .hasChildOfType(Padding.class) + .map(OAEP.class::isInstance) + .orElse(false); + }) + .perform( + (node, parent, roots) -> { + final Optional pke = + node.hasChildOfType(PublicKeyEncryption.class); + final Optional functionality = + node.hasChildOfType(Decrypt.class); + if (functionality.isEmpty()) { + return roots; + } + if (pke.isEmpty()) { + return roots; + } + + functionality + .get() + .hasChildOfType(Padding.class) + .ifPresent( + p -> { + pke.get().put(p); + functionality + .get() + .removeChildOfType(p.getKind()); + }); + return roots; + }); +} diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaRSA.java b/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaRSA.java index 3d0a9d21..ad6305b1 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaRSA.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaRSA.java @@ -60,6 +60,7 @@ private PycaRSA() { .createDetectionRule() .forObjectTypes(PADDING_TYPE) .forMethods("MGF1") + .shouldBeDetectedAs(new ValueActionFactory<>("MGF1")) .withMethodParameter(HASH_TYPE) // This "type" accepts both hashes // and pre-hashes .addDependingDetectionRules(PycaHash.rules()) @@ -101,7 +102,8 @@ private PycaRSA() { .forMethods("OAEP") .shouldBeDetectedAs(new ValueActionFactory<>("OAEP")) .withMethodParameter(ANY) - .shouldBeDetectedAs(new AlgorithmFactory<>()) + // .shouldBeDetectedAs(new AlgorithmFactory<>()) + // .asChildOfParameterWithId(-1) .addDependingDetectionRules(List.of(MGF1)) .withMethodParameter(HASH_TYPE) // This "type" accepts both hashes // and pre-hashes diff --git a/python/src/main/java/com/ibm/plugin/translation/reorganizer/PythonReorganizerRules.java b/python/src/main/java/com/ibm/plugin/translation/reorganizer/PythonReorganizerRules.java index 5bc67a38..ed90bce5 100644 --- a/python/src/main/java/com/ibm/plugin/translation/reorganizer/PythonReorganizerRules.java +++ b/python/src/main/java/com/ibm/plugin/translation/reorganizer/PythonReorganizerRules.java @@ -21,6 +21,7 @@ import com.ibm.mapper.reorganizer.IReorganizerRule; import com.ibm.mapper.reorganizer.rules.KeyAgreementReorganizer; +import com.ibm.mapper.reorganizer.rules.PaddingReorganizer; import com.ibm.mapper.reorganizer.rules.SignerReorganizer; import java.util.List; import java.util.stream.Stream; @@ -37,7 +38,8 @@ public static List rules() { return Stream.of( SignerReorganizer.MOVE_DIGEST_FROM_SIGN_ACTION_UNDER_SIGNATURE, SignerReorganizer.MERGE_SIGNATURE_WITH_PKE_UNDER_PRIVATE_KEY, - KeyAgreementReorganizer.MERGE_KEYAGREEMENT_WITH_PKE_UNDER_PRIVATE_KEY) + KeyAgreementReorganizer.MERGE_KEYAGREEMENT_WITH_PKE_UNDER_PRIVATE_KEY, + PaddingReorganizer.MOVE_OAEP_UNDER_ALGORITHM) .toList(); } } diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaDigestContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaDigestContextTranslator.java index 5a005988..5a4ad4d9 100644 --- a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaDigestContextTranslator.java +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaDigestContextTranslator.java @@ -26,6 +26,7 @@ import com.ibm.mapper.IContextTranslation; import com.ibm.mapper.mapper.pyca.PycaDigestMapper; import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.functionality.Digest; import com.ibm.mapper.utils.DetectionLocation; import java.util.Optional; import org.jetbrains.annotations.NotNull; @@ -42,7 +43,13 @@ public final class PycaDigestContextTranslator implements IContextTranslation) { final PycaDigestMapper pycaDigestMapper = new PycaDigestMapper(); - return pycaDigestMapper.parse(value.asString(), detectionLocation).map(i -> i); + return pycaDigestMapper + .parse(value.asString(), detectionLocation) + .map( + hash -> { + hash.put(new Digest(detectionLocation)); + return hash; + }); } return Optional.empty(); } diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaSignatureContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaSignatureContextTranslator.java index 89c34acd..6a420a0e 100644 --- a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaSignatureContextTranslator.java +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaSignatureContextTranslator.java @@ -74,13 +74,18 @@ public final class PycaSignatureContextTranslator implements IContextTranslation case VERIFY -> Optional.of(new Verify(detectionLocation)); }; } else if (value instanceof ValueAction - && detectionContext instanceof DetectionContext context - && context.get("kind").map(k -> k.equals("padding")).orElse(false) // padding case - ) { - return switch (value.asString().toUpperCase().trim()) { - case "PKCS1V15" -> Optional.empty(); // TODO - default -> Optional.empty(); - }; + && detectionContext instanceof DetectionContext context) { + if (context.get("kind").map(k -> k.equals("padding")).orElse(false)) { // padding case + return switch (value.asString().toUpperCase().trim()) { + case "PKCS1V15" -> Optional.empty(); // TODO + default -> Optional.empty(); + }; + } else { + return switch (value.asString().toUpperCase().trim()) { + case "MGF1" -> Optional.of(new MGF1(detectionLocation)); + default -> Optional.empty(); + }; + } } return Optional.empty(); } diff --git a/python/src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveVerifyTestFile.py b/python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTestFile.py similarity index 80% rename from python/src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveVerifyTestFile.py rename to python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTestFile.py index af22451d..c357dea0 100644 --- a/python/src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveVerifyTestFile.py +++ b/python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTestFile.py @@ -5,4 +5,4 @@ def verify(pubkey, signature, digest): if isinstance(pubkey, ec.EllipticCurvePublicKey): - pubkey.verify(signature, digest, ec.ECDSA(hashes.SHA3_512())) # TODO: What should I detect here? Should I use `verify` as an entry point? + pubkey.verify(signature, digest, ec.ECDSA(hashes.SHA3_512())) diff --git a/python/src/test/files/rules/detection/asymmetric/RSA/CryptographyRSADecryptTestFile.py b/python/src/test/files/rules/detection/asymmetric/RSA/PycaRSADecryptTestFile.py similarity index 95% rename from python/src/test/files/rules/detection/asymmetric/RSA/CryptographyRSADecryptTestFile.py rename to python/src/test/files/rules/detection/asymmetric/RSA/PycaRSADecryptTestFile.py index af15a9e8..23d137e4 100644 --- a/python/src/test/files/rules/detection/asymmetric/RSA/CryptographyRSADecryptTestFile.py +++ b/python/src/test/files/rules/detection/asymmetric/RSA/PycaRSADecryptTestFile.py @@ -11,7 +11,7 @@ def decrypt(ciphertext): plaintext = private_key.decrypt( ciphertext, padding.OAEP( - mgf=padding.MGF1(algorithm=hashes.SHA256()), + mgf=padding.MGF1(algorithm=hashes.SHA384()), algorithm=hashes.SHA256(), label=None ) diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTest.java index 113dcf66..95749cfe 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTest.java @@ -24,8 +24,8 @@ import com.ibm.plugin.TestBase; import java.util.List; import javax.annotation.Nonnull; +import org.junit.Test; import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; import org.sonar.plugins.python.api.PythonCheck; import org.sonar.plugins.python.api.PythonVisitorContext; import org.sonar.plugins.python.api.symbols.Symbol; @@ -33,12 +33,14 @@ import org.sonar.python.checks.utils.PythonCheckVerifier; public class PycaEllipticCurveVerifyTest extends TestBase { - @Disabled // TODO: Reenable once we have an approach to detect `verify` (either make it an entry - // point, or better handle file imports for depending detection rule) + + @Disabled( + "Reenable once we have an approach to detect `verify` (either make it an entry\n" + + "point, or better handle file imports for depending detection rule)") @Test - void test() { + public void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveVerifyTestFile.py", + "src/test/files/rules/detection/asymmetric/EllipticCurve/PycallipticCurveVerifyTestFile.py", this); } @@ -47,6 +49,6 @@ public void asserts( int findingId, @Nonnull DetectionStore detectionStore, @Nonnull List nodes) { - // TODO: + // TODO } } diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSADecryptTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSADecryptTest.java index e4dcda7f..48e9123e 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSADecryptTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSADecryptTest.java @@ -25,23 +25,28 @@ import com.ibm.engine.model.CipherAction; import com.ibm.engine.model.IValue; import com.ibm.engine.model.KeySize; +import com.ibm.engine.model.ValueAction; import com.ibm.engine.model.context.CipherContext; import com.ibm.engine.model.context.DigestContext; import com.ibm.engine.model.context.PrivateKeyContext; +import com.ibm.engine.model.context.SignatureContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; import com.ibm.mapper.model.INode; -import com.ibm.mapper.model.Key; import com.ibm.mapper.model.KeyLength; import com.ibm.mapper.model.MaskGenerationFunction; import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.Padding; import com.ibm.mapper.model.PrivateKey; -import com.ibm.mapper.model.PublicKey; +import com.ibm.mapper.model.Signature; import com.ibm.mapper.model.functionality.Decrypt; +import com.ibm.mapper.model.functionality.Digest; import com.ibm.mapper.model.functionality.KeyGeneration; -import com.ibm.mapper.model.padding.OAEP; import com.ibm.plugin.TestBase; import java.util.List; import javax.annotation.Nonnull; -import org.junit.jupiter.api.Test; +import org.junit.Test; import org.sonar.plugins.python.api.PythonCheck; import org.sonar.plugins.python.api.PythonVisitorContext; import org.sonar.plugins.python.api.symbols.Symbol; @@ -49,11 +54,11 @@ import org.sonar.python.checks.utils.PythonCheckVerifier; public class PycaRSADecryptTest extends TestBase { + @Test - void test() { + public void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/RSA/CryptographyRSADecryptTestFile.py", - this); + "src/test/files/rules/detection/asymmetric/RSA/PycaRSADecryptTestFile.py", this); } @Override @@ -61,162 +66,187 @@ public void asserts( int findingId, @Nonnull DetectionStore detectionStore, @Nonnull List nodes) { - /* - * Detection Store - */ - assertThat(detectionStore.getDetectionValues()).hasSize(1); - IValue value = detectionStore.getDetectionValues().get(0); - assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(PrivateKeyContext.class); - assertThat(value).isInstanceOf(KeySize.class); - assertThat(value.asString()).isEqualTo("1024"); - - DetectionStore algoStore = - getStoreOfValueType( - com.ibm.engine.model.Algorithm.class, detectionStore.getChildren()); - assertThat(algoStore).isNotNull(); - assertThat(algoStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); - assertThat(algoStore.getDetectionValues()).hasSize(2); - - value = algoStore.getDetectionValues().get(0); - assertThat(value).isInstanceOf(CipherAction.class); - assertThat(value.asString()).isEqualTo("PADDING"); - - value = algoStore.getDetectionValues().get(1); - assertThat(value).isInstanceOf(com.ibm.engine.model.Algorithm.class); - assertThat(value.asString()).isEqualTo("MGF1"); - - DetectionStore store = - getStoreOfValueType( - CipherAction.class, algoStore.getChildrenForParameterWithId(0).get()); - assertThat(store).isNotNull(); - assertThat(store.getDetectionValueContext()).isInstanceOf(DigestContext.class); - assertThat(store.getDetectionValues()).hasSize(1); - value = store.getDetectionValues().get(0); - assertThat(value).isInstanceOf(CipherAction.class); - assertThat(value.asString()).isEqualTo("HASH"); - - store = - getStoreOfValueType( - CipherAction.class, algoStore.getChildrenForParameterWithId(1).get()); - // detection store in this case - assertThat(store).isNotNull(); - assertThat(store.getDetectionValueContext()).isInstanceOf(DigestContext.class); - assertThat(store.getDetectionValues()).hasSize(1); - value = store.getDetectionValues().get(0); - assertThat(value).isInstanceOf(CipherAction.class); - assertThat(value.asString()).isEqualTo("HASH"); - - store = getStoreOfValueType(CipherAction.class, detectionStore.getChildren()); - assertThat(store).isNotNull(); - assertThat(store.getDetectionValueContext()).isInstanceOf(CipherContext.class); - assertThat(store.getDetectionValues()).hasSize(1); - value = store.getDetectionValues().get(0); - assertThat(value).isInstanceOf(CipherAction.class); - assertThat(value.asString()).isEqualTo("DECRYPT"); - - /* - * Translation - */ - assertThat(nodes).hasSize(2); - - // PrivateKey - INode privateKeyNode = nodes.get(0); - assertThat(privateKeyNode).isInstanceOf(PrivateKey.class); - assertThat(privateKeyNode.getChildren()).hasSize(2); - - // KeyLength under PrivateKey - INode privateKeyKeyLengthNode = privateKeyNode.getChildren().get(KeyLength.class); - assertThat(privateKeyKeyLengthNode).isNotNull(); - assertThat(privateKeyKeyLengthNode.asString()).isEqualTo("1024"); - - // Algorithm under PrivateKey - INode privateKeyAlgorithmNode = - privateKeyNode.getChildren().get(com.ibm.mapper.model.Algorithm.class); - assertThat(privateKeyAlgorithmNode).isNotNull(); - assertThat(privateKeyAlgorithmNode.asString()).isEqualTo("RSA"); - - // Decrypt under Algorithm under PrivateKey - INode privateKeyDecryptNode = privateKeyAlgorithmNode.getChildren().get(Decrypt.class); - assertThat(privateKeyDecryptNode).isNotNull(); - assertThat(privateKeyDecryptNode.asString()).isEqualTo("DECRYPT"); - - // KeyGeneration under Algorithm under PrivateKey - INode privateKeyKeyGenerationNode = - privateKeyAlgorithmNode.getChildren().get(KeyGeneration.class); - assertThat(privateKeyKeyGenerationNode).isNotNull(); - assertThat(privateKeyKeyGenerationNode.asString()).isEqualTo("KEYGENERATION"); - - // OptimalAsymmetricEncryptionPadding under Algorithm under PrivateKey - INode privateKeyOaepNode = privateKeyAlgorithmNode.getChildren().get(OAEP.class); - assertThat(privateKeyOaepNode).isNotNull(); - assertThat(privateKeyOaepNode.asString()).isEqualTo("OAEP"); - - // MessageDigest under OptimalAsymmetricEncryptionPadding under Algorithm under PrivateKey - INode messageDigestNode = privateKeyOaepNode.getChildren().get(MessageDigest.class); - assertThat(messageDigestNode).isNotNull(); - assertThat(messageDigestNode.asString()).isEqualTo("SHA256"); - - // MaskGenerationFunction under OptimalAsymmetricEncryptionPadding under Algorithm under - // PrivateKey - INode privateKeyMgfNode = - privateKeyOaepNode.getChildren().get(MaskGenerationFunction.class); - assertThat(privateKeyMgfNode).isNotNull(); - assertThat(privateKeyMgfNode.asString()).isEqualTo("MGF1"); - - // MessageDigest under MaskGenerationFunction under OptimalAsymmetricEncryptionPadding under - // Algorithm under PrivateKey - messageDigestNode = privateKeyMgfNode.getChildren().get(MessageDigest.class); - assertThat(messageDigestNode).isNotNull(); - assertThat(messageDigestNode.asString()).isEqualTo("SHA256"); - - // PublicKey - INode publicKeyNode = nodes.get(1); - assertThat(publicKeyNode) - .isInstanceOfAny(PublicKey.class, Key.class); // Special case because of .deepCopy - assertThat(publicKeyNode.getChildren()).hasSize(2); - - // KeyLength under PublicKey - INode publicKeyKeyLengthNode = publicKeyNode.getChildren().get(KeyLength.class); - assertThat(publicKeyKeyLengthNode).isNotNull(); - assertThat(publicKeyKeyLengthNode.asString()).isEqualTo("1024"); - - // Algorithm under PublicKey - INode publicKeyAlgorithmNode = - publicKeyNode.getChildren().get(com.ibm.mapper.model.Algorithm.class); - assertThat(publicKeyAlgorithmNode).isNotNull(); - assertThat(publicKeyAlgorithmNode.asString()).isEqualTo("RSA"); - - // Decrypt under Algorithm under PublicKey - INode publicKeyDecryptNode = publicKeyAlgorithmNode.getChildren().get(Decrypt.class); - assertThat(publicKeyDecryptNode).isNotNull(); - assertThat(publicKeyDecryptNode.asString()).isEqualTo("DECRYPT"); - - // KeyGeneration under Algorithm under PublicKey - INode publicKeyKeyGenerationNode = - publicKeyAlgorithmNode.getChildren().get(KeyGeneration.class); - assertThat(publicKeyKeyGenerationNode).isNotNull(); - assertThat(publicKeyKeyGenerationNode.asString()).isEqualTo("KEYGENERATION"); - - // OptimalAsymmetricEncryptionPadding under Algorithm under PublicKey - INode publicKeyOaepNode = publicKeyAlgorithmNode.getChildren().get(OAEP.class); - assertThat(publicKeyOaepNode).isNotNull(); - assertThat(publicKeyOaepNode.asString()).isEqualTo("OAEP"); - - // MessageDigest under OptimalAsymmetricEncryptionPadding under Algorithm under PublicKey - messageDigestNode = publicKeyOaepNode.getChildren().get(MessageDigest.class); - assertThat(messageDigestNode).isNotNull(); - assertThat(messageDigestNode.asString()).isEqualTo("SHA256"); - - // MaskGenerationFunction under OptimalAsymmetricEncryptionPadding under Algorithm under - // PublicKey - INode publicKeyMgfNode = publicKeyOaepNode.getChildren().get(MaskGenerationFunction.class); - assertThat(publicKeyMgfNode).isNotNull(); - assertThat(publicKeyMgfNode.asString()).isEqualTo("MGF1"); - - // MessageDigest under MaskGenerationFunction under OptimalAsymmetricEncryptionPadding under - // Algorithm under PublicKey - messageDigestNode = publicKeyMgfNode.getChildren().get(MessageDigest.class); - assertThat(messageDigestNode).isNotNull(); - assertThat(messageDigestNode.asString()).isEqualTo("SHA256"); + if (findingId == 0) { + /* + * Detection Store + */ + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(PrivateKeyContext.class); + IValue value0 = detectionStore.getDetectionValues().get(0); + assertThat(value0).isInstanceOf(KeySize.class); + assertThat(value0.asString()).isEqualTo("1024"); + + DetectionStore store_1 = + getStoreOfValueType(CipherAction.class, detectionStore.getChildren()); + assertThat(store_1).isNotNull(); + assertThat(store_1.getDetectionValues()).hasSize(1); + assertThat(store_1.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value0_1 = store_1.getDetectionValues().get(0); + assertThat(value0_1).isInstanceOf(CipherAction.class); + assertThat(value0_1.asString()).isEqualTo("DECRYPT"); + + DetectionStore store_1_1 = + getStoreOfValueType(ValueAction.class, store_1.getChildren()); + assertThat(store_1_1).isNotNull(); + assertThat(store_1_1.getDetectionValues()).hasSize(1); + assertThat(store_1_1.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value0_1_1 = store_1_1.getDetectionValues().get(0); + assertThat(value0_1_1).isInstanceOf(ValueAction.class); + assertThat(value0_1_1.asString()).isEqualTo("OAEP"); + + List> stores = + getStoresOfValueType(ValueAction.class, store_1_1.getChildren()); + assertThat(stores).isNotNull(); + for (DetectionStore s : stores) { + assertThat(s.getDetectionValues()).hasSize(1); + assertThat(s.getDetectionValueContext()) + .isInstanceOfAny(SignatureContext.class, DigestContext.class); + IValue v = s.getDetectionValues().get(0); + assertThat(v).isInstanceOf(ValueAction.class); + assertThat(v.asString()) + .satisfiesAnyOf( + str -> assertThat(str).isEqualTo("MGF1"), + str -> assertThat(str).isEqualTo("SHA256")); + + if (s.getDetectionValueContext().is(SignatureContext.class)) { + DetectionStore store_1_1_1_1 = + getStoreOfValueType(ValueAction.class, s.getChildren()); + assertThat(store_1_1_1_1).isNotNull(); + assertThat(store_1_1_1_1.getDetectionValues()).hasSize(1); + assertThat(store_1_1_1_1.getDetectionValueContext()) + .isInstanceOf(DigestContext.class); + IValue value0_1_1_1_1 = store_1_1_1_1.getDetectionValues().get(0); + assertThat(value0_1_1_1_1).isInstanceOf(ValueAction.class); + assertThat(value0_1_1_1_1.asString()).isEqualTo("SHA384"); + } + } + + /* + * Translation + */ + assertThat(nodes).hasSize(1); + + // PrivateKey + INode privateKeyNode = nodes.get(0); + assertThat(privateKeyNode.getKind()).isEqualTo(PrivateKey.class); + assertThat(privateKeyNode.getChildren()).hasSize(4); + assertThat(privateKeyNode.asString()).isEqualTo("RSA"); + + // KeyGeneration under PrivateKey + INode keyGenerationNode = privateKeyNode.getChildren().get(KeyGeneration.class); + assertThat(keyGenerationNode).isNotNull(); + assertThat(keyGenerationNode.getChildren()).isEmpty(); + assertThat(keyGenerationNode.asString()).isEqualTo("KEYGENERATION"); + + // Signature under PrivateKey + INode signatureNode = privateKeyNode.getChildren().get(Signature.class); + assertThat(signatureNode).isNotNull(); + assertThat(signatureNode.getChildren()).hasSize(2); + assertThat(signatureNode.asString()).isEqualTo("RSA"); + + // Oid under Signature under PrivateKey + INode oidNode = signatureNode.getChildren().get(Oid.class); + assertThat(oidNode).isNotNull(); + assertThat(oidNode.getChildren()).isEmpty(); + assertThat(oidNode.asString()).isEqualTo("1.2.840.113549.1.1.7"); + + // Padding under Signature under PrivateKey + INode paddingNode = signatureNode.getChildren().get(Padding.class); + assertThat(paddingNode).isNotNull(); + assertThat(paddingNode.getChildren()).hasSize(2); + assertThat(paddingNode.asString()).isEqualTo("OAEP"); + + // MessageDigest under Padding under Signature under PrivateKey + INode messageDigestNode = paddingNode.getChildren().get(MessageDigest.class); + assertThat(messageDigestNode).isNotNull(); + assertThat(messageDigestNode.getChildren()).hasSize(4); + assertThat(messageDigestNode.asString()).isEqualTo("SHA256"); + + // Oid under MessageDigest under Padding under Signature under PrivateKey + INode oidNode1 = messageDigestNode.getChildren().get(Oid.class); + assertThat(oidNode1).isNotNull(); + assertThat(oidNode1.getChildren()).isEmpty(); + assertThat(oidNode1.asString()).isEqualTo("2.16.840.1.101.3.4.2.1"); + + // Digest under MessageDigest under Padding under Signature under PrivateKey + INode digestNode = messageDigestNode.getChildren().get(Digest.class); + assertThat(digestNode).isNotNull(); + assertThat(digestNode.getChildren()).isEmpty(); + assertThat(digestNode.asString()).isEqualTo("DIGEST"); + + // BlockSize under MessageDigest under Padding under Signature under PrivateKey + INode blockSizeNode = messageDigestNode.getChildren().get(BlockSize.class); + assertThat(blockSizeNode).isNotNull(); + assertThat(blockSizeNode.getChildren()).isEmpty(); + assertThat(blockSizeNode.asString()).isEqualTo("512"); + + // DigestSize under MessageDigest under Padding under Signature under PrivateKey + INode digestSizeNode = messageDigestNode.getChildren().get(DigestSize.class); + assertThat(digestSizeNode).isNotNull(); + assertThat(digestSizeNode.getChildren()).isEmpty(); + assertThat(digestSizeNode.asString()).isEqualTo("256"); + + // MaskGenerationFunction under Padding under Signature under PrivateKey + INode maskGenerationFunctionNode = + paddingNode.getChildren().get(MaskGenerationFunction.class); + assertThat(maskGenerationFunctionNode).isNotNull(); + assertThat(maskGenerationFunctionNode.getChildren()).hasSize(2); + assertThat(maskGenerationFunctionNode.asString()).isEqualTo("MGF1"); + + // Oid under MaskGenerationFunction under Padding under Signature under PrivateKey + INode oidNode2 = maskGenerationFunctionNode.getChildren().get(Oid.class); + assertThat(oidNode2).isNotNull(); + assertThat(oidNode2.getChildren()).isEmpty(); + assertThat(oidNode2.asString()).isEqualTo("1.2.840.113549.1.1.8"); + + // MessageDigest under MaskGenerationFunction under Padding under Signature under + // PrivateKey + INode messageDigestNode1 = + maskGenerationFunctionNode.getChildren().get(MessageDigest.class); + assertThat(messageDigestNode1).isNotNull(); + assertThat(messageDigestNode1.getChildren()).hasSize(4); + assertThat(messageDigestNode1.asString()).isEqualTo("SHA384"); + + // Oid under MessageDigest under MaskGenerationFunction under Padding under Signature + // under PrivateKey + INode oidNode3 = messageDigestNode1.getChildren().get(Oid.class); + assertThat(oidNode3).isNotNull(); + assertThat(oidNode3.getChildren()).isEmpty(); + assertThat(oidNode3.asString()).isEqualTo("2.16.840.1.101.3.4.2.2"); + + // Digest under MessageDigest under MaskGenerationFunction under Padding under Signature + // under PrivateKey + INode digestNode1 = messageDigestNode1.getChildren().get(Digest.class); + assertThat(digestNode1).isNotNull(); + assertThat(digestNode1.getChildren()).isEmpty(); + assertThat(digestNode1.asString()).isEqualTo("DIGEST"); + + // BlockSize under MessageDigest under MaskGenerationFunction under Padding under + // Signature under PrivateKey + INode blockSizeNode1 = messageDigestNode1.getChildren().get(BlockSize.class); + assertThat(blockSizeNode1).isNotNull(); + assertThat(blockSizeNode1.getChildren()).isEmpty(); + assertThat(blockSizeNode1.asString()).isEqualTo("1024"); + + // DigestSize under MessageDigest under MaskGenerationFunction under Padding under + // Signature under PrivateKey + INode digestSizeNode1 = messageDigestNode1.getChildren().get(DigestSize.class); + assertThat(digestSizeNode1).isNotNull(); + assertThat(digestSizeNode1.getChildren()).isEmpty(); + assertThat(digestSizeNode1.asString()).isEqualTo("384"); + + // Decrypt under PrivateKey + INode decryptNode = privateKeyNode.getChildren().get(Decrypt.class); + assertThat(decryptNode).isNotNull(); + assertThat(decryptNode.getChildren()).isEmpty(); + assertThat(decryptNode.asString()).isEqualTo("DECRYPT"); + + // KeyLength under PrivateKey + INode keyLengthNode = privateKeyNode.getChildren().get(KeyLength.class); + assertThat(keyLengthNode).isNotNull(); + assertThat(keyLengthNode.getChildren()).isEmpty(); + assertThat(keyLengthNode.asString()).isEqualTo("1024"); + } } }