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/mapper/pyca/PycaHashBasedKeyDerivationMapper.java b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaHashBasedKeyDerivationMapper.java new file mode 100644 index 00000000..24b1914c --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaHashBasedKeyDerivationMapper.java @@ -0,0 +1,119 @@ +/* + * 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.mapper.pyca; + +import com.ibm.mapper.mapper.IMapper; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.KeyDerivationFunction; +import com.ibm.mapper.model.Mac; +import com.ibm.mapper.model.algorithms.MD5; +import com.ibm.mapper.model.algorithms.Poly1305; +import com.ibm.mapper.model.algorithms.SHA; +import com.ibm.mapper.model.algorithms.SHA2; +import com.ibm.mapper.model.algorithms.SHA3; +import com.ibm.mapper.model.algorithms.SHAKE; +import com.ibm.mapper.model.algorithms.SM3; +import com.ibm.mapper.utils.DetectionLocation; +import java.util.Optional; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class PycaHashBasedKeyDerivationMapper implements IMapper { + @Override + public @NotNull Optional parse( + @Nullable String str, @NotNull DetectionLocation detectionLocation) { + if (str == null) { + return Optional.empty(); + } + + return switch (str.toUpperCase().trim()) { + case "SHA1" -> + Optional.of(new SHA(KeyDerivationFunction.class, new SHA(detectionLocation))); + case "SHA512_224" -> + Optional.of( + new SHA2( + KeyDerivationFunction.class, + new SHA2( + 224, + new SHA2(512, detectionLocation), + detectionLocation))); + case "SHA512_256" -> + Optional.of( + new SHA2( + KeyDerivationFunction.class, + new SHA2( + 256, + new SHA2(512, detectionLocation), + detectionLocation))); + case "SHA224" -> + Optional.of( + new SHA2( + KeyDerivationFunction.class, new SHA2(224, detectionLocation))); + case "SHA256" -> + Optional.of( + new SHA2( + KeyDerivationFunction.class, new SHA2(256, detectionLocation))); + case "SHA384" -> + Optional.of( + new SHA2( + KeyDerivationFunction.class, new SHA2(384, detectionLocation))); + case "SHA512" -> + Optional.of( + new SHA2( + KeyDerivationFunction.class, new SHA2(512, detectionLocation))); + case "SHA3_224" -> + Optional.of( + new SHA3( + KeyDerivationFunction.class, new SHA3(224, detectionLocation))); + case "SHA3_256" -> + Optional.of( + new SHA3( + KeyDerivationFunction.class, new SHA3(256, detectionLocation))); + case "SHA3_384" -> + Optional.of( + new SHA3( + KeyDerivationFunction.class, new SHA3(384, detectionLocation))); + case "SHA3_512" -> + Optional.of( + new SHA3( + KeyDerivationFunction.class, new SHA3(512, detectionLocation))); + case "SHAKE128" -> + Optional.of( + new SHAKE( + KeyDerivationFunction.class, + new SHAKE(128, detectionLocation))); + case "SHAKE256" -> + Optional.of( + new SHAKE( + KeyDerivationFunction.class, + new SHAKE(256, detectionLocation))); + case "MD5" -> Optional.of(new MD5(Mac.class, detectionLocation)); + case "BLAKE2B" -> Optional.empty(); // TODO + case "BLAKE2S" -> Optional.empty(); // TODO + case "SM3" -> + Optional.of(new SM3(KeyDerivationFunction.class, new SM3(detectionLocation))); + case "POLY1305" -> + Optional.of( + new Poly1305( + KeyDerivationFunction.class, new Poly1305(detectionLocation))); + default -> Optional.empty(); + }; + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/algorithms/ECDH.java b/mapper/src/main/java/com/ibm/mapper/model/algorithms/ECDH.java index 36d2cc63..777a19ba 100644 --- a/mapper/src/main/java/com/ibm/mapper/model/algorithms/ECDH.java +++ b/mapper/src/main/java/com/ibm/mapper/model/algorithms/ECDH.java @@ -22,6 +22,7 @@ import com.ibm.mapper.model.Algorithm; import com.ibm.mapper.model.EllipticCurve; import com.ibm.mapper.model.KeyAgreement; +import com.ibm.mapper.model.Oid; import com.ibm.mapper.utils.DetectionLocation; import javax.annotation.Nonnull; import org.jetbrains.annotations.NotNull; @@ -31,11 +32,13 @@ public final class ECDH extends Algorithm implements KeyAgreement { public ECDH(@NotNull DetectionLocation detectionLocation) { super(NAME, KeyAgreement.class, detectionLocation); + this.put(new Oid("1.3.132.1.12", detectionLocation)); } public ECDH( @Nonnull EllipticCurve ellipticCurve, @Nonnull DetectionLocation detectionLocation) { super(NAME, KeyAgreement.class, detectionLocation); + this.put(new Oid("1.3.132.1.12", detectionLocation)); this.put(ellipticCurve); } } 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/model/curves/Brainpoolp256r1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Brainpoolp256r1.java new file mode 100644 index 00000000..7842540f --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Brainpoolp256r1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Brainpoolp256r1 extends EllipticCurve { + public Brainpoolp256r1(@NotNull DetectionLocation detectionLocation) { + super("Brainpoolp256r1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Brainpoolp384r1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Brainpoolp384r1.java new file mode 100644 index 00000000..bfda422c --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Brainpoolp384r1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Brainpoolp384r1 extends EllipticCurve { + public Brainpoolp384r1(@NotNull DetectionLocation detectionLocation) { + super("Brainpoolp384r1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Brainpoolp512r1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Brainpoolp512r1.java new file mode 100644 index 00000000..2038fb05 --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Brainpoolp512r1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Brainpoolp512r1 extends EllipticCurve { + public Brainpoolp512r1(@NotNull DetectionLocation detectionLocation) { + super("Brainpoolp512r1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Secp192r1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Secp192r1.java new file mode 100644 index 00000000..87d22433 --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Secp192r1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Secp192r1 extends EllipticCurve { + public Secp192r1(@NotNull DetectionLocation detectionLocation) { + super("secp192r1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Secp224r1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Secp224r1.java new file mode 100644 index 00000000..b5b98a3f --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Secp224r1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Secp224r1 extends EllipticCurve { + public Secp224r1(@NotNull DetectionLocation detectionLocation) { + super("secp224r1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Secp256k1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Secp256k1.java new file mode 100644 index 00000000..edc9240b --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Secp256k1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Secp256k1 extends EllipticCurve { + public Secp256k1(@NotNull DetectionLocation detectionLocation) { + super("secp256k1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Sect163k1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect163k1.java new file mode 100644 index 00000000..a0974dbc --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect163k1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Sect163k1 extends EllipticCurve { + public Sect163k1(@NotNull DetectionLocation detectionLocation) { + super("sect163k1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Sect163r2.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect163r2.java new file mode 100644 index 00000000..ee9b7b2a --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect163r2.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Sect163r2 extends EllipticCurve { + public Sect163r2(@NotNull DetectionLocation detectionLocation) { + super("sect163r2", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Sect233k1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect233k1.java new file mode 100644 index 00000000..61b7c4c9 --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect233k1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Sect233k1 extends EllipticCurve { + public Sect233k1(@NotNull DetectionLocation detectionLocation) { + super("sect233k1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Sect233r1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect233r1.java new file mode 100644 index 00000000..ea5328f9 --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect233r1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Sect233r1 extends EllipticCurve { + public Sect233r1(@NotNull DetectionLocation detectionLocation) { + super("sect233r1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Sect283k1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect283k1.java new file mode 100644 index 00000000..498500f0 --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect283k1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Sect283k1 extends EllipticCurve { + public Sect283k1(@NotNull DetectionLocation detectionLocation) { + super("sect283k1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Sect283r1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect283r1.java new file mode 100644 index 00000000..1490d082 --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect283r1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Sect283r1 extends EllipticCurve { + public Sect283r1(@NotNull DetectionLocation detectionLocation) { + super("sect283r1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Sect409k1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect409k1.java new file mode 100644 index 00000000..15c89e25 --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect409k1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Sect409k1 extends EllipticCurve { + public Sect409k1(@NotNull DetectionLocation detectionLocation) { + super("sect409k1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Sect409r1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect409r1.java new file mode 100644 index 00000000..9f0dd697 --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect409r1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Sect409r1 extends EllipticCurve { + public Sect409r1(@NotNull DetectionLocation detectionLocation) { + super("sect409r1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Sect571k1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect571k1.java new file mode 100644 index 00000000..c86faa85 --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect571k1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Sect571k1 extends EllipticCurve { + public Sect571k1(@NotNull DetectionLocation detectionLocation) { + super("sect571k1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/curves/Sect571r1.java b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect571r1.java new file mode 100644 index 00000000..bbd6e367 --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/curves/Sect571r1.java @@ -0,0 +1,30 @@ +/* + * 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.model.curves; + +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.utils.DetectionLocation; +import org.jetbrains.annotations.NotNull; + +public final class Sect571r1 extends EllipticCurve { + public Sect571r1(@NotNull DetectionLocation detectionLocation) { + super("sect571r1", detectionLocation); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/reorganizer/ReorganizerRule.java b/mapper/src/main/java/com/ibm/mapper/reorganizer/ReorganizerRule.java index 7a4c4683..b2443974 100644 --- a/mapper/src/main/java/com/ibm/mapper/reorganizer/ReorganizerRule.java +++ b/mapper/src/main/java/com/ibm/mapper/reorganizer/ReorganizerRule.java @@ -37,38 +37,33 @@ public record ReorganizerRule( @Override public boolean match(@Nonnull INode node, @Nonnull INode parent, @Nonnull List roots) { // Kind check - if (node.is(kind)) { - - // Name check - if (value != null && !value.equals(node.asString())) { - return false; - } + if (!node.is(kind)) { + return false; + } - // Children check - if (nonNullChildren && node.getChildren().isEmpty()) { - return false; - } - for (IReorganizerRule childRule : children) { - Class childKind = childRule.getNodeKind(); + // Name check + if (value != null && !value.equals(node.asString())) { + return false; + } - if (!node.getChildren().containsKey(childKind)) { - return false; - } + // Children check + if (nonNullChildren && node.getChildren().isEmpty()) { + return false; + } + for (IReorganizerRule childRule : children) { + Class childKind = childRule.getNodeKind(); - if (!childRule.match(node.getChildren().get(childKind), node, roots)) { - return false; - } + if (!node.getChildren().containsKey(childKind)) { + return false; } - // Detection condition check - if (detectionConditionFunction != null - && !(detectionConditionFunction.apply(node, parent, roots))) { + if (!childRule.match(node.getChildren().get(childKind), node, roots)) { return false; } - - return true; } - return false; + // Detection condition check + return detectionConditionFunction == null + || detectionConditionFunction.apply(node, parent, roots); } @Override diff --git a/mapper/src/main/java/com/ibm/mapper/reorganizer/rules/KeyAgreementReorganizer.java b/mapper/src/main/java/com/ibm/mapper/reorganizer/rules/KeyAgreementReorganizer.java new file mode 100644 index 00000000..86111d80 --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/reorganizer/rules/KeyAgreementReorganizer.java @@ -0,0 +1,58 @@ +/* + * 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.EllipticCurve; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.KeyAgreement; +import com.ibm.mapper.model.PrivateKey; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.reorganizer.IReorganizerRule; +import com.ibm.mapper.reorganizer.builder.ReorganizerRuleBuilder; +import java.util.Optional; + +public final class KeyAgreementReorganizer { + + private KeyAgreementReorganizer() { + // nothing + } + + public static final IReorganizerRule MERGE_KEYAGREEMENT_WITH_PKE_UNDER_PRIVATE_KEY = + new ReorganizerRuleBuilder() + .createReorganizerRule() + .forNodeKind(PrivateKey.class) + .withDetectionCondition( + (node, parent, roots) -> + node.hasChildOfType(PublicKeyEncryption.class).isPresent() + && node.hasChildOfType(KeyAgreement.class).isPresent()) + .perform( + (node, parent, roots) -> { + final Optional pke = + node.hasChildOfType(PublicKeyEncryption.class); + final Optional ka = node.hasChildOfType(KeyAgreement.class); + if (pke.isPresent() && ka.isPresent()) { + pke.get() + .hasChildOfType(EllipticCurve.class) + .ifPresent(e -> ka.get().put(e)); + node.removeChildOfType(pke.get().getKind()); + } + return roots; + }); +} 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/mapper/src/main/java/com/ibm/mapper/reorganizer/rules/SignerReorganizer.java b/mapper/src/main/java/com/ibm/mapper/reorganizer/rules/SignerReorganizer.java index 92ca70b1..e95f5e4d 100644 --- a/mapper/src/main/java/com/ibm/mapper/reorganizer/rules/SignerReorganizer.java +++ b/mapper/src/main/java/com/ibm/mapper/reorganizer/rules/SignerReorganizer.java @@ -19,8 +19,18 @@ */ package com.ibm.mapper.reorganizer.rules; +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.PrivateKey; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.functionality.Sign; import com.ibm.mapper.reorganizer.IReorganizerRule; +import com.ibm.mapper.reorganizer.builder.ReorganizerRuleBuilder; import java.util.List; +import java.util.Optional; import javax.annotation.Nonnull; import org.jetbrains.annotations.Unmodifiable; @@ -165,9 +175,69 @@ private SignerReorganizer() { */ + public static final IReorganizerRule MOVE_DIGEST_FROM_SIGN_ACTION_UNDER_SIGNATURE = + new ReorganizerRuleBuilder() + .createReorganizerRule() + .forNodeKind(Sign.class) + .withDetectionCondition( + (node, parent, roots) -> { + if (parent != null) { + return parent instanceof Key + && node.hasChildOfType(MessageDigest.class).isPresent() + && parent.hasChildOfType(Signature.class).isPresent(); + } + return false; + }) + .perform( + (node, parent, roots) -> { + if (parent == null) { + return roots; + } + + final Optional possibleDigest = + node.hasChildOfType(MessageDigest.class); + final Optional possibleSignature = + parent.hasChildOfType(Signature.class); + + if (possibleSignature.isEmpty()) { + return roots; + } + if (possibleDigest.isEmpty()) { + return roots; + } + + possibleSignature.get().put(possibleDigest.get()); + node.removeChildOfType(MessageDigest.class); + return roots; + }); + + public static final IReorganizerRule MERGE_SIGNATURE_WITH_PKE_UNDER_PRIVATE_KEY = + new ReorganizerRuleBuilder() + .createReorganizerRule() + .forNodeKind(PrivateKey.class) + .withDetectionCondition( + (node, parent, roots) -> + node.hasChildOfType(PublicKeyEncryption.class).isPresent() + && node.hasChildOfType(Signature.class).isPresent()) + .perform( + (node, parent, roots) -> { + final Optional pke = + node.hasChildOfType(PublicKeyEncryption.class); + final Optional s = node.hasChildOfType(Signature.class); + if (pke.isPresent() && s.isPresent()) { + pke.get() + .hasChildOfType(EllipticCurve.class) + .ifPresent(e -> s.get().put(e)); + node.removeChildOfType(pke.get().getKind()); + } + return roots; + }); + @Unmodifiable @Nonnull public static List rules() { - return List.of(); // RENAME_SIGNATURE, RENAME_SIGNATURE_PSS, RENAME_SIGNATURE_RSA + return List.of(MOVE_DIGEST_FROM_SIGN_ACTION_UNDER_SIGNATURE); // RENAME_SIGNATURE, + // RENAME_SIGNATURE_PSS, + // RENAME_SIGNATURE_RSA } } diff --git a/python/src/main/java/com/ibm/plugin/rules/PythonInventoryRule.java b/python/src/main/java/com/ibm/plugin/rules/PythonInventoryRule.java index 3c31a8ff..6487cdea 100644 --- a/python/src/main/java/com/ibm/plugin/rules/PythonInventoryRule.java +++ b/python/src/main/java/com/ibm/plugin/rules/PythonInventoryRule.java @@ -23,6 +23,7 @@ import com.ibm.engine.rule.IDetectionRule; import com.ibm.plugin.rules.detection.PythonBaseDetectionRule; import com.ibm.plugin.rules.detection.PythonDetectionRules; +import com.ibm.plugin.translation.reorganizer.PythonReorganizerRules; import java.util.List; import javax.annotation.Nonnull; import org.jetbrains.annotations.NotNull; @@ -38,13 +39,12 @@ public class PythonInventoryRule extends PythonBaseDetectionRule { public PythonInventoryRule() { - // TODO: add Python reorganizer rules here if necessary - super(PythonDetectionRules.rules(), List.of()); + super(PythonDetectionRules.rules(), PythonReorganizerRules.rules()); } @VisibleForTesting protected PythonInventoryRule(@Nonnull List> detectionRules) { - super(detectionRules, List.of()); + super(detectionRules, PythonReorganizerRules.rules()); } @Override diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaEllipticCurve.java b/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaEllipticCurve.java index f5493cd1..45b06a19 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaEllipticCurve.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaEllipticCurve.java @@ -28,6 +28,7 @@ import com.ibm.engine.model.context.PublicKeyContext; import com.ibm.engine.model.context.SignatureContext; import com.ibm.engine.model.factory.AlgorithmFactory; +import com.ibm.engine.model.factory.CurveFactory; import com.ibm.engine.model.factory.KeyActionFactory; import com.ibm.engine.model.factory.SignatureActionFactory; import com.ibm.engine.rule.IDetectionRule; @@ -66,7 +67,7 @@ private PycaEllipticCurve() { .inBundle(() -> "Pyca") .withoutDependingDetectionRules(); - private static final IDetectionRule KEY_EXCHANGE_EC = + public static final IDetectionRule KEY_EXCHANGE_EC = new DetectionRuleBuilder() .createDetectionRule() .forObjectTypes(TYPE + "." + GENERATE_METHOD) @@ -98,7 +99,7 @@ private PycaEllipticCurve() { .forObjectTypes(TYPE) .forMethods(GENERATE_METHOD) .withMethodParameter(ANY) - .shouldBeDetectedAs(new AlgorithmFactory<>()) + .shouldBeDetectedAs(new CurveFactory<>()) .buildForContext(new PrivateKeyContext(Map.of("algorithm", "EC"))) .inBundle(() -> "Pyca") .withDependingDetectionRules(List.of(SIGN_EC, KEY_EXCHANGE_EC)); @@ -110,7 +111,7 @@ private PycaEllipticCurve() { .forMethods("derive_private_key") .withMethodParameter(ANY) .withMethodParameter(ANY) - .shouldBeDetectedAs(new AlgorithmFactory<>()) + .shouldBeDetectedAs(new CurveFactory<>()) .buildForContext(new PrivateKeyContext(Map.of("algorithm", "EC"))) .inBundle(() -> "Pyca") .withDependingDetectionRules(List.of(SIGN_EC, KEY_EXCHANGE_EC)); 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/rules/detection/kdf/PycaKDF.java b/python/src/main/java/com/ibm/plugin/rules/detection/kdf/PycaKDF.java index bcd70ea6..329330ef 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/kdf/PycaKDF.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/kdf/PycaKDF.java @@ -22,13 +22,12 @@ import static com.ibm.engine.detection.MethodMatcher.ANY; import com.ibm.engine.model.AlgorithmParameter; -import com.ibm.engine.model.KeyAction; import com.ibm.engine.model.Size; import com.ibm.engine.model.context.KeyDerivationFunctionContext; import com.ibm.engine.model.factory.AlgorithmFactory; import com.ibm.engine.model.factory.AlgorithmParameterFactory; -import com.ibm.engine.model.factory.KeyActionFactory; import com.ibm.engine.model.factory.KeySizeFactory; +import com.ibm.engine.model.factory.ValueActionFactory; import com.ibm.engine.rule.IDetectionRule; import com.ibm.engine.rule.builder.DetectionRuleBuilder; import java.util.List; @@ -52,11 +51,11 @@ private PycaKDF() { .createDetectionRule() .forObjectTypes(KDF_TYPE_PREFIX + "x963kdf") .forMethods("X963KDF") - .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.KDF)) .withMethodParameter(HASH_TYPE) // Accepts only hashes (not pre-hashes) .shouldBeDetectedAs(new AlgorithmFactory<>()) .withMethodParameter("int") - .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BIT)) + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BYTE)) + .asChildOfParameterWithId(0) .withMethodParameter(ANY) .buildForContext(new KeyDerivationFunctionContext(Map.of("algorithm", "x963"))) .inBundle(() -> "Pyca") @@ -67,12 +66,12 @@ private PycaKDF() { .createDetectionRule() .forObjectTypes(KDF_TYPE_PREFIX + "kbkdf") .forMethods("KBKDFCMAC") - .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.KDF)) .withMethodParameter("cryptography.hazmat.primitives.ciphers.algorithms.*") .shouldBeDetectedAs(new AlgorithmFactory<>()) .withMethodParameter(ANY) // TODO: a Mode could be detected here .withMethodParameter("int") - .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BIT)) + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BYTE)) + .asChildOfParameterWithId(0) .withMethodParameter(ANY) .withMethodParameter(ANY) .withMethodParameter(ANY) @@ -88,12 +87,12 @@ private PycaKDF() { .createDetectionRule() .forObjectTypes(KDF_TYPE_PREFIX + "kbkdf") .forMethods("KBKDFHMAC") - .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.KDF)) .withMethodParameter(HASH_TYPE) // Accepts only hashes (not pre-hashes) .shouldBeDetectedAs(new AlgorithmFactory<>()) .withMethodParameter(ANY) // TODO: a Mode could be detected here .withMethodParameter("int") - .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BIT)) + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BYTE)) + .asChildOfParameterWithId(0) .withMethodParameter(ANY) .withMethodParameter(ANY) .withMethodParameter(ANY) @@ -109,11 +108,11 @@ private PycaKDF() { .createDetectionRule() .forObjectTypes(KDF_TYPE_PREFIX + "hkdf") .forMethods("HKDFExpand") - .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.KDF)) .withMethodParameter(HASH_TYPE) // Accepts only hashes (not pre-hashes) .shouldBeDetectedAs(new AlgorithmFactory<>()) .withMethodParameter("int") - .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BIT)) + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BYTE)) + .asChildOfParameterWithId(0) .withMethodParameter(ANY) .buildForContext(new KeyDerivationFunctionContext(Map.of("kind", "hash"))) .inBundle(() -> "Pyca") @@ -124,11 +123,11 @@ private PycaKDF() { .createDetectionRule() .forObjectTypes(KDF_TYPE_PREFIX + "hkdf") .forMethods("HKDF") - .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.KDF)) .withMethodParameter(HASH_TYPE) // Accepts only hashes (not pre-hashes) .shouldBeDetectedAs(new AlgorithmFactory<>()) .withMethodParameter("int") - .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BIT)) + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BYTE)) + .asChildOfParameterWithId(0) .withMethodParameter(ANY) .withMethodParameter(ANY) .buildForContext(new KeyDerivationFunctionContext(Map.of("kind", "hash"))) @@ -140,11 +139,11 @@ private PycaKDF() { .createDetectionRule() .forObjectTypes(KDF_TYPE_PREFIX + "concatkdf") .forMethods("ConcatKDFHMAC") - .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.KDF)) .withMethodParameter(HASH_TYPE) // Accepts only hashes (not pre-hashes) .shouldBeDetectedAs(new AlgorithmFactory<>()) .withMethodParameter("int") - .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BIT)) + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BYTE)) + .asChildOfParameterWithId(0) .withMethodParameter(ANY) .withMethodParameter(ANY) .buildForContext( @@ -160,11 +159,11 @@ private PycaKDF() { .createDetectionRule() .forObjectTypes(KDF_TYPE_PREFIX + "concatkdf") .forMethods("ConcatKDFHash") - .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.KDF)) .withMethodParameter(HASH_TYPE) // Accepts only hashes (not pre-hashes) .shouldBeDetectedAs(new AlgorithmFactory<>()) .withMethodParameter("int") - .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BIT)) + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BYTE)) + .asChildOfParameterWithId(0) .withMethodParameter(ANY) .buildForContext( new KeyDerivationFunctionContext( @@ -179,10 +178,11 @@ private PycaKDF() { .createDetectionRule() .forObjectTypes(KDF_TYPE_PREFIX + "scrypt") .forMethods("Scrypt") - .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.KDF)) + .shouldBeDetectedAs(new ValueActionFactory<>("scrypt")) .withMethodParameter(ANY) .withMethodParameter("int") - .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BIT)) + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BYTE)) + .asChildOfParameterWithId(0) .withMethodParameter("int") .withMethodParameter("int") .withMethodParameter("int") @@ -196,11 +196,11 @@ private PycaKDF() { .createDetectionRule() .forObjectTypes(KDF_TYPE_PREFIX + "pbkdf2") .forMethods("PBKDF2HMAC") - .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.KDF)) .withMethodParameter(HASH_TYPE) // Accepts only hashes (not pre-hashes) .shouldBeDetectedAs(new AlgorithmFactory<>()) .withMethodParameter("int") - .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BIT)) + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BYTE)) + .asChildOfParameterWithId(0) .withMethodParameter(ANY) .withMethodParameter("int") .shouldBeDetectedAs( 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 new file mode 100644 index 00000000..ed90bce5 --- /dev/null +++ b/python/src/main/java/com/ibm/plugin/translation/reorganizer/PythonReorganizerRules.java @@ -0,0 +1,45 @@ +/* + * 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.plugin.translation.reorganizer; + +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; +import javax.annotation.Nonnull; + +public final class PythonReorganizerRules { + + private PythonReorganizerRules() { + // private + } + + @Nonnull + 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, + 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/PycaKeyAgreementContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyAgreementContextTranslator.java index dbcb53df..96ccd23f 100644 --- a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyAgreementContextTranslator.java +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyAgreementContextTranslator.java @@ -29,6 +29,7 @@ import com.ibm.mapper.model.EllipticCurveAlgorithm; import com.ibm.mapper.model.INode; import com.ibm.mapper.model.KeyAgreement; +import com.ibm.mapper.model.algorithms.ECDH; import com.ibm.mapper.model.algorithms.X25519; import com.ibm.mapper.model.algorithms.X448; import com.ibm.mapper.utils.DetectionLocation; @@ -45,6 +46,7 @@ public class PycaKeyAgreementContextTranslator implements IContextTranslation algorithm) { return switch (algorithm.asString().toUpperCase().trim()) { + case "ECDH" -> Optional.of(new ECDH(detectionLocation)); case "EC" -> Optional.of( new EllipticCurveAlgorithm( diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyDerivationContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyDerivationContextTranslator.java index 860dbd23..b3dc08c8 100644 --- a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyDerivationContextTranslator.java +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyDerivationContextTranslator.java @@ -27,7 +27,7 @@ import com.ibm.engine.model.context.IDetectionContext; import com.ibm.engine.rule.IBundle; import com.ibm.mapper.IContextTranslation; -import com.ibm.mapper.mapper.pyca.PycaDigestMapper; +import com.ibm.mapper.mapper.pyca.PycaHashBasedKeyDerivationMapper; import com.ibm.mapper.model.INode; import com.ibm.mapper.model.KeyLength; import com.ibm.mapper.model.algorithms.ANSIX963; @@ -49,8 +49,15 @@ public class PycaKeyDerivationContextTranslator implements IContextTranslation algorithm) { // hash algorithm - final PycaDigestMapper pycaDigestMapper = new PycaDigestMapper(); - return pycaDigestMapper.parse(algorithm.asString(), detectionLocation).map(i -> i); + final PycaHashBasedKeyDerivationMapper pycaHashBasedKeyDerivationMapper = + new PycaHashBasedKeyDerivationMapper(); + return pycaHashBasedKeyDerivationMapper + .parse(algorithm.asString(), detectionLocation) + .map( + kdf -> { + kdf.put(new KeyDerivation(detectionLocation)); + return kdf; + }); } else if (value instanceof KeySize keySize) { return Optional.of(new KeyLength(keySize.getValue(), detectionLocation)); } else if (value instanceof KeyAction diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaPrivateKeyContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaPrivateKeyContextTranslator.java index 38ee11d8..925dae46 100644 --- a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaPrivateKeyContextTranslator.java +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaPrivateKeyContextTranslator.java @@ -19,6 +19,7 @@ */ package com.ibm.plugin.translation.translator.contexts; +import com.ibm.engine.model.Curve; import com.ibm.engine.model.IValue; import com.ibm.engine.model.KeyAction; import com.ibm.engine.model.KeySize; @@ -30,15 +31,36 @@ import com.ibm.mapper.model.INode; import com.ibm.mapper.model.KeyLength; import com.ibm.mapper.model.PrivateKey; +import com.ibm.mapper.model.PublicKeyEncryption; import com.ibm.mapper.model.algorithms.DH; import com.ibm.mapper.model.algorithms.DSA; import com.ibm.mapper.model.algorithms.Ed25519; import com.ibm.mapper.model.algorithms.Ed448; import com.ibm.mapper.model.algorithms.RSA; +import com.ibm.mapper.model.curves.Brainpoolp256r1; +import com.ibm.mapper.model.curves.Brainpoolp384r1; +import com.ibm.mapper.model.curves.Brainpoolp512r1; +import com.ibm.mapper.model.curves.Secp192r1; +import com.ibm.mapper.model.curves.Secp224r1; +import com.ibm.mapper.model.curves.Secp256k1; +import com.ibm.mapper.model.curves.Secp256r1; +import com.ibm.mapper.model.curves.Secp384r1; +import com.ibm.mapper.model.curves.Secp521r1; +import com.ibm.mapper.model.curves.Sect163k1; +import com.ibm.mapper.model.curves.Sect163r2; +import com.ibm.mapper.model.curves.Sect233k1; +import com.ibm.mapper.model.curves.Sect233r1; +import com.ibm.mapper.model.curves.Sect283k1; +import com.ibm.mapper.model.curves.Sect283r1; +import com.ibm.mapper.model.curves.Sect409k1; +import com.ibm.mapper.model.curves.Sect409r1; +import com.ibm.mapper.model.curves.Sect571k1; +import com.ibm.mapper.model.curves.Sect571r1; import com.ibm.mapper.model.functionality.KeyGeneration; import com.ibm.mapper.utils.DetectionLocation; import java.util.Optional; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.sonar.plugins.python.api.tree.Tree; @SuppressWarnings("java:S1301") @@ -52,19 +74,64 @@ public final class PycaPrivateKeyContextTranslator implements IContextTranslatio @NotNull DetectionLocation detectionLocation) { if (value instanceof KeyAction && detectionContext instanceof DetectionContext context) { - return getPrivateKey(detectionLocation, context); + return getPrivateKey(context, null, detectionLocation); } else if (value instanceof KeySize keySize) { if (detectionContext instanceof DetectionContext context && context.get("algorithm").isPresent()) { - return getPrivateKey(detectionLocation, context); + return getPrivateKey(context, keySize.getValue(), detectionLocation); } return Optional.of(new KeyLength(keySize.getValue(), detectionLocation)); + } else if (value instanceof Curve curve + && detectionContext instanceof DetectionContext context + && context.get("algorithm").map(a -> a.equalsIgnoreCase("EC")).orElse(false)) { + return Optional.of(curve.asString()) + .map( + str -> + switch (str.toUpperCase().trim()) { + case "SECP256R1" -> new Secp256r1(detectionLocation); + case "SECP384R1" -> new Secp384r1(detectionLocation); + case "SECP521R1" -> new Secp521r1(detectionLocation); + case "SECP224R1" -> new Secp224r1(detectionLocation); + case "SECP192R1" -> new Secp192r1(detectionLocation); + case "SECP256K1" -> new Secp256k1(detectionLocation); + case "BRAINPOOLP256R1" -> + new Brainpoolp256r1(detectionLocation); + case "BRAINPOOLP384R1" -> + new Brainpoolp384r1(detectionLocation); + case "BRAINPOOLP512R1" -> + new Brainpoolp512r1(detectionLocation); + case "SECT571K1" -> new Sect571k1(detectionLocation); + case "SECT409K1" -> new Sect409k1(detectionLocation); + case "SECT283K1" -> new Sect283k1(detectionLocation); + case "SECT233K1" -> new Sect233k1(detectionLocation); + case "SECT163K1" -> new Sect163k1(detectionLocation); + case "SECT571R1" -> new Sect571r1(detectionLocation); + case "SECT409R1" -> new Sect409r1(detectionLocation); + case "SECT283R1" -> new Sect283r1(detectionLocation); + case "SECT233R1" -> new Sect233r1(detectionLocation); + case "SECT163R2" -> new Sect163r2(detectionLocation); + default -> null; + }) + .map(EllipticCurveAlgorithm::new) + .map( + ec -> { + PrivateKey privateKey = new PrivateKey((PublicKeyEncryption) ec); + privateKey.put( + new KeyGeneration( + detectionLocation)); // currently only GENERATE is + // used as key action is this + // context + return privateKey; + }); } + return Optional.empty(); } private static @NotNull Optional getPrivateKey( - @NotNull DetectionLocation detectionLocation, @NotNull DetectionContext context) { + @NotNull DetectionContext context, + @Nullable Integer keySize, + @NotNull DetectionLocation detectionLocation) { return context.get("algorithm") .map( str -> @@ -87,6 +154,13 @@ public final class PycaPrivateKeyContextTranslator implements IContextTranslatio // used as key action is this // context return privateKey; + }) + .map( + key -> { + if (keySize != null) { + key.put(new KeyLength(keySize, detectionLocation)); + } + return key; }); } } 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/CryptographyEllipticCurveKeyExchangeTestFile.py b/python/src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveKeyExchangeTestFile.py deleted file mode 100644 index bc8cf8bd..00000000 --- a/python/src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveKeyExchangeTestFile.py +++ /dev/null @@ -1,34 +0,0 @@ -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.asymmetric import ec -from cryptography.hazmat.primitives.kdf.hkdf import HKDF - -# Generate a private key for use in the exchange. -server_private_key = ec.generate_private_key( # Noncompliant {{SECP384R1}} - ec.SECP384R1() -) - -def exchange(public_key): - shared_key = server_private_key.exchange( - ec.ECDH(), public_key) - - # Perform key derivation. // TODO: How should this key derivation be linked to the private key? - # derived_key = HKDF( - # algorithm=hashes.SHA256(), - # length=32, - # salt=None, - # info=b'handshake data', - # ).derive(shared_key) - # return derived_key - -# GROUND TRUTH (translation) -# -# PrivateKey EC -# Protocol ECDH // TODO: add Protocol to the model -# KeyDerivationFunction SHA-256 // TODO: add KeyDerivationFunction to the model -# EllipticCurveAlgorithm EC -# EllipticCurve SECP384R1 -# KeyGeneration KEYGENERATION -# PublicKey EC -# EllipticCurveAlgorithm EC -# EllipticCurve SECP384R1 -# KeyGeneration KEYGENERATION diff --git a/python/src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveDeriveTestFile.py b/python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveDeriveTestFile.py rename to python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTestFile.py b/python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTestFile.py new file mode 100644 index 00000000..ba90d84e --- /dev/null +++ b/python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTestFile.py @@ -0,0 +1,21 @@ +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric import ec +from cryptography.hazmat.primitives.kdf.hkdf import HKDF + +# Generate a private key for use in the exchange. +server_private_key = ec.generate_private_key( # Noncompliant {{SECP384R1}} + ec.SECP384R1() +) + +def exchange(public_key): + shared_key = server_private_key.exchange( + ec.ECDH(), public_key) + + # Perform key derivation. // TODO: How should this key derivation be linked to the private key? + derived_key = HKDF( # Noncompliant {{SHA256}} + algorithm=hashes.SHA256(), + length=32, + salt=None, + info=b'handshake data', + ).derive(shared_key) + return derived_key \ No newline at end of file diff --git a/python/src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveNumbersTestFile.py b/python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveNumbersTestFile.py rename to python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveSignTestFile.py b/python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSignTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveSignTestFile.py rename to python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSignTestFile.py 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/DSA/PycaDSASignTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DSA/PycaDSASignTest.java index 32c5131c..55412fb6 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DSA/PycaDSASignTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DSA/PycaDSASignTest.java @@ -22,21 +22,21 @@ import static org.assertj.core.api.Assertions.assertThat; import com.ibm.engine.detection.DetectionStore; -import com.ibm.engine.model.CipherAction; import com.ibm.engine.model.IValue; import com.ibm.engine.model.KeySize; import com.ibm.engine.model.SignatureAction; +import com.ibm.engine.model.ValueAction; 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.Algorithm; +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.MessageDigest; +import com.ibm.mapper.model.Oid; import com.ibm.mapper.model.PrivateKey; -import com.ibm.mapper.model.PublicKey; import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.functionality.Digest; import com.ibm.mapper.model.functionality.KeyGeneration; import com.ibm.mapper.model.functionality.Sign; import com.ibm.plugin.TestBase; @@ -62,121 +62,95 @@ 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"); + IValue value0 = detectionStore.getDetectionValues().get(0); + assertThat(value0).isInstanceOf(KeySize.class); + assertThat(value0.asString()).isEqualTo("1024"); - DetectionStore store = + DetectionStore store_1 = getStoreOfValueType(SignatureAction.class, detectionStore.getChildren()); - assertThat(store).isNotNull(); - assertThat(store.getDetectionValueContext()).isInstanceOf(SignatureContext.class); - assertThat(store.getDetectionValues()).hasSize(1); - value = store.getDetectionValues().get(0); - assertThat(value).isInstanceOf(SignatureAction.class); - assertThat(value.asString()).isEqualTo("SIGN"); - - store = - getStoreOfValueType( - com.ibm.engine.model.CipherAction.class, detectionStore.getChildren()); - 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"); + assertThat(store_1.getDetectionValues()).hasSize(1); + assertThat(store_1.getDetectionValueContext()).isInstanceOf(SignatureContext.class); + IValue value0_1 = store_1.getDetectionValues().get(0); + assertThat(value0_1).isInstanceOf(SignatureAction.class); + assertThat(value0_1.asString()).isEqualTo("SIGN"); + + DetectionStore store_1_1 = + getStoreOfValueType(ValueAction.class, store_1.getChildren()); + assertThat(store_1_1.getDetectionValues()).hasSize(1); + assertThat(store_1_1.getDetectionValueContext()).isInstanceOf(DigestContext.class); + IValue value0_1_1 = store_1_1.getDetectionValues().get(0); + assertThat(value0_1_1).isInstanceOf(ValueAction.class); + assertThat(value0_1_1.asString()).isEqualTo("SHA256"); /* * Translation */ - assertThat(nodes).hasSize(2); + assertThat(nodes).hasSize(1); // PrivateKey INode privateKeyNode = nodes.get(0); - assertThat(privateKeyNode).isInstanceOf(PrivateKey.class); - assertThat(privateKeyNode).isNotNull(); + assertThat(privateKeyNode.getKind()).isEqualTo(PrivateKey.class); + assertThat(privateKeyNode.getChildren()).hasSize(3); assertThat(privateKeyNode.asString()).isEqualTo("DSA"); - assertThat(privateKeyNode.getChildren()).hasSize(3); // Three children detected - - // KeyLength under PrivateKey - INode privateKeyKeyLengthNode = privateKeyNode.getChildren().get(KeyLength.class); - assertThat(privateKeyKeyLengthNode).isNotNull(); - assertThat(privateKeyKeyLengthNode.asString()).isEqualTo("1024"); // Signature under PrivateKey - INode privateKeySignatureNode = privateKeyNode.getChildren().get(Signature.class); - assertThat(privateKeySignatureNode).isNotNull(); - assertThat(privateKeySignatureNode.asString()).isEqualTo("SHA256withDSA"); + INode signatureNode = privateKeyNode.getChildren().get(Signature.class); + assertThat(signatureNode).isNotNull(); + assertThat(signatureNode.getChildren()).hasSize(2); + assertThat(signatureNode.asString()).isEqualTo("DSA"); + + // Oid under Signature under PrivateKey + INode oidNode = signatureNode.getChildren().get(Oid.class); + assertThat(oidNode).isNotNull(); + assertThat(oidNode.getChildren()).isEmpty(); + assertThat(oidNode.asString()).isEqualTo("2.16.840.1.101.3.4.3.2"); // MessageDigest under Signature under PrivateKey - INode privateKeyMessageDigestNode = - privateKeySignatureNode.getChildren().get(MessageDigest.class); - assertThat(privateKeyMessageDigestNode).isNotNull(); - assertThat(privateKeyMessageDigestNode.asString()).isEqualTo("SHA256"); - - // Sign under Signature under PrivateKey - INode privateKeySignNode = privateKeySignatureNode.getChildren().get(Sign.class); - assertThat(privateKeySignNode).isNotNull(); - assertThat(privateKeySignNode.asString()).isEqualTo("SIGN"); - - // Algorithm under Signature under PrivateKey - INode privateKeyAlgorithmNode = privateKeySignatureNode.getChildren().get(Algorithm.class); - assertThat(privateKeyAlgorithmNode).isNotNull(); - assertThat(privateKeyAlgorithmNode.asString()).isEqualTo("DSA"); - - // KeyLength under Algorithm under Signature under PrivateKey - INode privateKeyAlgorithmKeyLengthNode = - privateKeyAlgorithmNode.getChildren().get(KeyLength.class); - assertThat(privateKeyAlgorithmKeyLengthNode).isNotNull(); - assertThat(privateKeyAlgorithmKeyLengthNode.asString()).isEqualTo("1024"); - - // Algorithm under PrivateKey - INode privateKeyAlgorithmNode1 = privateKeyNode.getChildren().get(Algorithm.class); - assertThat(privateKeyAlgorithmNode1).isNotNull(); - assertThat(privateKeyAlgorithmNode1.asString()).isEqualTo("DSA"); - - // KeyLength under Algorithm under PrivateKey - privateKeyAlgorithmKeyLengthNode = - privateKeyAlgorithmNode1.getChildren().get(KeyLength.class); - assertThat(privateKeyAlgorithmKeyLengthNode).isNotNull(); - assertThat(privateKeyAlgorithmKeyLengthNode.asString()).isEqualTo("1024"); - - // KeyGeneration under Algorithm under PrivateKey - INode privateKeyAlgorithmKeyGenerationNode = - privateKeyAlgorithmNode1.getChildren().get(KeyGeneration.class); - assertThat(privateKeyAlgorithmKeyGenerationNode).isNotNull(); - assertThat(privateKeyAlgorithmKeyGenerationNode.asString()).isEqualTo("KEYGENERATION"); - - // PublicKey - INode publicKeyNode = nodes.get(1); - assertThat(publicKeyNode) - .isInstanceOfAny(PublicKey.class, Key.class); // Special case because of .deepCopy - assertThat(publicKeyNode.getChildren()).hasSize(2); // Two children detected - - // 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(Algorithm.class); - assertThat(publicKeyAlgorithmNode).isNotNull(); - assertThat(publicKeyAlgorithmNode.asString()).isEqualTo("DSA"); - - // KeyLength under Algorithm under PublicKey - INode publicKeyAlgorithmKeyLengthNode = - publicKeyAlgorithmNode.getChildren().get(KeyLength.class); - assertThat(publicKeyAlgorithmKeyLengthNode).isNotNull(); - assertThat(publicKeyAlgorithmKeyLengthNode.asString()).isEqualTo("1024"); - - // KeyGeneration under Algorithm under PublicKey - INode publicKeyAlgorithmKeyGenerationNode = - publicKeyAlgorithmNode.getChildren().get(KeyGeneration.class); - assertThat(publicKeyAlgorithmKeyGenerationNode).isNotNull(); - assertThat(publicKeyAlgorithmKeyGenerationNode.asString()).isEqualTo("KEYGENERATION"); + INode messageDigestNode = signatureNode.getChildren().get(MessageDigest.class); + assertThat(messageDigestNode).isNotNull(); + assertThat(messageDigestNode.getChildren()).hasSize(4); + assertThat(messageDigestNode.asString()).isEqualTo("SHA256"); + + // BlockSize under MessageDigest under Signature under PrivateKey + INode blockSizeNode = messageDigestNode.getChildren().get(BlockSize.class); + assertThat(blockSizeNode).isNotNull(); + assertThat(blockSizeNode.getChildren()).isEmpty(); + assertThat(blockSizeNode.asString()).isEqualTo("512"); + + // Oid under MessageDigest 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"); + + // DigestSize under MessageDigest under Signature under PrivateKey + INode digestSizeNode = messageDigestNode.getChildren().get(DigestSize.class); + assertThat(digestSizeNode).isNotNull(); + assertThat(digestSizeNode.getChildren()).isEmpty(); + assertThat(digestSizeNode.asString()).isEqualTo("256"); + + // Digest under MessageDigest under Signature under PrivateKey + INode digestNode = messageDigestNode.getChildren().get(Digest.class); + assertThat(digestNode).isNotNull(); + assertThat(digestNode.getChildren()).isEmpty(); + assertThat(digestNode.asString()).isEqualTo("DIGEST"); + + // KeyGeneration under PrivateKey + INode keyGenerationNode = privateKeyNode.getChildren().get(KeyGeneration.class); + assertThat(keyGenerationNode).isNotNull(); + assertThat(keyGenerationNode.getChildren()).isEmpty(); + assertThat(keyGenerationNode.asString()).isEqualTo("KEYGENERATION"); + + // Sign under PrivateKey + INode signNode = privateKeyNode.getChildren().get(Sign.class); + assertThat(signNode).isNotNull(); + assertThat(signNode.getChildren()).isEmpty(); + assertThat(signNode.asString()).isEqualTo("SIGN"); } } diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTest.java index b9fdf46d..9575b077 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTest.java @@ -22,20 +22,19 @@ import static org.assertj.core.api.Assertions.assertThat; import com.ibm.engine.detection.DetectionStore; -import com.ibm.engine.model.Algorithm; +import com.ibm.engine.model.Curve; import com.ibm.engine.model.IValue; import com.ibm.engine.model.context.PrivateKeyContext; import com.ibm.mapper.model.EllipticCurve; -import com.ibm.mapper.model.EllipticCurveAlgorithm; import com.ibm.mapper.model.INode; -import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.Oid; import com.ibm.mapper.model.PrivateKey; -import com.ibm.mapper.model.PublicKey; +import com.ibm.mapper.model.PublicKeyEncryption; import com.ibm.mapper.model.functionality.KeyGeneration; 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; @@ -43,10 +42,11 @@ import org.sonar.python.checks.utils.PythonCheckVerifier; public class PycaEllipticCurveDeriveTest extends TestBase { + @Test - void test() { + public void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveDeriveTestFile.py", + "src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTestFile.py", this); } @@ -55,62 +55,49 @@ 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(Algorithm.class); + assertThat(value).isInstanceOf(Curve.class); assertThat(value.asString()).isEqualTo("SECP256R1"); /* * Translation */ - assertThat(nodes).hasSize(2); + assertThat(nodes).hasSize(1); // PrivateKey INode privateKeyNode = nodes.get(0); - assertThat(privateKeyNode).isInstanceOf(PrivateKey.class); - assertThat(privateKeyNode.getChildren()).hasSize(1); - - // EllipticCurveAlgorithm under PrivateKey - INode privateKeyAlgorithmNode = - privateKeyNode.getChildren().get(EllipticCurveAlgorithm.class); - assertThat(privateKeyAlgorithmNode).isNotNull(); - assertThat(privateKeyAlgorithmNode.asString()).isEqualTo("EC"); - - // EllipticCurve under EllipticCurveAlgorithm under PrivateKey - INode privateKeyCurveNode = privateKeyAlgorithmNode.getChildren().get(EllipticCurve.class); - assertThat(privateKeyCurveNode).isNotNull(); - assertThat(privateKeyCurveNode.asString()).isEqualTo("SECP256R1"); - - // KeyGeneration under EllipticCurveAlgorithm under PrivateKey - INode privateKeyKeyGenerationNode = - privateKeyAlgorithmNode.getChildren().get(KeyGeneration.class); - assertThat(privateKeyKeyGenerationNode).isNotNull(); - assertThat(privateKeyKeyGenerationNode.asString()).isEqualTo("KEYGENERATION"); + assertThat(privateKeyNode.getKind()).isEqualTo(PrivateKey.class); + assertThat(privateKeyNode.getChildren()).hasSize(2); + assertThat(privateKeyNode.asString()).isEqualTo("EC-secp256r1"); - // PublicKey - INode publicKeyNode = nodes.get(1); - assertThat(publicKeyNode).isInstanceOfAny(PublicKey.class, Key.class); - assertThat(publicKeyNode.getChildren()).hasSize(1); + // KeyGeneration under PrivateKey + INode keyGenerationNode = privateKeyNode.getChildren().get(KeyGeneration.class); + assertThat(keyGenerationNode).isNotNull(); + assertThat(keyGenerationNode.getChildren()).isEmpty(); + assertThat(keyGenerationNode.asString()).isEqualTo("KEYGENERATION"); - // EllipticCurveAlgorithm under PublicKey - INode publicKeyAlgorithmNode = - publicKeyNode.getChildren().get(EllipticCurveAlgorithm.class); - assertThat(publicKeyAlgorithmNode).isNotNull(); - assertThat(publicKeyAlgorithmNode.asString()).isEqualTo("EC"); + // PublicKeyEncryption under PrivateKey + INode publicKeyEncryptionNode = privateKeyNode.getChildren().get(PublicKeyEncryption.class); + assertThat(publicKeyEncryptionNode).isNotNull(); + assertThat(publicKeyEncryptionNode.getChildren()).hasSize(2); + assertThat(publicKeyEncryptionNode.asString()).isEqualTo("EC-secp256r1"); - // EllipticCurve under EllipticCurveAlgorithm under PublicKey - INode publicKeyCurveNode = publicKeyAlgorithmNode.getChildren().get(EllipticCurve.class); - assertThat(publicKeyCurveNode).isNotNull(); - assertThat(publicKeyCurveNode.asString()).isEqualTo("SECP256R1"); + // EllipticCurve under PublicKeyEncryption under PrivateKey + INode ellipticCurveNode = publicKeyEncryptionNode.getChildren().get(EllipticCurve.class); + assertThat(ellipticCurveNode).isNotNull(); + assertThat(ellipticCurveNode.getChildren()).isEmpty(); + assertThat(ellipticCurveNode.asString()).isEqualTo("secp256r1"); - // KeyGeneration under EllipticCurveAlgorithm under PublicKey - INode publicKeyKeyGenerationNode = - publicKeyAlgorithmNode.getChildren().get(KeyGeneration.class); - assertThat(publicKeyKeyGenerationNode).isNotNull(); - assertThat(publicKeyKeyGenerationNode.asString()).isEqualTo("KEYGENERATION"); + // Oid under PublicKeyEncryption under PrivateKey + INode oidNode = publicKeyEncryptionNode.getChildren().get(Oid.class); + assertThat(oidNode).isNotNull(); + assertThat(oidNode.getChildren()).isEmpty(); + assertThat(oidNode.asString()).isEqualTo("1.2.840.10045.2.1"); } } diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTest.java index ebcf92df..4dcd443b 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTest.java @@ -23,20 +23,27 @@ import com.ibm.engine.detection.DetectionStore; import com.ibm.engine.model.Algorithm; +import com.ibm.engine.model.Curve; import com.ibm.engine.model.IValue; +import com.ibm.engine.model.KeySize; +import com.ibm.engine.model.context.KeyAgreementContext; +import com.ibm.engine.model.context.KeyDerivationFunctionContext; import com.ibm.engine.model.context.PrivateKeyContext; -import com.ibm.engine.model.context.SecretKeyContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; import com.ibm.mapper.model.EllipticCurve; -import com.ibm.mapper.model.EllipticCurveAlgorithm; import com.ibm.mapper.model.INode; -import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.KeyAgreement; +import com.ibm.mapper.model.KeyDerivationFunction; +import com.ibm.mapper.model.KeyLength; +import com.ibm.mapper.model.Oid; import com.ibm.mapper.model.PrivateKey; -import com.ibm.mapper.model.PublicKey; +import com.ibm.mapper.model.functionality.KeyDerivation; import com.ibm.mapper.model.functionality.KeyGeneration; 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; @@ -44,10 +51,11 @@ import org.sonar.python.checks.utils.PythonCheckVerifier; public class PycaEllipticCurveKeyExchangeTest extends TestBase { + @Test - void test() { + public void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveKeyExchangeTestFile.py", + "src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTestFile.py", this); } @@ -56,71 +64,122 @@ 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(Algorithm.class); - assertThat(value.asString()).isEqualTo("SECP384R1"); - - DetectionStore store = - getStoreOfValueType(Algorithm.class, detectionStore.getChildren()); - assertThat(store).isNotNull(); - assertThat(store.getDetectionValueContext()).isInstanceOf(SecretKeyContext.class); - assertThat(store.getDetectionValues()).hasSize(1); - value = store.getDetectionValues().get(0); - assertThat(value).isInstanceOf(Algorithm.class); - assertThat(value.asString()).isEqualTo("ECDH"); - - /* - * Translation - */ - assertThat(nodes).hasSize(2); - - // PrivateKey - INode privateKeyNode = nodes.get(0); - assertThat(privateKeyNode).isInstanceOf(PrivateKey.class); - assertThat(privateKeyNode.getChildren()).hasSize(1); - - // EllipticCurveAlgorithm under PrivateKey - INode privateKeyAlgorithmNode = - privateKeyNode.getChildren().get(EllipticCurveAlgorithm.class); - assertThat(privateKeyAlgorithmNode).isNotNull(); - assertThat(privateKeyAlgorithmNode.asString()).isEqualTo("EC"); - - // EllipticCurve under EllipticCurveAlgorithm under PrivateKey - INode privateKeyCurveNode = privateKeyAlgorithmNode.getChildren().get(EllipticCurve.class); - assertThat(privateKeyCurveNode).isNotNull(); - assertThat(privateKeyCurveNode.asString()).isEqualTo("SECP384R1"); - - // KeyGeneration under EllipticCurveAlgorithm under PrivateKey - INode privateKeyKeyGenerationNode = - privateKeyAlgorithmNode.getChildren().get(KeyGeneration.class); - assertThat(privateKeyKeyGenerationNode).isNotNull(); - assertThat(privateKeyKeyGenerationNode.asString()).isEqualTo("KEYGENERATION"); - - // PublicKey - INode publicKeyNode = nodes.get(1); - assertThat(publicKeyNode).isInstanceOfAny(PublicKey.class, Key.class); - assertThat(publicKeyNode.getChildren()).hasSize(1); - - // EllipticCurveAlgorithm under PublicKey - INode publicKeyAlgorithmNode = - publicKeyNode.getChildren().get(EllipticCurveAlgorithm.class); - assertThat(publicKeyAlgorithmNode).isNotNull(); - assertThat(publicKeyAlgorithmNode.asString()).isEqualTo("EC"); - - // EllipticCurve under EllipticCurveAlgorithm under PublicKey - INode publicKeyCurveNode = publicKeyAlgorithmNode.getChildren().get(EllipticCurve.class); - assertThat(publicKeyCurveNode).isNotNull(); - assertThat(publicKeyCurveNode.asString()).isEqualTo("SECP384R1"); - - // KeyGeneration under EllipticCurveAlgorithm under PublicKey - INode publicKeyKeyGenerationNode = - publicKeyAlgorithmNode.getChildren().get(KeyGeneration.class); - assertThat(publicKeyKeyGenerationNode).isNotNull(); - assertThat(publicKeyKeyGenerationNode.asString()).isEqualTo("KEYGENERATION"); + 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(Curve.class); + assertThat(value0.asString()).isEqualTo("SECP384R1"); + + DetectionStore store_1 = + getStoreOfValueType(Algorithm.class, detectionStore.getChildren()); + assertThat(store_1.getDetectionValues()).hasSize(1); + assertThat(store_1.getDetectionValueContext()).isInstanceOf(KeyAgreementContext.class); + IValue value0_1 = store_1.getDetectionValues().get(0); + assertThat(value0_1).isInstanceOf(Algorithm.class); + assertThat(value0_1.asString()).isEqualTo("ECDH"); + + /* + * Translation + */ + + assertThat(nodes).hasSize(1); + + // PrivateKey + INode privateKeyNode = nodes.get(0); + assertThat(privateKeyNode.getKind()).isEqualTo(PrivateKey.class); + assertThat(privateKeyNode.getChildren()).hasSize(2); + assertThat(privateKeyNode.asString()).isEqualTo("EC-secp384r1"); + + // KeyGeneration under PrivateKey + INode keyGenerationNode = privateKeyNode.getChildren().get(KeyGeneration.class); + assertThat(keyGenerationNode).isNotNull(); + assertThat(keyGenerationNode.getChildren()).isEmpty(); + assertThat(keyGenerationNode.asString()).isEqualTo("KEYGENERATION"); + + // KeyAgreement under PrivateKey + INode keyAgreementNode = privateKeyNode.getChildren().get(KeyAgreement.class); + assertThat(keyAgreementNode).isNotNull(); + assertThat(keyAgreementNode.getChildren()).hasSize(2); + assertThat(keyAgreementNode.asString()).isEqualTo("ECDH"); + + // EllipticCurve under KeyAgreement under PrivateKey + INode ellipticCurveNode = keyAgreementNode.getChildren().get(EllipticCurve.class); + assertThat(ellipticCurveNode).isNotNull(); + assertThat(ellipticCurveNode.getChildren()).isEmpty(); + assertThat(ellipticCurveNode.asString()).isEqualTo("secp384r1"); + + // Oid under KeyAgreement under PrivateKey + INode oidNode = keyAgreementNode.getChildren().get(Oid.class); + assertThat(oidNode).isNotNull(); + assertThat(oidNode.getChildren()).isEmpty(); + assertThat(oidNode.asString()).isEqualTo("1.3.132.1.12"); + } else if (findingId == 1) { + /* + * Detection Store + */ + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyDerivationFunctionContext.class); + IValue value0 = detectionStore.getDetectionValues().get(0); + assertThat(value0).isInstanceOf(Algorithm.class); + assertThat(value0.asString()).isEqualTo("SHA256"); + + DetectionStore store_1 = + getStoreOfValueType(KeySize.class, detectionStore.getChildren()); + assertThat(store_1.getDetectionValues()).hasSize(1); + assertThat(store_1.getDetectionValueContext()) + .isInstanceOf(KeyDerivationFunctionContext.class); + IValue value0_1 = store_1.getDetectionValues().get(0); + assertThat(value0_1).isInstanceOf(KeySize.class); + assertThat(value0_1.asString()).isEqualTo("256"); + + /* + * Translation + */ + assertThat(nodes).hasSize(1); + + // KeyDerivationFunction + INode keyDerivationFunctionNode = nodes.get(0); + assertThat(keyDerivationFunctionNode.getKind()).isEqualTo(KeyDerivationFunction.class); + assertThat(keyDerivationFunctionNode.getChildren()).hasSize(5); + assertThat(keyDerivationFunctionNode.asString()).isEqualTo("SHA256"); + + // BlockSize under KeyDerivationFunction + INode blockSizeNode = keyDerivationFunctionNode.getChildren().get(BlockSize.class); + assertThat(blockSizeNode).isNotNull(); + assertThat(blockSizeNode.getChildren()).isEmpty(); + assertThat(blockSizeNode.asString()).isEqualTo("512"); + + // DigestSize under KeyDerivationFunction + INode digestSizeNode = keyDerivationFunctionNode.getChildren().get(DigestSize.class); + assertThat(digestSizeNode).isNotNull(); + assertThat(digestSizeNode.getChildren()).isEmpty(); + assertThat(digestSizeNode.asString()).isEqualTo("256"); + + // KeyDerivation under KeyDerivationFunction + INode keyDerivationNode = + keyDerivationFunctionNode.getChildren().get(KeyDerivation.class); + assertThat(keyDerivationNode).isNotNull(); + assertThat(keyDerivationNode.getChildren()).isEmpty(); + assertThat(keyDerivationNode.asString()).isEqualTo("KEYDERIVATION"); + + // KeyLength under KeyDerivationFunction + INode keyLengthNode = keyDerivationFunctionNode.getChildren().get(KeyLength.class); + assertThat(keyLengthNode).isNotNull(); + assertThat(keyLengthNode.getChildren()).isEmpty(); + assertThat(keyLengthNode.asString()).isEqualTo("256"); + + // Oid under KeyDerivationFunction + INode oidNode = keyDerivationFunctionNode.getChildren().get(Oid.class); + assertThat(oidNode).isNotNull(); + assertThat(oidNode.getChildren()).isEmpty(); + assertThat(oidNode.asString()).isEqualTo("2.16.840.1.101.3.4.2.1"); + } } } diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTest.java index 9a9615df..4cbb17a3 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTest.java @@ -19,26 +19,13 @@ */ package com.ibm.plugin.rules.detection.asymmetric.EllipticCurve; -import static org.assertj.core.api.Assertions.assertThat; - import com.ibm.engine.detection.DetectionStore; -import com.ibm.engine.model.Algorithm; -import com.ibm.engine.model.IValue; -import com.ibm.engine.model.KeyAction; -import com.ibm.engine.model.context.PrivateKeyContext; -import com.ibm.engine.model.context.PublicKeyContext; -import com.ibm.mapper.model.EllipticCurve; -import com.ibm.mapper.model.EllipticCurveAlgorithm; import com.ibm.mapper.model.INode; -import com.ibm.mapper.model.Key; -import com.ibm.mapper.model.PrivateKey; -import com.ibm.mapper.model.PublicKey; -import com.ibm.mapper.model.functionality.KeyGeneration; 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; @@ -46,11 +33,12 @@ import org.sonar.python.checks.utils.PythonCheckVerifier; public class PycaEllipticCurveNumbersTest extends TestBase { - @Disabled // TODO: Make the curve lookout in the dictionnary work + + @Disabled @Test - void test() { + public void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveNumbersTestFile.py", + "src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTestFile.py", this); } @@ -58,68 +46,5 @@ void test() { public void asserts( int findingId, @Nonnull DetectionStore detectionStore, - @Nonnull List nodes) { - String curve = "SECP256R1"; - /* - * Detection Store - */ - assertThat(detectionStore.getDetectionValues()).hasSize(1); - IValue value = detectionStore.getDetectionValues().get(0); - assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(PublicKeyContext.class); - assertThat(value).isInstanceOf(Algorithm.class); - assertThat(value.asString()).isEqualTo(curve); - - DetectionStore store = - getStoreOfValueType(KeyAction.class, detectionStore.getChildren()); - assertThat(store).isNotNull(); - assertThat(store.getDetectionValueContext()).isInstanceOf(PrivateKeyContext.class); - assertThat(store.getDetectionValues()).hasSize(1); - value = store.getDetectionValues().get(0); - assertThat(value).isInstanceOf(KeyAction.class); - assertThat(value.asString()).isEqualTo("GENERATION"); - - /* - * Translation - */ - assertThat(nodes).hasSize(2); - - // Assert PublicKey translation - INode publicKeyNode = nodes.get(0); - assertThat(publicKeyNode).isInstanceOf(PublicKey.class); - assertThat(publicKeyNode.asString()).isEqualTo("EC"); - - INode ellipticCurveAlgorithmNode = - publicKeyNode.getChildren().get(EllipticCurveAlgorithm.class); - assertThat(ellipticCurveAlgorithmNode).isNotNull(); - assertThat(ellipticCurveAlgorithmNode.asString()).isEqualTo("EC"); - - INode ellipticCurveNode = ellipticCurveAlgorithmNode.getChildren().get(EllipticCurve.class); - assertThat(ellipticCurveNode).isNotNull(); - assertThat(ellipticCurveNode.asString()).isEqualTo(curve); - - INode publicKeyGenerationNode = - ellipticCurveAlgorithmNode.getChildren().get(KeyGeneration.class); - assertThat(publicKeyGenerationNode).isNotNull(); - assertThat(publicKeyGenerationNode.asString()).isEqualTo("KEYGENERATION"); - - // Assert PrivateKey translation - INode privateKeyNode = nodes.get(1); - assertThat(publicKeyNode).isInstanceOfAny(PrivateKey.class, Key.class); - assertThat(privateKeyNode.asString()).isEqualTo("EC"); - - INode privateKeyEllipticCurveAlgorithmNode = - privateKeyNode.getChildren().get(EllipticCurveAlgorithm.class); - assertThat(privateKeyEllipticCurveAlgorithmNode).isNotNull(); - assertThat(privateKeyEllipticCurveAlgorithmNode.asString()).isEqualTo("EC"); - - INode privateKeyEllipticCurveNode = - privateKeyEllipticCurveAlgorithmNode.getChildren().get(EllipticCurve.class); - assertThat(privateKeyEllipticCurveNode).isNotNull(); - assertThat(privateKeyEllipticCurveNode.asString()).isEqualTo(curve); - - INode privateKeyGenerationNode = - privateKeyEllipticCurveAlgorithmNode.getChildren().get(KeyGeneration.class); - assertThat(privateKeyGenerationNode).isNotNull(); - assertThat(privateKeyGenerationNode.asString()).isEqualTo("KEYGENERATION"); - } + @Nonnull List nodes) {} } diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSignTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSignTest.java index 8d294137..a81af5df 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSignTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSignTest.java @@ -23,26 +23,26 @@ import com.ibm.engine.detection.DetectionStore; import com.ibm.engine.model.Algorithm; -import com.ibm.engine.model.CipherAction; +import com.ibm.engine.model.Curve; import com.ibm.engine.model.IValue; import com.ibm.engine.model.SignatureAction; -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.EllipticCurve; -import com.ibm.mapper.model.EllipticCurveAlgorithm; import com.ibm.mapper.model.INode; -import com.ibm.mapper.model.Key; import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; import com.ibm.mapper.model.PrivateKey; -import com.ibm.mapper.model.PublicKey; import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.functionality.Digest; import com.ibm.mapper.model.functionality.KeyGeneration; import com.ibm.mapper.model.functionality.Sign; 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; @@ -50,10 +50,11 @@ import org.sonar.python.checks.utils.PythonCheckVerifier; public class PycaEllipticCurveSignTest extends TestBase { + @Test - void test() { + public void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/EllipticCurve/CryptographyEllipticCurveSignTestFile.py", + "src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSignTestFile.py", this); } @@ -66,89 +67,92 @@ public void asserts( * Detection Store */ assertThat(detectionStore.getDetectionValues()).hasSize(1); - IValue value = detectionStore.getDetectionValues().get(0); assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(PrivateKeyContext.class); - assertThat(value).isInstanceOf(Algorithm.class); - assertThat(value.asString()).isEqualTo("SECP384R1"); - - DetectionStore store = - getStoreOfValueType(Algorithm.class, detectionStore.getChildren()); - assertThat(store).isNotNull(); - assertThat(store.getDetectionValueContext()).isInstanceOf(SignatureContext.class); - assertThat(store.getDetectionValues()).hasSize(2); - value = store.getDetectionValues().get(0); - assertThat(value).isInstanceOf(SignatureAction.class); - assertThat(value.asString()).isEqualTo("SIGN"); - value = store.getDetectionValues().get(1); - assertThat(value).isInstanceOf(Algorithm.class); - assertThat(value.asString()).isEqualTo("ECDSA"); - - store = getStoreOfValueType(CipherAction.class, store.getChildren()); - 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"); + IValue value0 = detectionStore.getDetectionValues().get(0); + assertThat(value0).isInstanceOf(Curve.class); + assertThat(value0.asString()).isEqualTo("SECP384R1"); + + DetectionStore store_1 = + getStoreOfValueType(SignatureAction.class, detectionStore.getChildren()); + assertThat(store_1.getDetectionValues()).hasSize(2); + assertThat(store_1.getDetectionValueContext()).isInstanceOf(SignatureContext.class); + IValue value0_1 = store_1.getDetectionValues().get(0); + assertThat(value0_1).isInstanceOf(SignatureAction.class); + assertThat(value0_1.asString()).isEqualTo("SIGN"); + + IValue value1_1 = store_1.getDetectionValues().get(1); + assertThat(value1_1).isInstanceOf(Algorithm.class); + assertThat(value1_1.asString()).isEqualTo("ECDSA"); /* * Translation */ - assertThat(nodes).hasSize(2); + assertThat(nodes).hasSize(1); // PrivateKey INode privateKeyNode = nodes.get(0); - assertThat(privateKeyNode).isInstanceOf(PrivateKey.class); - assertThat(privateKeyNode.getChildren()).hasSize(2); + assertThat(privateKeyNode.getKind()).isEqualTo(PrivateKey.class); + assertThat(privateKeyNode.getChildren()).hasSize(3); + assertThat(privateKeyNode.asString()).isEqualTo("EC-secp384r1"); // Signature under PrivateKey - INode privateKeySignatureNode = privateKeyNode.getChildren().get(Signature.class); - assertThat(privateKeySignatureNode).isNotNull(); - assertThat(privateKeySignatureNode.asString()).isEqualTo("ECDSA"); + INode signatureNode = privateKeyNode.getChildren().get(Signature.class); + assertThat(signatureNode).isNotNull(); + assertThat(signatureNode.getChildren()).hasSize(3); + assertThat(signatureNode.asString()).isEqualTo("ECDSA"); // MessageDigest under Signature under PrivateKey - INode privateKeyMessageDigestNode = - privateKeySignatureNode.getChildren().get(MessageDigest.class); - assertThat(privateKeyMessageDigestNode).isNotNull(); - assertThat(privateKeyMessageDigestNode.asString()).isEqualTo("SHA3-512"); - - // Sign under Signature under PrivateKey - INode signNode = privateKeySignatureNode.getChildren().get(Sign.class); + INode messageDigestNode = signatureNode.getChildren().get(MessageDigest.class); + assertThat(messageDigestNode).isNotNull(); + assertThat(messageDigestNode.getChildren()).hasSize(4); + assertThat(messageDigestNode.asString()).isEqualTo("SHA3-512"); + + // BlockSize under MessageDigest under Signature under PrivateKey + INode blockSizeNode = messageDigestNode.getChildren().get(BlockSize.class); + assertThat(blockSizeNode).isNotNull(); + assertThat(blockSizeNode.getChildren()).isEmpty(); + assertThat(blockSizeNode.asString()).isEqualTo("576"); + + // Oid under MessageDigest under Signature under PrivateKey + INode oidNode = messageDigestNode.getChildren().get(Oid.class); + assertThat(oidNode).isNotNull(); + assertThat(oidNode.getChildren()).isEmpty(); + assertThat(oidNode.asString()).isEqualTo("2.16.840.1.101.3.4.2.10"); + + // DigestSize under MessageDigest under Signature under PrivateKey + INode digestSizeNode = messageDigestNode.getChildren().get(DigestSize.class); + assertThat(digestSizeNode).isNotNull(); + assertThat(digestSizeNode.getChildren()).isEmpty(); + assertThat(digestSizeNode.asString()).isEqualTo("512"); + + // Digest under MessageDigest under Signature under PrivateKey + INode digestNode = messageDigestNode.getChildren().get(Digest.class); + assertThat(digestNode).isNotNull(); + assertThat(digestNode.getChildren()).isEmpty(); + assertThat(digestNode.asString()).isEqualTo("DIGEST"); + + // Oid under Signature under PrivateKey + INode oidNode1 = signatureNode.getChildren().get(Oid.class); + assertThat(oidNode1).isNotNull(); + assertThat(oidNode1.getChildren()).isEmpty(); + assertThat(oidNode1.asString()).isEqualTo("2.16.840.1.101.3.4.3.12"); + + // EllipticCurve under Signature under PrivateKey + INode ellipticCurveNode = signatureNode.getChildren().get(EllipticCurve.class); + assertThat(ellipticCurveNode).isNotNull(); + assertThat(ellipticCurveNode.getChildren()).isEmpty(); + assertThat(ellipticCurveNode.asString()).isEqualTo("secp384r1"); + + // Sign under PrivateKey + INode signNode = privateKeyNode.getChildren().get(Sign.class); assertThat(signNode).isNotNull(); + assertThat(signNode.getChildren()).isEmpty(); assertThat(signNode.asString()).isEqualTo("SIGN"); - // EllipticCurveAlgorithm under Signature under PrivateKey - INode privateKeyAlgorithmNode = - privateKeySignatureNode.getChildren().get(EllipticCurveAlgorithm.class); - assertThat(privateKeyAlgorithmNode).isNotNull(); - assertThat(privateKeyAlgorithmNode.asString()).isEqualTo("EC"); - - // EllipticCurve under EllipticCurveAlgorithm under Signature under PrivateKey - INode privateKeyCurveNode = privateKeyAlgorithmNode.getChildren().get(EllipticCurve.class); - assertThat(privateKeyCurveNode).isNotNull(); - assertThat(privateKeyCurveNode.asString()).isEqualTo("SECP384R1"); - - // PublicKey - INode publicKeyNode = nodes.get(1); - assertThat(publicKeyNode) - .isInstanceOfAny(PublicKey.class, Key.class); // Special case because of .deepCopy - assertThat(publicKeyNode.getChildren()).hasSize(1); - - // EllipticCurveAlgorithm under PublicKey - INode publicKeyAlgorithmNode = - publicKeyNode.getChildren().get(EllipticCurveAlgorithm.class); - assertThat(publicKeyAlgorithmNode).isNotNull(); - assertThat(publicKeyAlgorithmNode.asString()).isEqualTo("EC"); - - // KeyGeneration under EllipticCurveAlgorithm under PublicKey - INode publicKeyKeyGenerationNode = - publicKeyAlgorithmNode.getChildren().get(KeyGeneration.class); - assertThat(publicKeyKeyGenerationNode).isNotNull(); - assertThat(publicKeyKeyGenerationNode.asString()).isEqualTo("KEYGENERATION"); - - // EllipticCurve under EllipticCurveAlgorithm under PublicKey - INode publicKeyCurveNode = publicKeyAlgorithmNode.getChildren().get(EllipticCurve.class); - assertThat(publicKeyCurveNode).isNotNull(); - assertThat(publicKeyCurveNode.asString()).isEqualTo("SECP384R1"); + // KeyGeneration under PrivateKey + INode keyGenerationNode = privateKeyNode.getChildren().get(KeyGeneration.class); + assertThat(keyGenerationNode).isNotNull(); + assertThat(keyGenerationNode.getChildren()).isEmpty(); + assertThat(keyGenerationNode.asString()).isEqualTo("KEYGENERATION"); } } 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"); + } } } diff --git a/python/src/test/java/com/ibm/plugin/utils/GenerateAssertsHelper.java b/python/src/test/java/com/ibm/plugin/utils/GenerateAssertsHelper.java index d568e068..d4f92ac2 100644 --- a/python/src/test/java/com/ibm/plugin/utils/GenerateAssertsHelper.java +++ b/python/src/test/java/com/ibm/plugin/utils/GenerateAssertsHelper.java @@ -170,7 +170,7 @@ private static void generateDetectionStoreAssertions( writer.write( String.format( - "DetectionStore %s = getStoreOfValueType(%s.class, %s.getChildren());%n", + "DetectionStore %s = getStoreOfValueType(%s.class, %s.getChildren());%n", childrenStoreVarName, kind, detectionStoreVarName)); generateDetectionStoreAssertions(writer, store, childrenStoreVarName);