diff --git a/java/src/main/java/com/ibm/plugin/rules/detection/bc/encapsulatedsecret/BcEncapsulatedSecretExtractor.java b/java/src/main/java/com/ibm/plugin/rules/detection/bc/encapsulatedsecret/BcEncapsulatedSecretExtractor.java index 4c7da405..dab1cb8f 100644 --- a/java/src/main/java/com/ibm/plugin/rules/detection/bc/encapsulatedsecret/BcEncapsulatedSecretExtractor.java +++ b/java/src/main/java/com/ibm/plugin/rules/detection/bc/encapsulatedsecret/BcEncapsulatedSecretExtractor.java @@ -42,7 +42,7 @@ private BcEncapsulatedSecretExtractor() { // nothing } - /* TODO: maybe the function `extractSecret` would be a better entry point than the constructors? */ + /* TODO: capture the `AsymmetricKeyParameter` argument in most contructors */ private static BouncyCastleInfoMap infoMap = new BouncyCastleInfoMap(); diff --git a/java/src/main/java/com/ibm/plugin/rules/detection/bc/encapsulatedsecret/BcEncapsulatedSecretGenerator.java b/java/src/main/java/com/ibm/plugin/rules/detection/bc/encapsulatedsecret/BcEncapsulatedSecretGenerator.java index fced2fe5..652984df 100644 --- a/java/src/main/java/com/ibm/plugin/rules/detection/bc/encapsulatedsecret/BcEncapsulatedSecretGenerator.java +++ b/java/src/main/java/com/ibm/plugin/rules/detection/bc/encapsulatedsecret/BcEncapsulatedSecretGenerator.java @@ -42,7 +42,7 @@ private BcEncapsulatedSecretGenerator() { // nothing } - /* TODO: maybe the function `generateEncapsulated` would be a better entry point than the constructors? */ + /* TODO: capture `generateEncapsulated` to obtain information from `AsymmetricKeyParameter` */ private static BouncyCastleInfoMap infoMap = new BouncyCastleInfoMap(); diff --git a/java/src/main/java/com/ibm/plugin/translation/translator/contexts/JavaCipherContextTranslator.java b/java/src/main/java/com/ibm/plugin/translation/translator/contexts/JavaCipherContextTranslator.java index 58c73dbb..56ca7fe5 100644 --- a/java/src/main/java/com/ibm/plugin/translation/translator/contexts/JavaCipherContextTranslator.java +++ b/java/src/main/java/com/ibm/plugin/translation/translator/contexts/JavaCipherContextTranslator.java @@ -130,9 +130,8 @@ public final class JavaCipherContextTranslator extends JavaAbstractLibraryTransl .parse(valueAction.asString(), detectionLocation) .map(f -> f); case ASYMMETRIC_CIPHER_ENGINE, ASYMMETRIC_CIPHER_ENGINE_SIGNATURE: - /* TODO: the Signature distinction (and therefore the asKind parameter of the mapper) does not seem necessary */ BcAsymCipherEngineMapper bcAsymCipherEngineMapper = - new BcAsymCipherEngineMapper(PublicKeyEncryption.class); + new BcAsymCipherEngineMapper(); return bcAsymCipherEngineMapper .parse(valueAction.asString(), detectionLocation) .map(f -> f); diff --git a/mapper/src/main/java/com/ibm/mapper/mapper/bc/BcAsymCipherEngineMapper.java b/mapper/src/main/java/com/ibm/mapper/mapper/bc/BcAsymCipherEngineMapper.java index 8a1b53dc..acb70d95 100644 --- a/mapper/src/main/java/com/ibm/mapper/mapper/bc/BcAsymCipherEngineMapper.java +++ b/mapper/src/main/java/com/ibm/mapper/mapper/bc/BcAsymCipherEngineMapper.java @@ -21,10 +21,8 @@ import com.ibm.mapper.mapper.IMapper; import com.ibm.mapper.model.Algorithm; -import com.ibm.mapper.model.BlockCipher; -import com.ibm.mapper.model.IAlgorithm; import com.ibm.mapper.model.INode; -import com.ibm.mapper.model.IPrimitive; +import com.ibm.mapper.model.PublicKeyEncryption; import com.ibm.mapper.model.Unknown; import com.ibm.mapper.model.algorithms.ElGamal; import com.ibm.mapper.model.algorithms.NaccacheStern; @@ -37,12 +35,6 @@ public class BcAsymCipherEngineMapper implements IMapper { - private final Class asKind; - - public BcAsymCipherEngineMapper(Class asKind) { - this.asKind = asKind; - } - @Override @Nonnull public Optional parse( @@ -50,12 +42,7 @@ public Optional parse( if (str == null) { return Optional.empty(); } - Optional node = map(str, detectionLocation); - if (node.isPresent()) { - // TODO: Change this to not use the `new Algorithm` hack to change the kind - return Optional.of(new Algorithm((IAlgorithm) node.get(), asKind)); - } - return Optional.empty(); + return map(str, detectionLocation); } @Nonnull @@ -70,7 +57,7 @@ private Optional map( case "RSAEngine" -> Optional.of(new RSA(detectionLocation)); default -> { final Algorithm algorithm = - new Algorithm(cipherString, BlockCipher.class, detectionLocation); + new Algorithm(cipherString, PublicKeyEncryption.class, detectionLocation); algorithm.put(new Unknown(detectionLocation)); yield Optional.of(algorithm); } diff --git a/mapper/src/main/java/com/ibm/mapper/mapper/bc/BcKemMapper.java b/mapper/src/main/java/com/ibm/mapper/mapper/bc/BcKemMapper.java index f435949c..5cbdde7b 100644 --- a/mapper/src/main/java/com/ibm/mapper/mapper/bc/BcKemMapper.java +++ b/mapper/src/main/java/com/ibm/mapper/mapper/bc/BcKemMapper.java @@ -29,9 +29,9 @@ import com.ibm.mapper.model.algorithms.ECIES; import com.ibm.mapper.model.algorithms.FrodoKEM; import com.ibm.mapper.model.algorithms.HQC; -import com.ibm.mapper.model.algorithms.MLKEM; import com.ibm.mapper.model.algorithms.RSAKEM; import com.ibm.mapper.model.algorithms.SABER; +import com.ibm.mapper.model.algorithms.kyber.Kyber; import com.ibm.mapper.model.algorithms.ntru.NTRU; import com.ibm.mapper.model.algorithms.ntru.NTRULPrime; import com.ibm.mapper.model.algorithms.ntru.StreamlinedNTRUPrime; @@ -66,7 +66,7 @@ private Optional map( case "HQCKEMExtractor", "HQCKEMGenerator" -> Optional.of(new HQC(KeyEncapsulationMechanism.class, detectionLocation)); case "KyberKEMExtractor", "KyberKEMGenerator" -> - Optional.of(new MLKEM(detectionLocation)); + Optional.of(new Kyber(detectionLocation)); case "NTRUKEMExtractor", "NTRUKEMGenerator" -> Optional.of(new NTRU(detectionLocation)); case "NTRULPRimeKEMExtractor", "NTRULPRimeKEMGenerator" -> Optional.of(new NTRULPrime(detectionLocation)); diff --git a/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaDigestMapper.java b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaDigestMapper.java index 7672aa46..a3dd3e76 100644 --- a/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaDigestMapper.java +++ b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaDigestMapper.java @@ -57,7 +57,8 @@ public final class PycaDigestMapper implements IMapper { case "SHA3_256" -> Optional.of(new SHA3(256, detectionLocation)); case "SHA3_384" -> Optional.of(new SHA3(384, detectionLocation)); case "SHA3_512" -> Optional.of(new SHA3(512, detectionLocation)); - case "SHAKE128", "SHAKE256" -> Optional.of(new SHAKE(detectionLocation)); + case "SHAKE128" -> Optional.of(new SHAKE(128, detectionLocation)); + case "SHAKE256" -> Optional.of(new SHAKE(256, detectionLocation)); case "MD5" -> Optional.of(new MD5(detectionLocation)); case "BLAKE2B" -> Optional.of(new BLAKE2b(false, detectionLocation)); case "BLAKE2S" -> Optional.of(new BLAKE2s(false, 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 index bb1051b2..3efd4324 100644 --- a/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaHashBasedKeyDerivationMapper.java +++ b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaHashBasedKeyDerivationMapper.java @@ -96,9 +96,16 @@ public final class PycaHashBasedKeyDerivationMapper implements IMapper { Optional.of( new SHA3( KeyDerivationFunction.class, new SHA3(512, detectionLocation))); - case "SHAKE128", "SHAKE256" -> + case "SHAKE128" -> Optional.of( - new SHAKE(KeyDerivationFunction.class, new SHAKE(detectionLocation))); + 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.of( diff --git a/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaMacMapper.java b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaMacMapper.java index b53befb8..a9d8b1d6 100644 --- a/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaMacMapper.java +++ b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaMacMapper.java @@ -99,8 +99,8 @@ public class PycaMacMapper implements IMapper { case "SHA3_256" -> Optional.of(new SHA3(Mac.class, new SHA3(256, detectionLocation))); case "SHA3_384" -> Optional.of(new SHA3(Mac.class, new SHA3(384, detectionLocation))); case "SHA3_512" -> Optional.of(new SHA3(Mac.class, new SHA3(512, detectionLocation))); - case "SHAKE128", "SHAKE256" -> - Optional.of(new SHAKE(Mac.class, new SHAKE(detectionLocation))); + case "SHAKE128" -> Optional.of(new SHAKE(Mac.class, new SHAKE(128, detectionLocation))); + case "SHAKE256" -> Optional.of(new SHAKE(Mac.class, new SHAKE(256, detectionLocation))); case "MD5" -> Optional.of(new MD5(Mac.class, detectionLocation)); case "BLAKE2B" -> Optional.of(new BLAKE2b(Mac.class, new BLAKE2b(false, detectionLocation))); diff --git a/mapper/src/main/java/com/ibm/mapper/model/algorithms/Ed448.java b/mapper/src/main/java/com/ibm/mapper/model/algorithms/Ed448.java index 774800ba..2667d6cd 100644 --- a/mapper/src/main/java/com/ibm/mapper/model/algorithms/Ed448.java +++ b/mapper/src/main/java/com/ibm/mapper/model/algorithms/Ed448.java @@ -31,7 +31,7 @@ public final class Ed448 extends EdDSA implements Signature { public Ed448(@NotNull DetectionLocation detectionLocation) { super(NAME, detectionLocation); this.put(new Edwards448(detectionLocation)); - this.put(new SHAKE(detectionLocation)); + this.put(new SHAKE(256, detectionLocation)); this.put(new Oid("1.3.101.113", detectionLocation)); } } diff --git a/mapper/src/main/java/com/ibm/mapper/model/algorithms/ElGamal.java b/mapper/src/main/java/com/ibm/mapper/model/algorithms/ElGamal.java index 33122b87..a7249884 100644 --- a/mapper/src/main/java/com/ibm/mapper/model/algorithms/ElGamal.java +++ b/mapper/src/main/java/com/ibm/mapper/model/algorithms/ElGamal.java @@ -20,21 +20,21 @@ package com.ibm.mapper.model.algorithms; import com.ibm.mapper.model.Algorithm; -import com.ibm.mapper.model.BlockCipher; import com.ibm.mapper.model.IPrimitive; import com.ibm.mapper.model.KeyLength; +import com.ibm.mapper.model.PublicKeyEncryption; import com.ibm.mapper.model.Signature; import com.ibm.mapper.utils.DetectionLocation; import javax.annotation.Nonnull; -public final class ElGamal extends Algorithm implements BlockCipher, Signature { +public final class ElGamal extends Algorithm implements PublicKeyEncryption, Signature { // https://en.wikipedia.org/wiki/ElGamal_encryption // https://en.wikipedia.org/wiki/ElGamal_signature_scheme private static final String NAME = "ElGamal"; public ElGamal(@Nonnull DetectionLocation detectionLocation) { - super(NAME, BlockCipher.class, detectionLocation); + super(NAME, PublicKeyEncryption.class, detectionLocation); } public ElGamal(int keyLength, @Nonnull DetectionLocation detectionLocation) { diff --git a/mapper/src/main/java/com/ibm/mapper/model/algorithms/NaccacheStern.java b/mapper/src/main/java/com/ibm/mapper/model/algorithms/NaccacheStern.java index 44624d2b..54b0b76e 100644 --- a/mapper/src/main/java/com/ibm/mapper/model/algorithms/NaccacheStern.java +++ b/mapper/src/main/java/com/ibm/mapper/model/algorithms/NaccacheStern.java @@ -20,19 +20,19 @@ package com.ibm.mapper.model.algorithms; import com.ibm.mapper.model.Algorithm; -import com.ibm.mapper.model.BlockCipher; import com.ibm.mapper.model.IPrimitive; import com.ibm.mapper.model.KeyLength; +import com.ibm.mapper.model.PublicKeyEncryption; import com.ibm.mapper.utils.DetectionLocation; import javax.annotation.Nonnull; -public final class NaccacheStern extends Algorithm implements BlockCipher { +public final class NaccacheStern extends Algorithm implements PublicKeyEncryption { // https://en.wikipedia.org/wiki/Naccache–Stern_cryptosystem private static final String NAME = "Naccache-Stern"; public NaccacheStern(@Nonnull DetectionLocation detectionLocation) { - super(NAME, BlockCipher.class, detectionLocation); + super(NAME, PublicKeyEncryption.class, detectionLocation); } public NaccacheStern(int keyLength, @Nonnull DetectionLocation detectionLocation) { diff --git a/mapper/src/main/java/com/ibm/mapper/model/algorithms/SHAKE.java b/mapper/src/main/java/com/ibm/mapper/model/algorithms/SHAKE.java index 65fce11a..670d3f1a 100644 --- a/mapper/src/main/java/com/ibm/mapper/model/algorithms/SHAKE.java +++ b/mapper/src/main/java/com/ibm/mapper/model/algorithms/SHAKE.java @@ -21,8 +21,11 @@ import com.ibm.mapper.model.Algorithm; import com.ibm.mapper.model.ExtendableOutputFunction; +import com.ibm.mapper.model.INode; import com.ibm.mapper.model.IPrimitive; +import com.ibm.mapper.model.ParameterSetIdentifier; import com.ibm.mapper.utils.DetectionLocation; +import java.util.Optional; import javax.annotation.Nonnull; public final class SHAKE extends Algorithm implements ExtendableOutputFunction { @@ -32,6 +35,28 @@ public SHAKE(@Nonnull DetectionLocation detectionLocation) { super(NAME, ExtendableOutputFunction.class, detectionLocation); } + /** Returns a name of the form "SHAKEXXX" where XXX is the parameter set identifer */ + @Override + @Nonnull + public String getName() { + StringBuilder builtName = new StringBuilder(this.name); + + Optional parameterSetIdentifier = this.hasChildOfType(ParameterSetIdentifier.class); + + if (parameterSetIdentifier.isPresent()) { + builtName.append(parameterSetIdentifier.get().asString()); + } + + return builtName.toString(); + } + + public SHAKE(int parameterSetIdentifier, @Nonnull DetectionLocation detectionLocation) { + this(detectionLocation); + this.put( + new ParameterSetIdentifier( + String.valueOf(parameterSetIdentifier), detectionLocation)); + } + public SHAKE(@Nonnull final Class asKind, @Nonnull SHAKE shake) { super(shake, asKind); } diff --git a/mapper/src/main/java/com/ibm/mapper/model/algorithms/kyber/Kyber.java b/mapper/src/main/java/com/ibm/mapper/model/algorithms/kyber/Kyber.java new file mode 100644 index 00000000..a5dc5542 --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/model/algorithms/kyber/Kyber.java @@ -0,0 +1,83 @@ +/* + * 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.algorithms.kyber; + +import com.ibm.mapper.model.Algorithm; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.KeyEncapsulationMechanism; +import com.ibm.mapper.model.ParameterSetIdentifier; +import com.ibm.mapper.model.Version; +import com.ibm.mapper.utils.DetectionLocation; +import java.util.Optional; +import javax.annotation.Nonnull; + +public class Kyber extends Algorithm implements KeyEncapsulationMechanism { + // https://pq-crystals.org/kyber/resources.shtml (details the multiple versions) + // https://en.wikipedia.org/wiki/Kyber + + private static final String NAME = "Kyber"; // this is *not* ML-KEM + + /** + * Returns a name of the form "Kyber-XXX (version YYY)" where XXX is the parameter set identifer + * and YYY the submission version + */ + @Override + @Nonnull + public String getName() { + StringBuilder builtName = new StringBuilder(this.name); + + Optional parameterSetIdentifier = this.hasChildOfType(ParameterSetIdentifier.class); + Optional version = this.hasChildOfType(Version.class); + + if (parameterSetIdentifier.isPresent()) { + builtName.append("-").append(parameterSetIdentifier.get().asString()); + } + if (version.isPresent()) { + builtName.append(" (version ").append(version.get().asString()).append(")"); + } + + return builtName.toString(); + } + + public Kyber(@Nonnull DetectionLocation detectionLocation) { + super(NAME, KeyEncapsulationMechanism.class, detectionLocation); + } + + public Kyber(int parameterSetIdentifier, @Nonnull DetectionLocation detectionLocation) { + this(detectionLocation); + this.put( + new ParameterSetIdentifier( + String.valueOf(parameterSetIdentifier), detectionLocation)); + } + + public Kyber( + @Nonnull String submissionVersionNumber, @Nonnull DetectionLocation detectionLocation) { + this(detectionLocation); + this.put(new Version(submissionVersionNumber, detectionLocation)); + } + + public Kyber( + int parameterSetIdentifier, + @Nonnull String submissionVersionNumber, + @Nonnull DetectionLocation detectionLocation) { + this(parameterSetIdentifier, detectionLocation); + this.put(new Version(submissionVersionNumber, detectionLocation)); + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/model/algorithms/MLKEM.java b/mapper/src/main/java/com/ibm/mapper/model/algorithms/kyber/MLKEM.java similarity index 52% rename from mapper/src/main/java/com/ibm/mapper/model/algorithms/MLKEM.java rename to mapper/src/main/java/com/ibm/mapper/model/algorithms/kyber/MLKEM.java index c861b133..897261bd 100644 --- a/mapper/src/main/java/com/ibm/mapper/model/algorithms/MLKEM.java +++ b/mapper/src/main/java/com/ibm/mapper/model/algorithms/kyber/MLKEM.java @@ -17,21 +17,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.mapper.model.algorithms; +package com.ibm.mapper.model.algorithms.kyber; import com.ibm.mapper.model.Algorithm; +import com.ibm.mapper.model.INode; import com.ibm.mapper.model.KeyEncapsulationMechanism; +import com.ibm.mapper.model.ParameterSetIdentifier; import com.ibm.mapper.utils.DetectionLocation; +import java.util.Optional; import javax.annotation.Nonnull; public class MLKEM extends Algorithm implements KeyEncapsulationMechanism { - // https://en.wikipedia.org/wiki/Kyber - // https://pq-crystals.org/kyber/ + // https://csrc.nist.gov/pubs/fips/203/final + // This is the standardized version of Kyber - private static final String NAME = - "ML-KEM"; // Kyber, Module-Lattice-Based Key-Encapsulation Mechanism + private static final String NAME = "ML-KEM"; // Module-Lattice-Based Key-Encapsulation Mechanism + + /** Returns a name of the form "ML-KEM-XXX" where XXX is the parameter set identifer */ + @Override + @Nonnull + public String getName() { + StringBuilder builtName = new StringBuilder(this.name); + + Optional parameterSetIdentifier = this.hasChildOfType(ParameterSetIdentifier.class); + + if (parameterSetIdentifier.isPresent()) { + builtName.append("-").append(parameterSetIdentifier.get().asString()); + } + + return builtName.toString(); + } public MLKEM(@Nonnull DetectionLocation detectionLocation) { super(NAME, KeyEncapsulationMechanism.class, detectionLocation); } + + public MLKEM(int parameterSetIdentifier, @Nonnull DetectionLocation detectionLocation) { + this(detectionLocation); + this.put( + new ParameterSetIdentifier( + String.valueOf(parameterSetIdentifier), detectionLocation)); + } } diff --git a/mapper/src/main/java/com/ibm/mapper/model/algorithms/ntru/NTRUEncrypt.java b/mapper/src/main/java/com/ibm/mapper/model/algorithms/ntru/NTRUEncrypt.java index ec6f77f3..26ebce48 100644 --- a/mapper/src/main/java/com/ibm/mapper/model/algorithms/ntru/NTRUEncrypt.java +++ b/mapper/src/main/java/com/ibm/mapper/model/algorithms/ntru/NTRUEncrypt.java @@ -20,19 +20,19 @@ package com.ibm.mapper.model.algorithms.ntru; import com.ibm.mapper.model.Algorithm; -import com.ibm.mapper.model.BlockCipher; import com.ibm.mapper.model.IPrimitive; import com.ibm.mapper.model.KeyLength; +import com.ibm.mapper.model.PublicKeyEncryption; import com.ibm.mapper.utils.DetectionLocation; import javax.annotation.Nonnull; -public final class NTRUEncrypt extends Algorithm implements BlockCipher { +public final class NTRUEncrypt extends Algorithm implements PublicKeyEncryption { // https://en.wikipedia.org/wiki/NTRU private static final String NAME = "NTRUEncrypt"; public NTRUEncrypt(@Nonnull DetectionLocation detectionLocation) { - super(NAME, BlockCipher.class, detectionLocation); + super(NAME, PublicKeyEncryption.class, detectionLocation); } public NTRUEncrypt(int keyLength, @Nonnull DetectionLocation detectionLocation) {