001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.geronimo.util.asn1.x509; 019 020 import java.util.Enumeration; 021 import java.util.Hashtable; 022 import java.util.Vector; 023 024 import org.apache.geronimo.util.asn1.ASN1Encodable; 025 import org.apache.geronimo.util.asn1.ASN1EncodableVector; 026 import org.apache.geronimo.util.asn1.ASN1OctetString; 027 import org.apache.geronimo.util.asn1.ASN1Sequence; 028 import org.apache.geronimo.util.asn1.ASN1TaggedObject; 029 import org.apache.geronimo.util.asn1.DERBoolean; 030 import org.apache.geronimo.util.asn1.DERObject; 031 import org.apache.geronimo.util.asn1.DERObjectIdentifier; 032 import org.apache.geronimo.util.asn1.DERSequence; 033 034 public class X509Extensions 035 extends ASN1Encodable 036 { 037 /** 038 * Subject Directory Attributes 039 */ 040 public static final DERObjectIdentifier SubjectDirectoryAttributes = new DERObjectIdentifier("2.5.29.9"); 041 042 /** 043 * Subject Key Identifier 044 */ 045 public static final DERObjectIdentifier SubjectKeyIdentifier = new DERObjectIdentifier("2.5.29.14"); 046 047 /** 048 * Key Usage 049 */ 050 public static final DERObjectIdentifier KeyUsage = new DERObjectIdentifier("2.5.29.15"); 051 052 /** 053 * Private Key Usage Period 054 */ 055 public static final DERObjectIdentifier PrivateKeyUsagePeriod = new DERObjectIdentifier("2.5.29.16"); 056 057 /** 058 * Subject Alternative Name 059 */ 060 public static final DERObjectIdentifier SubjectAlternativeName = new DERObjectIdentifier("2.5.29.17"); 061 062 /** 063 * Issuer Alternative Name 064 */ 065 public static final DERObjectIdentifier IssuerAlternativeName = new DERObjectIdentifier("2.5.29.18"); 066 067 /** 068 * Basic Constraints 069 */ 070 public static final DERObjectIdentifier BasicConstraints = new DERObjectIdentifier("2.5.29.19"); 071 072 /** 073 * CRL Number 074 */ 075 public static final DERObjectIdentifier CRLNumber = new DERObjectIdentifier("2.5.29.20"); 076 077 /** 078 * Reason code 079 */ 080 public static final DERObjectIdentifier ReasonCode = new DERObjectIdentifier("2.5.29.21"); 081 082 /** 083 * Hold Instruction Code 084 */ 085 public static final DERObjectIdentifier InstructionCode = new DERObjectIdentifier("2.5.29.23"); 086 087 /** 088 * Invalidity Date 089 */ 090 public static final DERObjectIdentifier InvalidityDate = new DERObjectIdentifier("2.5.29.24"); 091 092 /** 093 * Delta CRL indicator 094 */ 095 public static final DERObjectIdentifier DeltaCRLIndicator = new DERObjectIdentifier("2.5.29.27"); 096 097 /** 098 * Issuing Distribution Point 099 */ 100 public static final DERObjectIdentifier IssuingDistributionPoint = new DERObjectIdentifier("2.5.29.28"); 101 102 /** 103 * Certificate Issuer 104 */ 105 public static final DERObjectIdentifier CertificateIssuer = new DERObjectIdentifier("2.5.29.29"); 106 107 /** 108 * Name Constraints 109 */ 110 public static final DERObjectIdentifier NameConstraints = new DERObjectIdentifier("2.5.29.30"); 111 112 /** 113 * CRL Distribution Points 114 */ 115 public static final DERObjectIdentifier CRLDistributionPoints = new DERObjectIdentifier("2.5.29.31"); 116 117 /** 118 * Certificate Policies 119 */ 120 public static final DERObjectIdentifier CertificatePolicies = new DERObjectIdentifier("2.5.29.32"); 121 122 /** 123 * Policy Mappings 124 */ 125 public static final DERObjectIdentifier PolicyMappings = new DERObjectIdentifier("2.5.29.33"); 126 127 /** 128 * Authority Key Identifier 129 */ 130 public static final DERObjectIdentifier AuthorityKeyIdentifier = new DERObjectIdentifier("2.5.29.35"); 131 132 /** 133 * Policy Constraints 134 */ 135 public static final DERObjectIdentifier PolicyConstraints = new DERObjectIdentifier("2.5.29.36"); 136 137 /** 138 * Extended Key Usage 139 */ 140 public static final DERObjectIdentifier ExtendedKeyUsage = new DERObjectIdentifier("2.5.29.37"); 141 142 /** 143 * Freshest CRL 144 */ 145 public static final DERObjectIdentifier FreshestCRL = new DERObjectIdentifier("2.5.29.46"); 146 147 /** 148 * Inhibit Any Policy 149 */ 150 public static final DERObjectIdentifier InhibitAnyPolicy = new DERObjectIdentifier("2.5.29.54"); 151 152 /** 153 * Authority Info Access 154 */ 155 public static final DERObjectIdentifier AuthorityInfoAccess= new DERObjectIdentifier("1.3.6.1.5.5.7.1.1"); 156 157 /** 158 * Subject Info Access 159 */ 160 public static final DERObjectIdentifier SubjectInfoAccess= new DERObjectIdentifier("1.3.6.1.5.5.7.1.11"); 161 162 private Hashtable extensions = new Hashtable(); 163 private Vector ordering = new Vector(); 164 165 public static X509Extensions getInstance( 166 ASN1TaggedObject obj, 167 boolean explicit) 168 { 169 return getInstance(ASN1Sequence.getInstance(obj, explicit)); 170 } 171 172 public static X509Extensions getInstance( 173 Object obj) 174 { 175 if (obj == null || obj instanceof X509Extensions) 176 { 177 return (X509Extensions)obj; 178 } 179 180 if (obj instanceof ASN1Sequence) 181 { 182 return new X509Extensions((ASN1Sequence)obj); 183 } 184 185 if (obj instanceof ASN1TaggedObject) 186 { 187 return getInstance(((ASN1TaggedObject)obj).getObject()); 188 } 189 190 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); 191 } 192 193 /** 194 * Constructor from ASN1Sequence. 195 * 196 * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString) 197 */ 198 public X509Extensions( 199 ASN1Sequence seq) 200 { 201 Enumeration e = seq.getObjects(); 202 203 while (e.hasMoreElements()) 204 { 205 ASN1Sequence s = (ASN1Sequence)e.nextElement(); 206 207 if (s.size() == 3) 208 { 209 extensions.put(s.getObjectAt(0), new X509Extension((DERBoolean)s.getObjectAt(1), (ASN1OctetString)s.getObjectAt(2))); 210 } 211 else 212 { 213 extensions.put(s.getObjectAt(0), new X509Extension(false, (ASN1OctetString)s.getObjectAt(1))); 214 } 215 216 ordering.addElement(s.getObjectAt(0)); 217 } 218 } 219 220 /** 221 * constructor from a table of extensions. 222 * <p> 223 * it's is assumed the table contains OID/String pairs. 224 */ 225 public X509Extensions( 226 Hashtable extensions) 227 { 228 this(null, extensions); 229 } 230 231 /** 232 * Constructor from a table of extensions with ordering. 233 * <p> 234 * It's is assumed the table contains OID/String pairs. 235 */ 236 public X509Extensions( 237 Vector ordering, 238 Hashtable extensions) 239 { 240 Enumeration e; 241 242 if (ordering == null) 243 { 244 e = extensions.keys(); 245 } 246 else 247 { 248 e = ordering.elements(); 249 } 250 251 while (e.hasMoreElements()) 252 { 253 this.ordering.addElement(e.nextElement()); 254 } 255 256 e = this.ordering.elements(); 257 258 while (e.hasMoreElements()) 259 { 260 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); 261 X509Extension ext = (X509Extension)extensions.get(oid); 262 263 this.extensions.put(oid, ext); 264 } 265 } 266 267 /** 268 * Constructor from two vectors 269 * 270 * @param objectIDs a vector of the object identifiers. 271 * @param values a vector of the extension values. 272 */ 273 public X509Extensions( 274 Vector objectIDs, 275 Vector values) 276 { 277 Enumeration e = objectIDs.elements(); 278 279 while (e.hasMoreElements()) 280 { 281 this.ordering.addElement(e.nextElement()); 282 } 283 284 int count = 0; 285 286 e = this.ordering.elements(); 287 288 while (e.hasMoreElements()) 289 { 290 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); 291 X509Extension ext = (X509Extension)values.elementAt(count); 292 293 this.extensions.put(oid, ext); 294 count++; 295 } 296 } 297 298 /** 299 * return an Enumeration of the extension field's object ids. 300 */ 301 public Enumeration oids() 302 { 303 return ordering.elements(); 304 } 305 306 /** 307 * return the extension represented by the object identifier 308 * passed in. 309 * 310 * @return the extension if it's present, null otherwise. 311 */ 312 public X509Extension getExtension( 313 DERObjectIdentifier oid) 314 { 315 return (X509Extension)extensions.get(oid); 316 } 317 318 /** 319 * <pre> 320 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 321 * 322 * Extension ::= SEQUENCE { 323 * extnId EXTENSION.&id ({ExtensionSet}), 324 * critical BOOLEAN DEFAULT FALSE, 325 * extnValue OCTET STRING } 326 * </pre> 327 */ 328 public DERObject toASN1Object() 329 { 330 ASN1EncodableVector vec = new ASN1EncodableVector(); 331 Enumeration e = ordering.elements(); 332 333 while (e.hasMoreElements()) 334 { 335 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); 336 X509Extension ext = (X509Extension)extensions.get(oid); 337 ASN1EncodableVector v = new ASN1EncodableVector(); 338 339 v.add(oid); 340 341 if (ext.isCritical()) 342 { 343 v.add(new DERBoolean(true)); 344 } 345 346 v.add(ext.getValue()); 347 348 vec.add(new DERSequence(v)); 349 } 350 351 return new DERSequence(vec); 352 } 353 354 public int hashCode() 355 { 356 Enumeration e = extensions.keys(); 357 int hashCode = 0; 358 359 while (e.hasMoreElements()) 360 { 361 Object o = e.nextElement(); 362 363 hashCode ^= o.hashCode(); 364 hashCode ^= extensions.get(o).hashCode(); 365 } 366 367 return hashCode; 368 } 369 370 public boolean equals( 371 Object o) 372 { 373 if (o == null || !(o instanceof X509Extensions)) 374 { 375 return false; 376 } 377 378 X509Extensions other = (X509Extensions)o; 379 380 Enumeration e1 = extensions.keys(); 381 Enumeration e2 = other.extensions.keys(); 382 383 while (e1.hasMoreElements() && e2.hasMoreElements()) 384 { 385 Object o1 = e1.nextElement(); 386 Object o2 = e2.nextElement(); 387 388 if (!o1.equals(o2)) 389 { 390 return false; 391 } 392 } 393 394 if (e1.hasMoreElements() || e2.hasMoreElements()) 395 { 396 return false; 397 } 398 399 return true; 400 } 401 }