001/* 002 * Copyright 2008-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2008-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2008-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.util.ssl; 037 038 039 040import java.io.File; 041import java.lang.reflect.Constructor; 042import java.lang.reflect.Method; 043import java.security.KeyStoreException; 044import java.security.KeyStore; 045import java.security.Provider; 046import java.security.Security; 047import javax.net.ssl.KeyManager; 048import javax.net.ssl.KeyManagerFactory; 049 050import com.unboundid.util.CryptoHelper; 051import com.unboundid.util.Debug; 052import com.unboundid.util.NotMutable; 053import com.unboundid.util.NotNull; 054import com.unboundid.util.Nullable; 055import com.unboundid.util.StaticUtils; 056import com.unboundid.util.ThreadSafety; 057import com.unboundid.util.ThreadSafetyLevel; 058 059import static com.unboundid.util.ssl.SSLMessages.*; 060 061 062 063/** 064 * This class provides an SSL key manager that may be used to interact with 065 * PKCS #11 tokens. 066 */ 067@NotMutable() 068@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 069public final class PKCS11KeyManager 070 extends WrapperKeyManager 071{ 072 /** 073 * The default key store type to use when accessing PKCS #11 tokens. 074 */ 075 @NotNull public static final String DEFAULT_KEY_STORE_TYPE = "PKCS11"; 076 077 078 079 /** 080 * The fully-qualified name of the default provider class 081 * ({@code sun.security.pkcs11.SunPKCS11}) to use when accessing PKCS #11 082 * tokens. 083 */ 084 @NotNull public static final String DEFAULT_PROVIDER_CLASS = 085 "sun.security.pkcs11.SunPKCS11"; 086 087 088 089 /** 090 * The provider service type that will be used for key store implementations. 091 */ 092 @NotNull private static final String SERVICE_TYPE_KEY_STORE = "KeyStore"; 093 094 095 096 /** 097 * The name used for the SunJSSE provider. 098 */ 099 @NotNull private static final String SUN_JSSE_PROVIDER_NAME = "SunJSSE"; 100 101 102 103 /** 104 * The JSSE provider that should be used when interacting with PKCS #11 105 * tokens. This may be {@code null} if we can't automatically determine an 106 * appropriate provider. 107 */ 108 @Nullable private static final Provider PKCS11_JSSE_PROVIDER; 109 static 110 { 111 // NOTE: Even when we're operating in FIPS-compliant mode, we will likely 112 // want to use the SunJSSE provider in conjunction with PKCS #11 tokens 113 // because the Bouncy Castle FIPS-compliant BCJSSE provider does not work 114 // well in conjunction with PKCS #11 tokens. 115 final Provider sunJSSEProvider = 116 Security.getProvider(SUN_JSSE_PROVIDER_NAME); 117 if (sunJSSEProvider != null) 118 { 119 PKCS11_JSSE_PROVIDER = sunJSSEProvider; 120 } 121 else 122 { 123 // Select the first provider that offers support for TLSv1.3. If we 124 // can't find one, then select the first provider that offer support for 125 // TLSv1.2. 126 Provider tls13Provider = null; 127 Provider tls12Provider = null; 128 for (final Provider provider : Security.getProviders()) 129 { 130 if (provider.getService(SSLUtil.PROVIDER_SERVICE_TYPE_SSL_CONTEXT, 131 SSLUtil.SSL_PROTOCOL_TLS_1_3) != null) 132 { 133 tls13Provider = provider; 134 break; 135 } 136 else if (provider.getService(SSLUtil.PROVIDER_SERVICE_TYPE_SSL_CONTEXT, 137 SSLUtil.SSL_PROTOCOL_TLS_1_2) != null) 138 { 139 tls12Provider = provider; 140 } 141 } 142 143 if (tls13Provider != null) 144 { 145 PKCS11_JSSE_PROVIDER = tls13Provider; 146 } 147 else 148 { 149 PKCS11_JSSE_PROVIDER = tls12Provider; 150 } 151 } 152 } 153 154 155 156 /** 157 * Creates a new instance of this PKCS #11 key manager with the provided 158 * information. 159 * 160 * @param keyStorePIN The user PIN to use to access the PKCS #11 161 * token. This may be {@code null} if no PIN is 162 * required. 163 * @param certificateAlias The nickname for the key entry to use in the 164 * PKCS #11 token. It may be {@code null} if any 165 * acceptable entry may be used. 166 * 167 * @throws KeyStoreException If a problem occurs while initializing this key 168 * manager. 169 */ 170 public PKCS11KeyManager(@Nullable final char[] keyStorePIN, 171 @Nullable final String certificateAlias) 172 throws KeyStoreException 173 { 174 this(getProvider(null, null, null, false), null, keyStorePIN, 175 certificateAlias); 176 } 177 178 179 180 /** 181 * Creates a new instance of this PKCS11 key manager with the provided 182 * information. 183 * 184 * @param providerClassName The fully-qualified name of the Java class that 185 * implements the provider to use to interact with 186 * the PKCS #11 module. If this is {@code null}, 187 * then the key manager will attempt to 188 * automatically identify the appropriate 189 * provider. 190 * @param providerConfigFile A file that contains the configuration to use 191 * for the provider. This may be {@code null} if 192 * no provider configuration is needed, or if the 193 * provider is already properly instantiated. 194 * @param keyStoreType The name of the key store type to use when 195 * interacting with the PKCS #11 token. If this 196 * is {@code null}, then a default key store type 197 * of {@code PKCS11} will be used. 198 * @param keyStorePIN The user PIN to use to access the PKCS #11 199 * token. This may be {@code null} if no PIN is 200 * required. 201 * @param certificateAlias The nickname for the key entry to use in the 202 * PKCS #11 token. It may be {@code null} if any 203 * acceptable entry may be used. 204 * 205 * @throws KeyStoreException If a problem occurs while initializing this 206 * key manager. 207 */ 208 public PKCS11KeyManager(@Nullable final String providerClassName, 209 @Nullable final File providerConfigFile, 210 @Nullable final String keyStoreType, 211 @Nullable final char[] keyStorePIN, 212 @Nullable final String certificateAlias) 213 throws KeyStoreException 214 { 215 this(getProvider(providerClassName, providerConfigFile, keyStoreType, 216 false), 217 keyStoreType, keyStorePIN, certificateAlias); 218 } 219 220 221 222 /** 223 * Creates a new instance of this PKCS11 key manager with the provided 224 * information. 225 * 226 * @param provider The Java security provider to use to access the 227 * PKCS #11 token. It must not be {@code null}. 228 * @param keyStoreType The name of the key store type to use when 229 * interacting with the PKCS #11 token. If this 230 * is {@code null}, then a default key store type 231 * of {@code PKCS11} will be used. 232 * @param keyStorePIN The user PIN to use to access the PKCS #11 233 * token. This may be {@code null} if no PIN is 234 * required. 235 * @param certificateAlias The nickname for the key entry to use in the 236 * PKCS #11 token. It may be {@code null} if any 237 * acceptable entry may be used. 238 * 239 * @throws KeyStoreException If a problem occurs while initializing this 240 * key manager. 241 */ 242 public PKCS11KeyManager(@NotNull final Provider provider, 243 @Nullable final String keyStoreType, 244 @Nullable final char[] keyStorePIN, 245 @Nullable final String certificateAlias) 246 throws KeyStoreException 247 { 248 super(getKeyManagers(provider, keyStoreType, keyStorePIN), 249 certificateAlias); 250 } 251 252 253 254 /** 255 * Retrieves an instance of a Java security provider that may be used to 256 * interact with a PKCS #11 token. If a suitable new provider instance is 257 * created, then it will be added to the JVM's configured list of providers. 258 * 259 * @param providerClassName The fully-qualified name of the Java class 260 * to use for the provider. If this is 261 * {@code null}, then an attempt will be made 262 * to automatically identify the appropriate 263 * provider class. 264 * @param providerConfigFile A file that contains the configuration to 265 * use for the provider. This may be 266 * {@code null} if no provider configuration 267 * is needed, or if the provider is already 268 * properly instantiated. 269 * @param keyStoreType The name of the key store type to use when 270 * interacting with the PKCS #11 token. If 271 * this is {@code null}, then a default key 272 * store type of {@code PKCS11} will be used. 273 * @param alwaysCreateNewInstance Indicates whether to always create a new 274 * instance of the provider, even 275 * 276 * @return The provider instance that should be used to interact with a 277 * PKCS #11 token. 278 * 279 * @throws KeyStoreException If a problem occurs while retrieving the 280 */ 281 @NotNull() 282 public static Provider getProvider(@Nullable final String providerClassName, 283 @Nullable final File providerConfigFile, 284 @Nullable final String keyStoreType, 285 final boolean alwaysCreateNewInstance) 286 throws KeyStoreException 287 { 288 final String ksType; 289 if (keyStoreType == null) 290 { 291 ksType = DEFAULT_KEY_STORE_TYPE; 292 } 293 else 294 { 295 ksType = keyStoreType; 296 } 297 298 299 // If no provider class was specified, then try to automatically determine 300 // the provider class to use. Otherwise, try to load the provider class. 301 final Class<?> providerClass; 302 final Provider[] providers = Security.getProviders(); 303 if (providerClassName == null) 304 { 305 providerClass = inferProviderClass(providers, ksType); 306 } 307 else 308 { 309 try 310 { 311 providerClass = Class.forName(providerClassName); 312 } 313 catch (final Exception e) 314 { 315 Debug.debugException(e); 316 throw new KeyStoreException( 317 ERR_PCKS11_NO_SUCH_PROVIDER_CLASS.get(providerClassName, 318 StaticUtils.getExceptionMessage(e)), e); 319 } 320 } 321 322 323 // See if any of the already defined providers has the identified class. If 324 // there is already a provider of that type loaded, and if it advertises 325 // support for the desired key store type, and if we either don't have a 326 // configuration file or don't need to always create a new instance, then 327 // just use the existing provider. 328 // 329 // don't need to always 330 // create a new instance, then just use the existing provider. 331 Provider provider = null; 332 for (final Provider p : providers) 333 { 334 if (p.getClass().getName().equals(providerClass.getName())) 335 { 336 provider = p; 337 if ((p.getService(SERVICE_TYPE_KEY_STORE, ksType) != null) && 338 ((providerConfigFile == null) || (! alwaysCreateNewInstance))) 339 { 340 return p; 341 } 342 break; 343 } 344 } 345 346 347 // At this point, we know that we're going to need to create a new instance 348 // of the provider. Get the default constructor for the provider class, if 349 // there is one. 350 Constructor<?> defaultConstructor = null; 351 try 352 { 353 defaultConstructor = providerClass.getConstructor(); 354 } 355 catch (final Exception e) 356 { 357 Debug.debugException(e); 358 } 359 360 361 // If we don't have a configuration file, then there must be a default 362 // constructor. Invoke it to create the provider, and make sure that it 363 // advertises support for the target key store type. 364 if (providerConfigFile == null) 365 { 366 if (defaultConstructor == null) 367 { 368 throw new KeyStoreException( 369 ERR_PKCS11_NO_DEFAULT_CONSTRUCTOR_NO_CONFIG.get( 370 providerClass.getName(), ksType)); 371 } 372 373 try 374 { 375 provider = (Provider) defaultConstructor.newInstance(); 376 } 377 catch (final Exception e) 378 { 379 Debug.debugException(e); 380 throw new KeyStoreException( 381 ERR_PKCS11_CANNOT_INVOKE_DEFAULT_CONSTRUCTOR.get( 382 providerClass.getName(), ksType, 383 StaticUtils.getExceptionMessage(e)), 384 e); 385 } 386 387 if (provider.getService(SERVICE_TYPE_KEY_STORE, ksType) == null) 388 { 389 throw new KeyStoreException( 390 ERR_PKCS11_DEFAULT_CONSTRUCTOR_NO_KS_TYPE.get( 391 providerClass.getName(), ksType)); 392 } 393 else 394 { 395 Security.addProvider(provider); 396 return provider; 397 } 398 } 399 400 401 // We know that we need to configure the provider. If the provider offers 402 // a public configure(String) method, then use it to accomplish that. 403 if (defaultConstructor != null) 404 { 405 Method configureMethod = null; 406 try 407 { 408 configureMethod = providerClass.getMethod("configure", String.class); 409 } 410 catch (final Exception e) 411 { 412 Debug.debugException(e); 413 } 414 415 if (configureMethod != null) 416 { 417 if (provider == null) 418 { 419 try 420 { 421 provider = (Provider) defaultConstructor.newInstance(); 422 } 423 catch (final Exception e) 424 { 425 Debug.debugException(e); 426 throw new KeyStoreException( 427 ERR_PKCS11_CANNOT_INVOKE_DEFAULT_CONSTRUCTOR.get( 428 providerClass.getName(), ksType, 429 StaticUtils.getExceptionMessage(e)), 430 e); 431 } 432 } 433 434 final Provider configuredProvider; 435 try 436 { 437 configuredProvider = (Provider) configureMethod.invoke(provider, 438 providerConfigFile.getAbsolutePath()); 439 } 440 catch (final Exception e) 441 { 442 Debug.debugException(e); 443 throw new KeyStoreException( 444 ERR_PKCS11_CANNOT_CONFIGURE_PROVIDER.get( 445 providerClass.getName(), 446 providerConfigFile.getAbsolutePath(), 447 StaticUtils.getExceptionMessage(e)), 448 e); 449 } 450 451 if (configuredProvider.getService(SERVICE_TYPE_KEY_STORE, ksType) == 452 null) 453 { 454 throw new KeyStoreException( 455 ERR_PKCS11_CONFIGURED_PROVIDER_NO_KS_TYPE.get( 456 providerClass.getName(), ksType, 457 providerConfigFile.getAbsolutePath())); 458 } 459 else 460 { 461 Security.addProvider(configuredProvider); 462 return configuredProvider; 463 } 464 } 465 } 466 467 468 // If we've gotten here, then our last hope is that there's a public 469 // constructor that takes a single String argument. If there is, then 470 // invoke it with the path to the configuration file to create the provider. 471 final Constructor<?> stringConstructor; 472 try 473 { 474 stringConstructor = providerClass.getConstructor(String.class); 475 } 476 catch (final Exception e) 477 { 478 Debug.debugException(e); 479 throw new KeyStoreException( 480 ERR_PKCS11_NO_STRING_CONSTRUCTOR.get(providerClass.getName(), 481 providerConfigFile.getAbsolutePath(), ksType), 482 e); 483 } 484 485 final Provider configuredProvider; 486 try 487 { 488 configuredProvider = (Provider) stringConstructor.newInstance( 489 providerConfigFile.getAbsolutePath()); 490 } 491 catch (final Exception e) 492 { 493 Debug.debugException(e); 494 throw new KeyStoreException( 495 ERR_PKCS11_CANNOT_INVOKE_STRING_CONSTRUCTOR.get( 496 providerClass.getName(), providerConfigFile.getAbsolutePath(), 497 ksType, StaticUtils.getExceptionMessage(e)), 498 e); 499 } 500 501 502 // Make sure that the configured provider advertises support for the 503 // key store type. 504 if (configuredProvider.getService(SERVICE_TYPE_KEY_STORE, ksType) == null) 505 { 506 throw new KeyStoreException( 507 ERR_PKCS11_CONFIGURED_PROVIDER_NO_KS_TYPE.get( 508 providerClass.getName(), ksType, 509 providerConfigFile.getAbsolutePath())); 510 } 511 else 512 { 513 Security.addProvider(configuredProvider); 514 return configuredProvider; 515 } 516 } 517 518 519 520 /** 521 * Attempts to infer the class for the PKCS #11 provider to use. 522 * 523 * @param providers The set of providers that have already been loaded in 524 * the JVM. This must not be {@code null}. 525 * @param keyStoreType The name of the key store type to use when 526 * interacting with the PKCS #11 token. This must not 527 * be {@code null}. 528 * 529 * @return The class to use for the PKCS #11 provider. 530 * 531 * @throws KeyStoreException If no suitable class can be identified. 532 */ 533 @NotNull() 534 private static Class<?> inferProviderClass( 535 @NotNull final Provider[] providers, 536 @NotNull final String keyStoreType) 537 throws KeyStoreException 538 { 539 // First, see if there is already a provider defined in the JVM that already 540 // advertises support for the specified key store type. 541 for (final Provider p : providers) 542 { 543 if (p.getService(SERVICE_TYPE_KEY_STORE, keyStoreType) != null) 544 { 545 return p.getClass(); 546 } 547 } 548 549 550 // See if there is already a provider defined in the JVM whose provider or 551 // class name contains the string "PKCS11". 552 for (final Provider p : providers) 553 { 554 final Class<?> providerClass = p.getClass(); 555 if (StaticUtils.toUpperCase(p.getName()).contains("PKCS11") || 556 StaticUtils.toUpperCase(providerClass.getName()).contains("PKCS11")) 557 { 558 return providerClass; 559 } 560 } 561 562 563 // We couldn't find an existing provider that looks like it might support 564 // PKCS #11, so try to use the default provider class. 565 try 566 { 567 return Class.forName(DEFAULT_PROVIDER_CLASS); 568 } 569 catch (final Exception e) 570 { 571 Debug.debugException(e); 572 throw new KeyStoreException( 573 ERR_PKCS11_CANNOT_INFER_PROVIDER_CLASS.get( 574 DEFAULT_PROVIDER_CLASS), 575 e); 576 } 577 } 578 579 580 581 /** 582 * Retrieves the set of key managers that will be wrapped by this key manager. 583 * 584 * @param provider The Java security provider to use to access the PKCS 585 * #11 token. It must not be {@code null}. 586 * @param keyStoreType The name of the key store type to use when 587 * interacting with the PKCS #11 token. If this is 588 * {@code null}, then a default key store type of 589 * {@code PKCS11} will be used. 590 * @param keyStorePIN The user PIN to use to access the PKCS #11 token. 591 * This may be {@code null} if no PIN is required. 592 * 593 * @return The set of key managers that will be wrapped by this key manager. 594 * 595 * @throws KeyStoreException If a problem occurs while initializing this key 596 * manager. 597 */ 598 @NotNull() 599 private static KeyManager[] getKeyManagers( 600 @NotNull final Provider provider, 601 @Nullable final String keyStoreType, 602 @Nullable final char[] keyStorePIN) 603 throws KeyStoreException 604 { 605 final String ksType; 606 if (keyStoreType == null) 607 { 608 ksType = DEFAULT_KEY_STORE_TYPE; 609 } 610 else 611 { 612 ksType = keyStoreType; 613 } 614 615 final KeyStore ks = CryptoHelper.getKeyStore(ksType, provider); 616 try 617 { 618 ks.load(null, keyStorePIN); 619 } 620 catch (final Exception e) 621 { 622 Debug.debugException(e); 623 624 throw new KeyStoreException( 625 ERR_PKCS11_CANNOT_ACCESS.get(StaticUtils.getExceptionMessage(e)), e); 626 } 627 628 try 629 { 630 final KeyManagerFactory factory = CryptoHelper.getKeyManagerFactory(); 631 factory.init(ks, keyStorePIN); 632 return factory.getKeyManagers(); 633 } 634 catch (final Exception e) 635 { 636 Debug.debugException(e); 637 638 throw new KeyStoreException( 639 ERR_PKCS11_CANNOT_GET_KEY_MANAGERS.get( 640 StaticUtils.getExceptionMessage(e)), 641 e); 642 } 643 } 644 645 646 647 /** 648 * Retrieves an instance of a Java security provider that should be used when 649 * performing JSSE-related operations in conjunction with PKCS #11 tokens. 650 * The JVM's preferred JSSE provider may not be the best choice when using a 651 * PKCS #11 token (including when operating in FIPS-compliant mode). 652 * 653 * @return An instance of a Java security provider that should be used when 654 * performing JSSE-related operations in conjunction with PKCS #11 655 * tokens. It may be {@code null} if the best provider cannot be 656 * determined. 657 */ 658 @Nullable() 659 public static Provider getPKCS11JSSESProvider() 660 { 661 return PKCS11_JSSE_PROVIDER; 662 } 663}