001/*
002 * Copyright 2008-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2008-2018 Ping Identity Corporation
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.util.ssl;
022
023
024
025import java.security.KeyStoreException;
026import java.security.KeyStore;
027import javax.net.ssl.KeyManager;
028import javax.net.ssl.KeyManagerFactory;
029
030import com.unboundid.util.NotMutable;
031import com.unboundid.util.StaticUtils;
032import com.unboundid.util.ThreadSafety;
033import com.unboundid.util.ThreadSafetyLevel;
034
035import static com.unboundid.util.Debug.*;
036import static com.unboundid.util.ssl.SSLMessages.*;
037
038
039
040/**
041 * This class provides an SSL key manager that may be used to retrieve
042 * certificates from a PKCS#11 token.
043 */
044@NotMutable()
045@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
046public final class PKCS11KeyManager
047       extends WrapperKeyManager
048{
049  /**
050   * The key store type to use to access PKCS#11 tokens.
051   */
052  private static final String PKCS11_KEY_STORE_TYPE = "PKCS11";
053
054
055
056  /**
057   * Creates a new instance of this PKCS11 key manager that provides the ability
058   * to retrieve certificates from a PKCS#11 token.
059   *
060   * @param  keyStorePIN       The PIN to use to access the contents of the
061   *                           PKCS#11 token.  It may be {@code null} if no PIN
062   *                           is required.
063   * @param  certificateAlias  The nickname of the certificate that should be
064   *                           selected.  It may be {@code null} if any
065   *                           acceptable certificate found may be used.
066   *
067   * @throws  KeyStoreException  If a problem occurs while initializing this key
068   *                             manager.
069   */
070  public PKCS11KeyManager(final char[] keyStorePIN,
071                          final String certificateAlias)
072         throws KeyStoreException
073  {
074    super(getKeyManagers(keyStorePIN), certificateAlias);
075  }
076
077
078
079  /**
080   * Retrieves the set of key managers that will be wrapped by this key manager.
081   *
082   * @param  keyStorePIN  The PIN to use to access the contents of the PKCS#11
083   *                      token.  It may be {@code null} if no PIN is required.
084   *
085   * @return  The set of key managers that will be wrapped by this key manager.
086   *
087   * @throws  KeyStoreException  If a problem occurs while initializing this key
088   *                             manager.
089   */
090  private static KeyManager[] getKeyManagers(final char[] keyStorePIN)
091          throws KeyStoreException
092  {
093    final KeyStore ks = KeyStore.getInstance(PKCS11_KEY_STORE_TYPE);
094    try
095    {
096      ks.load(null, keyStorePIN);
097    }
098    catch (final Exception e)
099    {
100      debugException(e);
101
102      throw new KeyStoreException(
103           ERR_PKCS11_CANNOT_ACCESS.get(StaticUtils.getExceptionMessage(e)), e);
104    }
105
106    try
107    {
108      final KeyManagerFactory factory = KeyManagerFactory.getInstance(
109           KeyManagerFactory.getDefaultAlgorithm());
110      factory.init(ks, keyStorePIN);
111      return factory.getKeyManagers();
112    }
113    catch (final Exception e)
114    {
115      debugException(e);
116
117      throw new KeyStoreException(
118           ERR_PKCS11_CANNOT_GET_KEY_MANAGERS.get(
119                StaticUtils.getExceptionMessage(e)),
120           e);
121    }
122  }
123}