1 /* 2 * Copyright (c) 2005, 2016, 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%20Mechanism%20Requirements"> 66 * DOM Mechanism Requirements</a> section of the API overview. See the 67 * <a href="../../../../../../technotes/guides/security/xmldsig/overview.html#Service%20Provider"> 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 * @implNote 133 * The JDK Reference Implementation additionally uses the 134 * {@code jdk.security.provider.preferred} 135 * {@link Security#getProperty(String) Security} property to determine 136 * the preferred provider order for the specified algorithm. This 137 * may be different than the order of providers returned by 138 * {@link Security#getProviders() Security.getProviders()}. 139 * 140 * @param mechanismType the type of the XML processing mechanism and 141 * representation. See the <a 142 * href="../../../../../../technotes/guides/security/xmldsig/overview.html#Service%20Provider"> 143 * Service Providers</a> section of the API overview for a list of 144 * standard mechanism types. 145 * @return a new <code>KeyInfoFactory</code> 146 * @throws NullPointerException if <code>mechanismType</code> is 147 * <code>null</code> 148 * @throws NoSuchMechanismException if no <code>Provider</code> supports a 149 * <code>KeyInfoFactory</code> implementation for the specified mechanism 150 * @see Provider 151 */ 152 public static KeyInfoFactory getInstance(String mechanismType) { 153 if (mechanismType == null) { 154 throw new NullPointerException("mechanismType cannot be null"); 155 } 156 Instance instance; 157 try { 158 instance = GetInstance.getInstance 159 ("KeyInfoFactory", null, mechanismType); 160 } catch (NoSuchAlgorithmException nsae) { 161 throw new NoSuchMechanismException(nsae); 162 } 163 KeyInfoFactory factory = (KeyInfoFactory) instance.impl; 164 factory.mechanismType = mechanismType; 165 factory.provider = instance.provider; 166 return factory; 167 } 168 169 /** 170 * Returns a <code>KeyInfoFactory</code> that supports the 171 * requested XML processing mechanism and representation type (ex: "DOM"), 172 * as supplied by the specified provider. Note that the specified 173 * <code>Provider</code> object does not have to be registered in the 174 * provider list. 175 * 176 * @param mechanismType the type of the XML processing mechanism and 177 * representation. See the <a 178 * href="../../../../../../technotes/guides/security/xmldsig/overview.html#Service%20Provider"> 179 * Service Providers</a> section of the API overview for a list of 180 * standard mechanism types. 181 * @param provider the <code>Provider</code> object 182 * @return a new <code>KeyInfoFactory</code> 183 * @throws NullPointerException if <code>mechanismType</code> or 184 * <code>provider</code> are <code>null</code> 185 * @throws NoSuchMechanismException if a <code>KeyInfoFactory</code> 186 * implementation for the specified mechanism is not available from the 187 * specified <code>Provider</code> object 188 * @see Provider 189 */ 190 public static KeyInfoFactory getInstance(String mechanismType, 191 Provider provider) { 192 if (mechanismType == null) { 193 throw new NullPointerException("mechanismType cannot be null"); 194 } else if (provider == null) { 195 throw new NullPointerException("provider cannot be null"); 196 } 197 198 Instance instance; 199 try { 200 instance = GetInstance.getInstance 201 ("KeyInfoFactory", null, mechanismType, provider); 202 } catch (NoSuchAlgorithmException nsae) { 203 throw new NoSuchMechanismException(nsae); 204 } 205 KeyInfoFactory factory = (KeyInfoFactory) instance.impl; 206 factory.mechanismType = mechanismType; 207 factory.provider = instance.provider; 208 return factory; 209 } 210 211 /** 212 * Returns a <code>KeyInfoFactory</code> that supports the 213 * requested XML processing mechanism and representation type (ex: "DOM"), 214 * as supplied by the specified provider. The specified provider must be 215 * registered in the security provider list. 216 * 217 * <p>Note that the list of registered providers may be retrieved via 218 * the {@link Security#getProviders() Security.getProviders()} method. 219 * 220 * @param mechanismType the type of the XML processing mechanism and 221 * representation. See the <a 222 * href="../../../../../../technotes/guides/security/xmldsig/overview.html#Service%20Provider"> 223 * Service Providers</a> section of the API overview for a list of 224 * standard mechanism types. 225 * @param provider the string name of the provider 226 * @return a new <code>KeyInfoFactory</code> 227 * @throws NoSuchProviderException if the specified provider is not 228 * registered in the security provider list 229 * @throws NullPointerException if <code>mechanismType</code> or 230 * <code>provider</code> are <code>null</code> 231 * @throws NoSuchMechanismException if a <code>KeyInfoFactory</code> 232 * implementation for the specified mechanism is not available from the 233 * specified provider 234 * @see Provider 235 */ 236 public static KeyInfoFactory getInstance(String mechanismType, 237 String provider) throws NoSuchProviderException { 238 if (mechanismType == null) { 239 throw new NullPointerException("mechanismType cannot be null"); 240 } else if (provider == null) { 241 throw new NullPointerException("provider cannot be null"); 242 } else if (provider.length() == 0) { 243 throw new NoSuchProviderException(); 244 } 245 246 Instance instance; 247 try { 248 instance = GetInstance.getInstance 249 ("KeyInfoFactory", null, mechanismType, provider); 250 } catch (NoSuchAlgorithmException nsae) { 251 throw new NoSuchMechanismException(nsae); 252 } 253 KeyInfoFactory factory = (KeyInfoFactory) instance.impl; 254 factory.mechanismType = mechanismType; 255 factory.provider = instance.provider; 256 return factory; 257 } 258 259 /** 260 * Returns a <code>KeyInfoFactory</code> that supports the 261 * default XML processing mechanism and representation type ("DOM"). 262 * 263 * <p>This method uses the standard JCA provider lookup mechanism to 264 * locate and instantiate a <code>KeyInfoFactory</code> implementation of 265 * the default mechanism type. It traverses the list of registered security 266 * <code>Provider</code>s, starting with the most preferred 267 * <code>Provider</code>. A new <code>KeyInfoFactory</code> object 268 * from the first <code>Provider</code> that supports the DOM mechanism is 269 * returned. 270 * 271 * <p> Note that the list of registered providers may be retrieved via 272 * the {@link Security#getProviders() Security.getProviders()} method. 273 * 274 * @implNote 275 * The JDK Reference Implementation additionally uses the 276 * {@code jdk.security.provider.preferred} 277 * {@link Security#getProperty(String) Security} property to determine 278 * the preferred provider order for the specified algorithm. This 279 * may be different than the order of providers returned by 280 * {@link Security#getProviders() Security.getProviders()}. 281 * 282 * @return a new <code>KeyInfoFactory</code> 283 * @throws NoSuchMechanismException if no <code>Provider</code> supports a 284 * <code>KeyInfoFactory</code> implementation for the DOM mechanism 285 * @see Provider 286 */ 287 public static KeyInfoFactory getInstance() { 288 return getInstance("DOM"); 289 } 290 291 /** 292 * Returns the type of the XML processing mechanism and representation 293 * supported by this <code>KeyInfoFactory</code> (ex: "DOM") 294 * 295 * @return the XML processing mechanism type supported by this 296 * <code>KeyInfoFactory</code> 297 */ 298 public final String getMechanismType() { 299 return mechanismType; 300 } 301 302 /** 303 * Returns the provider of this <code>KeyInfoFactory</code>. 304 * 305 * @return the provider of this <code>KeyInfoFactory</code> 306 */ 307 public final Provider getProvider() { 308 return provider; 309 } 310 311 /** 312 * Creates a <code>KeyInfo</code> containing the specified list of 313 * key information types. 314 * 315 * @param content a list of one or more {@link XMLStructure}s representing 316 * key information types. The list is defensively copied to protect 317 * against subsequent modification. 318 * @return a <code>KeyInfo</code> 319 * @throws NullPointerException if <code>content</code> is <code>null</code> 320 * @throws IllegalArgumentException if <code>content</code> is empty 321 * @throws ClassCastException if <code>content</code> contains any entries 322 * that are not of type {@link XMLStructure} 323 */ 324 public abstract KeyInfo newKeyInfo(List<? extends XMLStructure> content); 325 326 /** 327 * Creates a <code>KeyInfo</code> containing the specified list of key 328 * information types and optional id. The 329 * <code>id</code> parameter represents the value of an XML 330 * <code>ID</code> attribute and is useful for referencing 331 * the <code>KeyInfo</code> from other XML structures. 332 * 333 * @param content a list of one or more {@link XMLStructure}s representing 334 * key information types. The list is defensively copied to protect 335 * against subsequent modification. 336 * @param id the value of an XML <code>ID</code> (may be <code>null</code>) 337 * @return a <code>KeyInfo</code> 338 * @throws NullPointerException if <code>content</code> is <code>null</code> 339 * @throws IllegalArgumentException if <code>content</code> is empty 340 * @throws ClassCastException if <code>content</code> contains any entries 341 * that are not of type {@link XMLStructure} 342 */ 343 public abstract KeyInfo newKeyInfo(List<? extends XMLStructure> content, 344 String id); 345 346 /** 347 * Creates a <code>KeyName</code> from the specified name. 348 * 349 * @param name the name that identifies the key 350 * @return a <code>KeyName</code> 351 * @throws NullPointerException if <code>name</code> is <code>null</code> 352 */ 353 public abstract KeyName newKeyName(String name); 354 355 /** 356 * Creates a <code>KeyValue</code> from the specified public key. 357 * 358 * @param key the public key 359 * @return a <code>KeyValue</code> 360 * @throws KeyException if the <code>key</code>'s algorithm is not 361 * recognized or supported by this <code>KeyInfoFactory</code> 362 * @throws NullPointerException if <code>key</code> is <code>null</code> 363 */ 364 public abstract KeyValue newKeyValue(PublicKey key) throws KeyException; 365 366 /** 367 * Creates a <code>PGPData</code> from the specified PGP public key 368 * identifier. 369 * 370 * @param keyId a PGP public key identifier as defined in <a href= 371 * "http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>, section 11.2. 372 * The array is cloned to protect against subsequent modification. 373 * @return a <code>PGPData</code> 374 * @throws NullPointerException if <code>keyId</code> is <code>null</code> 375 * @throws IllegalArgumentException if the key id is not in the correct 376 * format 377 */ 378 public abstract PGPData newPGPData(byte[] keyId); 379 380 /** 381 * Creates a <code>PGPData</code> from the specified PGP public key 382 * identifier, and optional key material packet and list of external 383 * elements. 384 * 385 * @param keyId a PGP public key identifier as defined in <a href= 386 * "http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>, section 11.2. 387 * The array is cloned to protect against subsequent modification. 388 * @param keyPacket a PGP key material packet as defined in <a href= 389 * "http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>, section 5.5. 390 * The array is cloned to protect against subsequent modification. May 391 * be <code>null</code>. 392 * @param other a list of {@link XMLStructure}s representing elements from 393 * an external namespace. The list is defensively copied to protect 394 * against subsequent modification. May be <code>null</code> or empty. 395 * @return a <code>PGPData</code> 396 * @throws NullPointerException if <code>keyId</code> is <code>null</code> 397 * @throws IllegalArgumentException if the <code>keyId</code> or 398 * <code>keyPacket</code> is not in the correct format. For 399 * <code>keyPacket</code>, the format of the packet header is 400 * checked and the tag is verified that it is of type key material. The 401 * contents and format of the packet body are not checked. 402 * @throws ClassCastException if <code>other</code> contains any 403 * entries that are not of type {@link XMLStructure} 404 */ 405 public abstract PGPData newPGPData(byte[] keyId, byte[] keyPacket, 406 List<? extends XMLStructure> other); 407 408 /** 409 * Creates a <code>PGPData</code> from the specified PGP key material 410 * packet and optional list of external elements. 411 * 412 * @param keyPacket a PGP key material packet as defined in <a href= 413 * "http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>, section 5.5. 414 * The array is cloned to protect against subsequent modification. 415 * @param other a list of {@link XMLStructure}s representing elements from 416 * an external namespace. The list is defensively copied to protect 417 * against subsequent modification. May be <code>null</code> or empty. 418 * @return a <code>PGPData</code> 419 * @throws NullPointerException if <code>keyPacket</code> is 420 * <code>null</code> 421 * @throws IllegalArgumentException if <code>keyPacket</code> is not in the 422 * correct format. For <code>keyPacket</code>, the format of the packet 423 * header is checked and the tag is verified that it is of type key 424 * material. The contents and format of the packet body are not checked. 425 * @throws ClassCastException if <code>other</code> contains any 426 * entries that are not of type {@link XMLStructure} 427 */ 428 public abstract PGPData newPGPData(byte[] keyPacket, 429 List<? extends XMLStructure> other); 430 431 /** 432 * Creates a <code>RetrievalMethod</code> from the specified URI. 433 * 434 * @param uri the URI that identifies the <code>KeyInfo</code> information 435 * to be retrieved 436 * @return a <code>RetrievalMethod</code> 437 * @throws NullPointerException if <code>uri</code> is <code>null</code> 438 * @throws IllegalArgumentException if <code>uri</code> is not RFC 2396 439 * compliant 440 */ 441 public abstract RetrievalMethod newRetrievalMethod(String uri); 442 443 /** 444 * Creates a <code>RetrievalMethod</code> from the specified parameters. 445 * 446 * @param uri the URI that identifies the <code>KeyInfo</code> information 447 * to be retrieved 448 * @param type a URI that identifies the type of <code>KeyInfo</code> 449 * information to be retrieved (may be <code>null</code>) 450 * @param transforms a list of {@link Transform}s. The list is defensively 451 * copied to protect against subsequent modification. May be 452 * <code>null</code> or empty. 453 * @return a <code>RetrievalMethod</code> 454 * @throws NullPointerException if <code>uri</code> is <code>null</code> 455 * @throws IllegalArgumentException if <code>uri</code> is not RFC 2396 456 * compliant 457 * @throws ClassCastException if <code>transforms</code> contains any 458 * entries that are not of type {@link Transform} 459 */ 460 public abstract RetrievalMethod newRetrievalMethod(String uri, String type, 461 List<? extends Transform> transforms); 462 463 /** 464 * Creates a <code>X509Data</code> containing the specified list of 465 * X.509 content. 466 * 467 * @param content a list of one or more X.509 content types. Valid types are 468 * {@link String} (subject names), <code>byte[]</code> (subject key ids), 469 * {@link java.security.cert.X509Certificate}, {@link X509CRL}, 470 * or {@link XMLStructure} ({@link X509IssuerSerial} 471 * objects or elements from an external namespace). Subject names are 472 * distinguished names in RFC 2253 String format. Implementations MUST 473 * support the attribute type keywords defined in RFC 2253 (CN, L, ST, 474 * O, OU, C, STREET, DC and UID). Implementations MAY support additional 475 * keywords. The list is defensively copied to protect against 476 * subsequent modification. 477 * @return a <code>X509Data</code> 478 * @throws NullPointerException if <code>content</code> is <code>null</code> 479 * @throws IllegalArgumentException if <code>content</code> is empty, or 480 * if a subject name is not RFC 2253 compliant or one of the attribute 481 * type keywords is not recognized. 482 * @throws ClassCastException if <code>content</code> contains any entries 483 * that are not of one of the valid types mentioned above 484 */ 485 public abstract X509Data newX509Data(List<?> content); 486 487 /** 488 * Creates an <code>X509IssuerSerial</code> from the specified X.500 issuer 489 * distinguished name and serial number. 490 * 491 * @param issuerName the issuer's distinguished name in RFC 2253 String 492 * format. Implementations MUST support the attribute type keywords 493 * defined in RFC 2253 (CN, L, ST, O, OU, C, STREET, DC and UID). 494 * Implementations MAY support additional keywords. 495 * @param serialNumber the serial number 496 * @return an <code>X509IssuerSerial</code> 497 * @throws NullPointerException if <code>issuerName</code> or 498 * <code>serialNumber</code> are <code>null</code> 499 * @throws IllegalArgumentException if the issuer name is not RFC 2253 500 * compliant or one of the attribute type keywords is not recognized. 501 */ 502 public abstract X509IssuerSerial newX509IssuerSerial 503 (String issuerName, BigInteger serialNumber); 504 505 /** 506 * Indicates whether a specified feature is supported. 507 * 508 * @param feature the feature name (as an absolute URI) 509 * @return <code>true</code> if the specified feature is supported, 510 * <code>false</code> otherwise 511 * @throws NullPointerException if <code>feature</code> is <code>null</code> 512 */ 513 public abstract boolean isFeatureSupported(String feature); 514 515 /** 516 * Returns a reference to the <code>URIDereferencer</code> that is used by 517 * default to dereference URIs in {@link RetrievalMethod} objects. 518 * 519 * @return a reference to the default <code>URIDereferencer</code> 520 */ 521 public abstract URIDereferencer getURIDereferencer(); 522 523 /** 524 * Unmarshals a new <code>KeyInfo</code> instance from a 525 * mechanism-specific <code>XMLStructure</code> (ex: {@link DOMStructure}) 526 * instance. 527 * 528 * @param xmlStructure a mechanism-specific XML structure from which to 529 * unmarshal the keyinfo from 530 * @return the <code>KeyInfo</code> 531 * @throws NullPointerException if <code>xmlStructure</code> is 532 * <code>null</code> 533 * @throws ClassCastException if the type of <code>xmlStructure</code> is 534 * inappropriate for this factory 535 * @throws MarshalException if an unrecoverable exception occurs during 536 * unmarshalling 537 */ 538 public abstract KeyInfo unmarshalKeyInfo(XMLStructure xmlStructure) 539 throws MarshalException; 540 }