JDK-8028431 : NullPointerException in DerValue.equals(DerValue)
  • Type: Bug
  • Component: security-libs
  • Sub-Component: java.security
  • Affected Version: 7,8
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2013-11-15
  • Updated: 2020-07-28
  • Resolved: 2014-01-22
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8 JDK 9 Other
7u271Fixed 8u261Fixed 9 b03Fixed openjdk7uFixed
Description
sun.security.util.DerValue.equals(DerValue) method does not check that null is passed. As a result, NullPointerException can occur.
Comments
Fix request (8u) I'd like to request an approval for a 8u backport so we have parity between different JDKs. Risk for this patch is minimal. It applied almost cleanly except for a copyright date. Review approval here: https://mail.openjdk.java.net/pipermail/jdk8u-dev/2020-April/011574.html
17-04-2020

The problem was found during fuzz testing. The following application was used: import java.io.FileInputStream; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; public class X509CertificateLoad { /** * Load a X509 certificate from file. */ public static void main(String[] args) throws Exception { FileInputStream fis = new FileInputStream(args[0]); CertificateFactory cf = CertificateFactory.getInstance("X509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(fis); System.out.println("SUCCESS"); } } It just loads x509 certificate from file that is fuzzed. Please see attached test. The test fails with the following output: x509: Error parsing extension: ObjectId: 1.3.6.1.5.5.7.1.1 Criticality=false java.io.IOException: insufficient data at sun.security.util.DerInputBuffer.truncate(DerInputBuffer.java:125) at sun.security.util.DerValue.<init>(DerValue.java:279) at sun.security.util.DerInputStream.getDerValue(DerInputStream.java:417) at sun.security.x509.AccessDescription.<init>(AccessDescription.java:65) at sun.security.x509.AuthorityInfoAccessExtension.<init>(AuthorityInfoAccessExtension.java:127) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:525) at sun.security.x509.CertificateExtensions.parseExtension(CertificateExtensions.java:111) at sun.security.x509.CertificateExtensions.init(CertificateExtensions.java:87) at sun.security.x509.CertificateExtensions.<init>(CertificateExtensions.java:77) at sun.security.x509.X509CertInfo.parse(X509CertInfo.java:740) at sun.security.x509.X509CertInfo.<init>(X509CertInfo.java:169) at sun.security.x509.X509CertImpl.parse(X509CertImpl.java:1747) at sun.security.x509.X509CertImpl.<init>(X509CertImpl.java:196) at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:97) at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:339) at X509CertificateLoad.main(X509CertificateLoad.java:13) 0000: 30 74 30 24 06 08 2B 06 01 05 05 07 30 01 86 18 0t0$..+.....0... 0010: 68 74 74 70 3A 2F 2F 6F 63 73 70 2E 64 69 67 69 http://ocsp.digi 0020: 63 65 72 74 2E 63 6F 6D 30 4C 06 0C 2B 06 01 05 cert.com0L..+... 0030: 05 07 30 02 86 40 68 74 74 70 3A 2F 2F 63 61 63 ..0..@http://cac 0040: 65 72 74 73 2E 64 69 67 69 63 65 72 74 2E 63 6F erts.digicert.co 0050: 6D 2F 44 69 67 69 43 65 72 74 41 73 73 75 72 65 m/DigiCertAssure 0060: 64 49 44 43 6F 64 65 53 69 67 6E 69 6E 67 43 41 dIDCodeSigningCA 0070: 2D 31 2E 63 72 74 -1.crt Exception in thread "main" java.lang.NullPointerException at sun.security.util.DerValue.equals(DerValue.java:772) at sun.security.x509.AlgorithmId.equals(AlgorithmId.java:274) at sun.security.x509.X509CertImpl.parse(X509CertImpl.java:1754) at sun.security.x509.X509CertImpl.<init>(X509CertImpl.java:196) at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:97) at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:339) at X509CertificateLoad.main(X509CertificateLoad.java:13) sun.security.x509.X509CertImpl.parse() method tries to create X509CertInfo instance, and IOException is thrown. But this exception is just ignored. But anyway then the "inner" and "outer" signature algorithms are compared: src/share/classes/sun/security/x509/X509CertImpl.java ... // The CertificateInfo info = new X509CertInfo(seq[0]); // the "inner" and "outer" signature algorithms must match AlgorithmId infoSigAlg = (AlgorithmId)info.get( CertificateAlgorithmId.NAME + DOT + CertificateAlgorithmId.ALGORITHM); if (! algId.equals(infoSigAlg)) throw new CertificateException("Signature algorithm mismatch"); ... AlgorithmId.equals() method does not check that params is null, so null is passed to DerValue.equals() method: src/share/classes/sun/security/util/DerValue.java ... public boolean equals(DerValue other) { if (this == other) { return true; } if (tag != other.tag) { return false; } if (data == other.data) { return true; } // make sure the order of lock is always consistent to avoid a deadlock return (System.identityHashCode(this.data) > System.identityHashCode(other.data)) ? doEquals(this, other): doEquals(other, this); } ... This is not a regression in 7u, NPE is thrown on JDK 7 b147. CertificateException is thrown as expected on JDK 8 b113, but anyway DerValue.equals() method does not check that null is passed. So JDK 8 is also affected. The certificate that was used for testing is invalid. I did not try to create a valid one that contains null in params of AlgorithmId instance. But according to http://www.ietf.org/rfc/rfc2459.txt, parameters is optional: AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameters ANY DEFINED BY algorithm OPTIONAL } So I guess it is possible to create a valid certificate to reproduce the problem. The problem can be fixed by adding a check that null is passed to DerValue.equals() method: http://cr.openjdk.java.net/~asmotrak/8028431/webrev.00/
07-12-2014