1 /** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one or more 4 * contributor license agreements. See the NOTICE file distributed with 5 * this work for additional information regarding copyright ownership. 6 * The ASF licenses this file to You under the Apache License, Version 2.0 7 * (the "License"); you may not use this file except in compliance with 8 * the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.geronimo.util.asn1.x509; 20 21 import java.util.Enumeration; 22 import java.util.Hashtable; 23 import java.util.Vector; 24 25 import org.apache.geronimo.util.asn1.ASN1Encodable; 26 import org.apache.geronimo.util.asn1.ASN1EncodableVector; 27 import org.apache.geronimo.util.asn1.ASN1OctetString; 28 import org.apache.geronimo.util.asn1.ASN1Sequence; 29 import org.apache.geronimo.util.asn1.ASN1TaggedObject; 30 import org.apache.geronimo.util.asn1.DERBoolean; 31 import org.apache.geronimo.util.asn1.DERObject; 32 import org.apache.geronimo.util.asn1.DERObjectIdentifier; 33 import org.apache.geronimo.util.asn1.DERSequence; 34 35 public class X509Extensions 36 extends ASN1Encodable 37 { 38 /** 39 * Subject Directory Attributes 40 */ 41 public static final DERObjectIdentifier SubjectDirectoryAttributes = new DERObjectIdentifier("2.5.29.9"); 42 43 /** 44 * Subject Key Identifier 45 */ 46 public static final DERObjectIdentifier SubjectKeyIdentifier = new DERObjectIdentifier("2.5.29.14"); 47 48 /** 49 * Key Usage 50 */ 51 public static final DERObjectIdentifier KeyUsage = new DERObjectIdentifier("2.5.29.15"); 52 53 /** 54 * Private Key Usage Period 55 */ 56 public static final DERObjectIdentifier PrivateKeyUsagePeriod = new DERObjectIdentifier("2.5.29.16"); 57 58 /** 59 * Subject Alternative Name 60 */ 61 public static final DERObjectIdentifier SubjectAlternativeName = new DERObjectIdentifier("2.5.29.17"); 62 63 /** 64 * Issuer Alternative Name 65 */ 66 public static final DERObjectIdentifier IssuerAlternativeName = new DERObjectIdentifier("2.5.29.18"); 67 68 /** 69 * Basic Constraints 70 */ 71 public static final DERObjectIdentifier BasicConstraints = new DERObjectIdentifier("2.5.29.19"); 72 73 /** 74 * CRL Number 75 */ 76 public static final DERObjectIdentifier CRLNumber = new DERObjectIdentifier("2.5.29.20"); 77 78 /** 79 * Reason code 80 */ 81 public static final DERObjectIdentifier ReasonCode = new DERObjectIdentifier("2.5.29.21"); 82 83 /** 84 * Hold Instruction Code 85 */ 86 public static final DERObjectIdentifier InstructionCode = new DERObjectIdentifier("2.5.29.23"); 87 88 /** 89 * Invalidity Date 90 */ 91 public static final DERObjectIdentifier InvalidityDate = new DERObjectIdentifier("2.5.29.24"); 92 93 /** 94 * Delta CRL indicator 95 */ 96 public static final DERObjectIdentifier DeltaCRLIndicator = new DERObjectIdentifier("2.5.29.27"); 97 98 /** 99 * Issuing Distribution Point 100 */ 101 public static final DERObjectIdentifier IssuingDistributionPoint = new DERObjectIdentifier("2.5.29.28"); 102 103 /** 104 * Certificate Issuer 105 */ 106 public static final DERObjectIdentifier CertificateIssuer = new DERObjectIdentifier("2.5.29.29"); 107 108 /** 109 * Name Constraints 110 */ 111 public static final DERObjectIdentifier NameConstraints = new DERObjectIdentifier("2.5.29.30"); 112 113 /** 114 * CRL Distribution Points 115 */ 116 public static final DERObjectIdentifier CRLDistributionPoints = new DERObjectIdentifier("2.5.29.31"); 117 118 /** 119 * Certificate Policies 120 */ 121 public static final DERObjectIdentifier CertificatePolicies = new DERObjectIdentifier("2.5.29.32"); 122 123 /** 124 * Policy Mappings 125 */ 126 public static final DERObjectIdentifier PolicyMappings = new DERObjectIdentifier("2.5.29.33"); 127 128 /** 129 * Authority Key Identifier 130 */ 131 public static final DERObjectIdentifier AuthorityKeyIdentifier = new DERObjectIdentifier("2.5.29.35"); 132 133 /** 134 * Policy Constraints 135 */ 136 public static final DERObjectIdentifier PolicyConstraints = new DERObjectIdentifier("2.5.29.36"); 137 138 /** 139 * Extended Key Usage 140 */ 141 public static final DERObjectIdentifier ExtendedKeyUsage = new DERObjectIdentifier("2.5.29.37"); 142 143 /** 144 * Freshest CRL 145 */ 146 public static final DERObjectIdentifier FreshestCRL = new DERObjectIdentifier("2.5.29.46"); 147 148 /** 149 * Inhibit Any Policy 150 */ 151 public static final DERObjectIdentifier InhibitAnyPolicy = new DERObjectIdentifier("2.5.29.54"); 152 153 /** 154 * Authority Info Access 155 */ 156 public static final DERObjectIdentifier AuthorityInfoAccess= new DERObjectIdentifier("1.3.6.1.5.5.7.1.1"); 157 158 /** 159 * Subject Info Access 160 */ 161 public static final DERObjectIdentifier SubjectInfoAccess= new DERObjectIdentifier("1.3.6.1.5.5.7.1.11"); 162 163 private Hashtable extensions = new Hashtable(); 164 private Vector ordering = new Vector(); 165 166 public static X509Extensions getInstance( 167 ASN1TaggedObject obj, 168 boolean explicit) 169 { 170 return getInstance(ASN1Sequence.getInstance(obj, explicit)); 171 } 172 173 public static X509Extensions getInstance( 174 Object obj) 175 { 176 if (obj == null || obj instanceof X509Extensions) 177 { 178 return (X509Extensions)obj; 179 } 180 181 if (obj instanceof ASN1Sequence) 182 { 183 return new X509Extensions((ASN1Sequence)obj); 184 } 185 186 if (obj instanceof ASN1TaggedObject) 187 { 188 return getInstance(((ASN1TaggedObject)obj).getObject()); 189 } 190 191 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); 192 } 193 194 /** 195 * Constructor from ASN1Sequence. 196 * 197 * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString) 198 */ 199 public X509Extensions( 200 ASN1Sequence seq) 201 { 202 Enumeration e = seq.getObjects(); 203 204 while (e.hasMoreElements()) 205 { 206 ASN1Sequence s = (ASN1Sequence)e.nextElement(); 207 208 if (s.size() == 3) 209 { 210 extensions.put(s.getObjectAt(0), new X509Extension((DERBoolean)s.getObjectAt(1), (ASN1OctetString)s.getObjectAt(2))); 211 } 212 else 213 { 214 extensions.put(s.getObjectAt(0), new X509Extension(false, (ASN1OctetString)s.getObjectAt(1))); 215 } 216 217 ordering.addElement(s.getObjectAt(0)); 218 } 219 } 220 221 /** 222 * constructor from a table of extensions. 223 * <p> 224 * it's is assumed the table contains OID/String pairs. 225 */ 226 public X509Extensions( 227 Hashtable extensions) 228 { 229 this(null, extensions); 230 } 231 232 /** 233 * Constructor from a table of extensions with ordering. 234 * <p> 235 * It's is assumed the table contains OID/String pairs. 236 */ 237 public X509Extensions( 238 Vector ordering, 239 Hashtable extensions) 240 { 241 Enumeration e; 242 243 if (ordering == null) 244 { 245 e = extensions.keys(); 246 } 247 else 248 { 249 e = ordering.elements(); 250 } 251 252 while (e.hasMoreElements()) 253 { 254 this.ordering.addElement(e.nextElement()); 255 } 256 257 e = this.ordering.elements(); 258 259 while (e.hasMoreElements()) 260 { 261 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); 262 X509Extension ext = (X509Extension)extensions.get(oid); 263 264 this.extensions.put(oid, ext); 265 } 266 } 267 268 /** 269 * Constructor from two vectors 270 * 271 * @param objectIDs a vector of the object identifiers. 272 * @param values a vector of the extension values. 273 */ 274 public X509Extensions( 275 Vector objectIDs, 276 Vector values) 277 { 278 Enumeration e = objectIDs.elements(); 279 280 while (e.hasMoreElements()) 281 { 282 this.ordering.addElement(e.nextElement()); 283 } 284 285 int count = 0; 286 287 e = this.ordering.elements(); 288 289 while (e.hasMoreElements()) 290 { 291 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); 292 X509Extension ext = (X509Extension)values.elementAt(count); 293 294 this.extensions.put(oid, ext); 295 count++; 296 } 297 } 298 299 /** 300 * return an Enumeration of the extension field's object ids. 301 */ 302 public Enumeration oids() 303 { 304 return ordering.elements(); 305 } 306 307 /** 308 * return the extension represented by the object identifier 309 * passed in. 310 * 311 * @return the extension if it's present, null otherwise. 312 */ 313 public X509Extension getExtension( 314 DERObjectIdentifier oid) 315 { 316 return (X509Extension)extensions.get(oid); 317 } 318 319 /** 320 * <pre> 321 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 322 * 323 * Extension ::= SEQUENCE { 324 * extnId EXTENSION.&id ({ExtensionSet}), 325 * critical BOOLEAN DEFAULT FALSE, 326 * extnValue OCTET STRING } 327 * </pre> 328 */ 329 public DERObject toASN1Object() 330 { 331 ASN1EncodableVector vec = new ASN1EncodableVector(); 332 Enumeration e = ordering.elements(); 333 334 while (e.hasMoreElements()) 335 { 336 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); 337 X509Extension ext = (X509Extension)extensions.get(oid); 338 ASN1EncodableVector v = new ASN1EncodableVector(); 339 340 v.add(oid); 341 342 if (ext.isCritical()) 343 { 344 v.add(new DERBoolean(true)); 345 } 346 347 v.add(ext.getValue()); 348 349 vec.add(new DERSequence(v)); 350 } 351 352 return new DERSequence(vec); 353 } 354 355 public int hashCode() 356 { 357 Enumeration e = extensions.keys(); 358 int hashCode = 0; 359 360 while (e.hasMoreElements()) 361 { 362 Object o = e.nextElement(); 363 364 hashCode ^= o.hashCode(); 365 hashCode ^= extensions.get(o).hashCode(); 366 } 367 368 return hashCode; 369 } 370 371 public boolean equals( 372 Object o) 373 { 374 if (o == null || !(o instanceof X509Extensions)) 375 { 376 return false; 377 } 378 379 X509Extensions other = (X509Extensions)o; 380 381 Enumeration e1 = extensions.keys(); 382 Enumeration e2 = other.extensions.keys(); 383 384 while (e1.hasMoreElements() && e2.hasMoreElements()) 385 { 386 Object o1 = e1.nextElement(); 387 Object o2 = e2.nextElement(); 388 389 if (!o1.equals(o2)) 390 { 391 return false; 392 } 393 } 394 395 if (e1.hasMoreElements() || e2.hasMoreElements()) 396 { 397 return false; 398 } 399 400 return true; 401 } 402 }