Home | History | Annotate | Download | only in x509
      1 package org.bouncycastle.x509;
      2 
      3 import java.io.IOException;
      4 import java.math.BigInteger;
      5 import java.security.MessageDigest;
      6 import java.security.Principal;
      7 import java.security.cert.CertSelector;
      8 import java.security.cert.Certificate;
      9 import java.security.cert.CertificateEncodingException;
     10 import java.security.cert.CertificateParsingException;
     11 import java.security.cert.X509Certificate;
     12 import java.util.ArrayList;
     13 import java.util.List;
     14 
     15 import javax.security.auth.x500.X500Principal;
     16 
     17 import org.bouncycastle.asn1.ASN1Encodable;
     18 import org.bouncycastle.asn1.ASN1Sequence;
     19 import org.bouncycastle.asn1.DERInteger;
     20 import org.bouncycastle.asn1.DERSequence;
     21 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
     22 import org.bouncycastle.asn1.x509.GeneralName;
     23 import org.bouncycastle.asn1.x509.GeneralNames;
     24 import org.bouncycastle.asn1.x509.Holder;
     25 import org.bouncycastle.asn1.x509.IssuerSerial;
     26 import org.bouncycastle.asn1.x509.ObjectDigestInfo;
     27 import org.bouncycastle.jce.PrincipalUtil;
     28 import org.bouncycastle.jce.X509Principal;
     29 import org.bouncycastle.util.Arrays;
     30 import org.bouncycastle.util.Selector;
     31 
     32 /**
     33  * The Holder object.
     34  *
     35  * <pre>
     36  *          Holder ::= SEQUENCE {
     37  *                baseCertificateID   [0] IssuerSerial OPTIONAL,
     38  *                         -- the issuer and serial number of
     39  *                         -- the holder's Public Key Certificate
     40  *                entityName          [1] GeneralNames OPTIONAL,
     41  *                         -- the name of the claimant or role
     42  *                objectDigestInfo    [2] ObjectDigestInfo OPTIONAL
     43  *                         -- used to directly authenticate the holder,
     44  *                         -- for example, an executable
     45  *          }
     46  * </pre>
     47  * @deprecated use org.bouncycastle.cert.AttributeCertificateHolder
     48  */
     49 public class AttributeCertificateHolder
     50     implements CertSelector, Selector
     51 {
     52     final Holder holder;
     53 
     54     AttributeCertificateHolder(ASN1Sequence seq)
     55     {
     56         holder = Holder.getInstance(seq);
     57     }
     58 
     59     public AttributeCertificateHolder(X509Principal issuerName,
     60         BigInteger serialNumber)
     61     {
     62         holder = new org.bouncycastle.asn1.x509.Holder(new IssuerSerial(
     63             new GeneralNames(new DERSequence(new GeneralName(issuerName))),
     64             new DERInteger(serialNumber)));
     65     }
     66 
     67     public AttributeCertificateHolder(X500Principal issuerName,
     68         BigInteger serialNumber)
     69     {
     70         this(X509Util.convertPrincipal(issuerName), serialNumber);
     71     }
     72 
     73     public AttributeCertificateHolder(X509Certificate cert)
     74         throws CertificateParsingException
     75     {
     76         X509Principal name;
     77 
     78         try
     79         {
     80             name = PrincipalUtil.getIssuerX509Principal(cert);
     81         }
     82         catch (Exception e)
     83         {
     84             throw new CertificateParsingException(e.getMessage());
     85         }
     86 
     87         holder = new Holder(new IssuerSerial(generateGeneralNames(name),
     88             new DERInteger(cert.getSerialNumber())));
     89     }
     90 
     91     public AttributeCertificateHolder(X509Principal principal)
     92     {
     93         holder = new Holder(generateGeneralNames(principal));
     94     }
     95 
     96     public AttributeCertificateHolder(X500Principal principal)
     97     {
     98         this(X509Util.convertPrincipal(principal));
     99     }
    100 
    101     /**
    102      * Constructs a holder for v2 attribute certificates with a hash value for
    103      * some type of object.
    104      * <p>
    105      * <code>digestedObjectType</code> can be one of the following:
    106      * <ul>
    107      * <li>0 - publicKey - A hash of the public key of the holder must be
    108      * passed.
    109      * <li>1 - publicKeyCert - A hash of the public key certificate of the
    110      * holder must be passed.
    111      * <li>2 - otherObjectDigest - A hash of some other object type must be
    112      * passed. <code>otherObjectTypeID</code> must not be empty.
    113      * </ul>
    114      * <p>
    115      * This cannot be used if a v1 attribute certificate is used.
    116      *
    117      * @param digestedObjectType The digest object type.
    118      * @param digestAlgorithm The algorithm identifier for the hash.
    119      * @param otherObjectTypeID The object type ID if
    120      *            <code>digestedObjectType</code> is
    121      *            <code>otherObjectDigest</code>.
    122      * @param objectDigest The hash value.
    123      */
    124     public AttributeCertificateHolder(int digestedObjectType,
    125         String digestAlgorithm, String otherObjectTypeID, byte[] objectDigest)
    126     {
    127         holder = new Holder(new ObjectDigestInfo(digestedObjectType,
    128             otherObjectTypeID, new AlgorithmIdentifier(digestAlgorithm), Arrays
    129                 .clone(objectDigest)));
    130     }
    131 
    132     /**
    133      * Returns the digest object type if an object digest info is used.
    134      * <p>
    135      * <ul>
    136      * <li>0 - publicKey - A hash of the public key of the holder must be
    137      * passed.
    138      * <li>1 - publicKeyCert - A hash of the public key certificate of the
    139      * holder must be passed.
    140      * <li>2 - otherObjectDigest - A hash of some other object type must be
    141      * passed. <code>otherObjectTypeID</code> must not be empty.
    142      * </ul>
    143      *
    144      * @return The digest object type or -1 if no object digest info is set.
    145      */
    146     public int getDigestedObjectType()
    147     {
    148         if (holder.getObjectDigestInfo() != null)
    149         {
    150             return holder.getObjectDigestInfo().getDigestedObjectType()
    151                 .getValue().intValue();
    152         }
    153         return -1;
    154     }
    155 
    156     /**
    157      * Returns the other object type ID if an object digest info is used.
    158      *
    159      * @return The other object type ID or <code>null</code> if no object
    160      *         digest info is set.
    161      */
    162     public String getDigestAlgorithm()
    163     {
    164         if (holder.getObjectDigestInfo() != null)
    165         {
    166             return holder.getObjectDigestInfo().getDigestAlgorithm().getObjectId()
    167                 .getId();
    168         }
    169         return null;
    170     }
    171 
    172     /**
    173      * Returns the hash if an object digest info is used.
    174      *
    175      * @return The hash or <code>null</code> if no object digest info is set.
    176      */
    177     public byte[] getObjectDigest()
    178     {
    179         if (holder.getObjectDigestInfo() != null)
    180         {
    181             return holder.getObjectDigestInfo().getObjectDigest().getBytes();
    182         }
    183         return null;
    184     }
    185 
    186     /**
    187      * Returns the digest algorithm ID if an object digest info is used.
    188      *
    189      * @return The digest algorithm ID or <code>null</code> if no object
    190      *         digest info is set.
    191      */
    192     public String getOtherObjectTypeID()
    193     {
    194         if (holder.getObjectDigestInfo() != null)
    195         {
    196             holder.getObjectDigestInfo().getOtherObjectTypeID().getId();
    197         }
    198         return null;
    199     }
    200 
    201     private GeneralNames generateGeneralNames(X509Principal principal)
    202     {
    203         return new GeneralNames(new DERSequence(new GeneralName(principal)));
    204     }
    205 
    206     private boolean matchesDN(X509Principal subject, GeneralNames targets)
    207     {
    208         GeneralName[] names = targets.getNames();
    209 
    210         for (int i = 0; i != names.length; i++)
    211         {
    212             GeneralName gn = names[i];
    213 
    214             if (gn.getTagNo() == GeneralName.directoryName)
    215             {
    216                 try
    217                 {
    218                     if (new X509Principal(((ASN1Encodable)gn.getName())
    219                         .getEncoded()).equals(subject))
    220                     {
    221                         return true;
    222                     }
    223                 }
    224                 catch (IOException e)
    225                 {
    226                 }
    227             }
    228         }
    229 
    230         return false;
    231     }
    232 
    233     private Object[] getNames(GeneralName[] names)
    234     {
    235         List l = new ArrayList(names.length);
    236 
    237         for (int i = 0; i != names.length; i++)
    238         {
    239             if (names[i].getTagNo() == GeneralName.directoryName)
    240             {
    241                 try
    242                 {
    243                     l.add(new X500Principal(
    244                         ((ASN1Encodable)names[i].getName()).getEncoded()));
    245                 }
    246                 catch (IOException e)
    247                 {
    248                     throw new RuntimeException("badly formed Name object");
    249                 }
    250             }
    251         }
    252 
    253         return l.toArray(new Object[l.size()]);
    254     }
    255 
    256     private Principal[] getPrincipals(GeneralNames names)
    257     {
    258         Object[] p = this.getNames(names.getNames());
    259         List l = new ArrayList();
    260 
    261         for (int i = 0; i != p.length; i++)
    262         {
    263             if (p[i] instanceof Principal)
    264             {
    265                 l.add(p[i]);
    266             }
    267         }
    268 
    269         return (Principal[])l.toArray(new Principal[l.size()]);
    270     }
    271 
    272     /**
    273      * Return any principal objects inside the attribute certificate holder
    274      * entity names field.
    275      *
    276      * @return an array of Principal objects (usually X500Principal), null if no
    277      *         entity names field is set.
    278      */
    279     public Principal[] getEntityNames()
    280     {
    281         if (holder.getEntityName() != null)
    282         {
    283             return getPrincipals(holder.getEntityName());
    284         }
    285 
    286         return null;
    287     }
    288 
    289     /**
    290      * Return the principals associated with the issuer attached to this holder
    291      *
    292      * @return an array of principals, null if no BaseCertificateID is set.
    293      */
    294     public Principal[] getIssuer()
    295     {
    296         if (holder.getBaseCertificateID() != null)
    297         {
    298             return getPrincipals(holder.getBaseCertificateID().getIssuer());
    299         }
    300 
    301         return null;
    302     }
    303 
    304     /**
    305      * Return the serial number associated with the issuer attached to this
    306      * holder.
    307      *
    308      * @return the certificate serial number, null if no BaseCertificateID is
    309      *         set.
    310      */
    311     public BigInteger getSerialNumber()
    312     {
    313         if (holder.getBaseCertificateID() != null)
    314         {
    315             return holder.getBaseCertificateID().getSerial().getValue();
    316         }
    317 
    318         return null;
    319     }
    320 
    321     public Object clone()
    322     {
    323         return new AttributeCertificateHolder((ASN1Sequence)holder
    324             .toASN1Object());
    325     }
    326 
    327     public boolean match(Certificate cert)
    328     {
    329         if (!(cert instanceof X509Certificate))
    330         {
    331             return false;
    332         }
    333 
    334         X509Certificate x509Cert = (X509Certificate)cert;
    335 
    336         try
    337         {
    338             if (holder.getBaseCertificateID() != null)
    339             {
    340                 return holder.getBaseCertificateID().getSerial().getValue().equals(x509Cert.getSerialNumber())
    341                     && matchesDN(PrincipalUtil.getIssuerX509Principal(x509Cert), holder.getBaseCertificateID().getIssuer());
    342             }
    343 
    344             if (holder.getEntityName() != null)
    345             {
    346                 if (matchesDN(PrincipalUtil.getSubjectX509Principal(x509Cert),
    347                     holder.getEntityName()))
    348                 {
    349                     return true;
    350                 }
    351             }
    352             if (holder.getObjectDigestInfo() != null)
    353             {
    354                 MessageDigest md = null;
    355                 try
    356                 {
    357                     md = MessageDigest.getInstance(getDigestAlgorithm(), "BC");
    358 
    359                 }
    360                 catch (Exception e)
    361                 {
    362                     return false;
    363                 }
    364                 switch (getDigestedObjectType())
    365                 {
    366                 case ObjectDigestInfo.publicKey:
    367                     // TODO: DSA Dss-parms
    368                     md.update(cert.getPublicKey().getEncoded());
    369                     break;
    370                 case ObjectDigestInfo.publicKeyCert:
    371                     md.update(cert.getEncoded());
    372                     break;
    373                 }
    374                 if (!Arrays.areEqual(md.digest(), getObjectDigest()))
    375                 {
    376                     return false;
    377                 }
    378             }
    379         }
    380         catch (CertificateEncodingException e)
    381         {
    382             return false;
    383         }
    384 
    385         return false;
    386     }
    387 
    388     public boolean equals(Object obj)
    389     {
    390         if (obj == this)
    391         {
    392             return true;
    393         }
    394 
    395         if (!(obj instanceof AttributeCertificateHolder))
    396         {
    397             return false;
    398         }
    399 
    400         AttributeCertificateHolder other = (AttributeCertificateHolder)obj;
    401 
    402         return this.holder.equals(other.holder);
    403     }
    404 
    405     public int hashCode()
    406     {
    407         return this.holder.hashCode();
    408     }
    409 
    410     public boolean match(Object obj)
    411     {
    412         if (!(obj instanceof X509Certificate))
    413         {
    414             return false;
    415         }
    416 
    417         return match((Certificate)obj);
    418     }
    419 }
    420