8296901: Do not create unsigned certificate and CRL

Reviewed-by: mullan
This commit is contained in:
Weijun Wang 2022-11-18 02:21:03 +00:00
parent 7b3984cb5a
commit ab6b7ef988
11 changed files with 396 additions and 415 deletions

View file

@ -335,12 +335,11 @@ public final class CertAndKeyGen {
} }
if (ext != null) info.setExtensions(ext); if (ext != null) info.setExtensions(ext);
cert = new X509CertImpl(info);
if (signerFlag) { if (signerFlag) {
// use signer's private key to sign // use signer's private key to sign
cert.sign(signerPrivateKey, sigAlg); cert = X509CertImpl.newSigned(info, signerPrivateKey, sigAlg);
} else { } else {
cert.sign(privateKey, sigAlg); cert = X509CertImpl.newSigned(info, privateKey, sigAlg);
} }
return cert; return cert;

View file

@ -1536,8 +1536,8 @@ public final class Main {
subjectPubKey, subjectPubKey,
signerSubjectKeyId); signerSubjectKeyId);
info.setExtensions(ext); info.setExtensions(ext);
X509CertImpl cert = new X509CertImpl(info); X509CertImpl cert = X509CertImpl
cert.sign(privateKey, sigAlgName); .newSigned(info, privateKey, sigAlgName);
dumpCert(cert, out); dumpCert(cert, out);
for (Certificate ca: keyStore.getCertificateChain(alias)) { for (Certificate ca: keyStore.getCertificateChain(alias)) {
if (ca instanceof X509Certificate xca) { if (ca instanceof X509Certificate xca) {
@ -1589,8 +1589,9 @@ public final class Main {
badCerts[i] = new X509CRLEntryImpl(new BigInteger(ids.get(i)), firstDate); badCerts[i] = new X509CRLEntryImpl(new BigInteger(ids.get(i)), firstDate);
} }
} }
X509CRLImpl crl = new X509CRLImpl(owner, firstDate, lastDate, badCerts); X509CRLImpl crl = X509CRLImpl.newSigned(
crl.sign(privateKey, sigAlgName); new X509CRLImpl.TBSCertList(owner, firstDate, lastDate, badCerts),
privateKey, sigAlgName);
if (rfc) { if (rfc) {
out.println("-----BEGIN X509 CRL-----"); out.println("-----BEGIN X509 CRL-----");
out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(crl.getEncodedInternal())); out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(crl.getEncodedInternal()));
@ -3228,8 +3229,8 @@ public final class Main {
null); null);
certInfo.setExtensions(ext); certInfo.setExtensions(ext);
// Sign the new certificate // Sign the new certificate
X509CertImpl newCert = new X509CertImpl(certInfo); X509CertImpl newCert = X509CertImpl.newSigned(
newCert.sign(privKey, sigAlgName); certInfo, privKey, sigAlgName);
// Store the new certificate as a single-element certificate chain // Store the new certificate as a single-element certificate chain
keyStore.setKeyEntry(alias, privKey, keyStore.setKeyEntry(alias, privKey,

View file

@ -26,7 +26,6 @@
package sun.security.x509; package sun.security.x509;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.cert.Certificate; import java.security.cert.Certificate;
@ -88,7 +87,10 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
private byte[] tbsCertList = null; // DER encoded "to-be-signed" CRL private byte[] tbsCertList = null; // DER encoded "to-be-signed" CRL
private AlgorithmId sigAlgId = null; // sig alg in CRL private AlgorithmId sigAlgId = null; // sig alg in CRL
private TBSCertList info;
// crl information // crl information
public static class TBSCertList {
private int version; private int version;
private AlgorithmId infoSigAlgId; // sig alg in "to-be-signed" crl private AlgorithmId infoSigAlgId; // sig alg in "to-be-signed" crl
private X500Name issuer = null; private X500Name issuer = null;
@ -99,94 +101,22 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
new TreeMap<>(); new TreeMap<>();
private final List<X509CRLEntry> revokedList = new LinkedList<>(); private final List<X509CRLEntry> revokedList = new LinkedList<>();
private CRLExtensions extensions = null; private CRLExtensions extensions = null;
private static final boolean isExplicit = true;
private boolean readOnly = false;
/** /**
* PublicKey that has previously been used to successfully verify * Initial TBSCertList constructor, no revoked certs, and no extensions.
* the signature of this CRL. Null if the CRL has not
* yet been verified (successfully).
*/
private PublicKey verifiedPublicKey;
/**
* If verifiedPublicKey is not null, name of the provider used to
* successfully verify the signature of this CRL, or the
* empty String if no provider was explicitly specified.
*/
private String verifiedProvider;
/**
* Not to be used. As it would lead to cases of uninitialized
* CRL objects.
*/
private X509CRLImpl() { }
/**
* Unmarshals an X.509 CRL from its encoded form, parsing the encoded
* bytes. This form of constructor is used by agents which
* need to examine and use CRL contents. Note that the buffer
* must include only one CRL, and no "garbage" may be left at
* the end.
*
* @param crlData the encoded bytes, with no trailing padding.
* @exception CRLException on parsing errors.
*/
public X509CRLImpl(byte[] crlData) throws CRLException {
try {
parse(new DerValue(crlData));
} catch (IOException e) {
signedCRL = null;
throw new CRLException("Parsing error: " + e.getMessage());
}
}
/**
* Unmarshals an X.509 CRL from an DER value.
*
* @param val a DER value holding at least one CRL
* @exception CRLException on parsing errors.
*/
public X509CRLImpl(DerValue val) throws CRLException {
try {
parse(val);
} catch (IOException e) {
signedCRL = null;
throw new CRLException("Parsing error: " + e.getMessage());
}
}
/**
* Unmarshals an X.509 CRL from an input stream. Only one CRL
* is expected at the end of the input stream.
*
* @param inStrm an input stream holding at least one CRL
* @exception CRLException on parsing errors.
*/
public X509CRLImpl(InputStream inStrm) throws CRLException {
try {
parse(new DerValue(inStrm));
} catch (IOException e) {
signedCRL = null;
throw new CRLException("Parsing error: " + e.getMessage());
}
}
/**
* Initial CRL constructor, no revoked certs, and no extensions.
* *
* @param issuer the name of the CA issuing this CRL. * @param issuer the name of the CA issuing this CRL.
* @param thisDate the Date of this issue. * @param thisDate the Date of this issue.
* @param nextDate the Date of the next CRL. * @param nextDate the Date of the next CRL.
*/ */
public X509CRLImpl(X500Name issuer, Date thisDate, Date nextDate) { public TBSCertList(X500Name issuer, Date thisDate, Date nextDate) {
this.issuer = issuer; this.issuer = issuer;
this.thisUpdate = thisDate; this.thisUpdate = thisDate;
this.nextUpdate = nextDate; this.nextUpdate = nextDate;
} }
/** /**
* CRL constructor, revoked certs, no extensions. * TBSCertList constructor, revoked certs, no extensions.
* *
* @param issuer the name of the CA issuing this CRL. * @param issuer the name of the CA issuing this CRL.
* @param thisDate the Date of this issue. * @param thisDate the Date of this issue.
@ -195,7 +125,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* *
* @exception CRLException on parsing/construction errors. * @exception CRLException on parsing/construction errors.
*/ */
public X509CRLImpl(X500Name issuer, Date thisDate, Date nextDate, public TBSCertList(X500Name issuer, Date thisDate, Date nextDate,
X509CRLEntry[] badCerts) X509CRLEntry[] badCerts)
throws CRLException throws CRLException
{ {
@ -221,7 +151,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
} }
/** /**
* CRL constructor, revoked certs and extensions. * TBSCertList constructor, revoked certs and extensions.
* *
* @param issuer the name of the CA issuing this CRL. * @param issuer the name of the CA issuing this CRL.
* @param thisDate the Date of this issue. * @param thisDate the Date of this issue.
@ -231,7 +161,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* *
* @exception CRLException on parsing/construction errors. * @exception CRLException on parsing/construction errors.
*/ */
public X509CRLImpl(X500Name issuer, Date thisDate, Date nextDate, public TBSCertList(X500Name issuer, Date thisDate, Date nextDate,
X509CRLEntry[] badCerts, CRLExtensions crlExts) X509CRLEntry[] badCerts, CRLExtensions crlExts)
throws CRLException throws CRLException
{ {
@ -243,33 +173,131 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
} }
/** /**
* Returned the encoding as an uncloned byte array. Callers must * Constructs from the encoding.
* guarantee that they neither modify it nor expose it to untrusted
* code.
*/ */
public byte[] getEncodedInternal() throws CRLException { public TBSCertList(DerValue value) throws IOException, CRLException {
if (signedCRL == null) {
throw new CRLException("Null CRL to encode"); if (value.tag != DerValue.tag_Sequence)
throw new CRLException("signed CRL fields invalid");
// parse the information
DerInputStream derStrm = value.data;
DerValue tmp;
byte nextByte;
// version (optional if v1)
version = 0; // by default, version = v1 == 0
nextByte = (byte)derStrm.peekByte();
if (nextByte == DerValue.tag_Integer) {
version = derStrm.getInteger();
if (version != 1) // i.e. v2
throw new CRLException("Invalid version");
}
tmp = derStrm.getDerValue();
// signature
infoSigAlgId = AlgorithmId.parse(tmp);
// issuer
issuer = new X500Name(derStrm);
if (issuer.isEmpty()) {
throw new CRLException("Empty issuer DN not allowed in X509CRLs");
}
// thisUpdate
// check if UTCTime encoded or GeneralizedTime
nextByte = (byte)derStrm.peekByte();
if (nextByte == DerValue.tag_UtcTime) {
thisUpdate = derStrm.getUTCTime();
} else if (nextByte == DerValue.tag_GeneralizedTime) {
thisUpdate = derStrm.getGeneralizedTime();
} else {
throw new CRLException("Invalid encoding for thisUpdate"
+ " (tag=" + nextByte + ")");
}
if (derStrm.available() == 0)
return; // done parsing no more optional fields present
// nextUpdate (optional)
nextByte = (byte)derStrm.peekByte();
if (nextByte == DerValue.tag_UtcTime) {
nextUpdate = derStrm.getUTCTime();
} else if (nextByte == DerValue.tag_GeneralizedTime) {
nextUpdate = derStrm.getGeneralizedTime();
} // else it is not present
if (derStrm.available() == 0)
return; // done parsing no more optional fields present
// revokedCertificates (optional)
nextByte = (byte)derStrm.peekByte();
if ((nextByte == DerValue.tag_SequenceOf)
&& (! ((nextByte & 0x0c0) == 0x080))) {
DerValue[] badCerts = derStrm.getSequence(4);
X500Principal crlIssuer = getIssuerX500Principal();
X500Principal badCertIssuer = crlIssuer;
for (int i = 0; i < badCerts.length; i++) {
X509CRLEntryImpl entry = new X509CRLEntryImpl(badCerts[i]);
badCertIssuer = getCertIssuer(entry, badCertIssuer);
entry.setCertificateIssuer(crlIssuer, badCertIssuer);
X509IssuerSerial issuerSerial = new X509IssuerSerial
(badCertIssuer, entry.getSerialNumber());
revokedMap.put(issuerSerial, entry);
revokedList.add(entry);
}
}
if (derStrm.available() == 0)
return; // done parsing no extensions
// crlExtensions (optional)
tmp = derStrm.getDerValue();
if (tmp.isConstructed() && tmp.isContextSpecific((byte)0)) {
extensions = new CRLExtensions(tmp.data);
} }
return signedCRL;
} }
/** /**
* Returns the ASN.1 DER encoded form of this CRL. * Return the issuer as X500Principal.
*
* @exception CRLException if an encoding error occurs.
*/ */
public byte[] getEncoded() throws CRLException { public X500Principal getIssuerX500Principal() {
return getEncodedInternal().clone(); if (issuerPrincipal == null) {
issuerPrincipal = issuer.asX500Principal();
}
return issuerPrincipal;
} }
/** /**
* Encodes the "to-be-signed" CRL to the OutputStream. * Returns the X500 certificate issuer DN of a CRL entry.
*
* @param entry the entry to check
* @param prevCertIssuer the previous entry's certificate issuer
* @return the X500Principal in a CertificateIssuerExtension, or
* prevCertIssuer if it does not exist
*/
private X500Principal getCertIssuer(X509CRLEntryImpl entry,
X500Principal prevCertIssuer) {
CertificateIssuerExtension ciExt =
entry.getCertificateIssuerExtension();
if (ciExt != null) {
GeneralNames names = ciExt.getNames();
X500Name issuerDN = (X500Name) names.get(0).getName();
return issuerDN.asX500Principal();
} else {
return prevCertIssuer;
}
}
/**
* Encodes the "to-be-signed" TBSCertList to the OutputStream.
* *
* @param out the OutputStream to write to.
* @exception CRLException on encoding errors. * @exception CRLException on encoding errors.
*/ */
public void encodeInfo(OutputStream out) throws CRLException { public byte[] encodeInfo() throws CRLException {
try { try {
DerOutputStream tmp = new DerOutputStream(); DerOutputStream tmp = new DerOutputStream();
DerOutputStream rCerts = new DerOutputStream(); DerOutputStream rCerts = new DerOutputStream();
@ -306,13 +334,111 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
seq.write(DerValue.tag_Sequence, tmp); seq.write(DerValue.tag_Sequence, tmp);
tbsCertList = seq.toByteArray(); return seq.toByteArray();
out.write(tbsCertList);
} catch (IOException e) { } catch (IOException e) {
throw new CRLException("Encoding error: " + e.getMessage()); throw new CRLException("Encoding error: " + e.getMessage());
} }
} }
}
private static final boolean isExplicit = true;
/**
* PublicKey that has previously been used to successfully verify
* the signature of this CRL. Null if the CRL has not
* yet been verified (successfully).
*/
private PublicKey verifiedPublicKey;
/**
* If verifiedPublicKey is not null, name of the provider used to
* successfully verify the signature of this CRL, or the
* empty String if no provider was explicitly specified.
*/
private String verifiedProvider;
/**
* Constructor simply setting all (non-cache) fields. Only used in
* {@link #newSigned}.
*/
public X509CRLImpl(TBSCertList info, AlgorithmId sigAlgId, byte[] signature,
byte[] tbsCertList, byte[] signedCRL) {
this.info = info;
this.sigAlgId = sigAlgId;
this.signature = signature;
this.tbsCertList = tbsCertList;
this.signedCRL = Objects.requireNonNull(signedCRL);
}
/**
* Unmarshals an X.509 CRL from its encoded form, parsing the encoded
* bytes. This form of constructor is used by agents which
* need to examine and use CRL contents. Note that the buffer
* must include only one CRL, and no "garbage" may be left at
* the end.
*
* @param crlData the encoded bytes, with no trailing padding.
* @exception CRLException on parsing errors.
*/
public X509CRLImpl(byte[] crlData) throws CRLException {
try {
parse(new DerValue(crlData));
} catch (IOException e) {
throw new CRLException("Parsing error: " + e.getMessage());
}
}
/**
* Unmarshals an X.509 CRL from an DER value.
*
* @param val a DER value holding at least one CRL
* @exception CRLException on parsing errors.
*/
public X509CRLImpl(DerValue val) throws CRLException {
try {
parse(val);
} catch (IOException e) {
throw new CRLException("Parsing error: " + e.getMessage());
}
}
/**
* Unmarshals an X.509 CRL from an input stream. Only one CRL
* is expected at the end of the input stream.
*
* @param inStrm an input stream holding at least one CRL
* @exception CRLException on parsing errors.
*/
public X509CRLImpl(InputStream inStrm) throws CRLException {
try {
parse(new DerValue(inStrm));
} catch (IOException e) {
throw new CRLException("Parsing error: " + e.getMessage());
}
}
public TBSCertList info() {
return info;
}
/**
* Returned the encoding as an uncloned byte array. Callers must
* guarantee that they neither modify it nor expose it to untrusted
* code.
*/
public byte[] getEncodedInternal() throws CRLException {
return signedCRL;
}
/**
* Returns the ASN.1 DER encoded form of this CRL.
*
* @exception CRLException if an encoding error occurs.
*/
public byte[] getEncoded() throws CRLException {
return getEncodedInternal().clone();
}
/** /**
* Verifies that this CRL was signed using the * Verifies that this CRL was signed using the
* private key that corresponds to the given public key. * private key that corresponds to the given public key.
@ -362,9 +488,6 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
return; return;
} }
} }
if (signedCRL == null) {
throw new CRLException("Uninitialized CRL");
}
Signature sigVerf; Signature sigVerf;
String sigName = sigAlgId.getName(); String sigName = sigAlgId.getName();
if (sigProvider.isEmpty()) { if (sigProvider.isEmpty()) {
@ -415,9 +538,6 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
throws CRLException, NoSuchAlgorithmException, InvalidKeyException, throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
SignatureException { SignatureException {
if (signedCRL == null) {
throw new CRLException("Uninitialized CRL");
}
Signature sigVerf; Signature sigVerf;
String sigName = sigAlgId.getName(); String sigName = sigAlgId.getName();
if (sigProvider == null) { if (sigProvider == null) {
@ -448,10 +568,12 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
} }
/** /**
* Encodes an X.509 CRL, and signs it using the given key. * Creates a new X.509 CRL, which is signed using the given key.
* *
* @param info the TBSCertList to sign
* @param key the private key used for signing. * @param key the private key used for signing.
* @param algorithm the name of the signature algorithm used. * @param algorithm the name of the signature algorithm used.
* @return a newly signed CRL
* *
* @exception NoSuchAlgorithmException on unsupported signature algorithms. * @exception NoSuchAlgorithmException on unsupported signature algorithms.
* @exception InvalidKeyException on incorrect key. * @exception InvalidKeyException on incorrect key.
@ -459,18 +581,20 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* @exception SignatureException on signature errors. * @exception SignatureException on signature errors.
* @exception CRLException if any mandatory data was omitted. * @exception CRLException if any mandatory data was omitted.
*/ */
public void sign(PrivateKey key, String algorithm) public static X509CRLImpl newSigned(TBSCertList info, PrivateKey key, String algorithm)
throws CRLException, NoSuchAlgorithmException, InvalidKeyException, throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
NoSuchProviderException, SignatureException { NoSuchProviderException, SignatureException {
sign(key, algorithm, null); return newSigned(info, key, algorithm, null);
} }
/** /**
* Encodes an X.509 CRL, and signs it using the given key. * Creates a new X.509 CRL, which is signed using the given key.
* *
* @param info the TBSCertList to sign
* @param key the private key used for signing. * @param key the private key used for signing.
* @param algorithm the name of the signature algorithm used. * @param algorithm the name of the signature algorithm used.
* @param provider (optional) the name of the provider. * @param provider (optional) the name of the provider.
* @return a newly signed CRL
* *
* @exception NoSuchAlgorithmException on unsupported signature algorithms. * @exception NoSuchAlgorithmException on unsupported signature algorithms.
* @exception InvalidKeyException on incorrect key. * @exception InvalidKeyException on incorrect key.
@ -478,36 +602,35 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* @exception SignatureException on signature errors. * @exception SignatureException on signature errors.
* @exception CRLException if any mandatory data was omitted. * @exception CRLException if any mandatory data was omitted.
*/ */
public void sign(PrivateKey key, String algorithm, String provider) public static X509CRLImpl newSigned(TBSCertList info, PrivateKey key, String algorithm, String provider)
throws CRLException, NoSuchAlgorithmException, InvalidKeyException, throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
NoSuchProviderException, SignatureException { NoSuchProviderException, SignatureException {
try { try {
if (readOnly)
throw new CRLException("cannot over-write existing CRL");
Signature sigEngine = SignatureUtil.fromKey(algorithm, key, provider); Signature sigEngine = SignatureUtil.fromKey(algorithm, key, provider);
sigAlgId = SignatureUtil.fromSignature(sigEngine, key); AlgorithmId sigAlgId = SignatureUtil.fromSignature(sigEngine, key);
infoSigAlgId = sigAlgId; info.infoSigAlgId = sigAlgId;
DerOutputStream out = new DerOutputStream(); DerOutputStream out = new DerOutputStream();
DerOutputStream tmp = new DerOutputStream(); DerOutputStream tmp = new DerOutputStream();
// encode crl info // encode crl info
encodeInfo(tmp); byte[] tbsCertList = info.encodeInfo();
tmp.writeBytes(tbsCertList);
// encode algorithm identifier // encode algorithm identifier
sigAlgId.encode(tmp); sigAlgId.encode(tmp);
// Create and encode the signature itself. // Create and encode the signature itself.
sigEngine.update(tbsCertList, 0, tbsCertList.length); sigEngine.update(tbsCertList, 0, tbsCertList.length);
signature = sigEngine.sign(); byte[] signature = sigEngine.sign();
tmp.putBitString(signature); tmp.putBitString(signature);
// Wrap the signed data in a SEQUENCE { data, algorithm, sig } // Wrap the signed data in a SEQUENCE { data, algorithm, sig }
out.write(DerValue.tag_Sequence, tmp); out.write(DerValue.tag_Sequence, tmp);
signedCRL = out.toByteArray(); byte[] signedCRL = out.toByteArray();
readOnly = true;
return new X509CRLImpl(info, sigAlgId, signature,
tbsCertList, signedCRL);
} catch (IOException e) { } catch (IOException e) {
throw new CRLException("Error while encoding data: " + throw new CRLException("Error while encoding data: " +
e.getMessage()); e.getMessage());
@ -527,7 +650,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
public String toStringWithAlgName(String name) { public String toStringWithAlgName(String name) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("X.509 CRL v") sb.append("X.509 CRL v")
.append(version+1) .append(info.version+1)
.append('\n'); .append('\n');
if (sigAlgId != null) if (sigAlgId != null)
sb.append("Signature Algorithm: ") sb.append("Signature Algorithm: ")
@ -535,33 +658,33 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
.append(", OID=") .append(", OID=")
.append(sigAlgId.getOID()) .append(sigAlgId.getOID())
.append('\n'); .append('\n');
if (issuer != null) if (info.issuer != null)
sb.append("Issuer: ") sb.append("Issuer: ")
.append(issuer) .append(info.issuer)
.append('\n'); .append('\n');
if (thisUpdate != null) if (info.thisUpdate != null)
sb.append("\nThis Update: ") sb.append("\nThis Update: ")
.append(thisUpdate) .append(info.thisUpdate)
.append('\n'); .append('\n');
if (nextUpdate != null) if (info.nextUpdate != null)
sb.append("Next Update: ") sb.append("Next Update: ")
.append(nextUpdate) .append(info.nextUpdate)
.append('\n'); .append('\n');
if (revokedList.isEmpty()) if (info.revokedList.isEmpty())
sb.append("\nNO certificates have been revoked\n"); sb.append("\nNO certificates have been revoked\n");
else { else {
sb.append("\nRevoked Certificates: ") sb.append("\nRevoked Certificates: ")
.append(revokedList.size()); .append(info.revokedList.size());
int i = 1; int i = 1;
for (X509CRLEntry entry: revokedList) { for (X509CRLEntry entry: info.revokedList) {
sb.append("\n[") sb.append("\n[")
.append(i++) .append(i++)
.append("] ") .append("] ")
.append(entry); .append(entry);
} }
} }
if (extensions != null) { if (info.extensions != null) {
Collection<Extension> allExts = extensions.getAllExtensions(); Collection<Extension> allExts = info.extensions.getAllExtensions();
Object[] objs = allExts.toArray(); Object[] objs = allExts.toArray();
sb.append("\nCRL Extensions: ") sb.append("\nCRL Extensions: ")
.append(objs.length); .append(objs.length);
@ -609,12 +732,12 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* false otherwise. * false otherwise.
*/ */
public boolean isRevoked(Certificate cert) { public boolean isRevoked(Certificate cert) {
if (revokedMap.isEmpty() || if (info.revokedMap.isEmpty() ||
(!(cert instanceof X509Certificate xcert))) { (!(cert instanceof X509Certificate xcert))) {
return false; return false;
} }
X509IssuerSerial issuerSerial = new X509IssuerSerial(xcert); X509IssuerSerial issuerSerial = new X509IssuerSerial(xcert);
return revokedMap.containsKey(issuerSerial); return info.revokedMap.containsKey(issuerSerial);
} }
/** /**
@ -628,7 +751,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* @return the version number, i.e. 1 or 2. * @return the version number, i.e. 1 or 2.
*/ */
public int getVersion() { public int getVersion() {
return version+1; return info.version+1;
} }
/** /**
@ -661,7 +784,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public Principal getIssuerDN() { public Principal getIssuerDN() {
return issuer; return info.issuer;
} }
/** /**
@ -669,10 +792,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* to provide a slightly more efficient version. * to provide a slightly more efficient version.
*/ */
public X500Principal getIssuerX500Principal() { public X500Principal getIssuerX500Principal() {
if (issuerPrincipal == null) { return info.getIssuerX500Principal();
issuerPrincipal = issuer.asX500Principal();
}
return issuerPrincipal;
} }
/** /**
@ -682,7 +802,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* @return the thisUpdate date from the CRL. * @return the thisUpdate date from the CRL.
*/ */
public Date getThisUpdate() { public Date getThisUpdate() {
return new Date(thisUpdate.getTime()); return new Date(info.thisUpdate.getTime());
} }
/** /**
@ -692,9 +812,9 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* not present. * not present.
*/ */
public Date getNextUpdate() { public Date getNextUpdate() {
if (nextUpdate == null) if (info.nextUpdate == null)
return null; return null;
return new Date(nextUpdate.getTime()); return new Date(info.nextUpdate.getTime());
} }
/** /**
@ -705,24 +825,24 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* @see X509CRLEntry * @see X509CRLEntry
*/ */
public X509CRLEntry getRevokedCertificate(BigInteger serialNumber) { public X509CRLEntry getRevokedCertificate(BigInteger serialNumber) {
if (revokedMap.isEmpty()) { if (info.revokedMap.isEmpty()) {
return null; return null;
} }
// assume this is a direct CRL entry (cert and CRL issuer are the same) // assume this is a direct CRL entry (cert and CRL issuer are the same)
X509IssuerSerial issuerSerial = new X509IssuerSerial X509IssuerSerial issuerSerial = new X509IssuerSerial
(getIssuerX500Principal(), serialNumber); (getIssuerX500Principal(), serialNumber);
return revokedMap.get(issuerSerial); return info.revokedMap.get(issuerSerial);
} }
/** /**
* Gets the CRL entry for the given certificate. * Gets the CRL entry for the given certificate.
*/ */
public X509CRLEntry getRevokedCertificate(X509Certificate cert) { public X509CRLEntry getRevokedCertificate(X509Certificate cert) {
if (revokedMap.isEmpty()) { if (info.revokedMap.isEmpty()) {
return null; return null;
} }
X509IssuerSerial issuerSerial = new X509IssuerSerial(cert); X509IssuerSerial issuerSerial = new X509IssuerSerial(cert);
return revokedMap.get(issuerSerial); return info.revokedMap.get(issuerSerial);
} }
/** /**
@ -734,10 +854,10 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* @see X509CRLEntry * @see X509CRLEntry
*/ */
public Set<X509CRLEntry> getRevokedCertificates() { public Set<X509CRLEntry> getRevokedCertificates() {
if (revokedList.isEmpty()) { if (info.revokedList.isEmpty()) {
return null; return null;
} else { } else {
return new TreeSet<>(revokedList); return new TreeSet<>(info.revokedList);
} }
} }
@ -929,9 +1049,9 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* not supported, otherwise return false. * not supported, otherwise return false.
*/ */
public boolean hasUnsupportedCriticalExtension() { public boolean hasUnsupportedCriticalExtension() {
if (extensions == null) if (info.extensions == null)
return false; return false;
return extensions.hasUnsupportedCriticalExtension(); return info.extensions.hasUnsupportedCriticalExtension();
} }
/** /**
@ -943,11 +1063,11 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* CRL that are marked critical. * CRL that are marked critical.
*/ */
public Set<String> getCriticalExtensionOIDs() { public Set<String> getCriticalExtensionOIDs() {
if (extensions == null) { if (info.extensions == null) {
return null; return null;
} }
Set<String> extSet = new TreeSet<>(); Set<String> extSet = new TreeSet<>();
for (Extension ex : extensions.getAllExtensions()) { for (Extension ex : info.extensions.getAllExtensions()) {
if (ex.isCritical()) { if (ex.isCritical()) {
extSet.add(ex.getExtensionId().toString()); extSet.add(ex.getExtensionId().toString());
} }
@ -964,11 +1084,11 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* CRL that are NOT marked critical. * CRL that are NOT marked critical.
*/ */
public Set<String> getNonCriticalExtensionOIDs() { public Set<String> getNonCriticalExtensionOIDs() {
if (extensions == null) { if (info.extensions == null) {
return null; return null;
} }
Set<String> extSet = new TreeSet<>(); Set<String> extSet = new TreeSet<>();
for (Extension ex : extensions.getAllExtensions()) { for (Extension ex : info.extensions.getAllExtensions()) {
if (!ex.isCritical()) { if (!ex.isCritical()) {
extSet.add(ex.getExtensionId().toString()); extSet.add(ex.getExtensionId().toString());
} }
@ -988,7 +1108,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* @return the der encoded octet string of the extension value. * @return the der encoded octet string of the extension value.
*/ */
public byte[] getExtensionValue(String oid) { public byte[] getExtensionValue(String oid) {
if (extensions == null) if (info.extensions == null)
return null; return null;
try { try {
String extAlias = OIDMap.getName(ObjectIdentifier.of(oid)); String extAlias = OIDMap.getName(ObjectIdentifier.of(oid));
@ -996,7 +1116,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
if (extAlias == null) { // may be unknown if (extAlias == null) { // may be unknown
ObjectIdentifier findOID = ObjectIdentifier.of(oid); ObjectIdentifier findOID = ObjectIdentifier.of(oid);
for (Extension ex : extensions.getAllExtensions()) { for (Extension ex : info.extensions.getAllExtensions()) {
ObjectIdentifier inCertOID = ex.getExtensionId(); ObjectIdentifier inCertOID = ex.getExtensionId();
if (inCertOID.equals(findOID)) { if (inCertOID.equals(findOID)) {
crlExt = ex; crlExt = ex;
@ -1004,7 +1124,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
} }
} }
} else } else
crlExt = extensions.getExtension(extAlias); crlExt = info.extensions.getExtension(extAlias);
if (crlExt == null) if (crlExt == null)
return null; return null;
byte[] extData = crlExt.getExtensionValue(); byte[] extData = crlExt.getExtensionValue();
@ -1025,20 +1145,17 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
* @return Object of type {@code <extension>} or null, if not found * @return Object of type {@code <extension>} or null, if not found
*/ */
public Object getExtension(ObjectIdentifier oid) { public Object getExtension(ObjectIdentifier oid) {
if (extensions == null) if (info.extensions == null)
return null; return null;
// XXX Consider cloning this // XXX Consider cloning this
return extensions.getExtension(OIDMap.getName(oid)); return info.extensions.getExtension(OIDMap.getName(oid));
} }
/* /*
* Parses an X.509 CRL, should be used only by constructors. * Parses an X.509 CRL, should be used only by constructors.
*/ */
private void parse(DerValue val) throws CRLException, IOException { private void parse(DerValue val) throws CRLException, IOException {
// check if we can overwrite the certificate
if (readOnly)
throw new CRLException("cannot over-write existing CRL");
if ( val.getData() == null || val.tag != DerValue.tag_Sequence) if ( val.getData() == null || val.tag != DerValue.tag_Sequence)
throw new CRLException("Invalid DER-encoded CRL data"); throw new CRLException("Invalid DER-encoded CRL data");
@ -1054,10 +1171,14 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
throw new CRLException("signed overrun, bytes = " throw new CRLException("signed overrun, bytes = "
+ val.data.available()); + val.data.available());
if (seq[0].tag != DerValue.tag_Sequence) info = new TBSCertList(seq[0]);
throw new CRLException("signed CRL fields invalid");
sigAlgId = AlgorithmId.parse(seq[1]); sigAlgId = AlgorithmId.parse(seq[1]);
// the "inner" and "outer" signature algorithms must match
if (!sigAlgId.equals(info.infoSigAlgId)) {
throw new CRLException("Signature algorithm mismatch");
}
signature = seq[2].getBitString(); signature = seq[2].getBitString();
if (seq[1].data.available() != 0) if (seq[1].data.available() != 0)
@ -1069,90 +1190,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
// the tbsCertsList // the tbsCertsList
tbsCertList = seq[0].toByteArray(); tbsCertList = seq[0].toByteArray();
// parse the information
DerInputStream derStrm = seq[0].data;
DerValue tmp;
byte nextByte;
// version (optional if v1)
version = 0; // by default, version = v1 == 0
nextByte = (byte)derStrm.peekByte();
if (nextByte == DerValue.tag_Integer) {
version = derStrm.getInteger();
if (version != 1) // i.e. v2
throw new CRLException("Invalid version");
}
tmp = derStrm.getDerValue();
// signature
AlgorithmId tmpId = AlgorithmId.parse(tmp);
// the "inner" and "outer" signature algorithms must match
if (! tmpId.equals(sigAlgId))
throw new CRLException("Signature algorithm mismatch");
infoSigAlgId = tmpId;
// issuer
issuer = new X500Name(derStrm);
if (issuer.isEmpty()) {
throw new CRLException("Empty issuer DN not allowed in X509CRLs");
}
// thisUpdate
// check if UTCTime encoded or GeneralizedTime
nextByte = (byte)derStrm.peekByte();
if (nextByte == DerValue.tag_UtcTime) {
thisUpdate = derStrm.getUTCTime();
} else if (nextByte == DerValue.tag_GeneralizedTime) {
thisUpdate = derStrm.getGeneralizedTime();
} else {
throw new CRLException("Invalid encoding for thisUpdate"
+ " (tag=" + nextByte + ")");
}
if (derStrm.available() == 0)
return; // done parsing no more optional fields present
// nextUpdate (optional)
nextByte = (byte)derStrm.peekByte();
if (nextByte == DerValue.tag_UtcTime) {
nextUpdate = derStrm.getUTCTime();
} else if (nextByte == DerValue.tag_GeneralizedTime) {
nextUpdate = derStrm.getGeneralizedTime();
} // else it is not present
if (derStrm.available() == 0)
return; // done parsing no more optional fields present
// revokedCertificates (optional)
nextByte = (byte)derStrm.peekByte();
if ((nextByte == DerValue.tag_SequenceOf)
&& (! ((nextByte & 0x0c0) == 0x080))) {
DerValue[] badCerts = derStrm.getSequence(4);
X500Principal crlIssuer = getIssuerX500Principal();
X500Principal badCertIssuer = crlIssuer;
for (int i = 0; i < badCerts.length; i++) {
X509CRLEntryImpl entry = new X509CRLEntryImpl(badCerts[i]);
badCertIssuer = getCertIssuer(entry, badCertIssuer);
entry.setCertificateIssuer(crlIssuer, badCertIssuer);
X509IssuerSerial issuerSerial = new X509IssuerSerial
(badCertIssuer, entry.getSerialNumber());
revokedMap.put(issuerSerial, entry);
revokedList.add(entry);
}
}
if (derStrm.available() == 0)
return; // done parsing no extensions
// crlExtensions (optional)
tmp = derStrm.getDerValue();
if (tmp.isConstructed() && tmp.isContextSpecific((byte)0)) {
extensions = new CRLExtensions(tmp.data);
}
readOnly = true;
} }
/** /**
@ -1212,32 +1250,8 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
} }
} }
/**
* Returns the X500 certificate issuer DN of a CRL entry.
*
* @param entry the entry to check
* @param prevCertIssuer the previous entry's certificate issuer
* @return the X500Principal in a CertificateIssuerExtension, or
* prevCertIssuer if it does not exist
*/
private X500Principal getCertIssuer(X509CRLEntryImpl entry,
X500Principal prevCertIssuer) {
CertificateIssuerExtension ciExt =
entry.getCertificateIssuerExtension();
if (ciExt != null) {
GeneralNames names = ciExt.getNames();
X500Name issuerDN = (X500Name) names.get(0).getName();
return issuerDN.asX500Principal();
} else {
return prevCertIssuer;
}
}
@Override @Override
public void encode(DerOutputStream out) throws IOException { public void encode(DerOutputStream out) throws IOException {
if (signedCRL == null)
throw new IOException("Null CRL to encode");
out.write(signedCRL.clone()); out.write(signedCRL.clone());
} }

View file

@ -25,12 +25,7 @@
package sun.security.x509; package sun.security.x509;
import java.io.BufferedReader; import java.io.*;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.*; import java.security.*;
import java.security.cert.*; import java.security.cert.*;
@ -79,10 +74,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
public static final String NAME = "x509"; public static final String NAME = "x509";
// when we sign and decode we set this to true
// this is our means to make certificates immutable
private boolean readOnly = false;
// Certificate data, and its envelope // Certificate data, and its envelope
private byte[] signedCert = null; private byte[] signedCert = null;
protected X509CertInfo info = null; protected X509CertInfo info = null;
@ -124,9 +115,16 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
private boolean verificationResult; private boolean verificationResult;
/** /**
* Default constructor. * Constructor simply setting all (non-cache) fields. Only used in
* {@link #newSigned}.
*/ */
public X509CertImpl() { } public X509CertImpl(X509CertInfo info, AlgorithmId algId, byte[] signature,
byte[] signedCert) {
this.info = info;
this.algId = algId;
this.signature = signature;
this.signedCert = Objects.requireNonNull(signedCert);
}
/** /**
* Unmarshals a certificate from its encoded form, parsing the * Unmarshals a certificate from its encoded form, parsing the
@ -144,13 +142,28 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
try { try {
parse(new DerValue(certData)); parse(new DerValue(certData));
} catch (IOException e) { } catch (IOException e) {
signedCert = null;
throw new CertificateException("Unable to initialize, " + e, e); throw new CertificateException("Unable to initialize, " + e, e);
} }
} }
/** /**
* unmarshals an X.509 certificate from an input stream. If the * Unmarshals a certificate from its encoded form, parsing a DER value.
* This form of constructor is used by agents which need to examine
* and use certificate contents.
*
* @param derVal the der value containing the encoded cert.
* @exception CertificateException on parsing and initialization errors.
*/
public X509CertImpl(DerValue derVal) throws CertificateException {
try {
parse(derVal);
} catch (IOException e) {
throw new CertificateException("Unable to initialize, " + e, e);
}
}
/**
* Unmarshals an X.509 certificate from an input stream. If the
* certificate is RFC1421 hex-encoded, then it must begin with * certificate is RFC1421 hex-encoded, then it must begin with
* the line X509Factory.BEGIN_CERT and end with the line * the line X509Factory.BEGIN_CERT and end with the line
* X509Factory.END_CERT. * X509Factory.END_CERT.
@ -235,37 +248,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
return der; return der;
} }
/**
* Construct an initialized X509 Certificate. The certificate is stored
* in raw form and has to be signed to be useful.
*
* The ALGORITHM_ID attribute will be rewritten when signed. The initial
* value is ignored.
*
* @param certInfo the X509CertificateInfo which the Certificate is to be
* created from.
*/
public X509CertImpl(X509CertInfo certInfo) {
this.info = certInfo;
}
/**
* Unmarshal a certificate from its encoded form, parsing a DER value.
* This form of constructor is used by agents which need to examine
* and use certificate contents.
*
* @param derVal the der value containing the encoded cert.
* @exception CertificateException on parsing and initialization errors.
*/
public X509CertImpl(DerValue derVal) throws CertificateException {
try {
parse(derVal);
} catch (IOException e) {
signedCert = null;
throw new CertificateException("Unable to initialize, " + e, e);
}
}
// helper method to record certificate, if necessary, after construction // helper method to record certificate, if necessary, after construction
public static X509CertImpl newX509CertImpl(byte[] certData) throws CertificateException { public static X509CertImpl newX509CertImpl(byte[] certData) throws CertificateException {
var cert = new X509CertImpl(certData); var cert = new X509CertImpl(certData);
@ -283,8 +265,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
*/ */
@Override @Override
public void encode(DerOutputStream out) throws IOException { public void encode(DerOutputStream out) throws IOException {
if (signedCert == null)
throw new IOException("Null certificate to encode");
out.write(signedCert.clone()); out.write(signedCert.clone());
} }
@ -306,10 +286,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
* code. * code.
*/ */
public byte[] getEncodedInternal() throws CertificateEncodingException { public byte[] getEncodedInternal() throws CertificateEncodingException {
if (signedCert == null) {
throw new CertificateEncodingException(
"Null certificate to encode");
}
return signedCert; return signedCert;
} }
@ -367,9 +343,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
} }
} }
} }
if (signedCert == null) {
throw new CertificateEncodingException("Uninitialized certificate");
}
// Verify the signature ... // Verify the signature ...
Signature sigVerf; Signature sigVerf;
String sigName = algId.getName(); String sigName = algId.getName();
@ -421,9 +394,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
public synchronized void verify(PublicKey key, Provider sigProvider) public synchronized void verify(PublicKey key, Provider sigProvider)
throws CertificateException, NoSuchAlgorithmException, throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, SignatureException { InvalidKeyException, SignatureException {
if (signedCert == null) {
throw new CertificateEncodingException("Uninitialized certificate");
}
// Verify the signature ... // Verify the signature ...
Signature sigVerf; Signature sigVerf;
String sigName = algId.getName(); String sigName = algId.getName();
@ -455,13 +425,15 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
} }
/** /**
* Creates an X.509 certificate, and signs it using the given key * Creates a new X.509 certificate, which is signed using the given key
* (associating a signature algorithm and an X.500 name). * (associating a signature algorithm and an X.500 name).
* This operation is used to implement the certificate generation * This operation is used to implement the certificate generation
* functionality of a certificate authority. * functionality of a certificate authority.
* *
* @param info the X509CertInfo to sign
* @param key the private key used for signing. * @param key the private key used for signing.
* @param algorithm the name of the signature algorithm used. * @param algorithm the name of the signature algorithm used.
* @return the newly signed certificate
* *
* @exception InvalidKeyException on incorrect key. * @exception InvalidKeyException on incorrect key.
* @exception NoSuchAlgorithmException on unsupported signature algorithms. * @exception NoSuchAlgorithmException on unsupported signature algorithms.
@ -469,21 +441,23 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
* @exception SignatureException on signature errors. * @exception SignatureException on signature errors.
* @exception CertificateException on encoding errors. * @exception CertificateException on encoding errors.
*/ */
public void sign(PrivateKey key, String algorithm) public static X509CertImpl newSigned(X509CertInfo info, PrivateKey key, String algorithm)
throws CertificateException, NoSuchAlgorithmException, throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException, SignatureException { InvalidKeyException, NoSuchProviderException, SignatureException {
sign(key, algorithm, null); return newSigned(info, key, algorithm, null);
} }
/** /**
* Creates an X.509 certificate, and signs it using the given key * Creates a new X.509 certificate, which is signed using the given key
* (associating a signature algorithm and an X.500 name). * (associating a signature algorithm and an X.500 name).
* This operation is used to implement the certificate generation * This operation is used to implement the certificate generation
* functionality of a certificate authority. * functionality of a certificate authority.
* *
* @param info the X509CertInfo to sign
* @param key the private key used for signing. * @param key the private key used for signing.
* @param algorithm the name of the signature algorithm used. * @param algorithm the name of the signature algorithm used.
* @param provider (optional) the name of the provider. * @param provider (optional) the name of the provider.
* @return the newly signed certificate
* *
* @exception NoSuchAlgorithmException on unsupported signature algorithms. * @exception NoSuchAlgorithmException on unsupported signature algorithms.
* @exception InvalidKeyException on incorrect key. * @exception InvalidKeyException on incorrect key.
@ -491,17 +465,13 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
* @exception SignatureException on signature errors. * @exception SignatureException on signature errors.
* @exception CertificateException on encoding errors. * @exception CertificateException on encoding errors.
*/ */
public void sign(PrivateKey key, String algorithm, String provider) public static X509CertImpl newSigned(X509CertInfo info, PrivateKey key, String algorithm, String provider)
throws CertificateException, NoSuchAlgorithmException, throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException, SignatureException { InvalidKeyException, NoSuchProviderException, SignatureException {
try { try {
if (readOnly) {
throw new CertificateEncodingException(
"cannot over-write existing certificate");
}
Signature sigEngine = SignatureUtil.fromKey( Signature sigEngine = SignatureUtil.fromKey(
algorithm, key, provider); algorithm, key, provider);
algId = SignatureUtil.fromSignature(sigEngine, key); AlgorithmId algId = SignatureUtil.fromSignature(sigEngine, key);
DerOutputStream out = new DerOutputStream(); DerOutputStream out = new DerOutputStream();
DerOutputStream tmp = new DerOutputStream(); DerOutputStream tmp = new DerOutputStream();
@ -516,14 +486,14 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
// Create and encode the signature itself. // Create and encode the signature itself.
sigEngine.update(rawCert, 0, rawCert.length); sigEngine.update(rawCert, 0, rawCert.length);
signature = sigEngine.sign(); byte[] signature = sigEngine.sign();
tmp.putBitString(signature); tmp.putBitString(signature);
// Wrap the signed data in a SEQUENCE { data, algorithm, sig } // Wrap the signed data in a SEQUENCE { data, algorithm, sig }
out.write(DerValue.tag_Sequence, tmp); out.write(DerValue.tag_Sequence, tmp);
signedCert = out.toByteArray(); byte[] signedCert = out.toByteArray();
readOnly = true;
return new X509CertImpl(info, algId, signature, signedCert);
} catch (IOException e) { } catch (IOException e) {
throw new CertificateEncodingException(e.toString()); throw new CertificateEncodingException(e.toString());
} }
@ -1160,7 +1130,7 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
@Override @Override
public synchronized List<String> getExtendedKeyUsage() public synchronized List<String> getExtendedKeyUsage()
throws CertificateParsingException { throws CertificateParsingException {
if (readOnly && extKeyUsage != null) { if (extKeyUsage != null) {
return extKeyUsage; return extKeyUsage;
} }
ExtendedKeyUsageExtension ext = (ExtendedKeyUsageExtension) ExtendedKeyUsageExtension ext = (ExtendedKeyUsageExtension)
@ -1351,7 +1321,7 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
public synchronized Collection<List<?>> getSubjectAlternativeNames() public synchronized Collection<List<?>> getSubjectAlternativeNames()
throws CertificateParsingException { throws CertificateParsingException {
// return cached value if we can // return cached value if we can
if (readOnly && subjectAlternativeNames != null) { if (subjectAlternativeNames != null) {
return cloneAltNames(subjectAlternativeNames); return cloneAltNames(subjectAlternativeNames);
} }
SubjectAlternativeNameExtension subjectAltNameExt = SubjectAlternativeNameExtension subjectAltNameExt =
@ -1403,7 +1373,7 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
public synchronized Collection<List<?>> getIssuerAlternativeNames() public synchronized Collection<List<?>> getIssuerAlternativeNames()
throws CertificateParsingException { throws CertificateParsingException {
// return cached value if we can // return cached value if we can
if (readOnly && issuerAlternativeNames != null) { if (issuerAlternativeNames != null) {
return cloneAltNames(issuerAlternativeNames); return cloneAltNames(issuerAlternativeNames);
} }
IssuerAlternativeNameExtension issuerAltNameExt = IssuerAlternativeNameExtension issuerAltNameExt =
@ -1465,9 +1435,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
private void parse(DerValue val) private void parse(DerValue val)
throws CertificateException, IOException { throws CertificateException, IOException {
// check if we can overwrite the certificate // check if we can overwrite the certificate
if (readOnly)
throw new CertificateParsingException(
"cannot over-write existing certificate");
if (val.data == null || val.tag != DerValue.tag_Sequence) if (val.data == null || val.tag != DerValue.tag_Sequence)
throw new CertificateParsingException( throw new CertificateParsingException(
@ -1504,7 +1471,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
AlgorithmId infoSigAlg = info.getAlgorithmId().getAlgId(); AlgorithmId infoSigAlg = info.getAlgorithmId().getAlgId();
if (! algId.equals(infoSigAlg)) if (! algId.equals(infoSigAlg))
throw new CertificateException("Signature algorithm mismatch"); throw new CertificateException("Signature algorithm mismatch");
readOnly = true;
} }
/** /**

View file

@ -79,9 +79,10 @@ public class EdCRLSign {
System.out.printf("Case Algo:%s, Param:%s, Intitiate with random:%s%n", System.out.printf("Case Algo:%s, Param:%s, Intitiate with random:%s%n",
name, param, initWithRandom); name, param, initWithRandom);
KeyPair kp = genKeyPair(provider, name, param, initWithRandom); KeyPair kp = genKeyPair(provider, name, param, initWithRandom);
X509CRLImpl crl = new X509CRLImpl( X509CRLImpl crl = X509CRLImpl.newSigned(
new X500Name("CN=Issuer"), new Date(), new Date()); new X509CRLImpl.TBSCertList(new X500Name("CN=Issuer"),
crl.sign(kp.getPrivate(), name); new Date(), new Date()),
kp.getPrivate(), name);
crl.verify(kp.getPublic()); crl.verify(kp.getPublic());
System.out.println("Passed."); System.out.println("Passed.");
} }

View file

@ -254,8 +254,7 @@ class SimpleSigner {
info.setValidity(interval); info.setValidity(interval);
info.setIssuer(agent); info.setIssuer(agent);
certLocal = new X509CertImpl(info); certLocal = X509CertImpl.newSigned(info, privateKey, algId.getName());
certLocal.sign(privateKey, algId.getName());
return certLocal; return certLocal;
} }

View file

@ -69,8 +69,9 @@ public class BigCRL {
badCerts[i] = new X509CRLEntryImpl( badCerts[i] = new X509CRLEntryImpl(
BigInteger.valueOf(i), date, ext); BigInteger.valueOf(i), date, ext);
} }
X509CRLImpl crl = new X509CRLImpl(owner, date, date, badCerts); X509CRLImpl crl = X509CRLImpl.newSigned(
crl.sign(privateKey, sigAlgName); new X509CRLImpl.TBSCertList(owner, date, date, badCerts),
privateKey, sigAlgName);
byte[] data = crl.getEncodedInternal(); byte[] data = crl.getEncodedInternal();
// Make sure the CRL is big enough // Make sure the CRL is big enough

View file

@ -49,8 +49,8 @@ public class DefaultParamSpec {
new MGF1ParameterSpec("SHA-384"), new MGF1ParameterSpec("SHA-384"),
48, PSSParameterSpec.TRAILER_FIELD_BC))); 48, PSSParameterSpec.TRAILER_FIELD_BC)));
X509CRLImpl crl = new X509CRLImpl( X509CRLImpl crl = X509CRLImpl.newSigned(
new X500Name("CN=Issuer"), new Date(), new Date()); new X509CRLImpl.TBSCertList(new X500Name("CN=Issuer"), new Date(), new Date()),
crl.sign(kpg.generateKeyPair().getPrivate(), "RSASSA-PSS"); kpg.generateKeyPair().getPrivate(), "RSASSA-PSS");
} }
} }

View file

@ -225,7 +225,7 @@ public class TestHostnameChecker {
} }
private static X509Certificate mock(String domain) { private static X509Certificate mock(String domain) {
return new X509CertImpl() { return new X509CertImpl(null, null, null, new byte[0]) {
@Override @Override
public Collection<List<?>> getSubjectAlternativeNames() { public Collection<List<?>> getSubjectAlternativeNames() {
return List.of(List.of(2, domain)); return List.of(List.of(2, domain));

View file

@ -55,9 +55,10 @@ public class OrderAndDup {
new Date(System.currentTimeMillis()+i*1000)); new Date(System.currentTimeMillis()+i*1000));
} }
X500Name owner = new X500Name("CN=CA"); X500Name owner = new X500Name("CN=CA");
X509CRLImpl crl = new X509CRLImpl(owner, new Date(), new Date(), badCerts);
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
crl.sign(kpg.genKeyPair().getPrivate(), "SHA1withRSA"); X509CRLImpl crl = X509CRLImpl.newSigned(
new X509CRLImpl.TBSCertList(owner, new Date(), new Date(), badCerts),
kpg.genKeyPair().getPrivate(), "SHA1withRSA");
byte[] data = crl.getEncodedInternal(); byte[] data = crl.getEncodedInternal();
// Check the encoding // Check the encoding

View file

@ -205,8 +205,7 @@ public class V3Certificate {
cert.setExtensions(exts); cert.setExtensions(exts);
// Generate and sign X509CertImpl // Generate and sign X509CertImpl
X509CertImpl crt = new X509CertImpl(cert); X509CertImpl crt = X509CertImpl.newSigned(cert, privateKey, sigAlg);
crt.sign(privateKey, sigAlg);
crt.verify(publicKey); crt.verify(publicKey);
try (FileOutputStream fos = new FileOutputStream(new File(V3_FILE)); try (FileOutputStream fos = new FileOutputStream(new File(V3_FILE));