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.ASN1Integer; 19 import org.bouncycastle.asn1.ASN1ObjectIdentifier; 20 import org.bouncycastle.asn1.ASN1Sequence; 21 import org.bouncycastle.asn1.DERSequence; 22 import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 23 import org.bouncycastle.asn1.x509.GeneralName; 24 import org.bouncycastle.asn1.x509.GeneralNames; 25 import org.bouncycastle.asn1.x509.Holder; 26 import org.bouncycastle.asn1.x509.IssuerSerial; 27 import org.bouncycastle.asn1.x509.ObjectDigestInfo; 28 import org.bouncycastle.jce.PrincipalUtil; 29 import org.bouncycastle.jce.X509Principal; 30 import org.bouncycastle.util.Arrays; 31 import org.bouncycastle.util.Selector; 32 33 /** 34 * The Holder object. 35 * 36 * <pre> 37 * Holder ::= SEQUENCE { 38 * baseCertificateID [0] IssuerSerial OPTIONAL, 39 * -- the issuer and serial number of 40 * -- the holder's Public Key Certificate 41 * entityName [1] GeneralNames OPTIONAL, 42 * -- the name of the claimant or role 43 * objectDigestInfo [2] ObjectDigestInfo OPTIONAL 44 * -- used to directly authenticate the holder, 45 * -- for example, an executable 46 * } 47 * </pre> 48 * @deprecated use org.bouncycastle.cert.AttributeCertificateHolder 49 */ 50 public class AttributeCertificateHolder 51 implements CertSelector, Selector 52 { 53 final Holder holder; 54 AttributeCertificateHolder(ASN1Sequence seq)55 AttributeCertificateHolder(ASN1Sequence seq) 56 { 57 holder = Holder.getInstance(seq); 58 } 59 AttributeCertificateHolder(X509Principal issuerName, BigInteger serialNumber)60 public AttributeCertificateHolder(X509Principal issuerName, 61 BigInteger serialNumber) 62 { 63 holder = new org.bouncycastle.asn1.x509.Holder(new IssuerSerial( 64 GeneralNames.getInstance(new DERSequence(new GeneralName(issuerName))), 65 new ASN1Integer(serialNumber))); 66 } 67 AttributeCertificateHolder(X500Principal issuerName, BigInteger serialNumber)68 public AttributeCertificateHolder(X500Principal issuerName, 69 BigInteger serialNumber) 70 { 71 this(X509Util.convertPrincipal(issuerName), serialNumber); 72 } 73 AttributeCertificateHolder(X509Certificate cert)74 public AttributeCertificateHolder(X509Certificate cert) 75 throws CertificateParsingException 76 { 77 X509Principal name; 78 79 try 80 { 81 name = PrincipalUtil.getIssuerX509Principal(cert); 82 } 83 catch (Exception e) 84 { 85 throw new CertificateParsingException(e.getMessage()); 86 } 87 88 holder = new Holder(new IssuerSerial(generateGeneralNames(name), 89 new ASN1Integer(cert.getSerialNumber()))); 90 } 91 AttributeCertificateHolder(X509Principal principal)92 public AttributeCertificateHolder(X509Principal principal) 93 { 94 holder = new Holder(generateGeneralNames(principal)); 95 } 96 AttributeCertificateHolder(X500Principal principal)97 public AttributeCertificateHolder(X500Principal principal) 98 { 99 this(X509Util.convertPrincipal(principal)); 100 } 101 102 /** 103 * Constructs a holder for v2 attribute certificates with a hash value for 104 * some type of object. 105 * <p> 106 * <code>digestedObjectType</code> can be one of the following: 107 * <ul> 108 * <li>0 - publicKey - A hash of the public key of the holder must be 109 * passed. 110 * <li>1 - publicKeyCert - A hash of the public key certificate of the 111 * holder must be passed. 112 * <li>2 - otherObjectDigest - A hash of some other object type must be 113 * passed. <code>otherObjectTypeID</code> must not be empty. 114 * </ul> 115 * <p> 116 * This cannot be used if a v1 attribute certificate is used. 117 * 118 * @param digestedObjectType The digest object type. 119 * @param digestAlgorithm The algorithm identifier for the hash. 120 * @param otherObjectTypeID The object type ID if 121 * <code>digestedObjectType</code> is 122 * <code>otherObjectDigest</code>. 123 * @param objectDigest The hash value. 124 */ AttributeCertificateHolder(int digestedObjectType, String digestAlgorithm, String otherObjectTypeID, byte[] objectDigest)125 public AttributeCertificateHolder(int digestedObjectType, 126 String digestAlgorithm, String otherObjectTypeID, byte[] objectDigest) 127 { 128 holder = new Holder(new ObjectDigestInfo(digestedObjectType, 129 new ASN1ObjectIdentifier(otherObjectTypeID), new AlgorithmIdentifier(new ASN1ObjectIdentifier(digestAlgorithm)), Arrays 130 .clone(objectDigest))); 131 } 132 133 /** 134 * Returns the digest object type if an object digest info is used. 135 * <p> 136 * <ul> 137 * <li>0 - publicKey - A hash of the public key of the holder must be 138 * passed. 139 * <li>1 - publicKeyCert - A hash of the public key certificate of the 140 * holder must be passed. 141 * <li>2 - otherObjectDigest - A hash of some other object type must be 142 * passed. <code>otherObjectTypeID</code> must not be empty. 143 * </ul> 144 * 145 * @return The digest object type or -1 if no object digest info is set. 146 */ getDigestedObjectType()147 public int getDigestedObjectType() 148 { 149 if (holder.getObjectDigestInfo() != null) 150 { 151 return holder.getObjectDigestInfo().getDigestedObjectType().intValueExact(); 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 */ getDigestAlgorithm()162 public String getDigestAlgorithm() 163 { 164 if (holder.getObjectDigestInfo() != null) 165 { 166 return holder.getObjectDigestInfo().getDigestAlgorithm().getAlgorithm() 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 */ getObjectDigest()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 */ getOtherObjectTypeID()192 public String getOtherObjectTypeID() 193 { 194 if (holder.getObjectDigestInfo() != null) 195 { 196 holder.getObjectDigestInfo().getOtherObjectTypeID().getId(); 197 } 198 return null; 199 } 200 generateGeneralNames(X509Principal principal)201 private GeneralNames generateGeneralNames(X509Principal principal) 202 { 203 return GeneralNames.getInstance(new DERSequence(new GeneralName(principal))); 204 } 205 matchesDN(X509Principal subject, GeneralNames targets)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()).toASN1Primitive() 219 .getEncoded()).equals(subject)) 220 { 221 return true; 222 } 223 } 224 catch (IOException e) 225 { 226 } 227 } 228 } 229 230 return false; 231 } 232 getNames(GeneralName[] names)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()).toASN1Primitive().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 getPrincipals(GeneralNames names)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 */ getEntityNames()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 */ getIssuer()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 */ getSerialNumber()311 public BigInteger getSerialNumber() 312 { 313 if (holder.getBaseCertificateID() != null) 314 { 315 return holder.getBaseCertificateID().getSerial().getValue(); 316 } 317 318 return null; 319 } 320 clone()321 public Object clone() 322 { 323 return new AttributeCertificateHolder((ASN1Sequence)holder 324 .toASN1Primitive()); 325 } 326 match(Certificate cert)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().hasValue(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 equals(Object obj)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 hashCode()405 public int hashCode() 406 { 407 return this.holder.hashCode(); 408 } 409 match(Object obj)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