001    /*
002     * Copyright 2008-2016 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2008-2016 UnboundID Corp.
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     */
021    package com.unboundid.util.ssl;
022    
023    
024    
025    import java.security.KeyStoreException;
026    import java.security.KeyStore;
027    import javax.net.ssl.KeyManager;
028    import javax.net.ssl.KeyManagerFactory;
029    
030    import com.unboundid.util.NotMutable;
031    import com.unboundid.util.ThreadSafety;
032    import com.unboundid.util.ThreadSafetyLevel;
033    
034    import static com.unboundid.util.Debug.*;
035    import static com.unboundid.util.ssl.SSLMessages.*;
036    
037    
038    
039    /**
040     * This class provides an SSL key manager that may be used to retrieve
041     * certificates from a PKCS#11 token.
042     */
043    @NotMutable()
044    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
045    public final class PKCS11KeyManager
046           extends WrapperKeyManager
047    {
048      /**
049       * The key store type to use to access PKCS#11 tokens.
050       */
051      private static final String PKCS11_KEY_STORE_TYPE = "PKCS11";
052    
053    
054    
055      /**
056       * Creates a new instance of this PKCS11 key manager that provides the ability
057       * to retrieve certificates from a PKCS#11 token.
058       *
059       * @param  keyStorePIN       The PIN to use to access the contents of the
060       *                           PKCS#11 token.  It may be {@code null} if no PIN
061       *                           is required.
062       * @param  certificateAlias  The nickname of the certificate that should be
063       *                           selected.  It may be {@code null} if any
064       *                           acceptable certificate found may be used.
065       *
066       * @throws  KeyStoreException  If a problem occurs while initializing this key
067       *                             manager.
068       */
069      public PKCS11KeyManager(final char[] keyStorePIN,
070                              final String certificateAlias)
071             throws KeyStoreException
072      {
073        super(getKeyManagers(keyStorePIN), certificateAlias);
074      }
075    
076    
077    
078      /**
079       * Retrieves the set of key managers that will be wrapped by this key manager.
080       *
081       * @param  keyStorePIN  The PIN to use to access the contents of the PKCS#11
082       *                      token.  It may be {@code null} if no PIN is required.
083       *
084       * @return  The set of key managers that will be wrapped by this key manager.
085       *
086       * @throws  KeyStoreException  If a problem occurs while initializing this key
087       *                             manager.
088       */
089      private static KeyManager[] getKeyManagers(final char[] keyStorePIN)
090              throws KeyStoreException
091      {
092        final KeyStore ks = KeyStore.getInstance(PKCS11_KEY_STORE_TYPE);
093        try
094        {
095          ks.load(null, keyStorePIN);
096        }
097        catch (Exception e)
098        {
099          debugException(e);
100    
101          throw new KeyStoreException(
102               ERR_PKCS11_CANNOT_ACCESS.get(String.valueOf(e)), e);
103        }
104    
105        try
106        {
107          final KeyManagerFactory factory = KeyManagerFactory.getInstance(
108               KeyManagerFactory.getDefaultAlgorithm());
109          factory.init(ks, keyStorePIN);
110          return factory.getKeyManagers();
111        }
112        catch (Exception e)
113        {
114          debugException(e);
115    
116          throw new KeyStoreException(
117               ERR_PKCS11_CANNOT_GET_KEY_MANAGERS.get(String.valueOf(e)), e);
118        }
119      }
120    }