Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update CBOM generation #138

Merged
merged 4 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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);
}
}
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
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
Loading