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