1 /* 2 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 /* 26 * $Id: KeyInfoFactory.java,v 1.12 2005/05/10 16:35:35 mullan Exp $ 27 */ 28 package javax.xml.crypto.dsig.keyinfo; 29 30 import java.math.BigInteger; 31 import java.security.KeyException; 32 import java.security.NoSuchAlgorithmException; 33 import java.security.NoSuchProviderException; 34 import java.security.Provider; 35 import java.security.PublicKey; 36 import java.security.Security; 37 import java.security.cert.X509CRL; 38 import java.util.List; 39 import javax.xml.crypto.MarshalException; 40 import javax.xml.crypto.NoSuchMechanismException; 41 import javax.xml.crypto.URIDereferencer; 42 import javax.xml.crypto.XMLStructure; 43 import javax.xml.crypto.dom.DOMStructure; 44 import javax.xml.crypto.dsig; 45 46 import sun.security.jca; 47 import sun.security.jca.GetInstance.Instance; 48 49 /** 50 * A factory for creating {@link KeyInfo} objects from scratch or for 51 * unmarshalling a <code>KeyInfo</code> object from a corresponding XML 52 * representation. 53 * 54 * <p>Each instance of <code>KeyInfoFactory</code> supports a specific 55 * XML mechanism type. To create a <code>KeyInfoFactory</code>, call one of the 56 * static {@link #getInstance getInstance} methods, passing in the XML 57 * mechanism type desired, for example: 58 * 59 * <blockquote><code> 60 * KeyInfoFactory factory = KeyInfoFactory.getInstance("DOM"); 61 * </code></blockquote> 62 * 63 * <p>The objects that this factory produces will be based 64 * on DOM and abide by the DOM interoperability requirements as defined in the 65 * <a href="../../../../../../technotes/guides/security/xmldsig/overview.html#DOM Mechanism Requirements"> 66 * DOM Mechanism Requirements</a> section of the API overview. See the 67 * <a href="../../../../../../technotes/guides/security/xmldsig/overview.html#Service Provider"> 68 * Service Providers</a> section of the API overview for a list of standard 69 * mechanism types. 70 * 71 * <p><code>KeyInfoFactory</code> implementations are registered and loaded 72 * using the {@link java.security.Provider} mechanism. 73 * For example, a service provider that supports the 74 * DOM mechanism would be specified in the <code>Provider</code> subclass as: 75 * <pre> 76 * put("KeyInfoFactory.DOM", "org.example.DOMKeyInfoFactory"); 77 * </pre> 78 * 79 * <p>Also, the <code>XMLStructure</code>s that are created by this factory 80 * may contain state specific to the <code>KeyInfo</code> and are not 81 * intended to be reusable. 82 * 83 * <p>An implementation MUST minimally support the default mechanism type: DOM. 84 * 85 * <p>Note that a caller must use the same <code>KeyInfoFactory</code> 86 * instance to create the <code>XMLStructure</code>s of a particular 87 * <code>KeyInfo</code> object. The behavior is undefined if 88 * <code>XMLStructure</code>s from different providers or different mechanism 89 * types are used together. 90 * 91 * <p><b>Concurrent Access</b> 92 * <p>The static methods of this class are guaranteed to be thread-safe. 93 * Multiple threads may concurrently invoke the static methods defined in this 94 * class with no ill effects. 95 * 96 * <p>However, this is not true for the non-static methods defined by this 97 * class. Unless otherwise documented by a specific provider, threads that 98 * need to access a single <code>KeyInfoFactory</code> instance concurrently 99 * should synchronize amongst themselves and provide the necessary locking. 100 * Multiple threads each manipulating a different <code>KeyInfoFactory</code> 101 * instance need not synchronize. 102 * 103 * @author Sean Mullan 104 * @author JSR 105 Expert Group 105 * @since 1.6 106 */ 107 public abstract class KeyInfoFactory { 108 109 private String mechanismType; 110 private Provider provider; 111 112 /** 113 * Default constructor, for invocation by subclasses. 114 */ 115 protected KeyInfoFactory() {} 116 117 /** 118 * Returns a <code>KeyInfoFactory</code> that supports the 119 * specified XML processing mechanism and representation type (ex: "DOM"). 120 * 121 * <p>This method uses the standard JCA provider lookup mechanism to 122 * locate and instantiate a <code>KeyInfoFactory</code> implementation of 123 * the desired mechanism type. It traverses the list of registered security 124 * <code>Provider</code>s, starting with the most preferred 125 * <code>Provider</code>. A new <code>KeyInfoFactory</code> object 126 * from the first <code>Provider</code> that supports the specified 127 * mechanism is returned. 128 * 129 * <p> Note that the list of registered providers may be retrieved via 130 * the {@link Security#getProviders() Security.getProviders()} method. 131 * 132 * @param mechanismType the type of the XML processing mechanism and 133 * representation. See the <a 134 * href="../../../../../../technotes/guides/security/xmldsig/overview.html#Service Provider"> 135 * Service Providers</a> section of the API overview for a list of 136 * standard mechanism types. 137 * @return a new <code>KeyInfoFactory</code> 138 * @throws NullPointerException if <code>mechanismType</code> is 139 * <code>null</code> 140 * @throws NoSuchMechanismException if no <code>Provider</code> supports a 141 * <code>KeyInfoFactory</code> implementation for the specified mechanism 142 * @see Provider 143 */ 144 public static KeyInfoFactory getInstance(String mechanismType) { 145 if (mechanismType == null) { 146 throw new NullPointerException("mechanismType cannot be null"); 147 } 148 Instance instance; 149 try { 150 instance = GetInstance.getInstance 151 ("KeyInfoFactory", null, mechanismType); 152 } catch (NoSuchAlgorithmException nsae) { 153 throw new NoSuchMechanismException(nsae); 154 } 155 KeyInfoFactory factory = (KeyInfoFactory) instance.impl; 156 factory.mechanismType = mechanismType; 157 factory.provider = instance.provider; 158 return factory; 159 } 160 161 /** 162 * Returns a <code>KeyInfoFactory</code> that supports the 163 * requested XML processing mechanism and representation type (ex: "DOM"), 164 * as supplied by the specified provider. Note that the specified 165 * <code>Provider</code> object does not have to be registered in the 166 * provider list. 167 * 168 * @param mechanismType the type of the XML processing mechanism and 169 * representation. See the <a 170 * href="../../../../../../technotes/guides/security/xmldsig/overview.html#Service Provider"> 171 * Service Providers</a> section of the API overview for a list of 172 * standard mechanism types. 173 * @param provider the <code>Provider</code> object 174 * @return a new <code>KeyInfoFactory</code> 175 * @throws NullPointerException if <code>mechanismType</code> or 176 * <code>provider</code> are <code>null</code> 177 * @throws NoSuchMechanismException if a <code>KeyInfoFactory</code> 178 * implementation for the specified mechanism is not available from the 179 * specified <code>Provider</code> object 180 * @see Provider 181 */ 182 public static KeyInfoFactory getInstance(String mechanismType, 183 Provider provider) { 184 if (mechanismType == null) { 185 throw new NullPointerException("mechanismType cannot be null"); 186 } else if (provider == null) { 187 throw new NullPointerException("provider cannot be null"); 188 } 189 190 Instance instance; 191 try { 192 instance = GetInstance.getInstance 193 ("KeyInfoFactory", null, mechanismType, provider); 194 } catch (NoSuchAlgorithmException nsae) { 195 throw new NoSuchMechanismException(nsae); 196 } 197 KeyInfoFactory factory = (KeyInfoFactory) instance.impl; 198 factory.mechanismType = mechanismType; 199 factory.provider = instance.provider; 200 return factory; 201 } 202 203 /** 204 * Returns a <code>KeyInfoFactory</code> that supports the 205 * requested XML processing mechanism and representation type (ex: "DOM"), 206 * as supplied by the specified provider. The specified provider must be 207 * registered in the security provider list. 208 * 209 * <p>Note that the list of registered providers may be retrieved via 210 * the {@link Security#getProviders() Security.getProviders()} method. 211 * 212 * @param mechanismType the type of the XML processing mechanism and 213 * representation. See the <a 214 * href="../../../../../../technotes/guides/security/xmldsig/overview.html#Service Provider"> 215 * Service Providers</a> section of the API overview for a list of 216 * standard mechanism types. 217 * @param provider the string name of the provider 218 * @return a new <code>KeyInfoFactory</code> 219 * @throws NoSuchProviderException if the specified provider is not 220 * registered in the security provider list 221 * @throws NullPointerException if <code>mechanismType</code> or 222 * <code>provider</code> are <code>null</code> 223 * @throws NoSuchMechanismException if a <code>KeyInfoFactory</code> 224 * implementation for the specified mechanism is not available from the 225 * specified provider 226 * @see Provider 227 */ 228 public static KeyInfoFactory getInstance(String mechanismType, 229 String provider) throws NoSuchProviderException { 230 if (mechanismType == null) { 231 throw new NullPointerException("mechanismType cannot be null"); 232 } else if (provider == null) { 233 throw new NullPointerException("provider cannot be null"); 234 } else if (provider.length() == 0) { 235 throw new NoSuchProviderException(); 236 } 237 238 Instance instance; 239 try { 240 instance = GetInstance.getInstance 241 ("KeyInfoFactory", null, mechanismType, provider); 242 } catch (NoSuchAlgorithmException nsae) { 243 throw new NoSuchMechanismException(nsae); 244 } 245 KeyInfoFactory factory = (KeyInfoFactory) instance.impl; 246 factory.mechanismType = mechanismType; 247 factory.provider = instance.provider; 248 return factory; 249 } 250 251 /** 252 * Returns a <code>KeyInfoFactory</code> that supports the 253 * default XML processing mechanism and representation type ("DOM"). 254 * 255 * <p>This method uses the standard JCA provider lookup mechanism to 256 * locate and instantiate a <code>KeyInfoFactory</code> implementation of 257 * the default mechanism type. It traverses the list of registered security 258 * <code>Provider</code>s, starting with the most preferred 259 * <code>Provider</code>. A new <code>KeyInfoFactory</code> object 260 * from the first <code>Provider</code> that supports the DOM mechanism is 261 * returned. 262 * 263 * <p> Note that the list of registered providers may be retrieved via 264 * the {@link Security#getProviders() Security.getProviders()} method. 265 * 266 * @return a new <code>KeyInfoFactory</code> 267 * @throws NoSuchMechanismException if no <code>Provider</code> supports a 268 * <code>KeyInfoFactory</code> implementation for the DOM mechanism 269 * @see Provider 270 */ 271 public static KeyInfoFactory getInstance() { 272 return getInstance("DOM"); 273 } 274 275 /** 276 * Returns the type of the XML processing mechanism and representation 277 * supported by this <code>KeyInfoFactory</code> (ex: "DOM") 278 * 279 * @return the XML processing mechanism type supported by this 280 * <code>KeyInfoFactory</code> 281 */ 282 public final String getMechanismType() { 283 return mechanismType; 284 } 285 286 /** 287 * Returns the provider of this <code>KeyInfoFactory</code>. 288 * 289 * @return the provider of this <code>KeyInfoFactory</code> 290 */ 291 public final Provider getProvider() { 292 return provider; 293 } 294 295 /** 296 * Creates a <code>KeyInfo</code> containing the specified list of 297 * key information types. 298 * 299 * @param content a list of one or more {@link XMLStructure}s representing 300 * key information types. The list is defensively copied to protect 301 * against subsequent modification. 302 * @return a <code>KeyInfo</code> 303 * @throws NullPointerException if <code>content</code> is <code>null</code> 304 * @throws IllegalArgumentException if <code>content</code> is empty 305 * @throws ClassCastException if <code>content</code> contains any entries 306 * that are not of type {@link XMLStructure} 307 */ 308 public abstract KeyInfo newKeyInfo(List content); 309 310 /** 311 * Creates a <code>KeyInfo</code> containing the specified list of key 312 * information types and optional id. The 313 * <code>id</code> parameter represents the value of an XML 314 * <code>ID</code> attribute and is useful for referencing 315 * the <code>KeyInfo</code> from other XML structures. 316 * 317 * @param content a list of one or more {@link XMLStructure}s representing 318 * key information types. The list is defensively copied to protect 319 * against subsequent modification. 320 * @param id the value of an XML <code>ID</code> (may be <code>null</code>) 321 * @return a <code>KeyInfo</code> 322 * @throws NullPointerException if <code>content</code> is <code>null</code> 323 * @throws IllegalArgumentException if <code>content</code> is empty 324 * @throws ClassCastException if <code>content</code> contains any entries 325 * that are not of type {@link XMLStructure} 326 */ 327 public abstract KeyInfo newKeyInfo(List content, String id); 328 329 /** 330 * Creates a <code>KeyName</code> from the specified name. 331 * 332 * @param name the name that identifies the key 333 * @return a <code>KeyName</code> 334 * @throws NullPointerException if <code>name</code> is <code>null</code> 335 */ 336 public abstract KeyName newKeyName(String name); 337 338 /** 339 * Creates a <code>KeyValue</code> from the specified public key. 340 * 341 * @param key the public key 342 * @return a <code>KeyValue</code> 343 * @throws KeyException if the <code>key</code>'s algorithm is not 344 * recognized or supported by this <code>KeyInfoFactory</code> 345 * @throws NullPointerException if <code>key</code> is <code>null</code> 346 */ 347 public abstract KeyValue newKeyValue(PublicKey key) throws KeyException; 348 349 /** 350 * Creates a <code>PGPData</code> from the specified PGP public key 351 * identifier. 352 * 353 * @param keyId a PGP public key identifier as defined in <a href= 354 * "http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>, section 11.2. 355 * The array is cloned to protect against subsequent modification. 356 * @return a <code>PGPData</code> 357 * @throws NullPointerException if <code>keyId</code> is <code>null</code> 358 * @throws IllegalArgumentException if the key id is not in the correct 359 * format 360 */ 361 public abstract PGPData newPGPData(byte[] keyId); 362 363 /** 364 * Creates a <code>PGPData</code> from the specified PGP public key 365 * identifier, and optional key material packet and list of external 366 * elements. 367 * 368 * @param keyId a PGP public key identifier as defined in <a href= 369 * "http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>, section 11.2. 370 * The array is cloned to protect against subsequent modification. 371 * @param keyPacket a PGP key material packet as defined in <a href= 372 * "http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>, section 5.5. 373 * The array is cloned to protect against subsequent modification. May 374 * be <code>null</code>. 375 * @param other a list of {@link XMLStructure}s representing elements from 376 * an external namespace. The list is defensively copied to protect 377 * against subsequent modification. May be <code>null</code> or empty. 378 * @return a <code>PGPData</code> 379 * @throws NullPointerException if <code>keyId</code> is <code>null</code> 380 * @throws IllegalArgumentException if the <code>keyId</code> or 381 * <code>keyPacket</code> is not in the correct format. For 382 * <code>keyPacket</code>, the format of the packet header is 383 * checked and the tag is verified that it is of type key material. The 384 * contents and format of the packet body are not checked. 385 * @throws ClassCastException if <code>other</code> contains any 386 * entries that are not of type {@link XMLStructure} 387 */ 388 public abstract PGPData newPGPData(byte[] keyId, byte[] keyPacket, 389 List other); 390 391 /** 392 * Creates a <code>PGPData</code> from the specified PGP key material 393 * packet and optional list of external elements. 394 * 395 * @param keyPacket a PGP key material packet as defined in <a href= 396 * "http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>, section 5.5. 397 * The array is cloned to protect against subsequent modification. 398 * @param other a list of {@link XMLStructure}s representing elements from 399 * an external namespace. The list is defensively copied to protect 400 * against subsequent modification. May be <code>null</code> or empty. 401 * @return a <code>PGPData</code> 402 * @throws NullPointerException if <code>keyPacket</code> is 403 * <code>null</code> 404 * @throws IllegalArgumentException if <code>keyPacket</code> is not in the 405 * correct format. For <code>keyPacket</code>, the format of the packet 406 * header is checked and the tag is verified that it is of type key 407 * material. The contents and format of the packet body are not checked. 408 * @throws ClassCastException if <code>other</code> contains any 409 * entries that are not of type {@link XMLStructure} 410 */ 411 public abstract PGPData newPGPData(byte[] keyPacket, List other); 412 413 /** 414 * Creates a <code>RetrievalMethod</code> from the specified URI. 415 * 416 * @param uri the URI that identifies the <code>KeyInfo</code> information 417 * to be retrieved 418 * @return a <code>RetrievalMethod</code> 419 * @throws NullPointerException if <code>uri</code> is <code>null</code> 420 * @throws IllegalArgumentException if <code>uri</code> is not RFC 2396 421 * compliant 422 */ 423 public abstract RetrievalMethod newRetrievalMethod(String uri); 424 425 /** 426 * Creates a <code>RetrievalMethod</code> from the specified parameters. 427 * 428 * @param uri the URI that identifies the <code>KeyInfo</code> information 429 * to be retrieved 430 * @param type a URI that identifies the type of <code>KeyInfo</code> 431 * information to be retrieved (may be <code>null</code>) 432 * @param transforms a list of {@link Transform}s. The list is defensively 433 * copied to protect against subsequent modification. May be 434 * <code>null</code> or empty. 435 * @return a <code>RetrievalMethod</code> 436 * @throws NullPointerException if <code>uri</code> is <code>null</code> 437 * @throws IllegalArgumentException if <code>uri</code> is not RFC 2396 438 * compliant 439 * @throws ClassCastException if <code>transforms</code> contains any 440 * entries that are not of type {@link Transform} 441 */ 442 public abstract RetrievalMethod newRetrievalMethod(String uri, String type, 443 List transforms); 444 445 /** 446 * Creates a <code>X509Data</code> containing the specified list of 447 * X.509 content. 448 * 449 * @param content a list of one or more X.509 content types. Valid types are 450 * {@link String} (subject names), <code>byte[]</code> (subject key ids), 451 * {@link java.security.cert.X509Certificate}, {@link X509CRL}, 452 * or {@link XMLStructure} ({@link X509IssuerSerial} 453 * objects or elements from an external namespace). Subject names are 454 * distinguished names in RFC 2253 String format. Implementations MUST 455 * support the attribute type keywords defined in RFC 2253 (CN, L, ST, 456 * O, OU, C, STREET, DC and UID). Implementations MAY support additional 457 * keywords. The list is defensively copied to protect against 458 * subsequent modification. 459 * @return a <code>X509Data</code> 460 * @throws NullPointerException if <code>content</code> is <code>null</code> 461 * @throws IllegalArgumentException if <code>content</code> is empty, or 462 * if a subject name is not RFC 2253 compliant or one of the attribute 463 * type keywords is not recognized. 464 * @throws ClassCastException if <code>content</code> contains any entries 465 * that are not of one of the valid types mentioned above 466 */ 467 public abstract X509Data newX509Data(List content); 468 469 /** 470 * Creates an <code>X509IssuerSerial</code> from the specified X.500 issuer 471 * distinguished name and serial number. 472 * 473 * @param issuerName the issuer's distinguished name in RFC 2253 String 474 * format. Implementations MUST support the attribute type keywords 475 * defined in RFC 2253 (CN, L, ST, O, OU, C, STREET, DC and UID). 476 * Implementations MAY support additional keywords. 477 * @param serialNumber the serial number 478 * @return an <code>X509IssuerSerial</code> 479 * @throws NullPointerException if <code>issuerName</code> or 480 * <code>serialNumber</code> are <code>null</code> 481 * @throws IllegalArgumentException if the issuer name is not RFC 2253 482 * compliant or one of the attribute type keywords is not recognized. 483 */ 484 public abstract X509IssuerSerial newX509IssuerSerial 485 (String issuerName, BigInteger serialNumber); 486 487 /** 488 * Indicates whether a specified feature is supported. 489 * 490 * @param feature the feature name (as an absolute URI) 491 * @return <code>true</code> if the specified feature is supported, 492 * <code>false</code> otherwise 493 * @throws NullPointerException if <code>feature</code> is <code>null</code> 494 */ 495 public abstract boolean isFeatureSupported(String feature); 496 497 /** 498 * Returns a reference to the <code>URIDereferencer</code> that is used by 499 * default to dereference URIs in {@link RetrievalMethod} objects. 500 * 501 * @return a reference to the default <code>URIDereferencer</code> 502 */ 503 public abstract URIDereferencer getURIDereferencer(); 504 505 /** 506 * Unmarshals a new <code>KeyInfo</code> instance from a 507 * mechanism-specific <code>XMLStructure</code> (ex: {@link DOMStructure}) 508 * instance. 509 * 510 * @param xmlStructure a mechanism-specific XML structure from which to 511 * unmarshal the keyinfo from 512 * @return the <code>KeyInfo</code> 513 * @throws NullPointerException if <code>xmlStructure</code> is 514 * <code>null</code> 515 * @throws ClassCastException if the type of <code>xmlStructure</code> is 516 * inappropriate for this factory 517 * @throws MarshalException if an unrecoverable exception occurs during 518 * unmarshalling 519 */ 520 public abstract KeyInfo unmarshalKeyInfo(XMLStructure xmlStructure) 521 throws MarshalException; 522 }