diff --git a/src/main/java/de/rub/nds/x509attacker/x509/model/X509Utf8String.java b/src/main/java/de/rub/nds/x509attacker/x509/model/X509Utf8String.java new file mode 100644 index 0000000..80c4382 --- /dev/null +++ b/src/main/java/de/rub/nds/x509attacker/x509/model/X509Utf8String.java @@ -0,0 +1,65 @@ +/* + * X.509-Attacker - A Library for Arbitrary X.509 Certificates + * + * Copyright 2014-2023 Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License, Version 2.0 + * http://www.apache.org/licenses/LICENSE-2.0.txt + */ +package de.rub.nds.x509attacker.x509.model; + +import de.rub.nds.asn1.model.Asn1Utf8String; +import de.rub.nds.asn1.preparator.Asn1PreparatorHelper; +import de.rub.nds.x509attacker.chooser.X509Chooser; +import de.rub.nds.x509attacker.x509.handler.EmptyHandler; +import de.rub.nds.x509attacker.x509.handler.X509Handler; +import de.rub.nds.x509attacker.x509.parser.X509ComponentFieldParser; +import de.rub.nds.x509attacker.x509.parser.X509Parser; +import de.rub.nds.x509attacker.x509.preparator.X509Asn1FieldPreparator; +import de.rub.nds.x509attacker.x509.preparator.X509Preparator; +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlRootElement; +import java.io.BufferedInputStream; + +/** Wrapper for Asn1Utf8String to implement X509Component */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class X509Utf8String extends Asn1Utf8String implements X509Component { + + private X509Utf8String() { + super(null); + } + + public X509Utf8String(String identifier) { + super(identifier); + } + + @Override + public X509Handler getHandler(X509Chooser chooser) { + return new EmptyHandler<>(chooser, this); + } + + @Override + public X509Parser getParser(X509Chooser chooser) { + return new X509ComponentFieldParser(chooser, this) { + @Override + protected void parseContent(BufferedInputStream inputStream) { + // Content is already parsed in the parent class + } + }; + } + + @Override + public X509Preparator getPreparator(X509Chooser chooser) { + return new X509Asn1FieldPreparator(chooser, this) { + @Override + protected byte[] encodeContent() { + if (field.getValue() != null) { + Asn1PreparatorHelper.prepareField(field, field.getValue().getValue()); + } + return field.getContent().getOriginalValue(); + } + }; + } +} diff --git a/src/main/java/de/rub/nds/x509attacker/x509/preparator/AnotherNamePreparator.java b/src/main/java/de/rub/nds/x509attacker/x509/preparator/AnotherNamePreparator.java index 2fdbf13..431de4c 100644 --- a/src/main/java/de/rub/nds/x509attacker/x509/preparator/AnotherNamePreparator.java +++ b/src/main/java/de/rub/nds/x509attacker/x509/preparator/AnotherNamePreparator.java @@ -8,22 +8,64 @@ */ package de.rub.nds.x509attacker.x509.preparator; +import de.rub.nds.asn1.oid.ObjectIdentifier; +import de.rub.nds.asn1.preparator.Asn1PreparatorHelper; import de.rub.nds.x509attacker.chooser.X509Chooser; import de.rub.nds.x509attacker.x509.model.AnotherName; +import de.rub.nds.x509attacker.x509.model.X509Component; +import de.rub.nds.x509attacker.x509.model.X509Explicit; +import de.rub.nds.x509attacker.x509.model.X509Utf8String; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; public class AnotherNamePreparator extends X509ContainerPreparator { + private static final Logger LOGGER = LogManager.getLogger(); + public AnotherNamePreparator(X509Chooser chooser, AnotherName otherName) { super(chooser, otherName); } @Override public void prepareSubComponents() { - throw new UnsupportedOperationException("AnotherName not yet implemented for creation"); + // Prepare the type-id (OID) + // If the typeId already has a value, use it; otherwise use a default + ObjectIdentifier oid; + if (field.getTypeId().getValue() != null + && field.getTypeId().getValue().getValue() != null) { + oid = new ObjectIdentifier(field.getTypeId().getValue().getValue()); + } else { + // Default OID for testing - could be any valid OID + oid = new ObjectIdentifier("1.2.3.4"); + LOGGER.warn("AnotherName typeId not set, using default OID: 1.2.3.4"); + } + Asn1PreparatorHelper.prepareField(field.getTypeId(), oid); + + // Prepare the value based on the configured value + if (field.getConfiguredValue() != null) { + // For now, we support UTF8String as the inner value + // This can be extended to support other types based on the OID + X509Utf8String innerValue = new X509Utf8String("innerValue"); + innerValue.setValue(field.getConfiguredValue()); + + // Create a new explicit wrapper with the inner value + X509Explicit explicitValue = new X509Explicit<>("value", 0, innerValue); + field.setValue(explicitValue); + + // Prepare the explicit value using ExplicitPreparator + ExplicitPreparator explicitPreparator = + new ExplicitPreparator<>(chooser, field.getValue()); + explicitPreparator.prepare(); + } } @Override public byte[] encodeChildrenContent() { - throw new UnsupportedOperationException("Unimplemented method 'encodeChildren'"); + if (field.getValue() != null && field.getValue().getInnerField() != null) { + return encodeChildren(field.getTypeId(), field.getValue()); + } else { + // Only encode type-id if no value is set + return encodeChildren(field.getTypeId()); + } } } diff --git a/src/test/java/de/rub/nds/x509attacker/x509/preparator/AnotherNamePreparatorTest.java b/src/test/java/de/rub/nds/x509attacker/x509/preparator/AnotherNamePreparatorTest.java new file mode 100644 index 0000000..e988198 --- /dev/null +++ b/src/test/java/de/rub/nds/x509attacker/x509/preparator/AnotherNamePreparatorTest.java @@ -0,0 +1,94 @@ +/* + * X.509-Attacker - A Library for Arbitrary X.509 Certificates + * + * Copyright 2014-2023 Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License, Version 2.0 + * http://www.apache.org/licenses/LICENSE-2.0.txt + */ +package de.rub.nds.x509attacker.x509.preparator; + +import de.rub.nds.x509attacker.chooser.X509Chooser; +import de.rub.nds.x509attacker.context.X509Context; +import de.rub.nds.x509attacker.x509.model.AnotherName; +import de.rub.nds.x509attacker.x509.model.X509Component; +import de.rub.nds.x509attacker.x509.model.X509Explicit; +import de.rub.nds.x509attacker.x509.model.X509Utf8String; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class AnotherNamePreparatorTest { + + private X509Context context; + private X509Chooser chooser; + + @BeforeEach + public void setUp() { + context = new X509Context(); + chooser = context.getChooser(); + } + + @Test + public void testPrepareWithConfiguredValue() { + // Create AnotherName with configured value + AnotherName anotherName = new AnotherName("anotherName"); + anotherName.setConfiguredValue("test value"); + + // Set OID + anotherName.getTypeId().setValue("1.2.3.4.5"); + + // Prepare + AnotherNamePreparator preparator = new AnotherNamePreparator(chooser, anotherName); + preparator.prepare(); + + // Verify type-id is prepared + Assertions.assertNotNull(anotherName.getTypeId().getValue()); + Assertions.assertEquals("1.2.3.4.5", anotherName.getTypeId().getValue().getValue()); + + // Verify value is prepared + Assertions.assertNotNull(anotherName.getValue()); + X509Explicit explicitValue = anotherName.getValue(); + Assertions.assertNotNull(explicitValue.getInnerField()); + Assertions.assertTrue(explicitValue.getInnerField() instanceof X509Utf8String); + + // Verify content + X509Utf8String innerValue = (X509Utf8String) explicitValue.getInnerField(); + Assertions.assertEquals("test value", innerValue.getValue().getValue()); + } + + @Test + public void testPrepareWithoutConfiguredValue() { + // Create AnotherName without configured value + AnotherName anotherName = new AnotherName("anotherName"); + + // Prepare + AnotherNamePreparator preparator = new AnotherNamePreparator(chooser, anotherName); + preparator.prepare(); + + // Verify type-id is prepared with default + Assertions.assertNotNull(anotherName.getTypeId().getValue()); + Assertions.assertEquals("1.2.3.4", anotherName.getTypeId().getValue().getValue()); + + // Verify value remains null + Assertions.assertNotNull(anotherName.getValue()); + Assertions.assertNull(anotherName.getValue().getInnerField()); + } + + @Test + public void testEncodingWithConfiguredValue() { + // Create AnotherName with configured value + AnotherName anotherName = new AnotherName("anotherName"); + anotherName.setConfiguredValue("encoded test"); + anotherName.getTypeId().setValue("2.5.4.3"); + + // Prepare + AnotherNamePreparator preparator = new AnotherNamePreparator(chooser, anotherName); + preparator.prepare(); + + // Test encoding + byte[] encoded = anotherName.getSerializer(chooser).serialize(); + Assertions.assertNotNull(encoded); + Assertions.assertTrue(encoded.length > 0); + } +}