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