Skip to content

Commit

Permalink
Update CBOM generation (#138)
Browse files Browse the repository at this point in the history
* add keylength fix

Signed-off-by: Nicklas Körtge <nicklas.koertge1@ibm.com>

* add ciphersuite to cbom

Signed-off-by: Nicklas Körtge <nicklas.koertge1@ibm.com>

* update cipher sute tests

Signed-off-by: Nicklas Körtge <nicklas.koertge1@ibm.com>

* update cipher sute tests

Signed-off-by: Nicklas Körtge <nicklas.koertge1@ibm.com>

---------

Signed-off-by: Nicklas Körtge <nicklas.koertge1@ibm.com>
  • Loading branch information
n1ckl0sk0rtge authored Sep 6, 2024
1 parent e876ccc commit 8b7b37a
Show file tree
Hide file tree
Showing 10 changed files with 378 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.ibm.mapper.model.CipherSuite;
import com.ibm.mapper.model.INode;
import com.ibm.mapper.model.Identifier;
import com.ibm.mapper.model.MessageDigest;
import com.ibm.mapper.model.collections.AssetCollection;
import com.ibm.mapper.model.collections.IdentifierCollection;
import com.ibm.mapper.utils.DetectionLocation;
Expand All @@ -49,7 +50,7 @@ public Optional<? extends INode> parse(
Optional<JsonCipherSuite> possibleJsonCipherSuite = findCipherSuite(str);
if (possibleJsonCipherSuite.isEmpty()) {
// return a 'simple' cipher object
return Optional.empty(); // TODO
return Optional.of(new CipherSuite(str, detectionLocation));
}
final JsonCipherSuite jsonCipherSuite = possibleJsonCipherSuite.get();

Expand All @@ -64,16 +65,6 @@ public Optional<? extends INode> parse(
return keyExchangeAlgorithmMapper.parse(algoStr, detectionLocation);
})
.ifPresent(assets::add);
// authentication agreement
jsonCipherSuite
.getAuthAlgorithm()
.flatMap(
algoStr -> {
final AuthenticationAlgorithmMapper authenticationAlgorithmMapper =
new AuthenticationAlgorithmMapper();
return authenticationAlgorithmMapper.parse(algoStr, detectionLocation);
})
.ifPresent(assets::add);
// encryption algorithm
jsonCipherSuite
.getEncAlgorithm()
Expand All @@ -85,15 +76,30 @@ public Optional<? extends INode> parse(
})
.ifPresent(assets::add);
// hash algorithm
final Optional<MessageDigest> hash =
jsonCipherSuite
.getHashAlgorithm()
.flatMap(
algoStr -> {
final HashAlgorithmMapper hashAlgorithmMapper =
new HashAlgorithmMapper();
return hashAlgorithmMapper.parse(algoStr, detectionLocation);
});
// authentication agreement
jsonCipherSuite
.getHashAlgorithm()
.getAuthAlgorithm()
.flatMap(
algoStr -> {
final HashAlgorithmMapper hashAlgorithmMapper =
new HashAlgorithmMapper();
return hashAlgorithmMapper.parse(algoStr, detectionLocation);
final AuthenticationAlgorithmMapper authenticationAlgorithmMapper =
new AuthenticationAlgorithmMapper();
return authenticationAlgorithmMapper.parse(algoStr, detectionLocation);
})
.ifPresent(assets::add);
.ifPresentOrElse(
sign -> {
hash.ifPresent(sign::put);
assets.add(sign);
},
() -> hash.ifPresent(assets::add));

final CipherSuite cipherSuite =
new CipherSuite(
Expand Down
5 changes: 5 additions & 0 deletions mapper/src/main/java/com/ibm/mapper/model/algorithms/DSA.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,9 @@ public DSA(@NotNull DetectionLocation detectionLocation) {
super(NAME, Signature.class, detectionLocation);
this.put(new Oid("1.2.840.10040.4.1", detectionLocation));
}

public DSA(@NotNull MessageDigest messageDigest) {
this(messageDigest.getDetectionContext());
this.put(messageDigest);
}
}
4 changes: 2 additions & 2 deletions mapper/src/main/java/com/ibm/mapper/model/algorithms/RSA.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ public RSA(@NotNull DetectionLocation detectionLocation) {
this.put(new Oid(OID, detectionLocation));
}

public RSA(@Nonnull KeyLength keyLength, @Nonnull DetectionLocation detectionLocation) {
public RSA(int keyLength, @Nonnull DetectionLocation detectionLocation) {
super(NAME, PublicKeyEncryption.class, detectionLocation);
this.put(keyLength);
this.put(new KeyLength(keyLength, detectionLocation));
this.put(new Oid(OID, detectionLocation));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,14 @@ public Class<? extends INode> getKind() {

@NotNull @Override
public String asString() {
final StringBuilder sb = new StringBuilder();
for (K c : collection) {
sb.append(c.asString()).append(", ");
final StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < this.collection.size(); i++) {
sb.append(this.collection.get(i).asString());
if (i != this.collection.size() - 1) {
sb.append(", ");
}
}
return sb.toString();
return sb.append("]").toString();
}

@NotNull @Override
Expand Down
38 changes: 34 additions & 4 deletions output/src/main/java/com/ibm/output/cyclondx/CBOMOutputFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import com.ibm.mapper.model.Algorithm;
import com.ibm.mapper.model.BlockSize;
import com.ibm.mapper.model.CipherSuite;
import com.ibm.mapper.model.DigestSize;
import com.ibm.mapper.model.EllipticCurve;
import com.ibm.mapper.model.IAsset;
Expand Down Expand Up @@ -50,6 +51,7 @@
import com.ibm.mapper.model.functionality.Tag;
import com.ibm.mapper.model.functionality.Verify;
import com.ibm.mapper.model.padding.OAEP;
import com.ibm.mapper.model.protocol.TLS;
import com.ibm.mapper.utils.DetectionLocation;
import com.ibm.output.Constants;
import com.ibm.output.IOutputFile;
Expand Down Expand Up @@ -115,6 +117,8 @@ private void add(@Nullable final String parentBomRef, @Nonnull List<INode> nodes
createKeyComponent(parentBomRef, key);
} else if (node instanceof Protocol protocol) {
createProtocolComponent(parentBomRef, protocol);
} else if (node instanceof CipherSuite cipherSuite) {
createCipherSuiteComponent(parentBomRef, cipherSuite);
} else if (node instanceof SaltLength || node instanceof PasswordLength) {
final IProperty property = (IProperty) node;
createRelatedCryptoMaterialComponent(parentBomRef, property);
Expand All @@ -124,7 +128,8 @@ private void add(@Nullable final String parentBomRef, @Nonnull List<INode> nodes
});
}

private void createAlgorithmComponent(@Nullable String parentBomRef, @Nonnull Algorithm node) {
@Nullable private String createAlgorithmComponent(
@Nullable String parentBomRef, @Nonnull Algorithm node) {
Map<Class<? extends INode>, INode> children = node.getChildren();
Component algorithm =
AlgorithmComponentBuilder.create()
Expand Down Expand Up @@ -157,22 +162,29 @@ private void createAlgorithmComponent(@Nullable String parentBomRef, @Nonnull Al
.build();
final Optional<String> optionalId = getIdentifierFunction().apply(algorithm);
if (optionalId.isEmpty()) {
return;
return null;
}
addComponentAndDependencies(algorithm, optionalId.get(), parentBomRef, node);
return this.components.get(optionalId.get()).getBomRef();
}

private void createKeyComponent(@Nullable String parentBomRef, @Nonnull Key node) {
// if functionality nodes are placed under the key node,
// they will be moved under the corresponding primitive node
// they will be moved under the corresponding primitive node.
Utils.pushNodesDownToFirstMatch(node, IPrimitive.getKinds(), Functionality.getKinds());
// if a key length is defined under the key node, this function makes sure that the
// underlying primitive
// will get the same key length associated.
Utils.pushNodesDownToFirstMatch(
node, IPrimitive.getKinds(), List.of(KeyLength.class), false);

createRelatedCryptoMaterialComponent(parentBomRef, node);
}

private void createProtocolComponent(@Nullable String parentBomRef, @Nonnull Protocol node) {
Map<Class<? extends INode>, INode> children = node.getChildren();
Component protocol =
ProtocolComponentBuilder.create()
ProtocolComponentBuilder.create(this::createAlgorithmComponent)
.name(node)
.type(node)
.version(children.get(com.ibm.mapper.model.Version.class))
Expand All @@ -186,6 +198,24 @@ private void createProtocolComponent(@Nullable String parentBomRef, @Nonnull Pro
addComponentAndDependencies(protocol, optionalId.get(), parentBomRef, node);
}

private void createCipherSuiteComponent(
@Nullable String parentBomRef, @Nonnull CipherSuite node) {
final TLS tls = new TLS(node.getDetectionContext());
Component protocol =
ProtocolComponentBuilder.create(this::createAlgorithmComponent)
.name(tls)
.type(tls)
.version(null)
.cipherSuites(new CipherSuiteCollection(List.of(node)))
.occurrences(createOccurrenceForm(node.getDetectionContext()))
.build();
final Optional<String> optionalId = getIdentifierFunction().apply(protocol);
if (optionalId.isEmpty()) {
return;
}
addComponentAndDependencies(protocol, optionalId.get(), parentBomRef, node);
}

private void createRelatedCryptoMaterialComponent(
@Nullable String parentBomRef, @Nonnull INode node) {
Map<Class<? extends INode>, INode> children = node.getChildren();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@
*/
package com.ibm.output.cyclondx.builder;

import com.ibm.mapper.model.Algorithm;
import com.ibm.mapper.model.CipherSuite;
import com.ibm.mapper.model.INode;
import com.ibm.mapper.model.Identifier;
import com.ibm.mapper.model.Protocol;
import com.ibm.mapper.model.collections.CipherSuiteCollection;
import com.ibm.mapper.model.protocol.TLS;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.function.BiFunction;
import javax.annotation.Nonnull;
import org.cyclonedx.model.Component;
import org.cyclonedx.model.Evidence;
Expand All @@ -41,42 +45,51 @@ public class ProtocolComponentBuilder implements IProtocolComponentBuilder {
@Nonnull private final Component component;
@Nonnull private final CryptoProperties cryptoProperties;
@Nonnull private final ProtocolProperties protocolProperties;
@Nonnull private final BiFunction<String, Algorithm, String> algorithmComponentBuilder;

protected ProtocolComponentBuilder() {
protected ProtocolComponentBuilder(
@Nonnull BiFunction<String, Algorithm, String> algorithmComponentBuilder) {
this.component = new Component();
this.cryptoProperties = new CryptoProperties();
this.protocolProperties = new ProtocolProperties();
this.algorithmComponentBuilder = algorithmComponentBuilder;
}

private ProtocolComponentBuilder(
@Nonnull Component component,
@Nonnull CryptoProperties cryptoProperties,
@Nonnull ProtocolProperties protocolProperties) {
@Nonnull ProtocolProperties protocolProperties,
@Nonnull BiFunction<String, Algorithm, String> algorithmComponentBuilder) {
this.component = component;
this.cryptoProperties = cryptoProperties;
this.protocolProperties = protocolProperties;
this.algorithmComponentBuilder = algorithmComponentBuilder;
}

@Nonnull
public static IProtocolComponentBuilder create() {
return new ProtocolComponentBuilder();
public static IProtocolComponentBuilder create(
@Nonnull BiFunction<String, Algorithm, String> algorithmComponentBuilder) {
return new ProtocolComponentBuilder(algorithmComponentBuilder);
}

@NotNull @Override
public IProtocolComponentBuilder name(@Nullable Protocol name) {
if (name == null) {
return new ProtocolComponentBuilder(component, cryptoProperties, protocolProperties);
return new ProtocolComponentBuilder(
component, cryptoProperties, protocolProperties, algorithmComponentBuilder);
}

this.component.setName(name.asString());
return new ProtocolComponentBuilder(component, cryptoProperties, protocolProperties);
return new ProtocolComponentBuilder(
component, cryptoProperties, protocolProperties, algorithmComponentBuilder);
}

@NotNull @Override
public IProtocolComponentBuilder type(@Nullable Protocol type) {
if (type == null) {
protocolProperties.setType(ProtocolType.UNKNOWN);
return new ProtocolComponentBuilder(component, cryptoProperties, protocolProperties);
return new ProtocolComponentBuilder(
component, cryptoProperties, protocolProperties, algorithmComponentBuilder);
}

if (type instanceof TLS) {
Expand All @@ -85,46 +98,83 @@ public IProtocolComponentBuilder type(@Nullable Protocol type) {
protocolProperties.setType(ProtocolType.OTHER);
}

return new ProtocolComponentBuilder(component, cryptoProperties, protocolProperties);
return new ProtocolComponentBuilder(
component, cryptoProperties, protocolProperties, algorithmComponentBuilder);
}

@NotNull @Override
public IProtocolComponentBuilder version(@Nullable INode version) {
if (version == null) {
return new ProtocolComponentBuilder(component, cryptoProperties, protocolProperties);
return new ProtocolComponentBuilder(
component, cryptoProperties, protocolProperties, algorithmComponentBuilder);
}
protocolProperties.setVersion(version.asString());
return new ProtocolComponentBuilder(component, cryptoProperties, protocolProperties);
return new ProtocolComponentBuilder(
component, cryptoProperties, protocolProperties, algorithmComponentBuilder);
}

@NotNull @Override
public IProtocolComponentBuilder cipherSuites(@Nullable INode node) {
if (node == null) {
return new ProtocolComponentBuilder(component, cryptoProperties, protocolProperties);
return new ProtocolComponentBuilder(
component, cryptoProperties, protocolProperties, algorithmComponentBuilder);
}

if (node instanceof CipherSuiteCollection cipherSuiteCollection) {
List<org.cyclonedx.model.component.crypto.CipherSuite> suites = new ArrayList<>();
for (CipherSuite cipherSuite : cipherSuiteCollection.getCollection()) {
final org.cyclonedx.model.component.crypto.CipherSuite suite =
new org.cyclonedx.model.component.crypto.CipherSuite();
// name
suite.setName(cipherSuite.getName());
// algorithms
cipherSuite
.getAssetCollection()
.ifPresent(
assetCollection -> {
final List<String> algorithmRefs = new ArrayList<>();
for (final INode asset : assetCollection.getCollection()) {
if (asset instanceof Algorithm algorithm) {
final String ref =
this.algorithmComponentBuilder.apply(
"", algorithm);
algorithmRefs.add(ref);
}
}
suite.setAlgorithms(algorithmRefs);
});
// identifiers
cipherSuite
.getIdentifierCollection()
.ifPresent(
identifierCollection -> {
final List<String> identifiers = new ArrayList<>();
for (final Identifier identifier :
identifierCollection.getCollection()) {
identifiers.add(identifier.getValue());
}
suite.setIdentifiers(identifiers);
});
suites.add(suite);
}
protocolProperties.setCipherSuites(suites);
}

return new ProtocolComponentBuilder(component, cryptoProperties, protocolProperties);
return new ProtocolComponentBuilder(
component, cryptoProperties, protocolProperties, algorithmComponentBuilder);
}

@NotNull @Override
public IProtocolComponentBuilder occurrences(@Nullable Occurrence... occurrences) {
if (occurrences == null) {
return new ProtocolComponentBuilder(component, cryptoProperties, protocolProperties);
return new ProtocolComponentBuilder(
component, cryptoProperties, protocolProperties, algorithmComponentBuilder);
}
final Evidence evidence = new Evidence();
evidence.setOccurrences(List.of(occurrences));
this.component.setEvidence(evidence);
return new ProtocolComponentBuilder(component, cryptoProperties, protocolProperties);
return new ProtocolComponentBuilder(
component, cryptoProperties, protocolProperties, algorithmComponentBuilder);
}

@NotNull @Override
Expand Down
Loading

0 comments on commit 8b7b37a

Please sign in to comment.