mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8256895: Add support for RFC 8954: Online Certificate Status Protocol (OCSP) Nonce Extension
Reviewed-by: jnimeh, mullan
This commit is contained in:
parent
4f11ff325f
commit
8b95d9549e
5 changed files with 77 additions and 24 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -76,14 +76,16 @@ public final class OCSPNonceExtension extends Extension {
|
||||||
*
|
*
|
||||||
* @throws IOException if any errors happen during encoding of the
|
* @throws IOException if any errors happen during encoding of the
|
||||||
* extension.
|
* extension.
|
||||||
* @throws IllegalArgumentException if length is not a positive integer.
|
* @throws IllegalArgumentException if length is not in the range of 1 to 32.
|
||||||
*/
|
*/
|
||||||
public OCSPNonceExtension(boolean isCritical, int length)
|
public OCSPNonceExtension(boolean isCritical, int length)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
this.extensionId = PKIXExtensions.OCSPNonce_Id;
|
this.extensionId = PKIXExtensions.OCSPNonce_Id;
|
||||||
this.critical = isCritical;
|
this.critical = isCritical;
|
||||||
|
|
||||||
if (length > 0) {
|
// RFC 8954, section 2.1: the length of the nonce MUST be at least 1 octet
|
||||||
|
// and can be up to 32 octets.
|
||||||
|
if (length > 0 && length <= 32) {
|
||||||
SecureRandom rng = new SecureRandom();
|
SecureRandom rng = new SecureRandom();
|
||||||
this.nonceData = new byte[length];
|
this.nonceData = new byte[length];
|
||||||
rng.nextBytes(nonceData);
|
rng.nextBytes(nonceData);
|
||||||
|
@ -91,7 +93,7 @@ public final class OCSPNonceExtension extends Extension {
|
||||||
nonceData).toByteArray();
|
nonceData).toByteArray();
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Length must be a positive integer");
|
"Length of nonce must be at least 1 byte and can be up to 32 bytes");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,12 +123,13 @@ public final class OCSPNonceExtension extends Extension {
|
||||||
* @param isCritical a boolean flag indicating whether the criticality bit
|
* @param isCritical a boolean flag indicating whether the criticality bit
|
||||||
* is set for this extension
|
* is set for this extension
|
||||||
* @param incomingNonce The nonce data to be set for the extension. This
|
* @param incomingNonce The nonce data to be set for the extension. This
|
||||||
* must be a non-null array of at least one byte long.
|
* must be a non-null array of at least one byte long and can be up to
|
||||||
|
* 32 bytes.
|
||||||
*
|
*
|
||||||
* @throws IOException if any errors happen during encoding of the
|
* @throws IOException if any errors happen during encoding of the
|
||||||
* extension.
|
* extension.
|
||||||
* @throws IllegalArgumentException if the incomingNonce length is not a
|
* @throws IllegalArgumentException if the incomingNonce length is not
|
||||||
* positive integer.
|
* in the range of 1 to 32.
|
||||||
* @throws NullPointerException if the incomingNonce is null.
|
* @throws NullPointerException if the incomingNonce is null.
|
||||||
*/
|
*/
|
||||||
public OCSPNonceExtension(boolean isCritical, byte[] incomingNonce)
|
public OCSPNonceExtension(boolean isCritical, byte[] incomingNonce)
|
||||||
|
@ -135,13 +138,15 @@ public final class OCSPNonceExtension extends Extension {
|
||||||
this.critical = isCritical;
|
this.critical = isCritical;
|
||||||
|
|
||||||
Objects.requireNonNull(incomingNonce, "Nonce data must be non-null");
|
Objects.requireNonNull(incomingNonce, "Nonce data must be non-null");
|
||||||
if (incomingNonce.length > 0) {
|
// RFC 8954, section 2.1: the length of the nonce MUST be at least 1 octet
|
||||||
|
// and can be up to 32 octets.
|
||||||
|
if (incomingNonce.length > 0 && incomingNonce.length <= 32) {
|
||||||
this.nonceData = incomingNonce.clone();
|
this.nonceData = incomingNonce.clone();
|
||||||
this.extensionValue = new DerValue(DerValue.tag_OctetString,
|
this.extensionValue = new DerValue(DerValue.tag_OctetString,
|
||||||
nonceData).toByteArray();
|
nonceData).toByteArray();
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Nonce data must be at least 1 byte in length");
|
"Nonce data must be at least 1 byte and can be up to 32 bytes in length");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -83,7 +83,10 @@ class RevocationChecker extends PKIXRevocationChecker {
|
||||||
String ocspSubject;
|
String ocspSubject;
|
||||||
String ocspIssuer;
|
String ocspIssuer;
|
||||||
String ocspSerial;
|
String ocspSerial;
|
||||||
|
boolean ocspNonce;
|
||||||
}
|
}
|
||||||
|
private RevocationProperties rp;
|
||||||
|
private static final int DEFAULT_NONCE_BYTES = 16;
|
||||||
|
|
||||||
RevocationChecker() {
|
RevocationChecker() {
|
||||||
legacy = false;
|
legacy = false;
|
||||||
|
@ -99,7 +102,7 @@ class RevocationChecker extends PKIXRevocationChecker {
|
||||||
void init(TrustAnchor anchor, ValidatorParams params)
|
void init(TrustAnchor anchor, ValidatorParams params)
|
||||||
throws CertPathValidatorException
|
throws CertPathValidatorException
|
||||||
{
|
{
|
||||||
RevocationProperties rp = getRevocationProperties();
|
rp = getRevocationProperties();
|
||||||
URI uri = getOcspResponder();
|
URI uri = getOcspResponder();
|
||||||
responderURI = (uri == null) ? toURI(rp.ocspUrl) : uri;
|
responderURI = (uri == null) ? toURI(rp.ocspUrl) : uri;
|
||||||
X509Certificate cert = getOcspResponderCert();
|
X509Certificate cert = getOcspResponderCert();
|
||||||
|
@ -198,6 +201,8 @@ class RevocationChecker extends PKIXRevocationChecker {
|
||||||
= Security.getProperty("ocsp.responderCertSerialNumber");
|
= Security.getProperty("ocsp.responderCertSerialNumber");
|
||||||
rp.crlDPEnabled
|
rp.crlDPEnabled
|
||||||
= Boolean.getBoolean("com.sun.security.enableCRLDP");
|
= Boolean.getBoolean("com.sun.security.enableCRLDP");
|
||||||
|
rp.ocspNonce
|
||||||
|
= Boolean.getBoolean("jdk.security.certpath.ocspNonce");
|
||||||
return rp;
|
return rp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -712,6 +717,13 @@ class RevocationChecker extends PKIXRevocationChecker {
|
||||||
certId = new CertId(issuerInfo.getName(), issuerInfo.getPublicKey(),
|
certId = new CertId(issuerInfo.getName(), issuerInfo.getPublicKey(),
|
||||||
currCert.getSerialNumberObject());
|
currCert.getSerialNumberObject());
|
||||||
|
|
||||||
|
byte[] nonce = null;
|
||||||
|
for (Extension ext : ocspExtensions) {
|
||||||
|
if (ext.getId().equals(KnownOIDs.OCSPNonceExt.value())) {
|
||||||
|
nonce = ext.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check if there is a cached OCSP response available
|
// check if there is a cached OCSP response available
|
||||||
byte[] responseBytes = ocspResponses.get(cert);
|
byte[] responseBytes = ocspResponses.get(cert);
|
||||||
if (responseBytes != null) {
|
if (responseBytes != null) {
|
||||||
|
@ -721,12 +733,6 @@ class RevocationChecker extends PKIXRevocationChecker {
|
||||||
response = new OCSPResponse(responseBytes);
|
response = new OCSPResponse(responseBytes);
|
||||||
|
|
||||||
// verify the response
|
// verify the response
|
||||||
byte[] nonce = null;
|
|
||||||
for (Extension ext : ocspExtensions) {
|
|
||||||
if (ext.getId().equals(KnownOIDs.OCSPNonceExt.value())) {
|
|
||||||
nonce = ext.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response.verify(Collections.singletonList(certId), issuerInfo,
|
response.verify(Collections.singletonList(certId), issuerInfo,
|
||||||
responderCert, params.date(), nonce, params.variant());
|
responderCert, params.date(), nonce, params.variant());
|
||||||
|
|
||||||
|
@ -740,9 +746,43 @@ class RevocationChecker extends PKIXRevocationChecker {
|
||||||
null, -1);
|
null, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Extension> tmpExtensions = null;
|
||||||
|
if (rp.ocspNonce) {
|
||||||
|
if (nonce == null) {
|
||||||
|
try {
|
||||||
|
// create the 16-byte nonce by default
|
||||||
|
Extension nonceExt = new OCSPNonceExtension(DEFAULT_NONCE_BYTES);
|
||||||
|
|
||||||
|
if (ocspExtensions.size() > 0) {
|
||||||
|
tmpExtensions = new ArrayList<Extension>(ocspExtensions);
|
||||||
|
tmpExtensions.add(nonceExt);
|
||||||
|
} else {
|
||||||
|
tmpExtensions = List.of(nonceExt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug != null) {
|
||||||
|
debug.println("Default nonce has been created in the OCSP extensions");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new CertPathValidatorException("Failed to create the default nonce " +
|
||||||
|
"in OCSP extensions", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new CertPathValidatorException("Application provided nonce cannot be " +
|
||||||
|
"used if the value of the jdk.security.certpath.ocspNonce system " +
|
||||||
|
"property is true");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (nonce != null) {
|
||||||
|
if (debug != null) {
|
||||||
|
debug.println("Using application provided nonce");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
response = OCSP.check(Collections.singletonList(certId),
|
response = OCSP.check(Collections.singletonList(certId),
|
||||||
responderURI, issuerInfo, responderCert, null,
|
responderURI, issuerInfo, responderCert, null,
|
||||||
ocspExtensions, params.variant());
|
rp.ocspNonce ? tmpExtensions : ocspExtensions, params.variant());
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CertPathValidatorException(
|
throw new CertPathValidatorException(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8232019
|
* @bug 8232019 8256895
|
||||||
* @summary Interoperability tests with LuxTrust Global Root 2 CA
|
* @summary Interoperability tests with LuxTrust Global Root 2 CA
|
||||||
* @build ValidatePathWithParams
|
* @build ValidatePathWithParams
|
||||||
* @run main/othervm -Djava.security.debug=certpath LuxTrustCA OCSP
|
* @run main/othervm -Djava.security.debug=certpath LuxTrustCA OCSP
|
||||||
|
@ -173,6 +173,7 @@ public class LuxTrustCA {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
System.setProperty("jdk.security.certpath.ocspNonce", "true");
|
||||||
ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
|
ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
|
||||||
|
|
||||||
if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
|
if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8243320
|
* @bug 8243320 8256895
|
||||||
* @summary Interoperability tests with SSL.com's RSA, EV RSA, and ECC CA
|
* @summary Interoperability tests with SSL.com's RSA, EV RSA, and ECC CA
|
||||||
* @build ValidatePathWithParams
|
* @build ValidatePathWithParams
|
||||||
* @run main/othervm -Djava.security.debug=certpath SSLCA OCSP
|
* @run main/othervm -Djava.security.debug=certpath SSLCA OCSP
|
||||||
|
@ -47,6 +47,7 @@ public class SSLCA {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
System.setProperty("jdk.security.certpath.ocspNonce", "true");
|
||||||
ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
|
ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
|
||||||
boolean ocspEnabled = false;
|
boolean ocspEnabled = false;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8046321
|
* @bug 8046321 8256895
|
||||||
* @summary Unit tests for OCSPNonceExtension objects
|
* @summary Unit tests for OCSPNonceExtension objects
|
||||||
* @modules java.base/sun.security.provider.certpath
|
* @modules java.base/sun.security.provider.certpath
|
||||||
* java.base/sun.security.util
|
* java.base/sun.security.util
|
||||||
|
@ -192,6 +192,12 @@ public class OCSPNonceExtensionTests {
|
||||||
throw new RuntimeException("Accepted a zero length nonce");
|
throw new RuntimeException("Accepted a zero length nonce");
|
||||||
} catch (IllegalArgumentException iae) { }
|
} catch (IllegalArgumentException iae) { }
|
||||||
|
|
||||||
|
// Length of the nonce exceeds the maximum 32 bytes
|
||||||
|
try {
|
||||||
|
Extension bigLenNonce = new OCSPNonceExtension(33);
|
||||||
|
throw new RuntimeException("Accepted a larger than 32 bytes of nonce");
|
||||||
|
} catch (IllegalArgumentException iae) { }
|
||||||
|
|
||||||
// Valid input to constructor
|
// Valid input to constructor
|
||||||
Extension nonceByLen = new OCSPNonceExtension(32);
|
Extension nonceByLen = new OCSPNonceExtension(32);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue