Skip to content

Commit

Permalink
8274471: Verification of OCSP Response signed with RSASSA-PSS fails
Browse files Browse the repository at this point in the history
Reviewed-by: hchao, jnimeh
  • Loading branch information
wangweij committed Oct 4, 2021
1 parent f2404d6 commit f63c4a8
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.cert.CRLReason;
import java.security.cert.Extension;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Date;
Expand All @@ -46,7 +45,6 @@
import sun.security.util.Debug;
import sun.security.util.Event;
import sun.security.util.IOUtils;
import sun.security.validator.Validator;
import sun.security.x509.AccessDescription;
import sun.security.x509.AuthorityInfoAccessExtension;
import sun.security.x509.GeneralName;
Expand Down Expand Up @@ -166,22 +164,26 @@ public static byte[] getOCSPBytes(List<CertId> certIds, URI responderURI,
List<Extension> extensions) throws IOException {
OCSPRequest request = new OCSPRequest(certIds, extensions);
byte[] bytes = request.encodeBytes();
String responder = responderURI.toString();

if (debug != null) {
debug.println("connecting to OCSP service at: " + responderURI);
debug.println("connecting to OCSP service at: " + responder);
}
Event.report(Event.ReporterCategory.CRLCHECK, "event.ocsp.check",
responderURI.toString());
responder);

URL url;
HttpURLConnection con = null;
try {
String encodedGetReq = responderURI.toString() + "/" +
URLEncoder.encode(Base64.getEncoder().encodeToString(bytes),
UTF_8);
StringBuilder encodedGetReq = new StringBuilder(responder);
if (!responder.endsWith("/")) {
encodedGetReq.append("/");
}
encodedGetReq.append(URLEncoder.encode(
Base64.getEncoder().encodeToString(bytes), UTF_8));

if (encodedGetReq.length() <= 255) {
url = new URL(encodedGetReq);
url = new URL(encodedGetReq.toString());
con = (HttpURLConnection)url.openConnection();
con.setDoOutput(true);
con.setDoInput(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,10 @@ private boolean verifySignature(X509Certificate cert)

try {
Signature respSignature = Signature.getInstance(sigAlgId.getName());
respSignature.initVerify(cert.getPublicKey());
SignatureUtil.initVerifyWithParam(respSignature,
cert.getPublicKey(),
SignatureUtil.getParamSpec(sigAlgId.getName(),
sigAlgId.getEncodedParams()));
respSignature.update(tbsResponseData);

if (respSignature.verify(signature)) {
Expand All @@ -654,8 +657,8 @@ private boolean verifySignature(X509Certificate cert)
}
return false;
}
} catch (InvalidKeyException | NoSuchAlgorithmException |
SignatureException e)
} catch (InvalidAlgorithmParameterException | InvalidKeyException
| NoSuchAlgorithmException | SignatureException e)
{
throw new CertPathValidatorException(e);
}
Expand Down
28 changes: 10 additions & 18 deletions src/java.base/share/classes/sun/security/util/SignatureUtil.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -170,8 +170,7 @@ public static AlgorithmParameterSpec getParamSpec(String sigName,
// for verification with the specified key and params (may be null)
public static void initVerifyWithParam(Signature s, PublicKey key,
AlgorithmParameterSpec params)
throws ProviderException, InvalidAlgorithmParameterException,
InvalidKeyException {
throws InvalidAlgorithmParameterException, InvalidKeyException {
SharedSecrets.getJavaSecuritySignatureAccess().initVerify(s, key, params);
}

Expand All @@ -180,17 +179,15 @@ public static void initVerifyWithParam(Signature s, PublicKey key,
public static void initVerifyWithParam(Signature s,
java.security.cert.Certificate cert,
AlgorithmParameterSpec params)
throws ProviderException, InvalidAlgorithmParameterException,
InvalidKeyException {
throws InvalidAlgorithmParameterException, InvalidKeyException {
SharedSecrets.getJavaSecuritySignatureAccess().initVerify(s, cert, params);
}

// Utility method for initializing the specified Signature object
// for signing with the specified key and params (may be null)
public static void initSignWithParam(Signature s, PrivateKey key,
AlgorithmParameterSpec params, SecureRandom sr)
throws ProviderException, InvalidAlgorithmParameterException,
InvalidKeyException {
throws InvalidAlgorithmParameterException, InvalidKeyException {
SharedSecrets.getJavaSecuritySignatureAccess().initSign(s, key, params, sr);
}

Expand Down Expand Up @@ -342,10 +339,10 @@ public static AlgorithmParameterSpec getDefaultParamSpec(
* Create a Signature that has been initialized with proper key and params.
*
* @param sigAlg signature algorithms
* @param key public or private key
* @param key private key
* @param provider (optional) provider
*/
public static Signature fromKey(String sigAlg, Key key, String provider)
public static Signature fromKey(String sigAlg, PrivateKey key, String provider)
throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException{
Signature sigEngine = (provider == null || provider.isEmpty())
Expand All @@ -358,28 +355,23 @@ public static Signature fromKey(String sigAlg, Key key, String provider)
* Create a Signature that has been initialized with proper key and params.
*
* @param sigAlg signature algorithms
* @param key public or private key
* @param key private key
* @param provider (optional) provider
*/
public static Signature fromKey(String sigAlg, Key key, Provider provider)
public static Signature fromKey(String sigAlg, PrivateKey key, Provider provider)
throws NoSuchAlgorithmException, InvalidKeyException{
Signature sigEngine = (provider == null)
? Signature.getInstance(sigAlg)
: Signature.getInstance(sigAlg, provider);
return autoInitInternal(sigAlg, key, sigEngine);
}

private static Signature autoInitInternal(String alg, Key key, Signature s)
private static Signature autoInitInternal(String alg, PrivateKey key, Signature s)
throws InvalidKeyException {
AlgorithmParameterSpec params = SignatureUtil
.getDefaultParamSpec(alg, key);
try {
if (key instanceof PrivateKey) {
SignatureUtil.initSignWithParam(s, (PrivateKey) key, params,
null);
} else {
SignatureUtil.initVerifyWithParam(s, (PublicKey) key, params);
}
SignatureUtil.initSignWithParam(s, key, params, null);
} catch (InvalidAlgorithmParameterException e) {
throw new AssertionError("Should not happen", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ public AlgorithmParameters getParameters() {
*
* @return DER encoded parameters, or null not present.
*/
public byte[] getEncodedParams() throws IOException {
public byte[] getEncodedParams() {
return (encodedParams == null ||
algid.toString().equals(KnownOIDs.SpecifiedSHA2withECDSA.value()))
? null
Expand Down
10 changes: 2 additions & 8 deletions src/java.base/share/classes/sun/security/x509/X509CRLImpl.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -820,13 +820,7 @@ public String getSigAlgOID() {
* null if no parameters are present.
*/
public byte[] getSigAlgParams() {
if (sigAlgId == null)
return null;
try {
return sigAlgId.getEncodedParams();
} catch (IOException e) {
return null;
}
return sigAlgId == null ? null : sigAlgId.getEncodedParams();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1030,13 +1030,7 @@ public String getSigAlgOID() {
* null if no parameters are present.
*/
public byte[] getSigAlgParams() {
if (algId == null)
return null;
try {
return algId.getEncodedParams();
} catch (IOException e) {
return null;
}
return algId == null ? null : algId.getEncodedParams();
}

/**
Expand Down
42 changes: 15 additions & 27 deletions test/jdk/java/security/testlibrary/CertificateBuilder.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2020, 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.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -38,6 +38,7 @@
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
import sun.security.util.ObjectIdentifier;
import sun.security.util.SignatureUtil;
import sun.security.x509.AccessDescription;
import sun.security.x509.AlgorithmId;
import sun.security.x509.AuthorityInfoAccessExtension;
Expand Down Expand Up @@ -364,8 +365,7 @@ public X509Certificate build(X509Certificate issuerCert,
throws IOException, CertificateException, NoSuchAlgorithmException {
// TODO: add some basic checks (key usage, basic constraints maybe)

AlgorithmId signAlg = AlgorithmId.get(algName);
byte[] encodedCert = encodeTopLevel(issuerCert, issuerKey, signAlg);
byte[] encodedCert = encodeTopLevel(issuerCert, issuerKey, algName);
ByteArrayInputStream bais = new ByteArrayInputStream(encodedCert);
return (X509Certificate)factory.generateCertificate(bais);
}
Expand All @@ -392,18 +392,24 @@ public X509Certificate build(X509Certificate issuerCert,
* @throws IOException if an encoding error occurs.
*/
private byte[] encodeTopLevel(X509Certificate issuerCert,
PrivateKey issuerKey, AlgorithmId signAlg)
throws CertificateException, IOException {
PrivateKey issuerKey, String algName)
throws CertificateException, IOException, NoSuchAlgorithmException {

AlgorithmId signAlg = AlgorithmId.get(algName);
DerOutputStream outerSeq = new DerOutputStream();
DerOutputStream topLevelItems = new DerOutputStream();

tbsCertBytes = encodeTbsCert(issuerCert, signAlg);
topLevelItems.write(tbsCertBytes);
try {
signatureBytes = signCert(issuerKey, signAlg);
Signature sig = SignatureUtil.fromKey(signAlg.getName(), issuerKey, (Provider)null);
// Rewrite signAlg, RSASSA-PSS needs some parameters.
signAlg = SignatureUtil.fromSignature(sig, issuerKey);
tbsCertBytes = encodeTbsCert(issuerCert, signAlg);
sig.update(tbsCertBytes);
signatureBytes = sig.sign();
} catch (GeneralSecurityException ge) {
throw new CertificateException(ge);
}
topLevelItems.write(tbsCertBytes);
signAlg.derEncode(topLevelItems);
topLevelItems.putBitString(signatureBytes);
outerSeq.write(DerValue.tag_Sequence, topLevelItems);
Expand Down Expand Up @@ -518,22 +524,4 @@ private void encodeExtensions(DerOutputStream tbsStream)
(byte)3), extSequence);
}

/**
* Digitally sign the X.509 certificate.
*
* @param issuerKey The private key of the issuing authority
* @param signAlg The signature algorithm object
*
* @return The digital signature bytes.
*
* @throws GeneralSecurityException If any errors occur during the
* digital signature process.
*/
private byte[] signCert(PrivateKey issuerKey, AlgorithmId signAlg)
throws GeneralSecurityException {
Signature sig = Signature.getInstance(signAlg.getName());
sig.initSign(issuerKey);
sig.update(tbsCertBytes);
return sig.sign();
}
}
}
14 changes: 7 additions & 7 deletions test/jdk/java/security/testlibrary/SimpleOCSPServer.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2020, 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.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -174,8 +174,7 @@ public SimpleOCSPServer(InetAddress addr, int port, KeyStore ks,
issuerAlias + " not found");
}
}

sigAlgId = AlgorithmId.get("Sha256withRSA");
sigAlgId = AlgorithmId.get(SignatureUtil.getDefaultSigAlgForKey(signerKey));
respId = new ResponderId(signerCert.getSubjectX500Principal());
listenAddress = addr;
listenPort = port;
Expand Down Expand Up @@ -1348,13 +1347,14 @@ private byte[] encodeBasicOcspResponse() throws IOException {
basicORItemStream.write(tbsResponseBytes);

try {
sigAlgId.derEncode(basicORItemStream);

// Create the signature
Signature sig = Signature.getInstance(sigAlgId.getName());
sig.initSign(signerKey);
Signature sig = SignatureUtil.fromKey(
sigAlgId.getName(), signerKey, (Provider)null);
sig.update(tbsResponseBytes);
signature = sig.sign();
// Rewrite signAlg, RSASSA-PSS needs some parameters.
sigAlgId = SignatureUtil.fromSignature(sig, signerKey);
sigAlgId.derEncode(basicORItemStream);
basicORItemStream.putBitString(signature);
} catch (GeneralSecurityException exc) {
err(exc);
Expand Down
20 changes: 13 additions & 7 deletions test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, 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.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -30,7 +30,8 @@
* @summary OCSP Stapling for TLS
* @library ../../../../java/security/testlibrary
* @build CertificateBuilder SimpleOCSPServer
* @run main/othervm HttpsUrlConnClient
* @run main/othervm HttpsUrlConnClient RSA SHA256withRSA
* @run main/othervm HttpsUrlConnClient RSASSA-PSS RSASSA-PSS
*/

import java.io.*;
Expand Down Expand Up @@ -60,7 +61,6 @@

import sun.security.testlibrary.SimpleOCSPServer;
import sun.security.testlibrary.CertificateBuilder;
import sun.security.validator.ValidatorException;

public class HttpsUrlConnClient {

Expand All @@ -73,6 +73,9 @@ public class HttpsUrlConnClient {
static final byte[] LINESEP = { 10 };
static final Base64.Encoder B64E = Base64.getMimeEncoder(64, LINESEP);

static String SIGALG;
static String KEYALG;

// Turn on TLS debugging
static boolean debug = true;

Expand Down Expand Up @@ -137,6 +140,9 @@ public static void main(String[] args) throws Exception {
System.setProperty("javax.net.ssl.trustStore", "");
System.setProperty("javax.net.ssl.trustStorePassword", "");

KEYALG = args[0];
SIGALG = args[1];

// Create the PKI we will use for the test and start the OCSP servers
createPKI();
utcDateFmt.setTimeZone(TimeZone.getTimeZone("GMT"));
Expand Down Expand Up @@ -514,7 +520,7 @@ public void run() {
*/
private static void createPKI() throws Exception {
CertificateBuilder cbld = new CertificateBuilder();
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(KEYALG);
keyGen.initialize(2048);
KeyStore.Builder keyStoreBuilder =
KeyStore.Builder.newInstance("PKCS12", null,
Expand All @@ -540,7 +546,7 @@ private static void createPKI() throws Exception {
addCommonCAExts(cbld);
// Make our Root CA Cert!
X509Certificate rootCert = cbld.build(null, rootCaKP.getPrivate(),
"SHA256withRSA");
SIGALG);
log("Root CA Created:\n" + certInfo(rootCert));

// Now build a keystore and add the keys and cert
Expand Down Expand Up @@ -582,7 +588,7 @@ private static void createPKI() throws Exception {
cbld.addAIAExt(Collections.singletonList(rootRespURI));
// Make our Intermediate CA Cert!
X509Certificate intCaCert = cbld.build(rootCert, rootCaKP.getPrivate(),
"SHA256withRSA");
SIGALG);
log("Intermediate CA Created:\n" + certInfo(intCaCert));

// Provide intermediate CA cert revocation info to the Root CA
Expand Down Expand Up @@ -644,7 +650,7 @@ private static void createPKI() throws Exception {
cbld.addAIAExt(Collections.singletonList(intCaRespURI));
// Make our SSL Server Cert!
X509Certificate sslCert = cbld.build(intCaCert, intCaKP.getPrivate(),
"SHA256withRSA");
SIGALG);
log("SSL Certificate Created:\n" + certInfo(sslCert));

// Provide SSL server cert revocation info to the Intermeidate CA
Expand Down

1 comment on commit f63c4a8

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.