diff options
Diffstat (limited to 'prov/src/main/jdk1.3/org/spongycastle/x509')
11 files changed, 4035 insertions, 0 deletions
diff --git a/prov/src/main/jdk1.3/org/spongycastle/x509/AttributeCertificateHolder.java b/prov/src/main/jdk1.3/org/spongycastle/x509/AttributeCertificateHolder.java new file mode 100644 index 00000000..5b161b4d --- /dev/null +++ b/prov/src/main/jdk1.3/org/spongycastle/x509/AttributeCertificateHolder.java @@ -0,0 +1,406 @@ +package org.spongycastle.x509; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.Principal; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.GeneralName; +import org.spongycastle.asn1.x509.GeneralNames; +import org.spongycastle.asn1.x509.Holder; +import org.spongycastle.asn1.x509.IssuerSerial; +import org.spongycastle.asn1.x509.ObjectDigestInfo; +import org.spongycastle.jce.PrincipalUtil; +import org.spongycastle.jce.X509Principal; +import org.spongycastle.jce.cert.CertSelector; +import org.spongycastle.util.Arrays; +import org.spongycastle.util.Selector; + +/** + * The Holder object. + * + * <pre> + * Holder ::= SEQUENCE { + * baseCertificateID [0] IssuerSerial OPTIONAL, + * -- the issuer and serial number of + * -- the holder's Public Key Certificate + * entityName [1] GeneralNames OPTIONAL, + * -- the name of the claimant or role + * objectDigestInfo [2] ObjectDigestInfo OPTIONAL + * -- used to directly authenticate the holder, + * -- for example, an executable + * } + * </pre> + * @deprecated use org.spongycastle.cert.AttributeCertificateHolder + */ +public class AttributeCertificateHolder + implements CertSelector, Selector +{ + final Holder holder; + + AttributeCertificateHolder(ASN1Sequence seq) + { + holder = Holder.getInstance(seq); + } + + public AttributeCertificateHolder(X509Principal issuerName, + BigInteger serialNumber) + { + holder = new org.spongycastle.asn1.x509.Holder(new IssuerSerial( + new GeneralNames(new GeneralName(issuerName)), + new ASN1Integer(serialNumber))); + } + + public AttributeCertificateHolder(X509Certificate cert) + throws CertificateParsingException + { + X509Principal name; + + try + { + name = PrincipalUtil.getIssuerX509Principal(cert); + } + catch (Exception e) + { + throw new CertificateParsingException(e.getMessage()); + } + + holder = new Holder(new IssuerSerial(generateGeneralNames(name), + new ASN1Integer(cert.getSerialNumber()))); + } + + public AttributeCertificateHolder(X509Principal principal) + { + holder = new Holder(generateGeneralNames(principal)); + } + + /** + * Constructs a holder for v2 attribute certificates with a hash value for + * some type of object. + * <p> + * <code>digestedObjectType</code> can be one of the following: + * <ul> + * <li>0 - publicKey - A hash of the public key of the holder must be + * passed. + * <li>1 - publicKeyCert - A hash of the public key certificate of the + * holder must be passed. + * <li>2 - otherObjectDigest - A hash of some other object type must be + * passed. <code>otherObjectTypeID</code> must not be empty. + * </ul> + * <p> + * This cannot be used if a v1 attribute certificate is used. + * + * @param digestedObjectType The digest object type. + * @param digestAlgorithm The algorithm identifier for the hash. + * @param otherObjectTypeID The object type ID if + * <code>digestedObjectType</code> is + * <code>otherObjectDigest</code>. + * @param objectDigest The hash value. + */ + public AttributeCertificateHolder(int digestedObjectType, + String digestAlgorithm, String otherObjectTypeID, byte[] objectDigest) + { + holder = new Holder(new ObjectDigestInfo(digestedObjectType, + new ASN1ObjectIdentifier(otherObjectTypeID), new AlgorithmIdentifier(digestAlgorithm), Arrays + .clone(objectDigest))); + } + + /** + * Returns the digest object type if an object digest info is used. + * <p> + * <ul> + * <li>0 - publicKey - A hash of the public key of the holder must be + * passed. + * <li>1 - publicKeyCert - A hash of the public key certificate of the + * holder must be passed. + * <li>2 - otherObjectDigest - A hash of some other object type must be + * passed. <code>otherObjectTypeID</code> must not be empty. + * </ul> + * + * @return The digest object type or -1 if no object digest info is set. + */ + public int getDigestedObjectType() + { + if (holder.getObjectDigestInfo() != null) + { + return holder.getObjectDigestInfo().getDigestedObjectType() + .getValue().intValue(); + } + return -1; + } + + /** + * Returns the other object type ID if an object digest info is used. + * + * @return The other object type ID or <code>null</code> if no object + * digest info is set. + */ + public String getDigestAlgorithm() + { + if (holder.getObjectDigestInfo() != null) + { + return holder.getObjectDigestInfo().getDigestAlgorithm().getObjectId() + .getId(); + } + return null; + } + + /** + * Returns the hash if an object digest info is used. + * + * @return The hash or <code>null</code> if no object digest info is set. + */ + public byte[] getObjectDigest() + { + if (holder.getObjectDigestInfo() != null) + { + return holder.getObjectDigestInfo().getObjectDigest().getBytes(); + } + return null; + } + + /** + * Returns the digest algorithm ID if an object digest info is used. + * + * @return The digest algorithm ID or <code>null</code> if no object + * digest info is set. + */ + public String getOtherObjectTypeID() + { + if (holder.getObjectDigestInfo() != null) + { + holder.getObjectDigestInfo().getOtherObjectTypeID().getId(); + } + return null; + } + + private GeneralNames generateGeneralNames(X509Principal principal) + { + return new GeneralNames(new GeneralName(principal)); + } + + private boolean matchesDN(X509Principal subject, GeneralNames targets) + { + GeneralName[] names = targets.getNames(); + + for (int i = 0; i != names.length; i++) + { + GeneralName gn = names[i]; + + if (gn.getTagNo() == GeneralName.directoryName) + { + try + { + if (new X509Principal(((ASN1Encodable)gn.getName()).toASN1Primitive() + .getEncoded()).equals(subject)) + { + return true; + } + } + catch (IOException e) + { + } + } + } + + return false; + } + + private Object[] getNames(GeneralName[] names) + { + List l = new ArrayList(names.length); + + for (int i = 0; i != names.length; i++) + { + if (names[i].getTagNo() == GeneralName.directoryName) + { + try + { + l.add(new X509Principal( + ((ASN1Encodable)names[i].getName()).toASN1Primitive().getEncoded())); + } + catch (IOException e) + { + throw new RuntimeException("badly formed Name object"); + } + } + } + + return l.toArray(new Object[l.size()]); + } + + private Principal[] getPrincipals(GeneralNames names) + { + Object[] p = this.getNames(names.getNames()); + List l = new ArrayList(); + + for (int i = 0; i != p.length; i++) + { + if (p[i] instanceof Principal) + { + l.add(p[i]); + } + } + + return (Principal[])l.toArray(new Principal[l.size()]); + } + + /** + * Return any principal objects inside the attribute certificate holder + * entity names field. + * + * @return an array of Principal objects (usually X509Principal), null if no + * entity names field is set. + */ + public Principal[] getEntityNames() + { + if (holder.getEntityName() != null) + { + return getPrincipals(holder.getEntityName()); + } + + return null; + } + + /** + * Return the principals associated with the issuer attached to this holder + * + * @return an array of principals, null if no BaseCertificateID is set. + */ + public Principal[] getIssuer() + { + if (holder.getBaseCertificateID() != null) + { + return getPrincipals(holder.getBaseCertificateID().getIssuer()); + } + + return null; + } + + /** + * Return the serial number associated with the issuer attached to this + * holder. + * + * @return the certificate serial number, null if no BaseCertificateID is + * set. + */ + public BigInteger getSerialNumber() + { + if (holder.getBaseCertificateID() != null) + { + return holder.getBaseCertificateID().getSerial().getValue(); + } + + return null; + } + + public Object clone() + { + return new AttributeCertificateHolder((ASN1Sequence)holder + .toASN1Object()); + } + + public boolean match(Certificate cert) + { + if (!(cert instanceof X509Certificate)) + { + return false; + } + + X509Certificate x509Cert = (X509Certificate)cert; + + try + { + if (holder.getBaseCertificateID() != null) + { + return holder.getBaseCertificateID().getSerial().getValue().equals(x509Cert.getSerialNumber()) + && matchesDN(PrincipalUtil.getIssuerX509Principal(x509Cert), holder.getBaseCertificateID().getIssuer()); + } + + if (holder.getEntityName() != null) + { + if (matchesDN(PrincipalUtil.getSubjectX509Principal(x509Cert), + holder.getEntityName())) + { + return true; + } + } + if (holder.getObjectDigestInfo() != null) + { + MessageDigest md = null; + try + { + md = MessageDigest.getInstance(getDigestAlgorithm(), "SC"); + + } + catch (Exception e) + { + return false; + } + switch (getDigestedObjectType()) + { + case ObjectDigestInfo.publicKey: + // TODO: DSA Dss-parms + md.update(cert.getPublicKey().getEncoded()); + break; + case ObjectDigestInfo.publicKeyCert: + md.update(cert.getEncoded()); + break; + } + if (!Arrays.areEqual(md.digest(), getObjectDigest())) + { + return false; + } + } + } + catch (CertificateEncodingException e) + { + return false; + } + + return false; + } + + public boolean equals(Object obj) + { + if (obj == this) + { + return true; + } + + if (!(obj instanceof AttributeCertificateHolder)) + { + return false; + } + + AttributeCertificateHolder other = (AttributeCertificateHolder)obj; + + return this.holder.equals(other.holder); + } + + public int hashCode() + { + return this.holder.hashCode(); + } + + public boolean match(Object obj) + { + if (!(obj instanceof X509Certificate)) + { + return false; + } + + return match((Certificate)obj); + } +} diff --git a/prov/src/main/jdk1.3/org/spongycastle/x509/AttributeCertificateIssuer.java b/prov/src/main/jdk1.3/org/spongycastle/x509/AttributeCertificateIssuer.java new file mode 100644 index 00000000..44512802 --- /dev/null +++ b/prov/src/main/jdk1.3/org/spongycastle/x509/AttributeCertificateIssuer.java @@ -0,0 +1,211 @@ +package org.spongycastle.x509; + +import java.io.IOException; +import java.security.Principal; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.x509.AttCertIssuer; +import org.spongycastle.asn1.x509.GeneralName; +import org.spongycastle.asn1.x509.GeneralNames; +import org.spongycastle.asn1.x509.V2Form; +import org.spongycastle.jce.PrincipalUtil; +import org.spongycastle.jce.X509Principal; +import org.spongycastle.jce.cert.CertSelector; +import org.spongycastle.util.Selector; + +/** + * Carrying class for an attribute certificate issuer. + */ +public class AttributeCertificateIssuer + implements CertSelector, Selector +{ + final ASN1Encodable form; + + /** + * @param issuer + */ + AttributeCertificateIssuer( + AttCertIssuer issuer) + { + form = issuer.getIssuer(); + } + + public AttributeCertificateIssuer( + X509Principal principal) + { + form = new V2Form(new GeneralNames(new GeneralName(principal))); + } + + private Object[] getNames() + { + GeneralNames name; + + if (form instanceof V2Form) + { + name = ((V2Form)form).getIssuerName(); + } + else + { + name = (GeneralNames)form; + } + + GeneralName[] names = name.getNames(); + + List l = new ArrayList(names.length); + + for (int i = 0; i != names.length; i++) + { + if (names[i].getTagNo() == GeneralName.directoryName) + { + try + { + l.add(new X509Principal(((ASN1Encodable)names[i].getName()).toASN1Primitive().getEncoded())); + } + catch (IOException e) + { + throw new RuntimeException("badly formed Name object"); + } + } + } + + return l.toArray(new Object[l.size()]); + } + + /** + * Return any principal objects inside the attribute certificate issuer object. + * + * @return an array of Principal objects (usually X509Principal) + */ + public Principal[] getPrincipals() + { + Object[] p = this.getNames(); + List l = new ArrayList(); + + for (int i = 0; i != p.length; i++) + { + if (p[i] instanceof Principal) + { + l.add(p[i]); + } + } + + return (Principal[])l.toArray(new Principal[l.size()]); + } + + private boolean matchesDN(X509Principal subject, GeneralNames targets) + { + GeneralName[] names = targets.getNames(); + + for (int i = 0; i != names.length; i++) + { + GeneralName gn = names[i]; + + if (gn.getTagNo() == GeneralName.directoryName) + { + try + { + if (new X509Principal(((ASN1Encodable)gn.getName()).toASN1Primitive().getEncoded()).equals(subject)) + { + return true; + } + } + catch (IOException e) + { + } + } + } + + return false; + } + + /* (non-Javadoc) + * @see java.security.cert.CertSelector#clone() + */ + public Object clone() + { + return new AttributeCertificateIssuer(AttCertIssuer.getInstance(form)); + } + + /* (non-Javadoc) + * @see java.security.cert.CertSelector#match(java.security.cert.Certificate) + */ + public boolean match(Certificate cert) + { + if (!(cert instanceof X509Certificate)) + { + return false; + } + + X509Certificate x509Cert = (X509Certificate)cert; + + try + { + if (form instanceof V2Form) + { + V2Form issuer = (V2Form)form; + if (issuer.getBaseCertificateID() != null) + { + return issuer.getBaseCertificateID().getSerial().getValue().equals(x509Cert.getSerialNumber()) + && matchesDN(PrincipalUtil.getIssuerX509Principal(x509Cert), issuer.getBaseCertificateID().getIssuer()); + } + + GeneralNames name = issuer.getIssuerName(); + if (matchesDN(PrincipalUtil.getSubjectX509Principal(x509Cert), name)) + { + return true; + } + } + else + { + GeneralNames name = (GeneralNames)form; + if (matchesDN(PrincipalUtil.getSubjectX509Principal(x509Cert), name)) + { + return true; + } + } + } + catch (CertificateEncodingException e) + { + return false; + } + + return false; + } + + public boolean equals(Object obj) + { + if (obj == this) + { + return true; + } + + if (!(obj instanceof AttributeCertificateIssuer)) + { + return false; + } + + AttributeCertificateIssuer other = (AttributeCertificateIssuer)obj; + + return this.form.equals(other.form); + } + + public int hashCode() + { + return this.form.hashCode(); + } + + public boolean match(Object obj) + { + if (!(obj instanceof X509Certificate)) + { + return false; + } + + return match((Certificate)obj); + } +} diff --git a/prov/src/main/jdk1.3/org/spongycastle/x509/ExtendedPKIXBuilderParameters.java b/prov/src/main/jdk1.3/org/spongycastle/x509/ExtendedPKIXBuilderParameters.java new file mode 100644 index 00000000..55d80de9 --- /dev/null +++ b/prov/src/main/jdk1.3/org/spongycastle/x509/ExtendedPKIXBuilderParameters.java @@ -0,0 +1,210 @@ +package org.spongycastle.x509; + +import org.spongycastle.util.Selector; + +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidParameterException; +import org.spongycastle.jce.cert.PKIXBuilderParameters; +import org.spongycastle.jce.cert.PKIXParameters; +import org.spongycastle.jce.cert.TrustAnchor; +import org.spongycastle.jce.cert.X509CertSelector; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * This class contains extended parameters for PKIX certification path builders. + * + * @see java.security.cert.PKIXBuilderParameters + * @see org.spongycastle.jce.provider.PKIXCertPathBuilderSpi + */ +public class ExtendedPKIXBuilderParameters extends ExtendedPKIXParameters +{ + + private int maxPathLength = 5; + + private Set excludedCerts = Collections.EMPTY_SET; + + /** + * Excluded certificates are not used for building a certification path. + * <p> + * The returned set is immutable. + * + * @return Returns the excluded certificates. + */ + public Set getExcludedCerts() + { + return Collections.unmodifiableSet(excludedCerts); + } + + /** + * Sets the excluded certificates which are not used for building a + * certification path. If the <code>Set</code> is <code>null</code> an + * empty set is assumed. + * <p> + * The given set is cloned to protect it against subsequent modifications. + * + * @param excludedCerts The excluded certificates to set. + */ + public void setExcludedCerts(Set excludedCerts) + { + if (excludedCerts == null) + { + excludedCerts = Collections.EMPTY_SET; + } + else + { + this.excludedCerts = new HashSet(excludedCerts); + } + } + + /** + * Creates an instance of <code>PKIXBuilderParameters</code> with the + * specified <code>Set</code> of most-trusted CAs. Each element of the set + * is a {@link TrustAnchor TrustAnchor}. + * + * <p> + * Note that the <code>Set</code> is copied to protect against subsequent + * modifications. + * + * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s + * @param targetConstraints a <code>Selector</code> specifying the + * constraints on the target certificate or attribute + * certificate. + * @throws InvalidAlgorithmParameterException if <code>trustAnchors</code> + * is empty. + * @throws NullPointerException if <code>trustAnchors</code> is + * <code>null</code> + * @throws ClassCastException if any of the elements of + * <code>trustAnchors</code> is not of type + * <code>java.security.cert.TrustAnchor</code> + */ + public ExtendedPKIXBuilderParameters(Set trustAnchors, + Selector targetConstraints) + throws InvalidAlgorithmParameterException + { + super(trustAnchors); + setTargetConstraints(targetConstraints); + } + + /** + * Sets the maximum number of intermediate non-self-issued certificates in a + * certification path. The PKIX <code>CertPathBuilder</code> must not + * build paths longer then this length. + * <p> + * A value of 0 implies that the path can only contain a single certificate. + * A value of -1 does not limit the length. The default length is 5. + * + * <p> + * + * The basic constraints extension of a CA certificate overrides this value + * if smaller. + * + * @param maxPathLength the maximum number of non-self-issued intermediate + * certificates in the certification path + * @throws InvalidParameterException if <code>maxPathLength</code> is set + * to a value less than -1 + * + * @see org.spongycastle.jce.provider.PKIXCertPathBuilderSpi + * @see #getMaxPathLength + */ + public void setMaxPathLength(int maxPathLength) + { + if (maxPathLength < -1) + { + throw new InvalidParameterException("The maximum path " + + "length parameter can not be less than -1."); + } + this.maxPathLength = maxPathLength; + } + + /** + * Returns the value of the maximum number of intermediate non-self-issued + * certificates in the certification path. + * + * @return the maximum number of non-self-issued intermediate certificates + * in the certification path, or -1 if no limit exists. + * + * @see #setMaxPathLength(int) + */ + public int getMaxPathLength() + { + return maxPathLength; + } + + /** + * Can alse handle <code>ExtendedPKIXBuilderParameters</code> and + * <code>PKIXBuilderParameters</code>. + * + * @param params Parameters to set. + * @see org.spongycastle.x509.ExtendedPKIXParameters#setParams(java.security.cert.PKIXParameters) + */ + protected void setParams(PKIXParameters params) + { + super.setParams(params); + if (params instanceof ExtendedPKIXBuilderParameters) + { + ExtendedPKIXBuilderParameters _params = (ExtendedPKIXBuilderParameters) params; + maxPathLength = _params.maxPathLength; + excludedCerts = new HashSet(_params.excludedCerts); + } + if (params instanceof PKIXBuilderParameters) + { + PKIXBuilderParameters _params = (PKIXBuilderParameters) params; + maxPathLength = _params.getMaxPathLength(); + } + } + + /** + * Makes a copy of this <code>PKIXParameters</code> object. Changes to the + * copy will not affect the original and vice versa. + * + * @return a copy of this <code>PKIXParameters</code> object + */ + public Object clone() + { + ExtendedPKIXBuilderParameters params = null; + try + { + params = new ExtendedPKIXBuilderParameters(getTrustAnchors(), + getTargetConstraints()); + } + catch (Exception e) + { + // cannot happen + throw new RuntimeException(e.getMessage()); + } + params.setParams(this); + return params; + } + + /** + * Returns an instance of <code>ExtendedPKIXParameters</code> which can be + * safely casted to <code>ExtendedPKIXBuilderParameters</code>. + * <p> + * This method can be used to get a copy from other + * <code>PKIXBuilderParameters</code>, <code>PKIXParameters</code>, + * and <code>ExtendedPKIXParameters</code> instances. + * + * @param pkixParams The PKIX parameters to create a copy of. + * @return An <code>ExtendedPKIXBuilderParameters</code> instance. + */ + public static ExtendedPKIXParameters getInstance(PKIXParameters pkixParams) + { + ExtendedPKIXBuilderParameters params; + try + { + params = new ExtendedPKIXBuilderParameters(pkixParams + .getTrustAnchors(), X509CertStoreSelector + .getInstance((X509CertSelector) pkixParams + .getTargetCertConstraints())); + } + catch (Exception e) + { + // cannot happen + throw new RuntimeException(e.getMessage()); + } + params.setParams(pkixParams); + return params; + } +} diff --git a/prov/src/main/jdk1.3/org/spongycastle/x509/ExtendedPKIXParameters.java b/prov/src/main/jdk1.3/org/spongycastle/x509/ExtendedPKIXParameters.java new file mode 100644 index 00000000..c2636c5b --- /dev/null +++ b/prov/src/main/jdk1.3/org/spongycastle/x509/ExtendedPKIXParameters.java @@ -0,0 +1,647 @@ +package org.spongycastle.x509; + +import org.spongycastle.util.Selector; +import org.spongycastle.util.Store; + +import java.security.InvalidAlgorithmParameterException; +import org.spongycastle.jce.cert.CertSelector; +import org.spongycastle.jce.cert.CertStore; +import org.spongycastle.jce.cert.CollectionCertStoreParameters; +import org.spongycastle.jce.cert.LDAPCertStoreParameters; +import org.spongycastle.jce.cert.PKIXParameters; +import org.spongycastle.jce.cert.TrustAnchor; +import org.spongycastle.jce.cert.X509CertSelector; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +/** + * This class extends the PKIXParameters with a validity model parameter. + */ +public class ExtendedPKIXParameters + extends PKIXParameters +{ + + private List stores; + + private Selector selector; + + private boolean additionalLocationsEnabled; + + private List additionalStores; + + private Set trustedACIssuers; + + private Set necessaryACAttributes; + + private Set prohibitedACAttributes; + + private Set attrCertCheckers; + + /** + * Creates an instance of <code>PKIXParameters</code> with the specified + * <code>Set</code> of most-trusted CAs. Each element of the set is a + * {@link TrustAnchor TrustAnchor}. <p/> Note that the <code>Set</code> + * is copied to protect against subsequent modifications. + * + * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s + * @throws InvalidAlgorithmParameterException if the specified + * <code>Set</code> is empty. + * @throws NullPointerException if the specified <code>Set</code> is + * <code>null</code> + * @throws ClassCastException if any of the elements in the <code>Set</code> + * is not of type <code>java.security.cert.TrustAnchor</code> + */ + public ExtendedPKIXParameters(Set trustAnchors) + throws InvalidAlgorithmParameterException + { + super(trustAnchors); + stores = new ArrayList(); + additionalStores = new ArrayList(); + trustedACIssuers = new HashSet(); + necessaryACAttributes = new HashSet(); + prohibitedACAttributes = new HashSet(); + attrCertCheckers = new HashSet(); + } + + /** + * Returns an instance with the parameters of a given + * <code>PKIXParameters</code> object. + * + * @param pkixParams The given <code>PKIXParameters</code> + * @return an extended PKIX params object + */ + public static ExtendedPKIXParameters getInstance(PKIXParameters pkixParams) + { + ExtendedPKIXParameters params; + try + { + params = new ExtendedPKIXParameters(pkixParams.getTrustAnchors()); + } + catch (Exception e) + { + // cannot happen + throw new RuntimeException(e.getMessage()); + } + params.setParams(pkixParams); + return params; + } + + /** + * Method to support <code>clone()</code> under J2ME. + * <code>super.clone()</code> does not exist and fields are not copied. + * + * @param params Parameters to set. If this are + * <code>ExtendedPKIXParameters</code> they are copied to. + */ + protected void setParams(PKIXParameters params) + { + setDate(params.getDate()); + setCertPathCheckers(params.getCertPathCheckers()); + setCertStores(params.getCertStores()); + setAnyPolicyInhibited(params.isAnyPolicyInhibited()); + setExplicitPolicyRequired(params.isExplicitPolicyRequired()); + setPolicyMappingInhibited(params.isPolicyMappingInhibited()); + setRevocationEnabled(params.isRevocationEnabled()); + setInitialPolicies(params.getInitialPolicies()); + setPolicyQualifiersRejected(params.getPolicyQualifiersRejected()); + setSigProvider(params.getSigProvider()); + setTargetCertConstraints(params.getTargetCertConstraints()); + try + { + setTrustAnchors(params.getTrustAnchors()); + } + catch (Exception e) + { + // cannot happen + throw new RuntimeException(e.getMessage()); + } + if (params instanceof ExtendedPKIXParameters) + { + ExtendedPKIXParameters _params = (ExtendedPKIXParameters) params; + validityModel = _params.validityModel; + useDeltas = _params.useDeltas; + additionalLocationsEnabled = _params.additionalLocationsEnabled; + selector = _params.selector == null ? null + : (Selector) _params.selector.clone(); + stores = new ArrayList(_params.stores); + additionalStores = new ArrayList(_params.additionalStores); + trustedACIssuers = new HashSet(_params.trustedACIssuers); + prohibitedACAttributes = new HashSet(_params.prohibitedACAttributes); + necessaryACAttributes = new HashSet(_params.necessaryACAttributes); + attrCertCheckers = new HashSet(_params.attrCertCheckers); + } + } + + /** + * This is the default PKIX validity model. Actually there are two variants + * of this: The PKIX model and the modified PKIX model. The PKIX model + * verifies that all involved certificates must have been valid at the + * current time. The modified PKIX model verifies that all involved + * certificates were valid at the signing time. Both are indirectly choosen + * with the {@link PKIXParameters#setDate(java.util.Date)} method, so this + * methods sets the Date when <em>all</em> certificates must have been + * valid. + */ + public static final int PKIX_VALIDITY_MODEL = 0; + + /** + * This model uses the following validity model. Each certificate must have + * been valid at the moment where is was used. That means the end + * certificate must have been valid at the time the signature was done. The + * CA certificate which signed the end certificate must have been valid, + * when the end certificate was signed. The CA (or Root CA) certificate must + * have been valid, when the CA certificate was signed and so on. So the + * {@link PKIXParameters#setDate(java.util.Date)} method sets the time, when + * the <em>end certificate</em> must have been valid. <p/> It is used e.g. + * in the German signature law. + */ + public static final int CHAIN_VALIDITY_MODEL = 1; + + private int validityModel = PKIX_VALIDITY_MODEL; + + private boolean useDeltas = false; + + /** + * Defaults to <code>false</code>. + * + * @return Returns if delta CRLs should be used. + */ + public boolean isUseDeltasEnabled() + { + return useDeltas; + } + + /** + * Sets if delta CRLs should be used for checking the revocation status. + * + * @param useDeltas <code>true</code> if delta CRLs should be used. + */ + public void setUseDeltasEnabled(boolean useDeltas) + { + this.useDeltas = useDeltas; + } + + /** + * @return Returns the validity model. + * @see #CHAIN_VALIDITY_MODEL + * @see #PKIX_VALIDITY_MODEL + */ + public int getValidityModel() + { + return validityModel; + } + + /** + * Sets the Java CertStore to this extended PKIX parameters. + * + * @throws ClassCastException if an element of <code>stores</code> is not + * a <code>CertStore</code>. + */ + public void setCertStores(List stores) + { + if (stores != null) + { + Iterator it = stores.iterator(); + while (it.hasNext()) + { + addCertStore((CertStore)it.next()); + } + } + } + + /** + * Sets the Bouncy Castle Stores for finding CRLs, certificates, attribute + * certificates or cross certificates. + * <p> + * The <code>List</code> is cloned. + * + * @param stores A list of stores to use. + * @see #getStores + * @throws ClassCastException if an element of <code>stores</code> is not + * a {@link Store}. + */ + public void setStores(List stores) + { + if (stores == null) + { + this.stores = new ArrayList(); + } + else + { + for (Iterator i = stores.iterator(); i.hasNext();) + { + if (!(i.next() instanceof Store)) + { + throw new ClassCastException( + "All elements of list must be " + + "of type org.spongycastle.util.Store."); + } + } + this.stores = new ArrayList(stores); + } + } + + /** + * Adds a Bouncy Castle {@link Store} to find CRLs, certificates, attribute + * certificates or cross certificates. + * <p> + * This method should be used to add local stores, like collection based + * X.509 stores, if available. Local stores should be considered first, + * before trying to use additional (remote) locations, because they do not + * need possible additional network traffic. + * <p> + * If <code>store</code> is <code>null</code> it is ignored. + * + * @param store The store to add. + * @see #getStores + */ + public void addStore(Store store) + { + if (stores != null) + { + stores.add(store); + } + } + + /** + * Adds a additional Bouncy Castle {@link Store} to find CRLs, certificates, + * attribute certificates or cross certificates. + * <p> + * You should not use this method. This method is used for adding additional + * X.509 stores, which are used to add (remote) locations, e.g. LDAP, found + * during X.509 object processing, e.g. in certificates or CRLs. This method + * is used in PKIX certification path processing. + * <p> + * If <code>store</code> is <code>null</code> it is ignored. + * + * @param store The store to add. + * @see #getStores() + */ + public void addAddionalStore(Store store) + { + if (store != null) + { + additionalStores.add(store); + } + } + + /** + * Returns an immutable <code>List</code> of additional Bouncy Castle + * <code>Store</code>s used for finding CRLs, certificates, attribute + * certificates or cross certificates. + * + * @return an immutable <code>List</code> of additional Bouncy Castle + * <code>Store</code>s. Never <code>null</code>. + * + * @see #addAddionalStore(Store) + */ + public List getAdditionalStores() + { + return Collections.unmodifiableList(additionalStores); + } + + /** + * Returns an immutable <code>List</code> of Bouncy Castle + * <code>Store</code>s used for finding CRLs, certificates, attribute + * certificates or cross certificates. + * + * @return an immutable <code>List</code> of Bouncy Castle + * <code>Store</code>s. Never <code>null</code>. + * + * @see #setStores(List) + */ + public List getStores() + { + return Collections.unmodifiableList(new ArrayList(stores)); + } + + /** + * @param validityModel The validity model to set. + * @see #CHAIN_VALIDITY_MODEL + * @see #PKIX_VALIDITY_MODEL + */ + public void setValidityModel(int validityModel) + { + this.validityModel = validityModel; + } + + public Object clone() + { + ExtendedPKIXParameters params; + try + { + params = new ExtendedPKIXParameters(getTrustAnchors()); + } + catch (Exception e) + { + // cannot happen + throw new RuntimeException(e.getMessage()); + } + params.setParams(this); + return params; + } + + /** + * Returns if additional {@link X509Store}s for locations like LDAP found + * in certificates or CRLs should be used. + * + * @return Returns <code>true</code> if additional stores are used. + */ + public boolean isAdditionalLocationsEnabled() + { + return additionalLocationsEnabled; + } + + /** + * Sets if additional {@link X509Store}s for locations like LDAP found in + * certificates or CRLs should be used. + * + * @param enabled <code>true</code> if additional stores are used. + */ + public void setAdditionalLocationsEnabled(boolean enabled) + { + additionalLocationsEnabled = enabled; + } + + /** + * Returns the required constraints on the target certificate or attribute + * certificate. The constraints are returned as an instance of + * <code>Selector</code>. If <code>null</code>, no constraints are + * defined. + * + * <p> + * The target certificate in a PKIX path may be a certificate or an + * attribute certificate. + * <p> + * Note that the <code>Selector</code> returned is cloned to protect + * against subsequent modifications. + * + * @return a <code>Selector</code> specifying the constraints on the + * target certificate or attribute certificate (or <code>null</code>) + * @see #setTargetConstraints + * @see X509CertStoreSelector + * @see X509AttributeCertStoreSelector + */ + public Selector getTargetConstraints() + { + if (selector != null) + { + return (Selector) selector.clone(); + } + else + { + return null; + } + } + + /** + * Sets the required constraints on the target certificate or attribute + * certificate. The constraints are specified as an instance of + * <code>Selector</code>. If <code>null</code>, no constraints are + * defined. + * <p> + * The target certificate in a PKIX path may be a certificate or an + * attribute certificate. + * <p> + * Note that the <code>Selector</code> specified is cloned to protect + * against subsequent modifications. + * + * @param selector a <code>Selector</code> specifying the constraints on + * the target certificate or attribute certificate (or + * <code>null</code>) + * @see #getTargetConstraints + * @see X509CertStoreSelector + * @see X509AttributeCertStoreSelector + */ + public void setTargetConstraints(Selector selector) + { + if (selector != null) + { + this.selector = (Selector) selector.clone(); + } + else + { + this.selector = null; + } + } + + /** + * Sets the required constraints on the target certificate. The constraints + * are specified as an instance of <code>X509CertSelector</code>. If + * <code>null</code>, no constraints are defined. + * + * <p> + * This method wraps the given <code>X509CertSelector</code> into a + * <code>X509CertStoreSelector</code>. + * <p> + * Note that the <code>X509CertSelector</code> specified is cloned to + * protect against subsequent modifications. + * + * @param selector a <code>X509CertSelector</code> specifying the + * constraints on the target certificate (or <code>null</code>) + * @see #getTargetCertConstraints + * @see X509CertStoreSelector + */ + public void setTargetCertConstraints(CertSelector selector) + { + super.setTargetCertConstraints(selector); + if (selector != null) + { + this.selector = X509CertStoreSelector + .getInstance((X509CertSelector) selector); + } + else + { + this.selector = null; + } + } + + /** + * Returns the trusted attribute certificate issuers. If attribute + * certificates is verified the trusted AC issuers must be set. + * <p> + * The returned <code>Set</code> consists of <code>TrustAnchor</code>s. + * <p> + * The returned <code>Set</code> is immutable. Never <code>null</code> + * + * @return Returns an immutable set of the trusted AC issuers. + */ + public Set getTrustedACIssuers() + { + return Collections.unmodifiableSet(trustedACIssuers); + } + + /** + * Sets the trusted attribute certificate issuers. If attribute certificates + * is verified the trusted AC issuers must be set. + * <p> + * The <code>trustedACIssuers</code> must be a <code>Set</code> of + * <code>TrustAnchor</code> + * <p> + * The given set is cloned. + * + * @param trustedACIssuers The trusted AC issuers to set. Is never + * <code>null</code>. + * @throws ClassCastException if an element of <code>stores</code> is not + * a <code>TrustAnchor</code>. + */ + public void setTrustedACIssuers(Set trustedACIssuers) + { + if (trustedACIssuers == null) + { + trustedACIssuers.clear(); + return; + } + for (Iterator it = trustedACIssuers.iterator(); it.hasNext();) + { + if (!(it.next() instanceof TrustAnchor)) + { + throw new ClassCastException("All elements of set must be " + + "of type " + TrustAnchor.class.getName() + "."); + } + } + this.trustedACIssuers.clear(); + this.trustedACIssuers.addAll(trustedACIssuers); + } + + /** + * Returns the neccessary attributes which must be contained in an attribute + * certificate. + * <p> + * The returned <code>Set</code> is immutable and contains + * <code>String</code>s with the OIDs. + * + * @return Returns the necessary AC attributes. + */ + public Set getNecessaryACAttributes() + { + return Collections.unmodifiableSet(necessaryACAttributes); + } + + /** + * Sets the neccessary which must be contained in an attribute certificate. + * <p> + * The <code>Set</code> must contain <code>String</code>s with the + * OIDs. + * <p> + * The set is cloned. + * + * @param necessaryACAttributes The necessary AC attributes to set. + * @throws ClassCastException if an element of + * <code>necessaryACAttributes</code> is not a + * <code>String</code>. + */ + public void setNecessaryACAttributes(Set necessaryACAttributes) + { + if (necessaryACAttributes == null) + { + this.necessaryACAttributes.clear(); + return; + } + for (Iterator it = necessaryACAttributes.iterator(); it.hasNext();) + { + if (!(it.next() instanceof String)) + { + throw new ClassCastException("All elements of set must be " + + "of type String."); + } + } + this.necessaryACAttributes.clear(); + this.necessaryACAttributes.addAll(necessaryACAttributes); + } + + /** + * Returns the attribute certificates which are not allowed. + * <p> + * The returned <code>Set</code> is immutable and contains + * <code>String</code>s with the OIDs. + * + * @return Returns the prohibited AC attributes. Is never <code>null</code>. + */ + public Set getProhibitedACAttributes() + { + return prohibitedACAttributes; + } + + /** + * Sets the attribute certificates which are not allowed. + * <p> + * The <code>Set</code> must contain <code>String</code>s with the + * OIDs. + * <p> + * The set is cloned. + * + * @param prohibitedACAttributes The prohibited AC attributes to set. + * @throws ClassCastException if an element of + * <code>prohibitedACAttributes</code> is not a + * <code>String</code>. + */ + public void setProhibitedACAttributes(Set prohibitedACAttributes) + { + if (prohibitedACAttributes == null) + { + this.prohibitedACAttributes.clear(); + return; + } + for (Iterator it = prohibitedACAttributes.iterator(); it.hasNext();) + { + if (!(it.next() instanceof String)) + { + throw new ClassCastException("All elements of set must be " + + "of type String."); + } + } + this.prohibitedACAttributes.clear(); + this.prohibitedACAttributes.addAll(prohibitedACAttributes); + } + + /** + * Returns the attribute certificate checker. The returned set contains + * {@link PKIXAttrCertChecker}s and is immutable. + * + * @return Returns the attribute certificate checker. Is never + * <code>null</code>. + */ + public Set getAttrCertCheckers() + { + return Collections.unmodifiableSet(attrCertCheckers); + } + + /** + * Sets the attribute certificate checkers. + * <p> + * All elements in the <code>Set</code> must a {@link PKIXAttrCertChecker}. + * <p> + * The given set is cloned. + * + * @param attrCertCheckers The attribute certificate checkers to set. Is + * never <code>null</code>. + * @throws ClassCastException if an element of <code>attrCertCheckers</code> + * is not a <code>PKIXAttrCertChecker</code>. + */ +/* + public void setAttrCertCheckers(Set attrCertCheckers) + { + if (attrCertCheckers == null) + { + this.attrCertCheckers.clear(); + return; + } + for (Iterator it = attrCertCheckers.iterator(); it.hasNext();) + { + if (!(it.next() instanceof PKIXAttrCertChecker)) + { + throw new ClassCastException("All elements of set must be " + + "of type " + PKIXAttrCertChecker.class.getName() + "."); + } + } + this.attrCertCheckers.clear(); + this.attrCertCheckers.addAll(attrCertCheckers); + } +*/ +} diff --git a/prov/src/main/jdk1.3/org/spongycastle/x509/X509AttributeCertStoreSelector.java b/prov/src/main/jdk1.3/org/spongycastle/x509/X509AttributeCertStoreSelector.java new file mode 100644 index 00000000..b47236d1 --- /dev/null +++ b/prov/src/main/jdk1.3/org/spongycastle/x509/X509AttributeCertStoreSelector.java @@ -0,0 +1,486 @@ +package org.spongycastle.x509; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Primitive; +import org.spongycastle.asn1.DEROctetString; +import org.spongycastle.asn1.x509.GeneralName; +import org.spongycastle.asn1.x509.Target; +import org.spongycastle.asn1.x509.TargetInformation; +import org.spongycastle.asn1.x509.Targets; +import org.spongycastle.asn1.x509.X509Extensions; +import org.spongycastle.util.Selector; + +/** + * This class is an <code>Selector</code> like implementation to select + * attribute certificates from a given set of criteria. + * + * @see org.spongycastle.x509.X509AttributeCertificate + * @see org.spongycastle.x509.X509Store + */ +public class X509AttributeCertStoreSelector + implements Selector +{ + + // TODO: name constraints??? + + private AttributeCertificateHolder holder; + + private AttributeCertificateIssuer issuer; + + private BigInteger serialNumber; + + private Date attributeCertificateValid; + + private X509AttributeCertificate attributeCert; + + private Collection targetNames = new HashSet(); + + private Collection targetGroups = new HashSet(); + + public X509AttributeCertStoreSelector() + { + super(); + } + + /** + * Decides if the given attribute certificate should be selected. + * + * @param obj The attribute certificate which should be checked. + * @return <code>true</code> if the attribute certificate can be selected, + * <code>false</code> otherwise. + */ + public boolean match(Object obj) + { + if (!(obj instanceof X509AttributeCertificate)) + { + return false; + } + + X509AttributeCertificate attrCert = (X509AttributeCertificate) obj; + + if (this.attributeCert != null) + { + if (!this.attributeCert.equals(attrCert)) + { + return false; + } + } + if (serialNumber != null) + { + if (!attrCert.getSerialNumber().equals(serialNumber)) + { + return false; + } + } + if (holder != null) + { + if (!attrCert.getHolder().equals(holder)) + { + return false; + } + } + if (issuer != null) + { + if (!attrCert.getIssuer().equals(issuer)) + { + return false; + } + } + + if (attributeCertificateValid != null) + { + try + { + attrCert.checkValidity(attributeCertificateValid); + } + catch (CertificateExpiredException e) + { + return false; + } + catch (CertificateNotYetValidException e) + { + return false; + } + } + if (!targetNames.isEmpty() || !targetGroups.isEmpty()) + { + + byte[] targetInfoExt = attrCert + .getExtensionValue(X509Extensions.TargetInformation.getId()); + if (targetInfoExt != null) + { + TargetInformation targetinfo; + try + { + targetinfo = TargetInformation + .getInstance(new ASN1InputStream( + ((DEROctetString) DEROctetString + .fromByteArray(targetInfoExt)).getOctets()) + .readObject()); + } + catch (IOException e) + { + return false; + } + catch (IllegalArgumentException e) + { + return false; + } + Targets[] targetss = targetinfo.getTargetsObjects(); + if (!targetNames.isEmpty()) + { + boolean found = false; + + for (int i=0; i<targetss.length; i++) + { + Targets t = targetss[i]; + Target[] targets = t.getTargets(); + for (int j=0; j<targets.length; j++) + { + if (targetNames.contains(targets[j] + .getTargetName())) + { + found = true; + break; + } + } + } + if (!found) + { + return false; + } + } + if (!targetGroups.isEmpty()) + { + boolean found = false; + + for (int i=0; i<targetss.length; i++) + { + Targets t = targetss[i]; + Target[] targets = t.getTargets(); + for (int j=0; j<targets.length; j++) + { + if (targetGroups.contains(targets[j] + .getTargetGroup())) + { + found = true; + break; + } + } + } + if (!found) + { + return false; + } + } + } + } + return true; + } + + /** + * Returns a clone of this object. + * + * @return the clone. + */ + public Object clone() + { + X509AttributeCertStoreSelector sel = new X509AttributeCertStoreSelector(); + sel.attributeCert = attributeCert; + sel.attributeCertificateValid = getAttributeCertificateValid(); + sel.holder = holder; + sel.issuer = issuer; + sel.serialNumber = serialNumber; + sel.targetGroups = getTargetGroups(); + sel.targetNames = getTargetNames(); + return sel; + } + + /** + * Returns the attribute certificate which must be matched. + * + * @return Returns the attribute certificate. + */ + public X509AttributeCertificate getAttributeCert() + { + return attributeCert; + } + + /** + * Set the attribute certificate to be matched. If <code>null</code> is + * given any will do. + * + * @param attributeCert The attribute certificate to set. + */ + public void setAttributeCert(X509AttributeCertificate attributeCert) + { + this.attributeCert = attributeCert; + } + + /** + * Get the criteria for the validity. + * + * @return Returns the attributeCertificateValid. + */ + public Date getAttributeCertificateValid() + { + if (attributeCertificateValid != null) + { + return new Date(attributeCertificateValid.getTime()); + } + + return null; + } + + /** + * Set the time, when the certificate must be valid. If <code>null</code> + * is given any will do. + * + * @param attributeCertificateValid The attribute certificate validation + * time to set. + */ + public void setAttributeCertificateValid(Date attributeCertificateValid) + { + if (attributeCertificateValid != null) + { + this.attributeCertificateValid = new Date(attributeCertificateValid + .getTime()); + } + else + { + this.attributeCertificateValid = null; + } + } + + /** + * Gets the holder. + * + * @return Returns the holder. + */ + public AttributeCertificateHolder getHolder() + { + return holder; + } + + /** + * Sets the holder. If <code>null</code> is given any will do. + * + * @param holder The holder to set. + */ + public void setHolder(AttributeCertificateHolder holder) + { + this.holder = holder; + } + + /** + * Returns the issuer criterion. + * + * @return Returns the issuer. + */ + public AttributeCertificateIssuer getIssuer() + { + return issuer; + } + + /** + * Sets the issuer the attribute certificate must have. If <code>null</code> + * is given any will do. + * + * @param issuer The issuer to set. + */ + public void setIssuer(AttributeCertificateIssuer issuer) + { + this.issuer = issuer; + } + + /** + * Gets the serial number the attribute certificate must have. + * + * @return Returns the serialNumber. + */ + public BigInteger getSerialNumber() + { + return serialNumber; + } + + /** + * Sets the serial number the attribute certificate must have. If + * <code>null</code> is given any will do. + * + * @param serialNumber The serialNumber to set. + */ + public void setSerialNumber(BigInteger serialNumber) + { + this.serialNumber = serialNumber; + } + + /** + * Adds a target name criterion for the attribute certificate to the target + * information extension criteria. The <code>X509AttributeCertificate</code> + * must contain at least one of the specified target names. + * <p> + * Each attribute certificate may contain a target information extension + * limiting the servers where this attribute certificate can be used. If + * this extension is not present, the attribute certificate is not targeted + * and may be accepted by any server. + * + * @param name The name as a GeneralName (not <code>null</code>) + */ + public void addTargetName(GeneralName name) + { + targetNames.add(name); + } + + /** + * Adds a target name criterion for the attribute certificate to the target + * information extension criteria. The <code>X509AttributeCertificate</code> + * must contain at least one of the specified target names. + * <p> + * Each attribute certificate may contain a target information extension + * limiting the servers where this attribute certificate can be used. If + * this extension is not present, the attribute certificate is not targeted + * and may be accepted by any server. + * + * @param name a byte array containing the name in ASN.1 DER encoded form of a GeneralName + * @throws IOException if a parsing error occurs. + */ + public void addTargetName(byte[] name) throws IOException + { + addTargetName(GeneralName.getInstance(ASN1Primitive.fromByteArray(name))); + } + + /** + * Adds a collection with target names criteria. If <code>null</code> is + * given any will do. + * <p> + * The collection consists of either GeneralName objects or byte[] arrays representing + * DER encoded GeneralName structures. + * + * @param names A collection of target names. + * @throws IOException if a parsing error occurs. + * @see #addTargetName(byte[]) + * @see #addTargetName(GeneralName) + */ + public void setTargetNames(Collection names) throws IOException + { + targetNames = extractGeneralNames(names); + } + + /** + * Gets the target names. The collection consists of <code>List</code>s + * made up of an <code>Integer</code> in the first entry and a DER encoded + * byte array or a <code>String</code> in the second entry. + * <p> + * The returned collection is immutable. + * + * @return The collection of target names + * @see #setTargetNames(Collection) + */ + public Collection getTargetNames() + { + return Collections.unmodifiableCollection(targetNames); + } + + /** + * Adds a target group criterion for the attribute certificate to the target + * information extension criteria. The <code>X509AttributeCertificate</code> + * must contain at least one of the specified target groups. + * <p> + * Each attribute certificate may contain a target information extension + * limiting the servers where this attribute certificate can be used. If + * this extension is not present, the attribute certificate is not targeted + * and may be accepted by any server. + * + * @param group The group as GeneralName form (not <code>null</code>) + */ + public void addTargetGroup(GeneralName group) + { + targetGroups.add(group); + } + + /** + * Adds a target group criterion for the attribute certificate to the target + * information extension criteria. The <code>X509AttributeCertificate</code> + * must contain at least one of the specified target groups. + * <p> + * Each attribute certificate may contain a target information extension + * limiting the servers where this attribute certificate can be used. If + * this extension is not present, the attribute certificate is not targeted + * and may be accepted by any server. + * + * @param name a byte array containing the group in ASN.1 DER encoded form of a GeneralName + * @throws IOException if a parsing error occurs. + */ + public void addTargetGroup(byte[] name) throws IOException + { + addTargetGroup(GeneralName.getInstance(ASN1Primitive.fromByteArray(name))); + } + + /** + * Adds a collection with target groups criteria. If <code>null</code> is + * given any will do. + * <p> + * The collection consists of <code>GeneralName</code> objects or <code>byte[]</code representing DER + * encoded GeneralNames. + * + * @param names A collection of target groups. + * @throws IOException if a parsing error occurs. + * @see #addTargetGroup(byte[]) + * @see #addTargetGroup(GeneralName) + */ + public void setTargetGroups(Collection names) throws IOException + { + targetGroups = extractGeneralNames(names); + } + + + + /** + * Gets the target groups. The collection consists of <code>List</code>s + * made up of an <code>Integer</code> in the first entry and a DER encoded + * byte array or a <code>String</code> in the second entry. + * <p> + * The returned collection is immutable. + * + * @return The collection of target groups. + * @see #setTargetGroups(Collection) + */ + public Collection getTargetGroups() + { + return Collections.unmodifiableCollection(targetGroups); + } + + private Set extractGeneralNames(Collection names) + throws IOException + { + if (names == null || names.isEmpty()) + { + return new HashSet(); + } + Set temp = new HashSet(); + for (Iterator it = names.iterator(); it.hasNext();) + { + Object o = it.next(); + if (o instanceof GeneralName) + { + temp.add(o); + } + else + { + temp.add(GeneralName.getInstance(ASN1Primitive.fromByteArray((byte[])o))); + } + } + return temp; + } +} diff --git a/prov/src/main/jdk1.3/org/spongycastle/x509/X509CRLStoreSelector.java b/prov/src/main/jdk1.3/org/spongycastle/x509/X509CRLStoreSelector.java new file mode 100644 index 00000000..554911f0 --- /dev/null +++ b/prov/src/main/jdk1.3/org/spongycastle/x509/X509CRLStoreSelector.java @@ -0,0 +1,330 @@ +package org.spongycastle.x509; + +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.x509.X509Extensions; +import org.spongycastle.util.Arrays; +import org.spongycastle.util.Selector; +import org.spongycastle.x509.extension.X509ExtensionUtil; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CRL; +import java.security.cert.X509CRL; +import org.spongycastle.jce.cert.X509CRLSelector; + +/** + * This class is a Selector implementation for X.509 certificate revocation + * lists. + * + * @see org.spongycastle.util.Selector + * @see org.spongycastle.x509.X509Store + * @see org.spongycastle.jce.provider.X509StoreCRLCollection + */ +public class X509CRLStoreSelector + extends X509CRLSelector + implements Selector +{ + private boolean deltaCRLIndicator = false; + + private boolean completeCRLEnabled = false; + + private BigInteger maxBaseCRLNumber = null; + + private byte[] issuingDistributionPoint = null; + + private boolean issuingDistributionPointEnabled = false; + + private X509AttributeCertificate attrCertChecking; + + /** + * Returns if the issuing distribution point criteria should be applied. + * Defaults to <code>false</code>. + * <p> + * You may also set the issuing distribution point criteria if not a missing + * issuing distribution point should be assumed. + * + * @return Returns if the issuing distribution point check is enabled. + */ + public boolean isIssuingDistributionPointEnabled() + { + return issuingDistributionPointEnabled; + } + + /** + * Enables or disables the issuing distribution point check. + * + * @param issuingDistributionPointEnabled <code>true</code> to enable the + * issuing distribution point check. + */ + public void setIssuingDistributionPointEnabled( + boolean issuingDistributionPointEnabled) + { + this.issuingDistributionPointEnabled = issuingDistributionPointEnabled; + } + + /** + * Sets the attribute certificate being checked. This is not a criterion. + * Rather, it is optional information that may help a {@link X509Store} find + * CRLs that would be relevant when checking revocation for the specified + * attribute certificate. If <code>null</code> is specified, then no such + * optional information is provided. + * + * @param attrCert the <code>X509AttributeCertificate</code> being checked (or + * <code>null</code>) + * @see #getAttrCertificateChecking() + */ + public void setAttrCertificateChecking(X509AttributeCertificate attrCert) + { + attrCertChecking = attrCert; + } + + /** + * Returns the attribute certificate being checked. + * + * @return Returns the attribute certificate being checked. + * @see #setAttrCertificateChecking(X509AttributeCertificate) + */ + public X509AttributeCertificate getAttrCertificateChecking() + { + return attrCertChecking; + } + + public boolean match(Object obj) + { + if (!(obj instanceof X509CRL)) + { + return false; + } + X509CRL crl = (X509CRL)obj; + ASN1Integer dci = null; + try + { + byte[] bytes = crl + .getExtensionValue(X509Extensions.DeltaCRLIndicator.getId()); + if (bytes != null) + { + dci = ASN1Integer.getInstance(X509ExtensionUtil + .fromExtensionValue(bytes)); + } + } + catch (Exception e) + { + return false; + } + if (isDeltaCRLIndicatorEnabled()) + { + if (dci == null) + { + return false; + } + } + if (isCompleteCRLEnabled()) + { + if (dci != null) + { + return false; + } + } + if (dci != null) + { + + if (maxBaseCRLNumber != null) + { + if (dci.getPositiveValue().compareTo(maxBaseCRLNumber) == 1) + { + return false; + } + } + } + if (issuingDistributionPointEnabled) + { + byte[] idp = crl + .getExtensionValue(X509Extensions.IssuingDistributionPoint + .getId()); + if (issuingDistributionPoint == null) + { + if (idp != null) + { + return false; + } + } + else + { + if (!Arrays.areEqual(idp, issuingDistributionPoint)) + { + return false; + } + } + + } + return super.match((X509CRL)obj); + } + + public boolean match(CRL crl) + { + return match((Object)crl); + } + + /** + * Returns if this selector must match CRLs with the delta CRL indicator + * extension set. Defaults to <code>false</code>. + * + * @return Returns <code>true</code> if only CRLs with the delta CRL + * indicator extension are selected. + */ + public boolean isDeltaCRLIndicatorEnabled() + { + return deltaCRLIndicator; + } + + /** + * If this is set to <code>true</code> the CRL reported contains the delta + * CRL indicator CRL extension. + * <p> + * {@link #setCompleteCRLEnabled(boolean)} and + * {@link #setDeltaCRLIndicatorEnabled(boolean)} excluded each other. + * + * @param deltaCRLIndicator <code>true</code> if the delta CRL indicator + * extension must be in the CRL. + */ + public void setDeltaCRLIndicatorEnabled(boolean deltaCRLIndicator) + { + this.deltaCRLIndicator = deltaCRLIndicator; + } + + /** + * Returns an instance of this from a <code>X509CRLSelector</code>. + * + * @param selector A <code>X509CRLSelector</code> instance. + * @return An instance of an <code>X509CRLStoreSelector</code>. + * @exception IllegalArgumentException if selector is null or creation + * fails. + */ + public static X509CRLStoreSelector getInstance(X509CRLSelector selector) + { + if (selector == null) + { + throw new IllegalArgumentException( + "cannot create from null selector"); + } + X509CRLStoreSelector cs = new X509CRLStoreSelector(); + cs.setCertificateChecking(selector.getCertificateChecking()); + cs.setDateAndTime(selector.getDateAndTime()); + try + { + cs.setIssuerNames(selector.getIssuerNames()); + } + catch (IOException e) + { + // cannot happen + throw new IllegalArgumentException(e.getMessage()); + } + //cs.setIssuers(selector.getIssuers()); + cs.setMaxCRLNumber(selector.getMaxCRL()); + cs.setMinCRLNumber(selector.getMinCRL()); + return cs; + } + + public Object clone() + { + X509CRLStoreSelector sel = X509CRLStoreSelector.getInstance(this); + sel.deltaCRLIndicator = deltaCRLIndicator; + sel.completeCRLEnabled = completeCRLEnabled; + sel.maxBaseCRLNumber = maxBaseCRLNumber; + sel.attrCertChecking = attrCertChecking; + sel.issuingDistributionPointEnabled = issuingDistributionPointEnabled; + sel.issuingDistributionPoint = Arrays.clone(issuingDistributionPoint); + return sel; + } + + /** + * If <code>true</code> only complete CRLs are returned. Defaults to + * <code>false</code>. + * + * @return <code>true</code> if only complete CRLs are returned. + */ + public boolean isCompleteCRLEnabled() + { + return completeCRLEnabled; + } + + /** + * If set to <code>true</code> only complete CRLs are returned. + * <p> + * {@link #setCompleteCRLEnabled(boolean)} and + * {@link #setDeltaCRLIndicatorEnabled(boolean)} excluded each other. + * + * @param completeCRLEnabled <code>true</code> if only complete CRLs + * should be returned. + */ + public void setCompleteCRLEnabled(boolean completeCRLEnabled) + { + this.completeCRLEnabled = completeCRLEnabled; + } + + /** + * Get the maximum base CRL number. Defaults to <code>null</code>. + * + * @return Returns the maximum base CRL number. + * @see #setMaxBaseCRLNumber(BigInteger) + */ + public BigInteger getMaxBaseCRLNumber() + { + return maxBaseCRLNumber; + } + + /** + * Sets the maximum base CRL number. Setting to <code>null</code> disables + * this cheack. + * <p> + * This is only meaningful for delta CRLs. Complete CRLs must have a CRL + * number which is greater or equal than the base number of the + * corresponding CRL. + * + * @param maxBaseCRLNumber The maximum base CRL number to set. + */ + public void setMaxBaseCRLNumber(BigInteger maxBaseCRLNumber) + { + this.maxBaseCRLNumber = maxBaseCRLNumber; + } + + /** + * Returns the issuing distribution point. Defaults to <code>null</code>, + * which is a missing issuing distribution point extension. + * <p> + * The internal byte array is cloned before it is returned. + * <p> + * The criteria must be enable with + * {@link #setIssuingDistributionPointEnabled(boolean)}. + * + * @return Returns the issuing distribution point. + * @see #setIssuingDistributionPoint(byte[]) + */ + public byte[] getIssuingDistributionPoint() + { + return Arrays.clone(issuingDistributionPoint); + } + + /** + * Sets the issuing distribution point. + * <p> + * The issuing distribution point extension is a CRL extension which + * identifies the scope and the distribution point of a CRL. The scope + * contains among others information about revocation reasons contained in + * the CRL. Delta CRLs and complete CRLs must have matching issuing + * distribution points. + * <p> + * The byte array is cloned to protect against subsequent modifications. + * <p> + * You must also enable or disable this criteria with + * {@link #setIssuingDistributionPointEnabled(boolean)}. + * + * @param issuingDistributionPoint The issuing distribution point to set. + * This is the DER encoded OCTET STRING extension value. + * @see #getIssuingDistributionPoint() + */ + public void setIssuingDistributionPoint(byte[] issuingDistributionPoint) + { + this.issuingDistributionPoint = Arrays.clone(issuingDistributionPoint); + } +} diff --git a/prov/src/main/jdk1.3/org/spongycastle/x509/X509CertStoreSelector.java b/prov/src/main/jdk1.3/org/spongycastle/x509/X509CertStoreSelector.java new file mode 100644 index 00000000..f4efcddb --- /dev/null +++ b/prov/src/main/jdk1.3/org/spongycastle/x509/X509CertStoreSelector.java @@ -0,0 +1,86 @@ +package org.spongycastle.x509; + +import org.spongycastle.util.Selector; + +import java.io.IOException; +import java.security.cert.Certificate; +import org.spongycastle.jce.cert.X509CertSelector; +import java.security.cert.X509Certificate; + +/** + * This class is a Selector implementation for X.509 certificates. + * + * @see org.spongycastle.util.Selector + * @see org.spongycastle.x509.X509Store + * @see org.spongycastle.jce.provider.X509StoreCertCollection + */ +public class X509CertStoreSelector + extends X509CertSelector + implements Selector +{ + public boolean match(Object obj) + { + if (!(obj instanceof X509Certificate)) + { + return false; + } + + X509Certificate other = (X509Certificate)obj; + + return super.match(other); + } + + public boolean match(Certificate cert) + { + return match((Object)cert); + } + + public Object clone() + { + X509CertStoreSelector selector = (X509CertStoreSelector)super.clone(); + + return selector; + } + + /** + * Returns an instance of this from a <code>X509CertSelector</code>. + * + * @param selector A <code>X509CertSelector</code> instance. + * @return An instance of an <code>X509CertStoreSelector</code>. + * @exception IllegalArgumentException if selector is null or creation fails. + */ + public static X509CertStoreSelector getInstance(X509CertSelector selector) + { + if (selector == null) + { + throw new IllegalArgumentException("cannot create from null selector"); + } + X509CertStoreSelector cs = new X509CertStoreSelector(); + cs.setAuthorityKeyIdentifier(selector.getAuthorityKeyIdentifier()); + cs.setBasicConstraints(selector.getBasicConstraints()); + cs.setCertificate(selector.getCertificate()); + cs.setCertificateValid(selector.getCertificateValid()); + cs.setMatchAllSubjectAltNames(selector.getMatchAllSubjectAltNames()); + try + { + cs.setPathToNames(selector.getPathToNames()); + cs.setExtendedKeyUsage(selector.getExtendedKeyUsage()); + //cs.setNameConstraints(selector.getNameConstraints()); + cs.setPolicy(selector.getPolicy()); + cs.setSubjectPublicKeyAlgID(selector.getSubjectPublicKeyAlgID()); + cs.setSubject(selector.getSubjectAsBytes()); + cs.setIssuer(selector.getIssuerAsBytes()); + } + catch (IOException e) + { + throw new IllegalArgumentException("error in passed in selector: " + e); + } + cs.setKeyUsage(selector.getKeyUsage()); + cs.setPrivateKeyValid(selector.getPrivateKeyValid()); + cs.setSerialNumber(selector.getSerialNumber()); + cs.setSubjectKeyIdentifier(selector.getSubjectKeyIdentifier()); + cs.setSubjectPublicKey(selector.getSubjectPublicKey()); + return cs; + } + +} diff --git a/prov/src/main/jdk1.3/org/spongycastle/x509/X509Util.java b/prov/src/main/jdk1.3/org/spongycastle/x509/X509Util.java new file mode 100644 index 00000000..93ec8b63 --- /dev/null +++ b/prov/src/main/jdk1.3/org/spongycastle/x509/X509Util.java @@ -0,0 +1,397 @@ +package org.spongycastle.x509; + +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.SecureRandom; +import java.security.Security; +import java.security.Signature; +import java.security.SignatureException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1Encoding; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.DERNull; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +import org.spongycastle.asn1.nist.NISTObjectIdentifiers; +import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.pkcs.RSASSAPSSparams; +import org.spongycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x9.X9ObjectIdentifiers; +import org.spongycastle.jce.X509Principal; +import org.spongycastle.util.Strings; + +class X509Util +{ + private static Hashtable algorithms = new Hashtable(); + private static Hashtable params = new Hashtable(); + private static Set noParams = new HashSet(); + + static + { + algorithms.put("MD2WITHRSAENCRYPTION", PKCSObjectIdentifiers.md2WithRSAEncryption); + algorithms.put("MD2WITHRSA", PKCSObjectIdentifiers.md2WithRSAEncryption); + algorithms.put("MD5WITHRSAENCRYPTION", PKCSObjectIdentifiers.md5WithRSAEncryption); + algorithms.put("MD5WITHRSA", PKCSObjectIdentifiers.md5WithRSAEncryption); + algorithms.put("SHA1WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha1WithRSAEncryption); + algorithms.put("SHA1WITHRSA", PKCSObjectIdentifiers.sha1WithRSAEncryption); + algorithms.put("SHA224WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha224WithRSAEncryption); + algorithms.put("SHA224WITHRSA", PKCSObjectIdentifiers.sha224WithRSAEncryption); + algorithms.put("SHA256WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha256WithRSAEncryption); + algorithms.put("SHA256WITHRSA", PKCSObjectIdentifiers.sha256WithRSAEncryption); + algorithms.put("SHA384WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha384WithRSAEncryption); + algorithms.put("SHA384WITHRSA", PKCSObjectIdentifiers.sha384WithRSAEncryption); + algorithms.put("SHA512WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha512WithRSAEncryption); + algorithms.put("SHA512WITHRSA", PKCSObjectIdentifiers.sha512WithRSAEncryption); + algorithms.put("SHA1WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); + algorithms.put("SHA224WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); + algorithms.put("SHA256WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); + algorithms.put("SHA384WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); + algorithms.put("SHA512WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); + algorithms.put("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); + algorithms.put("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); + algorithms.put("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); + algorithms.put("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); + algorithms.put("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); + algorithms.put("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); + algorithms.put("SHA1WITHDSA", X9ObjectIdentifiers.id_dsa_with_sha1); + algorithms.put("DSAWITHSHA1", X9ObjectIdentifiers.id_dsa_with_sha1); + algorithms.put("SHA224WITHDSA", NISTObjectIdentifiers.dsa_with_sha224); + algorithms.put("SHA256WITHDSA", NISTObjectIdentifiers.dsa_with_sha256); + algorithms.put("SHA384WITHDSA", NISTObjectIdentifiers.dsa_with_sha384); + algorithms.put("SHA512WITHDSA", NISTObjectIdentifiers.dsa_with_sha512); + algorithms.put("SHA1WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA1); + algorithms.put("ECDSAWITHSHA1", X9ObjectIdentifiers.ecdsa_with_SHA1); + algorithms.put("SHA224WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA224); + algorithms.put("SHA256WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA256); + algorithms.put("SHA384WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384); + algorithms.put("SHA512WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA512); + algorithms.put("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); + algorithms.put("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); + algorithms.put("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); + algorithms.put("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); + algorithms.put("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); + + // + // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field. + // The parameters field SHALL be NULL for RSA based signature algorithms. + // + noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA1); + noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA224); + noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA256); + noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA384); + noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA512); + noParams.add(X9ObjectIdentifiers.id_dsa_with_sha1); + noParams.add(NISTObjectIdentifiers.dsa_with_sha224); + noParams.add(NISTObjectIdentifiers.dsa_with_sha256); + noParams.add(NISTObjectIdentifiers.dsa_with_sha384); + noParams.add(NISTObjectIdentifiers.dsa_with_sha512); + + // + // RFC 4491 + // + noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); + noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); + + // + // explicit params + // + AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, new DERNull()); + params.put("SHA1WITHRSAANDMGF1", creatPSSParams(sha1AlgId, 20)); + + AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha224, new DERNull()); + params.put("SHA224WITHRSAANDMGF1", creatPSSParams(sha224AlgId, 28)); + + AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256, new DERNull()); + params.put("SHA256WITHRSAANDMGF1", creatPSSParams(sha256AlgId, 32)); + + AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha384, new DERNull()); + params.put("SHA384WITHRSAANDMGF1", creatPSSParams(sha384AlgId, 48)); + + AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha512, new DERNull()); + params.put("SHA512WITHRSAANDMGF1", creatPSSParams(sha512AlgId, 64)); + } + + private static RSASSAPSSparams creatPSSParams(AlgorithmIdentifier hashAlgId, int saltSize) + { + return new RSASSAPSSparams( + hashAlgId, + new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, hashAlgId), + new ASN1Integer(saltSize), + new ASN1Integer(1)); + } + + static ASN1ObjectIdentifier getAlgorithmOID( + String algorithmName) + { + algorithmName = Strings.toUpperCase(algorithmName); + + if (algorithms.containsKey(algorithmName)) + { + return (ASN1ObjectIdentifier)algorithms.get(algorithmName); + } + + return new ASN1ObjectIdentifier(algorithmName); + } + + static AlgorithmIdentifier getSigAlgID( + ASN1ObjectIdentifier sigOid, + String algorithmName) + { + if (noParams.contains(sigOid)) + { + return new AlgorithmIdentifier(sigOid); + } + + algorithmName = Strings.toUpperCase(algorithmName); + + if (params.containsKey(algorithmName)) + { + return new AlgorithmIdentifier(sigOid, (ASN1Encodable)params.get(algorithmName)); + } + else + { + return new AlgorithmIdentifier(sigOid, new DERNull()); + } + } + + static Iterator getAlgNames() + { + Enumeration e = algorithms.keys(); + List l = new ArrayList(); + + while (e.hasMoreElements()) + { + l.add(e.nextElement()); + } + + return l.iterator(); + } + + static Signature getSignatureInstance( + String algorithm) + throws NoSuchAlgorithmException + { + return Signature.getInstance(algorithm); + } + + static Signature getSignatureInstance( + String algorithm, + String provider) + throws NoSuchProviderException, NoSuchAlgorithmException + { + if (provider != null) + { + return Signature.getInstance(algorithm, provider); + } + else + { + return Signature.getInstance(algorithm); + } + } + + static byte[] calculateSignature( + ASN1ObjectIdentifier sigOid, + String sigName, + PrivateKey key, + SecureRandom random, + ASN1Encodable object) + throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException + { + Signature sig; + + if (sigOid == null) + { + throw new IllegalStateException("no signature algorithm specified"); + } + + sig = X509Util.getSignatureInstance(sigName); + + if (random != null) + { + sig.initSign(key, random); + } + else + { + sig.initSign(key); + } + + sig.update(object.toASN1Primitive().getEncoded(ASN1Encoding.DER)); + + return sig.sign(); + } + + static byte[] calculateSignature( + ASN1ObjectIdentifier sigOid, + String sigName, + String provider, + PrivateKey key, + SecureRandom random, + ASN1Encodable object) + throws IOException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException, SignatureException + { + Signature sig; + + if (sigOid == null) + { + throw new IllegalStateException("no signature algorithm specified"); + } + + sig = X509Util.getSignatureInstance(sigName, provider); + + if (random != null) + { + sig.initSign(key, random); + } + else + { + sig.initSign(key); + } + + sig.update(object.toASN1Primitive().getEncoded(ASN1Encoding.DER)); + + return sig.sign(); + } + + static class Implementation + { + Object engine; + Provider provider; + + Implementation( + Object engine, + Provider provider) + { + this.engine = engine; + this.provider = provider; + } + + Object getEngine() + { + return engine; + } + + Provider getProvider() + { + return provider; + } + } + + /** + * see if we can find an algorithm (or its alias and what it represents) in + * the property table for the given provider. + */ + static Implementation getImplementation( + String baseName, + String algorithm, + Provider prov) + throws NoSuchAlgorithmException + { + algorithm = Strings.toUpperCase(algorithm); + + String alias; + + while ((alias = prov.getProperty("Alg.Alias." + baseName + "." + algorithm)) != null) + { + algorithm = alias; + } + + String className = prov.getProperty(baseName + "." + algorithm); + + if (className != null) + { + try + { + Class cls; + ClassLoader clsLoader = prov.getClass().getClassLoader(); + + if (clsLoader != null) + { + cls = clsLoader.loadClass(className); + } + else + { + cls = Class.forName(className); + } + + return new Implementation(cls.newInstance(), prov); + } + catch (ClassNotFoundException e) + { + throw new IllegalStateException( + "algorithm " + algorithm + " in provider " + prov.getName() + " but no class \"" + className + "\" found!"); + } + catch (Exception e) + { + throw new IllegalStateException( + "algorithm " + algorithm + " in provider " + prov.getName() + " but class \"" + className + "\" inaccessible!"); + } + } + + throw new NoSuchAlgorithmException("cannot find implementation " + algorithm + " for provider " + prov.getName()); + } + + /** + * return an implementation for a given algorithm/provider. + * If the provider is null, we grab the first avalaible who has the required algorithm. + */ + static Implementation getImplementation( + String baseName, + String algorithm) + throws NoSuchAlgorithmException + { + Provider[] prov = Security.getProviders(); + + // + // search every provider looking for the algorithm we want. + // + for (int i = 0; i != prov.length; i++) + { + // + // try case insensitive + // + Implementation imp = getImplementation(baseName, Strings.toUpperCase(algorithm), prov[i]); + if (imp != null) + { + return imp; + } + + try + { + imp = getImplementation(baseName, algorithm, prov[i]); + } + catch (NoSuchAlgorithmException e) + { + // continue + } + } + + throw new NoSuchAlgorithmException("cannot find implementation " + algorithm); + } + + static Provider getProvider(String provider) + throws NoSuchProviderException + { + Provider prov = Security.getProvider(provider); + + if (prov == null) + { + throw new NoSuchProviderException("Provider " + provider + " not found"); + } + + return prov; + } +} diff --git a/prov/src/main/jdk1.3/org/spongycastle/x509/X509V1CertificateGenerator.java b/prov/src/main/jdk1.3/org/spongycastle/x509/X509V1CertificateGenerator.java new file mode 100644 index 00000000..d038b5cf --- /dev/null +++ b/prov/src/main/jdk1.3/org/spongycastle/x509/X509V1CertificateGenerator.java @@ -0,0 +1,341 @@ +package org.spongycastle.x509; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.SignatureException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Iterator; + +import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.DERBitString; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.DERSequence; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.asn1.x509.TBSCertificate; +import org.spongycastle.asn1.x509.Time; +import org.spongycastle.asn1.x509.V1TBSCertificateGenerator; +import org.spongycastle.asn1.x509.Certificate; +import org.spongycastle.asn1.x509.X509Name; +import org.spongycastle.jce.provider.X509CertificateObject; + +/** + * class to produce an X.509 Version 1 certificate. + * @deprecated use org.spongycastle.cert.X509v1CertificateBuilder. + */ +public class X509V1CertificateGenerator +{ + private V1TBSCertificateGenerator tbsGen; + private ASN1ObjectIdentifier sigOID; + private AlgorithmIdentifier sigAlgId; + private String signatureAlgorithm; + + public X509V1CertificateGenerator() + { + tbsGen = new V1TBSCertificateGenerator(); + } + + /** + * reset the generator + */ + public void reset() + { + tbsGen = new V1TBSCertificateGenerator(); + } + + /** + * set the serial number for the certificate. + */ + public void setSerialNumber( + BigInteger serialNumber) + { + if (serialNumber.compareTo(BigInteger.ZERO) <= 0) + { + throw new IllegalArgumentException("serial number must be a positive integer"); + } + + tbsGen.setSerialNumber(new ASN1Integer(serialNumber)); + } + + /** + * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the + * certificate. + */ + public void setIssuerDN( + X509Name issuer) + { + tbsGen.setIssuer(issuer); + } + + public void setNotBefore( + Date date) + { + tbsGen.setStartDate(new Time(date)); + } + + public void setNotAfter( + Date date) + { + tbsGen.setEndDate(new Time(date)); + } + + /** + * Set the subject distinguished name. The subject describes the entity associated with the public key. + */ + public void setSubjectDN( + X509Name subject) + { + tbsGen.setSubject(subject); + } + + public void setPublicKey( + PublicKey key) + { + try + { + tbsGen.setSubjectPublicKeyInfo(new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream( + new ByteArrayInputStream(key.getEncoded())).readObject())); + } + catch (Exception e) + { + throw new IllegalArgumentException("unable to process key - " + e.toString()); + } + } + + /** + * Set the signature algorithm. This can be either a name or an OID, names + * are treated as case insensitive. + * + * @param signatureAlgorithm string representation of the algorithm name. + */ + public void setSignatureAlgorithm( + String signatureAlgorithm) + { + this.signatureAlgorithm = signatureAlgorithm; + + try + { + sigOID = X509Util.getAlgorithmOID(signatureAlgorithm); + } + catch (Exception e) + { + throw new IllegalArgumentException("Unknown signature type requested"); + } + + sigAlgId = X509Util.getSigAlgID(sigOID, signatureAlgorithm); + + tbsGen.setSignature(sigAlgId); + } + + /** + * generate an X509 certificate, based on the current issuer and subject + * using the default provider "SC". + * @deprecated use generate(key, "SC") + */ + public X509Certificate generateX509Certificate( + PrivateKey key) + throws SecurityException, SignatureException, InvalidKeyException + { + try + { + return generateX509Certificate(key, "SC", null); + } + catch (NoSuchProviderException e) + { + throw new SecurityException("BC provider not installed!"); + } + } + + /** + * generate an X509 certificate, based on the current issuer and subject + * using the default provider "SC" and the passed in source of randomness + * @deprecated use generate(key, random, "SC") + */ + public X509Certificate generateX509Certificate( + PrivateKey key, + SecureRandom random) + throws SecurityException, SignatureException, InvalidKeyException + { + try + { + return generateX509Certificate(key, "SC", random); + } + catch (NoSuchProviderException e) + { + throw new SecurityException("BC provider not installed!"); + } + } + + /** + * generate an X509 certificate, based on the current issuer and subject, + * using the passed in provider for the signing, and the passed in source + * of randomness (if required). + * @deprecated use generate() + */ + public X509Certificate generateX509Certificate( + PrivateKey key, + String provider) + throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException + { + return generateX509Certificate(key, provider, null); + } + + /** + * generate an X509 certificate, based on the current issuer and subject, + * using the passed in provider for the signing, and the passed in source + * of randomness (if required). + * @deprecated use generate() + */ + public X509Certificate generateX509Certificate( + PrivateKey key, + String provider, + SecureRandom random) + throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException + { + try + { + return generate(key, provider, random); + } + catch (NoSuchProviderException e) + { + throw e; + } + catch (SignatureException e) + { + throw e; + } + catch (InvalidKeyException e) + { + throw e; + } + catch (GeneralSecurityException e) + { + throw new SecurityException("exception: " + e); + } + } + + /** + * generate an X509 certificate, based on the current issuer and subject + * using the default provider. + * <p> + * <b>Note:</b> this differs from the deprecated method in that the default provider is + * used - not "SC". + * </p> + */ + public X509Certificate generate( + PrivateKey key) + throws CertificateEncodingException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException + { + return generate(key, (SecureRandom)null); + } + + /** + * generate an X509 certificate, based on the current issuer and subject + * using the default provider and the passed in source of randomness + * <p> + * <b>Note:</b> this differs from the deprecated method in that the default provider is + * used - not "SC". + * </p> + */ + public X509Certificate generate( + PrivateKey key, + SecureRandom random) + throws CertificateEncodingException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException + { + TBSCertificate tbsCert = tbsGen.generateTBSCertificate(); + byte[] signature; + + try + { + signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, key, random, tbsCert); + } + catch (IOException e) + { + throw new ExtCertificateEncodingException("exception encoding TBS cert", e); + } + + return generateJcaObject(tbsCert, signature); + } + + /** + * generate an X509 certificate, based on the current issuer and subject, + * using the passed in provider for the signing, and the passed in source + * of randomness (if required). + */ + public X509Certificate generate( + PrivateKey key, + String provider) + throws CertificateEncodingException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException + { + return generate(key, provider, null); + } + + /** + * generate an X509 certificate, based on the current issuer and subject, + * using the passed in provider for the signing, and the passed in source + * of randomness (if required). + */ + public X509Certificate generate( + PrivateKey key, + String provider, + SecureRandom random) + throws CertificateEncodingException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException + { + TBSCertificate tbsCert = tbsGen.generateTBSCertificate(); + byte[] signature; + + try + { + signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, provider, key, random, tbsCert); + } + catch (IOException e) + { + throw new ExtCertificateEncodingException("exception encoding TBS cert", e); + } + + return generateJcaObject(tbsCert, signature); + } + + private X509Certificate generateJcaObject(TBSCertificate tbsCert, byte[] signature) + throws CertificateEncodingException + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(tbsCert); + v.add(sigAlgId); + v.add(new DERBitString(signature)); + + try + { + return new X509CertificateObject(Certificate.getInstance(new DERSequence(v))); + } + catch (CertificateParsingException e) + { + throw new ExtCertificateEncodingException("exception producing certificate object", e); + } + } + + /** + * Return an iterator of the signature names supported by the generator. + * + * @return an iterator containing recognised names. + */ + public Iterator getSignatureAlgNames() + { + return X509Util.getAlgNames(); + } +} diff --git a/prov/src/main/jdk1.3/org/spongycastle/x509/X509V2CRLGenerator.java b/prov/src/main/jdk1.3/org/spongycastle/x509/X509V2CRLGenerator.java new file mode 100644 index 00000000..8da36afb --- /dev/null +++ b/prov/src/main/jdk1.3/org/spongycastle/x509/X509V2CRLGenerator.java @@ -0,0 +1,430 @@ +package org.spongycastle.x509; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.security.SignatureException; +import java.security.cert.CRLException; +import java.security.cert.X509CRL; +import java.security.cert.X509CRLEntry; +import java.util.Date; +import java.util.Iterator; +import java.util.Set; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.ASN1GeneralizedTime; +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.DERBitString; +import org.spongycastle.asn1.DERSequence; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.CertificateList; +import org.spongycastle.asn1.x509.Extensions; +import org.spongycastle.asn1.x509.TBSCertList; +import org.spongycastle.asn1.x509.Time; +import org.spongycastle.asn1.x509.V2TBSCertListGenerator; +import org.spongycastle.asn1.x509.X509Extensions; +import org.spongycastle.asn1.x509.X509ExtensionsGenerator; +import org.spongycastle.asn1.x509.X509Name; +import org.spongycastle.jce.provider.X509CRLObject; + +/** + * class to produce an X.509 Version 2 CRL. + * @deprecated use org.spongycastle.cert.X509v2CRLBuilder. + */ +public class X509V2CRLGenerator +{ + private V2TBSCertListGenerator tbsGen; + private ASN1ObjectIdentifier sigOID; + private AlgorithmIdentifier sigAlgId; + private String signatureAlgorithm; + private X509ExtensionsGenerator extGenerator; + + public X509V2CRLGenerator() + { + tbsGen = new V2TBSCertListGenerator(); + extGenerator = new X509ExtensionsGenerator(); + } + + /** + * reset the generator + */ + public void reset() + { + tbsGen = new V2TBSCertListGenerator(); + extGenerator.reset(); + } + + /** + * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the + * certificate. + */ + public void setIssuerDN( + X509Name issuer) + { + tbsGen.setIssuer(issuer); + } + + public void setThisUpdate( + Date date) + { + tbsGen.setThisUpdate(new Time(date)); + } + + public void setNextUpdate( + Date date) + { + tbsGen.setNextUpdate(new Time(date)); + } + + /** + * Reason being as indicated by CRLReason, i.e. CRLReason.keyCompromise + * or 0 if CRLReason is not to be used + **/ + public void addCRLEntry(BigInteger userCertificate, Date revocationDate, int reason) + { + tbsGen.addCRLEntry(new ASN1Integer(userCertificate), new Time(revocationDate), reason); + } + + /** + * Add a CRL entry with an Invalidity Date extension as well as a CRLReason extension. + * Reason being as indicated by CRLReason, i.e. CRLReason.keyCompromise + * or 0 if CRLReason is not to be used + **/ + public void addCRLEntry(BigInteger userCertificate, Date revocationDate, int reason, Date invalidityDate) + { + tbsGen.addCRLEntry(new ASN1Integer(userCertificate), new Time(revocationDate), reason, new ASN1GeneralizedTime(invalidityDate)); + } + + /** + * Add a CRL entry with extensions. + **/ + public void addCRLEntry(BigInteger userCertificate, Date revocationDate, X509Extensions extensions) + { + tbsGen.addCRLEntry(new ASN1Integer(userCertificate), new Time(revocationDate), Extensions.getInstance(extensions)); + } + + /** + * Add the CRLEntry objects contained in a previous CRL. + * + * @param other the X509CRL to source the other entries from. + */ + public void addCRL(X509CRL other) + throws CRLException + { + Set revocations = other.getRevokedCertificates(); + + if (revocations != null) + { + Iterator it = revocations.iterator(); + while (it.hasNext()) + { + X509CRLEntry entry = (X509CRLEntry)it.next(); + + ASN1InputStream aIn = new ASN1InputStream(entry.getEncoded()); + + try + { + tbsGen.addCRLEntry(ASN1Sequence.getInstance(aIn.readObject())); + } + catch (IOException e) + { + throw new CRLException("exception processing encoding of CRL: " + e.toString()); + } + } + } + } + + /** + * Set the signature algorithm. This can be either a name or an OID, names + * are treated as case insensitive. + * + * @param signatureAlgorithm string representation of the algorithm name. + */ + public void setSignatureAlgorithm( + String signatureAlgorithm) + { + this.signatureAlgorithm = signatureAlgorithm; + + try + { + sigOID = X509Util.getAlgorithmOID(signatureAlgorithm); + } + catch (Exception e) + { + throw new IllegalArgumentException("Unknown signature type requested"); + } + + sigAlgId = X509Util.getSigAlgID(sigOID, signatureAlgorithm); + + tbsGen.setSignature(sigAlgId); + } + + /** + * add a given extension field for the standard extensions tag (tag 0) + */ + public void addExtension( + String oid, + boolean critical, + ASN1Encodable value) + { + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); + } + + /** + * add a given extension field for the standard extensions tag (tag 0) + */ + public void addExtension( + ASN1ObjectIdentifier oid, + boolean critical, + ASN1Encodable value) + { + extGenerator.addExtension(new ASN1ObjectIdentifier(oid.getId()), critical, value); + } + + /** + * add a given extension field for the standard extensions tag (tag 0) + */ + public void addExtension( + String oid, + boolean critical, + byte[] value) + { + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); + } + + /** + * add a given extension field for the standard extensions tag (tag 0) + */ + public void addExtension( + ASN1ObjectIdentifier oid, + boolean critical, + byte[] value) + { + extGenerator.addExtension(new ASN1ObjectIdentifier(oid.getId()), critical, value); + } + + /** + * generate an X509 CRL, based on the current issuer and subject + * using the default provider "SC". + * @deprecated use generate(key, "SC") + */ + public X509CRL generateX509CRL( + PrivateKey key) + throws SecurityException, SignatureException, InvalidKeyException + { + try + { + return generateX509CRL(key, "SC", null); + } + catch (NoSuchProviderException e) + { + throw new SecurityException("BC provider not installed!"); + } + } + + /** + * generate an X509 CRL, based on the current issuer and subject + * using the default provider "SC" and an user defined SecureRandom object as + * source of randomness. + * @deprecated use generate(key, random, "SC") + */ + public X509CRL generateX509CRL( + PrivateKey key, + SecureRandom random) + throws SecurityException, SignatureException, InvalidKeyException + { + try + { + return generateX509CRL(key, "SC", random); + } + catch (NoSuchProviderException e) + { + throw new SecurityException("BC provider not installed!"); + } + } + + /** + * generate an X509 certificate, based on the current issuer and subject + * using the passed in provider for the signing. + * @deprecated use generate() + */ + public X509CRL generateX509CRL( + PrivateKey key, + String provider) + throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException + { + return generateX509CRL(key, provider, null); + } + + /** + * generate an X509 CRL, based on the current issuer and subject, + * using the passed in provider for the signing. + * @deprecated use generate() + */ + public X509CRL generateX509CRL( + PrivateKey key, + String provider, + SecureRandom random) + throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException + { + try + { + return generate(key, provider, random); + } + catch (NoSuchProviderException e) + { + throw e; + } + catch (SignatureException e) + { + throw e; + } + catch (InvalidKeyException e) + { + throw e; + } + catch (GeneralSecurityException e) + { + throw new SecurityException("exception: " + e); + } + } + + /** + * generate an X509 CRL, based on the current issuer and subject + * using the default provider. + * <p> + * <b>Note:</b> this differs from the deprecated method in that the default provider is + * used - not "SC". + * </p> + */ + public X509CRL generate( + PrivateKey key) + throws CRLException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException + { + return generate(key, (SecureRandom)null); + } + + /** + * generate an X509 CRL, based on the current issuer and subject + * using the default provider and an user defined SecureRandom object as + * source of randomness. + * <p> + * <b>Note:</b> this differs from the deprecated method in that the default provider is + * used - not "SC". + * </p> + */ + public X509CRL generate( + PrivateKey key, + SecureRandom random) + throws CRLException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException + { + TBSCertList tbsCrl = generateCertList(); + byte[] signature; + + try + { + signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, key, random, tbsCrl); + } + catch (IOException e) + { + throw new ExtCRLException("cannot generate CRL encoding", e); + } + + return generateJcaObject(tbsCrl, signature); + } + + /** + * generate an X509 certificate, based on the current issuer and subject + * using the passed in provider for the signing. + */ + public X509CRL generate( + PrivateKey key, + String provider) + throws CRLException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException + { + return generate(key, provider, null); + } + + /** + * generate an X509 CRL, based on the current issuer and subject, + * using the passed in provider for the signing. + */ + public X509CRL generate( + PrivateKey key, + String provider, + SecureRandom random) + throws CRLException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException + { + TBSCertList tbsCrl = generateCertList(); + byte[] signature; + + try + { + signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, provider, key, random, tbsCrl); + } + catch (IOException e) + { + throw new ExtCRLException("cannot generate CRL encoding", e); + } + + return generateJcaObject(tbsCrl, signature); + } + + private TBSCertList generateCertList() + { + if (!extGenerator.isEmpty()) + { + tbsGen.setExtensions(extGenerator.generate()); + } + + return tbsGen.generateTBSCertList(); + } + + private X509CRL generateJcaObject(TBSCertList tbsCrl, byte[] signature) + throws CRLException + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(tbsCrl); + v.add(sigAlgId); + v.add(new DERBitString(signature)); + + return new X509CRLObject(new CertificateList(new DERSequence(v))); + } + + /** + * Return an iterator of the signature names supported by the generator. + * + * @return an iterator containing recognised names. + */ + public Iterator getSignatureAlgNames() + { + return X509Util.getAlgNames(); + } + + private static class ExtCRLException + extends CRLException + { + Throwable cause; + + ExtCRLException(String message, Throwable cause) + { + super(message); + this.cause = cause; + } + + public Throwable getCause() + { + return cause; + } + } +} diff --git a/prov/src/main/jdk1.3/org/spongycastle/x509/X509V3CertificateGenerator.java b/prov/src/main/jdk1.3/org/spongycastle/x509/X509V3CertificateGenerator.java new file mode 100644 index 00000000..e58310e2 --- /dev/null +++ b/prov/src/main/jdk1.3/org/spongycastle/x509/X509V3CertificateGenerator.java @@ -0,0 +1,491 @@ +package org.spongycastle.x509; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.SignatureException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Iterator; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.DERBitString; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.DERSequence; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.asn1.x509.TBSCertificate; +import org.spongycastle.asn1.x509.Time; +import org.spongycastle.asn1.x509.V3TBSCertificateGenerator; +import org.spongycastle.asn1.x509.Certificate; +import org.spongycastle.asn1.x509.X509ExtensionsGenerator; +import org.spongycastle.asn1.x509.X509Name; +import org.spongycastle.jce.provider.X509CertificateObject; +import org.spongycastle.x509.extension.X509ExtensionUtil; + +/** + * class to produce an X.509 Version 3 certificate. + * @deprecated use org.spongycastle.cert.X509v3CertificateBuilder. + */ +public class X509V3CertificateGenerator +{ + private V3TBSCertificateGenerator tbsGen; + private ASN1ObjectIdentifier sigOID; + private AlgorithmIdentifier sigAlgId; + private String signatureAlgorithm; + private X509ExtensionsGenerator extGenerator; + + public X509V3CertificateGenerator() + { + tbsGen = new V3TBSCertificateGenerator(); + extGenerator = new X509ExtensionsGenerator(); + } + + /** + * reset the generator + */ + public void reset() + { + tbsGen = new V3TBSCertificateGenerator(); + extGenerator.reset(); + } + + /** + * set the serial number for the certificate. + */ + public void setSerialNumber( + BigInteger serialNumber) + { + if (serialNumber.compareTo(BigInteger.ZERO) <= 0) + { + throw new IllegalArgumentException("serial number must be a positive integer"); + } + + tbsGen.setSerialNumber(new ASN1Integer(serialNumber)); + } + + /** + * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the + * certificate. + */ + public void setIssuerDN( + X509Name issuer) + { + tbsGen.setIssuer(issuer); + } + + public void setNotBefore( + Date date) + { + tbsGen.setStartDate(new Time(date)); + } + + public void setNotAfter( + Date date) + { + tbsGen.setEndDate(new Time(date)); + } + + /** + * Set the subject distinguished name. The subject describes the entity associated with the public key. + */ + public void setSubjectDN( + X509Name subject) + { + tbsGen.setSubject(subject); + } + + public void setPublicKey( + PublicKey key) + throws IllegalArgumentException + { + try + { + tbsGen.setSubjectPublicKeyInfo( + SubjectPublicKeyInfo.getInstance(new ASN1InputStream(key.getEncoded()).readObject())); + } + catch (Exception e) + { + throw new IllegalArgumentException("unable to process key - " + e.toString()); + } + } + + /** + * Set the signature algorithm. This can be either a name or an OID, names + * are treated as case insensitive. + * + * @param signatureAlgorithm string representation of the algorithm name. + */ + public void setSignatureAlgorithm( + String signatureAlgorithm) + { + this.signatureAlgorithm = signatureAlgorithm; + + try + { + sigOID = X509Util.getAlgorithmOID(signatureAlgorithm); + } + catch (Exception e) + { + throw new IllegalArgumentException("Unknown signature type requested: " + signatureAlgorithm); + } + + sigAlgId = X509Util.getSigAlgID(sigOID, signatureAlgorithm); + + tbsGen.setSignature(sigAlgId); + } + + /** + * Set the subject unique ID - note: it is very rare that it is correct to do this. + */ + public void setSubjectUniqueID(boolean[] uniqueID) + { + tbsGen.setSubjectUniqueID(booleanToBitString(uniqueID)); + } + + /** + * Set the issuer unique ID - note: it is very rare that it is correct to do this. + */ + public void setIssuerUniqueID(boolean[] uniqueID) + { + tbsGen.setIssuerUniqueID(booleanToBitString(uniqueID)); + } + + private DERBitString booleanToBitString(boolean[] id) + { + byte[] bytes = new byte[(id.length + 7) / 8]; + + for (int i = 0; i != id.length; i++) + { + bytes[i / 8] |= (id[i]) ? (1 << ((7 - (i % 8)))) : 0; + } + + int pad = id.length % 8; + + if (pad == 0) + { + return new DERBitString(bytes); + } + else + { + return new DERBitString(bytes, 8 - pad); + } + } + + /** + * add a given extension field for the standard extensions tag (tag 3) + */ + public void addExtension( + String oid, + boolean critical, + ASN1Encodable value) + { + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); + } + + /** + * add a given extension field for the standard extensions tag (tag 3) + */ + public void addExtension( + ASN1ObjectIdentifier oid, + boolean critical, + ASN1Encodable value) + { + extGenerator.addExtension(new ASN1ObjectIdentifier(oid.getId()), critical, value); + } + + /** + * add a given extension field for the standard extensions tag (tag 3) + * The value parameter becomes the contents of the octet string associated + * with the extension. + */ + public void addExtension( + String oid, + boolean critical, + byte[] value) + { + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); + } + + /** + * add a given extension field for the standard extensions tag (tag 3) + */ + public void addExtension( + ASN1ObjectIdentifier oid, + boolean critical, + byte[] value) + { + extGenerator.addExtension(new ASN1ObjectIdentifier(oid.getId()), critical, value); + } + + /** + * add a given extension field for the standard extensions tag (tag 3) + * copying the extension value from another certificate. + * @throws CertificateParsingException if the extension cannot be extracted. + */ + public void copyAndAddExtension( + String oid, + boolean critical, + X509Certificate cert) + throws CertificateParsingException + { + byte[] extValue = cert.getExtensionValue(oid); + + if (extValue == null) + { + throw new CertificateParsingException("extension " + oid + " not present"); + } + + try + { + ASN1Encodable value = X509ExtensionUtil.fromExtensionValue(extValue); + + this.addExtension(oid, critical, value); + } + catch (IOException e) + { + throw new CertificateParsingException(e.toString()); + } + } + + /** + * add a given extension field for the standard extensions tag (tag 3) + * copying the extension value from another certificate. + * @throws CertificateParsingException if the extension cannot be extracted. + */ + public void copyAndAddExtension( + ASN1ObjectIdentifier oid, + boolean critical, + X509Certificate cert) + throws CertificateParsingException + { + this.copyAndAddExtension(oid.getId(), critical, cert); + } + + /** + * generate an X509 certificate, based on the current issuer and subject + * using the default provider "SC". + * @deprecated use generate(key, "SC") + */ + public X509Certificate generateX509Certificate( + PrivateKey key) + throws SecurityException, SignatureException, InvalidKeyException + { + try + { + return generateX509Certificate(key, "SC", null); + } + catch (NoSuchProviderException e) + { + throw new SecurityException("BC provider not installed!"); + } + } + + /** + * generate an X509 certificate, based on the current issuer and subject + * using the default provider "SC", and the passed in source of randomness + * (if required). + * @deprecated use generate(key, random, "SC") + */ + public X509Certificate generateX509Certificate( + PrivateKey key, + SecureRandom random) + throws SecurityException, SignatureException, InvalidKeyException + { + try + { + return generateX509Certificate(key, "SC", random); + } + catch (NoSuchProviderException e) + { + throw new SecurityException("BC provider not installed!"); + } + } + + /** + * generate an X509 certificate, based on the current issuer and subject, + * using the passed in provider for the signing. + * @deprecated use generate() + */ + public X509Certificate generateX509Certificate( + PrivateKey key, + String provider) + throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException + { + return generateX509Certificate(key, provider, null); + } + + /** + * generate an X509 certificate, based on the current issuer and subject, + * using the passed in provider for the signing and the supplied source + * of randomness, if required. + * @deprecated use generate() + */ + public X509Certificate generateX509Certificate( + PrivateKey key, + String provider, + SecureRandom random) + throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException + { + try + { + return generate(key, provider, random); + } + catch (NoSuchProviderException e) + { + throw e; + } + catch (SignatureException e) + { + throw e; + } + catch (InvalidKeyException e) + { + throw e; + } + catch (GeneralSecurityException e) + { + throw new SecurityException("exception: " + e); + } + } + + /** + * generate an X509 certificate, based on the current issuer and subject + * using the default provider. + * <p> + * <b>Note:</b> this differs from the deprecated method in that the default provider is + * used - not "SC". + * </p> + */ + public X509Certificate generate( + PrivateKey key) + throws CertificateEncodingException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException + { + return generate(key, (SecureRandom)null); + } + + /** + * generate an X509 certificate, based on the current issuer and subject + * using the default provider, and the passed in source of randomness + * (if required). + * <p> + * <b>Note:</b> this differs from the deprecated method in that the default provider is + * used - not "SC". + * </p> + */ + public X509Certificate generate( + PrivateKey key, + SecureRandom random) + throws CertificateEncodingException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException + { + TBSCertificate tbsCert = generateTbsCert(); + byte[] signature; + + try + { + signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, key, random, tbsCert); + } + catch (IOException e) + { + throw new ExtCertificateEncodingException("exception encoding TBS cert", e); + } + + try + { + return generateJcaObject(tbsCert, signature); + } + catch (CertificateParsingException e) + { + throw new ExtCertificateEncodingException("exception producing certificate object", e); + } + } + + /** + * generate an X509 certificate, based on the current issuer and subject, + * using the passed in provider for the signing. + */ + public X509Certificate generate( + PrivateKey key, + String provider) + throws CertificateEncodingException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException + { + return generate(key, provider, null); + } + + /** + * generate an X509 certificate, based on the current issuer and subject, + * using the passed in provider for the signing and the supplied source + * of randomness, if required. + */ + public X509Certificate generate( + PrivateKey key, + String provider, + SecureRandom random) + throws CertificateEncodingException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException + { + TBSCertificate tbsCert = generateTbsCert(); + byte[] signature; + + try + { + signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, provider, key, random, tbsCert); + } + catch (IOException e) + { + throw new ExtCertificateEncodingException("exception encoding TBS cert", e); + } + + try + { + return generateJcaObject(tbsCert, signature); + } + catch (CertificateParsingException e) + { + throw new ExtCertificateEncodingException("exception producing certificate object", e); + } + } + + private TBSCertificate generateTbsCert() + { + if (!extGenerator.isEmpty()) + { + tbsGen.setExtensions(extGenerator.generate()); + } + + return tbsGen.generateTBSCertificate(); + } + + private X509Certificate generateJcaObject(TBSCertificate tbsCert, byte[] signature) + throws CertificateParsingException + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(tbsCert); + v.add(sigAlgId); + v.add(new DERBitString(signature)); + + return new X509CertificateObject(Certificate.getInstance(new DERSequence(v))); + } + + /** + * Return an iterator of the signature names supported by the generator. + * + * @return an iterator containing recognised names. + */ + public Iterator getSignatureAlgNames() + { + return X509Util.getAlgNames(); + } +} |