Resolving OPC UA Duplicate Extensions Error on S7-1500

David Krause13 min read
OPC / OPC UASiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Summary

Engineers integrating a Java-based OPC UA client with the embedded OPC UA server of a Siemens SIMATIC S7-1500 CPU frequently encounter the runtime exception java.io.IOException: Duplicate extensions not allowed. The error is raised while the client stack is parsing the server's X.509 application certificate during the CreateSecureChannel phase of the OPC UA binary transport handshake. Although the S7-1500 server still answers and advertises its endpoints, no CreateSession request is ever issued, and the client terminates the connection with the OPC UA status code Bad_CertificateInvalid (0x80120000).

The same S7-1500 server is reachable without errors from .NET-based OPC UA clients (including the C# sample distributed with the Siemens OPC UA client toolkit) because the .NET X.509 parser is more permissive than the JDK parser. The asymmetry between stacks is the symptom that leads most teams to believe the Java client is at fault, when the real defect is on the server side: the PLC presents an X.509 certificate that contains more than one instance of a critical or non-critical extension, which is forbidden by the X.509 v3 specification.

Error Code and Stack Trace Anatomy

The exception is delivered to the application as a ServiceResultException with the standard OPC UA status code Bad_CertificateInvalid. The numeric identifier 0x80120000 maps to a 32-bit signed value of -2130706432 and an unsigned decimal representation of 2148663296, both of which appear in the description field of the status code depending on how the Java SDK formats the result.

A typical stack trace observed with the Prosys OPC UA Java SDK against an S7-1500 OPC UA server is reproduced below for reference:

Exception in thread "main" org.opcfoundation.ua.common.RuntimeServiceResultException:
  org.opcfoundation.ua.common.ServiceResultException:
    Bad_CertificateInvalid (code=0x80120000,
    description="2148663296, java.io.IOException: Duplicate extensions not allowed")
    at org.opcfoundation.ua.transport.TransportChannelSettings.getServerCertificate(TransportChannelSettings.java:114)
    at org.opcfoundation.ua.transport.tcp.io.TcpConnection.initialize(TcpConnection.java:376)
    at org.opcfoundation.ua.transport.tcp.io.SecureChannelTcp.initialize(SecureChannelTcp.java:273)
    at org.opcfoundation.ua.transport.tcp.io.SecureChannelTcp.initialize(SecureChannelTcp.java:246)
    at org.opcfoundation.ua.application.Client.createSecureChannel(Client.java:640)
    at org.opcfoundation.ua.application.Client.createSecureChannel(Client.java:555)
    at org.opcfoundation.ua.application.Client.createSessionChannel(Client.java:370)
    at org.opcfoundation.ua.application.Client.createSessionChannel(Client.java:345)
    at org.opcfoundation.ua.examples.SampleClient.main(SampleClient.java:109)
Caused by: java.security.cert.CertificateParsingException:
  java.io.IOException: Duplicate extensions not allowed
    at sun.security.x509.X509CertInfo.<init>(X509CertInfo.java:169)
    at sun.security.x509.X509CertImpl.parse(X509CertImpl.java:1804)
    at sun.security.x509.X509CertImpl.<init>(X509CertImpl.java:195)
    at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:102)
    at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:339)
    at org.opcfoundation.ua.utils.CertificateUtils.decodeX509Certificate(CertificateUtils.java:193)
    at org.opcfoundation.ua.transport.security.Cert.<init>(Cert.java:136)
Caused by: java.io.IOException: Duplicate extensions not allowed
    at sun.security.x509.CertificateExtensions.parseExtension(CertificateExtensions.java:115)
    at sun.security.x509.CertificateExtensions.init(CertificateExtensions.java:88)
    at sun.security.x509.CertificateExtensions.<init>(CertificateExtensions.java:78)
    at sun.security.x509.X509CertInfo.parse(X509CertInfo.java:702)
    at sun.security.x509.X509CertInfo.<init>(X509CertInfo.java:167)

The deepest cause is always CertificateExtensions.parseExtension throwing because it has located two extensions with the same Object Identifier (OID) in the certificate's TBSCertificate.extensions sequence.

Root Cause: X.509 v3 Extension Uniqueness Violation

The X.509 v3 certificate profile, defined in IETF RFC 5280 (which obsoletes RFC 3280), states in section 4.2:

"A certificate MUST NOT include more than one instance of a particular extension."

The Java Development Kit's built-in sun.security.x509 parser, used by java.security.cert.CertificateFactory, enforces this restriction strictly. When it encounters a certificate that violates the rule, the parser aborts with CertificateParsingException before the certificate is ever handed back to the OPC UA stack. Once parsing fails, the OPC UA security layer cannot construct a Cert object, cannot compare the certificate against the client trust list, and therefore cannot complete the secure channel.

The S7-1500 firmware versions affected by this defect ship an OPC UA server certificate that contains duplicated X.509 extensions - typically duplicate Basic Constraints, duplicate Subject Alternative Name, or duplicate Key Usage entries - depending on how TIA Portal generated and bundled the certificate at project compile time and how the firmware provisioned it at first boot.

Why .NET Works and Java Fails

The .NET System.Security.Cryptography.X509Certificates.X509Certificate2 parser silently merges or ignores duplicate extensions rather than throwing. The OPC UA .NET reference stack (and the Siemens-supplied C# sample client built on top of it) therefore never sees the duplicate. The Java stack, in contrast, follows the JCE/JCA specification strictly and throws on the second occurrence. This is not a Java bug - it is the Java parser correctly refusing to interpret an X.509 structure that violates RFC 5280.

Affected Siemens Products and Versions

Component Affected Versions Fixed Versions
TIA Portal (engineering framework generating the OPC UA server certificate) V15 and earlier V15.1 or later
S7-1500 CPU firmware (e.g. CPU 1511, 1512, 1515, 1516, 1517, 1518) Firmware < V2.5 for OPC UA, generally any firmware paired with TIA Portal V15 Firmware generated with TIA Portal V15.1 onward
ET 200SP CPU firmware Firmware bundled with TIA Portal V15 Firmware bundled with TIA Portal V15.1 onward
S7-1200 CPU firmware (V4.4 and later also expose OPC UA) Firmware < V4.4 or paired with TIA Portal V15 Firmware paired with TIA Portal V15.1 onward
Prosys OPC UA Java SDK (reference client) 3.0.x and 3.1.x confirmed to expose the issue because of strict JDK parsing Behavior unchanged - relies on certificate compliance to succeed
Java Runtime (server-side TLS fixes needed in parallel) Java 8 update 141 and earlier updates Java 8 update 172 (8u172) or later

The endpoint string returned by an affected CPU typically advertises:

ProductName = SIMATIC S7-1500 OPC UA
SoftwareVersion = V02.05.00

or earlier 02.0x.yy versions, depending on the GSD/UDT load.

Solution Overview

There are three independent layers that must be addressed for a permanent fix:

  1. Regenerate and reload the S7-1500 OPC UA server certificate using TIA Portal V15.1 (or later) and firmware that bundles a corrected OPC UA certificate profile.
  2. Update the Java Runtime on the client host to a level that incorporates the JDK SSL/TLS handshake fix (8u172 or later recommended).
  3. Install the Siemens root CA certificate into the client's Java trust store (cacerts) so that the OPC UA stack accepts the freshly generated server certificate.

Solution Step 1: Upgrade TIA Portal and CPU Firmware

Prerequisites

  • Administrative workstation running TIA Portal V15.1 or later (V16 or V17 are equally valid for new projects).
  • S7-1500 CPU with at least one free Ethernet port and current firmware image accessible on the engineering station.
  • Original STEP 7 project archive (.zap15 or later) that contains the OPC UA server configuration block.
  • Siemens Automation License Manager for any certificate-related license tokens.

Procedure

  1. Back up the S7-1500 project, including the OPC UA server interface settings block. Export the project archive from TIA Portal before any change.
  2. Install TIA Portal V15.1 (or later) on the engineering workstation. Do not uninstall V15 first - parallel install is supported.
  3. Open the project in V15.1 and accept the upgrade prompt. TIA Portal will re-issue and re-sign the OPC UA server certificate as part of the project migration.
  4. Update the CPU firmware to the matching image shipped with V15.1 or later. Use the online & diagnostics view, then "Update firmware". Power-cycle is not normally required for the CPU to pick up the new OPC UA certificate bundle.
  5. In the CPU properties, under "OPC UA" → "Server", re-validate the security policy. Common selections: None for diagnostic pilots, Basic128Rsa15, Basic256, or Basic256Sha256 for production. The certificate regenerated by V15.1 complies with RFC 5280 and contains a single instance of each extension.
  6. Download the hardware configuration and the software (including the regenerated OPC UA certificate) to the CPU. Perform a STOP → RUN transition only if the CPU requires it after firmware update.

Verification

Open a browser pointed at the OPC UA discovery URL opc.tcp://<cpu-ip>:4840 and verify the ProductName and SoftwareVersion parameters reflect the post-V15.1 firmware. Export the certificate from the PLC's web server (Security → Certificates) and inspect it locally:

openssl x509 -in plc-server.der -inform DER -text -noout

Confirm that each X.509v3 extension appears exactly once. The expected output for a fixed certificate lists every extension (Basic Constraints, Key Usage, Extended Key Usage, Subject Alternative Name) only one time in the X509v3 extensions section.

Solution Step 2: Update the Java Runtime

The original symptom (Duplicate extensions not allowed) is fixed by TIA Portal V15.1 alone. However, a separate class of TLS handshake issues can still surface between the Java client and the S7-1500 if the JDK is too old. Java 8 update 141, for example, is known to fail the TLS 1.2 handshake with the Siemens OPC UA endpoint because of incomplete cipher suite coverage. Upgrade the JRE or JDK on the client host to at least 8u172.

Procedure

  1. Verify the current Java version on the client host:
java -version
# openjdk version "1.8.0_172" Java(TM) SE Runtime Environment (build 1.8.0_172-b11)
  1. If the version is below 8u172, download the Java 8 update 172 (or later) runtime from the Oracle Java archive or use an OpenJDK distribution of equivalent date.
  2. Set JAVA_HOME and update the system PATH to point to the new installation.
  3. Rebuild the OPC UA client application against the new JDK to ensure no stale JCE provider is bundled into the deployment.

Solution Step 3: Install the Siemens Root Certificate in cacerts

The S7-1500 OPC UA server certificate issued by TIA Portal V15.1 is signed by a Siemens-internal root or by a project-specific sub-CA generated inside TIA Portal. To allow the Java client to trust the certificate, install the appropriate CA certificate into the Java trust store.

Locate the Trust Store

The default Java trust store on most installations is at:

$JAVA_HOME/lib/security/cacerts
$JAVA_HOME/jre/lib/security/cacerts        (legacy JRE layout)

The default password is changeit.

Procedure

  1. Export the OPC UA server certificate from TIA Portal: CPU properties → OPC UA → Server → Certificate → Export as DER.
  2. Copy the exported file (typically OPCUAServer.der) to the client host.
  3. Import it into cacerts:
keytool -importcert -alias siemens-s7-1500-opcua \
  -file OPCUAServer.der -keystore $JAVA_HOME/lib/security/cacerts \
  -storepass changeit
  1. Confirm the alias is present:
keytool -list -keystore $JAVA_HOME/lib/security/cacerts \
  -storepass changeit | grep siemens-s7-1500-opcua

If the S7-1500 server certificate is signed by an intermediate or root CA exported from TIA Portal, repeat the import for each CA in the chain. The Java trust store must contain every CA certificate that signs the server certificate, up to the trust anchor.

Verification

Once all three solution steps are complete, run the OPC UA Java sample client against the S7-1500 to confirm a clean session:

java -cp prosys-opc-ua-sdk-client.jar:prosys-opc-ua-sdk-core.jar:bcprov-jdk15on-1.60.jar \
  org.opcfoundation.ua.examples.SampleClient
# Endpoint: opc.tcp://192.168.0.10:4840
# Session activated. ServerProductName = SIMATIC S7-1500 OPC UA

Expected behavior:

  • No ServiceResultException with code 0x80120000.
  • The session activation message prints the S7-1500 server ProductName and SoftwareVersion.
  • Read, subscription, and monitored-item operations on UDTs (user-defined data types) and instance DBs return values without further certificate errors.

Alternative Workarounds (When an Upgrade Is Not Possible)

If the affected S7-1500 cannot be upgraded because of plant constraints (for example, validated production code freeze), the following workarounds reduce but do not eliminate the impact:

  • Switch the S7-1500 OPC UA server security policy to None temporarily for development. This avoids certificate verification but is not acceptable for production.
  • Use a Java OPC UA stack that uses Bouncy Castle as the certificate provider instead of the JDK's sun.security.x509 parser. Bouncy Castle is permissive on duplicate extensions and will load the certificate, though the resulting trust chain still requires manual acceptance. Add the Bouncy Castle provider before the JDK default provider in your Java application:
import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

static {
    Security.insertProviderAt(new BouncyCastleProvider(), 1);
}
  • Use a non-Java OPC UA client (for example, the Siemens-supplied .NET sample, or an OPC UA client built on Python asyncua) to extract the duplicate-extension certificate, then reissue it externally with OpenSSL so that duplicates are removed. The reissued certificate can be loaded back into TIA Portal as the project-specific OPC UA server certificate.

None of these workarounds is a long-term substitute for upgrading TIA Portal and the CPU firmware. The duplicate-extension defect is a server-side problem; the fix belongs on the server.

Related OPC UA Security Considerations

OPC UA Security Policy Signature Algorithm Minimum Java Requirement Notes
None None Java 7+ No certificate verification - diagnostic only
Basic128Rsa15 RSA-SHA1 (deprecated by OPC UA) Java 8u161+ with custom JCE Legacy - avoid in new deployments
Basic256 RSA-SHA256 Java 8u171+ Acceptable for closed production cells
Basic256Sha256 RSA-SHA256 Java 8u171+ Default choice for new S7-1500 projects
Aes128_Sha256_RsaOaep RSA-OAEP-SHA256 Java 8u252+ Preferred for new deployments
Aes256_Sha256_RsaPss RSA-PSS-SHA256 Java 11+ recommended Latest profile from OPC UA 1.04 specification

When using a security policy other than None, the Java client must trust the S7-1500's certificate chain. Java's trust manager will reject the connection if the cacerts store does not contain the issuing CA. The Bad_CertificateUntrusted (0x80120009) and Bad_CertificateChainIncomplete (0x8012000D) status codes are related but distinct from the Bad_CertificateInvalid (0x80120000) discussed here.

Diagnostic Decision Tree

Symptom Likely Cause Recommended Action
Duplicate extensions not allowed in CertificateExtensions.parseExtension Server X.509 certificate violates RFC 5280 §4.2 Upgrade TIA Portal to V15.1+, reload firmware and certificate
SSLHandshakeException: PKIX path building failed CA chain missing from cacerts Import Siemens root CA into cacerts
Bad_CertificateTimeInvalid (0x80120002) PLC or client clock out of sync Enable NTP on CPU and on client host
Bad_CertificateHostNameInvalid (0x80120004) ApplicationUri mismatch Match ApplicationUri in client configuration to the CPU's OPC UA discovery URL
Bad_SecurityChecksFailed (0x80120000 sub-codes) Security policy mismatch between client and server Align SecurityPolicy and SecurityMode on both sides

Operational Notes for Subscriptions on UDTs

After resolving the certificate issue, Java OPC UA clients typically move on to subscription-based polling of UDTs (structures) and instance DBs. A few field-proven tips for this next phase, drawn from the same case history:

  • Subscribe at the UDT boundary rather than at individual members - the S7-1500 will publish changes to the entire UDT, and the client can decode the structure by referencing the UDT type definition retrieved via Browse on the type hierarchy.
  • Use MonitoredItem with a sampling interval of 250 ms or 500 ms as a starting point; the S7-1500 supports publishing intervals down to 100 ms but the CPU's cyclic task must be able to keep up.
  • For arrays inside a UDT, retrieve the array length dynamically; the S7-1500 returns null-padded arrays if the request size exceeds the actual data length.
  • Ensure the Java SDK is configured with the same localeId as the PLC to avoid coercion errors on numeric values.

FAQ

What OPC UA status code triggers the "Duplicate extensions not allowed" IOException?

The error surfaces as Bad_CertificateInvalid (0x80120000). The Java stack first parses the S7-1500 server certificate and throws a CertificateParsingException wrapping the IOException before the OPC UA layer can convert it into a structured OPC UA result, so the description field carries the original Java exception text.

Which TIA Portal version fixed the duplicate X.509 extension defect in the S7-1500?

TIA Portal V15.1, released in 2018, reissues the OPC UA server certificate without duplicated extensions. The matching S7-1500 firmware image bundled with V15.1 (for example, V02.05.00 or later) must also be downloaded to the CPU so that the runtime uses the corrected certificate.

Why does the .NET sample client connect but the Java sample fails?

The .NET X509Certificate2 parser tolerates duplicate X.509v3 extensions by merging or ignoring them, whereas the Java sun.security.x509 parser strictly enforces RFC 5280 §4.2 and throws on the second occurrence. The Java stack is correct; the certificate is invalid.

Do I need to import the S7-1500 certificate into the Java cacerts trust store?

Yes. After upgrading TIA Portal and CPU firmware, export the OPC UA server certificate (and any intermediate CA) from TIA Portal and import it with keytool -importcert into $JAVA_HOME/lib/security/cacerts. Without the CA in the trust store, the client will fail with PKIX path building failed even though the duplicate-extension error is gone.

Which Java version should I run for the OPC UA Java client to a Siemens S7-1500?

Use Java 8 update 172 (8u172) or later to avoid a separate TLS handshake bug that affected earlier 8u141 builds. For new deployments that need the Aes256_Sha256_RsaPss security policy, use Java 11 or later because of stronger cipher suite support.

Can Bouncy Castle be used as a workaround for the duplicate-extension issue?

Yes. Registering BouncyCastleProvider at position 1 of the JCE provider list makes the OPC UA Java SDK parse certificates through BC instead of the JDK's strict parser. BC accepts the duplicate extensions, but the workaround is acceptable only for diagnostic or development environments - production deployments must still upgrade TIA Portal and CPU firmware.

How do I confirm that the S7-1500 server certificate is now RFC 5280 compliant?

Export the certificate from the PLC and run openssl x509 -in plc-server.der -inform DER -text -noout. Each X.509v3 extension (Basic Constraints, Key Usage, Extended Key Usage, Subject Alternative Name, Authority Information Access, Subject Key Identifier, and so on) must appear exactly once in the output.

Back to blog