/*
 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.security.pkcs11;

import java.math.BigInteger;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;

import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Set;

import java.security.*;
import java.security.KeyStore.*;

import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateException;

import java.security.interfaces.*;
import java.security.spec.*;

import javax.crypto.SecretKey;
import javax.crypto.interfaces.*;

import javax.security.auth.x500.X500Principal;
import javax.security.auth.login.LoginException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import sun.security.util.Debug;
import sun.security.util.DerValue;
import sun.security.util.ECUtil;

import sun.security.ec.ECParameters;

import sun.security.pkcs11.Secmod.*;
import static sun.security.pkcs11.P11Util.*;

import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;

import sun.security.rsa.RSAKeyFactory;

final class P11KeyStore extends KeyStoreSpi {

    private static final CK_ATTRIBUTE ATTR_CLASS_CERT =
                        new CK_ATTRIBUTE(CKA_CLASS, CKO_CERTIFICATE);
    private static final CK_ATTRIBUTE ATTR_CLASS_PKEY =
                        new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY);
    private static final CK_ATTRIBUTE ATTR_CLASS_SKEY =
                        new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY);

    private static final CK_ATTRIBUTE ATTR_X509_CERT_TYPE =
                        new CK_ATTRIBUTE(CKA_CERTIFICATE_TYPE, CKC_X_509);

    private static final CK_ATTRIBUTE ATTR_TOKEN_TRUE =
                        new CK_ATTRIBUTE(CKA_TOKEN, true);

    // XXX for testing purposes only
    //  - NSS doesn't support persistent secret keys
    //    (key type gets mangled if secret key is a token key)
    //  - if debug is turned on, then this is set to false
    private static CK_ATTRIBUTE ATTR_SKEY_TOKEN_TRUE = ATTR_TOKEN_TRUE;

    private static final CK_ATTRIBUTE ATTR_TRUSTED_TRUE =
                        new CK_ATTRIBUTE(CKA_TRUSTED, true);
    private static final CK_ATTRIBUTE ATTR_PRIVATE_TRUE =
                        new CK_ATTRIBUTE(CKA_PRIVATE, true);

    private static final long NO_HANDLE = -1;
    private static final long FINDOBJECTS_MAX = 100;
    private static final String ALIAS_SEP = "/";

    private static final boolean NSS_TEST = false;
    private static final Debug debug =
                        Debug.getInstance("pkcs11keystore");
    private static boolean CKA_TRUSTED_SUPPORTED = true;

    private final Token token;

    // If multiple certs are found to share the same CKA_LABEL
    // at load time (NSS-style keystore), then the keystore is read
    // and the unique keystore aliases are mapped to the entries.
    // However, write capabilities are disabled.
    private boolean writeDisabled = false;

    // Map of unique keystore aliases to entries in the token
    private HashMap<String, AliasInfo> aliasMap;

    // whether to use NSS Secmod info for trust attributes
    private final boolean useSecmodTrust;

    // if useSecmodTrust == true, which type of trust we are interested in
    private Secmod.TrustType nssTrustType;

    /**
     * The underlying token may contain multiple certs belonging to the
     * same "personality" (for example, a signing cert and encryption cert),
     * all sharing the same CKA_LABEL.  These must be resolved
     * into unique keystore aliases.
     *
     * In addition, private keys and certs may not have a CKA_LABEL.
     * It is assumed that a private key and corresponding certificate
     * share the same CKA_ID, and that the CKA_ID is unique across the token.
     * The CKA_ID may not be human-readable.
     * These pairs must be resolved into unique keystore aliases.
     *
     * Furthermore, secret keys are assumed to have a CKA_LABEL
     * unique across the entire token.
     *
     * When the KeyStore is loaded, instances of this class are
     * created to represent the private keys/secret keys/certs
     * that reside on the token.
     */
    private static class AliasInfo {

        // CKA_CLASS - entry type
        private CK_ATTRIBUTE type = null;

        // CKA_LABEL of cert and secret key
        private String label = null;

        // CKA_ID of the private key/cert pair
        private byte[] id = null;

        // CKA_TRUSTED - true if cert is trusted
        private boolean trusted = false;

        // either end-entity cert or trusted cert depending on 'type'
        private X509Certificate cert = null;

        // chain
        private X509Certificate chain[] = null;

        // true if CKA_ID for private key and cert match up
        private boolean matched = false;

        // SecretKeyEntry
        public AliasInfo(String label) {
            this.type = ATTR_CLASS_SKEY;
            this.label = label;
        }

        // PrivateKeyEntry
        public AliasInfo(String label,
                        byte[] id,
                        boolean trusted,
                        X509Certificate cert) {
            this.type = ATTR_CLASS_PKEY;
            this.label = label;
            this.id = id;
            this.trusted = trusted;
            this.cert = cert;
        }

        public String toString() {
            StringBuilder sb = new StringBuilder();
            if (type == ATTR_CLASS_PKEY) {
                sb.append("\ttype=[private key]\n");
            } else if (type == ATTR_CLASS_SKEY) {
                sb.append("\ttype=[secret key]\n");
            } else if (type == ATTR_CLASS_CERT) {
                sb.append("\ttype=[trusted cert]\n");
            }
            sb.append("\tlabel=[" + label + "]\n");
            if (id == null) {
                sb.append("\tid=[null]\n");
            } else {
                sb.append("\tid=" + P11KeyStore.getID(id) + "\n");
            }
            sb.append("\ttrusted=[" + trusted + "]\n");
            sb.append("\tmatched=[" + matched + "]\n");
            if (cert == null) {
                sb.append("\tcert=[null]\n");
            } else {
                sb.append("\tcert=[\tsubject: " +
                        cert.getSubjectX500Principal() +
                        "\n\t\tissuer: " +
                        cert.getIssuerX500Principal() +
                        "\n\t\tserialNum: " +
                        cert.getSerialNumber().toString() +
                        "]");
            }
            return sb.toString();
        }
    }

    /**
     * callback handler for passing password to Provider.login method
     */
    private static class PasswordCallbackHandler implements CallbackHandler {

        private char[] password;

        private PasswordCallbackHandler(char[] password) {
            if (password != null) {
                this.password = password.clone();
            }
        }

        public void handle(Callback[] callbacks)
                throws IOException, UnsupportedCallbackException {
            if (!(callbacks[0] instanceof PasswordCallback)) {
                throw new UnsupportedCallbackException(callbacks[0]);
            }
            PasswordCallback pc = (PasswordCallback)callbacks[0];
            pc.setPassword(password);  // this clones the password if not null
        }

        protected void finalize() throws Throwable {
            if (password != null) {
                Arrays.fill(password, ' ');
            }
            super.finalize();
        }
    }

    /**
     * getTokenObject return value.
     *
     * if object is not found, type is set to null.
     * otherwise, type is set to the requested type.
     */
    private static class THandle {
        private final long handle;              // token object handle
        private final CK_ATTRIBUTE type;        // CKA_CLASS

        private THandle(long handle, CK_ATTRIBUTE type) {
            this.handle = handle;
            this.type = type;
        }
    }

    P11KeyStore(Token token) {
        this.token = token;
        this.useSecmodTrust = token.provider.nssUseSecmodTrust;
    }

    /**
     * Returns the key associated with the given alias.
     * The key must have been associated with
     * the alias by a call to <code>setKeyEntry</code>,
     * or by a call to <code>setEntry</code> with a
     * <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code>.
     *
     * @param alias the alias name
     * @param password the password, which must be <code>null</code>
     *
     * @return the requested key, or null if the given alias does not exist
     * or does not identify a key-related entry.
     *
     * @exception NoSuchAlgorithmException if the algorithm for recovering the
     * key cannot be found
     * @exception UnrecoverableKeyException if the key cannot be recovered
     */
    public synchronized Key engineGetKey(String alias, char[] password)
                throws NoSuchAlgorithmException, UnrecoverableKeyException {

        token.ensureValid();
        if (password != null && !token.config.getKeyStoreCompatibilityMode()) {
            throw new NoSuchAlgorithmException("password must be null");
        }

        AliasInfo aliasInfo = aliasMap.get(alias);
        if (aliasInfo == null || aliasInfo.type == ATTR_CLASS_CERT) {
            return null;
        }

        Session session = null;
        try {
            session = token.getOpSession();

            if (aliasInfo.type == ATTR_CLASS_PKEY) {
                THandle h = getTokenObject(session,
                                        aliasInfo.type,
                                        aliasInfo.id,
                                        null);
                if (h.type == ATTR_CLASS_PKEY) {
                    return loadPkey(session, h.handle);
                }
            } else {
                THandle h = getTokenObject(session,
                                        ATTR_CLASS_SKEY,
                                        null,
                                        alias);
                if (h.type == ATTR_CLASS_SKEY) {
                    return loadSkey(session, h.handle);
                }
            }

            // did not find anything
            return null;
        } catch (PKCS11Exception | KeyStoreException e) {
            throw new ProviderException(e);
        } finally {
            token.releaseSession(session);
        }
    }

    /**
     * Returns the certificate chain associated with the given alias.
     * The certificate chain must have been associated with the alias
     * by a call to <code>setKeyEntry</code>,
     * or by a call to <code>setEntry</code> with a
     * <code>PrivateKeyEntry</code>.
     *
     * @param alias the alias name
     *
     * @return the certificate chain (ordered with the user's certificate first
     * and the root certificate authority last), or null if the given alias
     * does not exist or does not contain a certificate chain
     */
    public synchronized Certificate[] engineGetCertificateChain(String alias) {

        token.ensureValid();

        AliasInfo aliasInfo = aliasMap.get(alias);
        if (aliasInfo == null || aliasInfo.type != ATTR_CLASS_PKEY) {
            return null;
        }
        return aliasInfo.chain;
    }

    /**
     * Returns the certificate associated with the given alias.
     *
     * <p> If the given alias name identifies an entry
     * created by a call to <code>setCertificateEntry</code>,
     * or created by a call to <code>setEntry</code> with a
     * <code>TrustedCertificateEntry</code>,
     * then the trusted certificate contained in that entry is returned.
     *
     * <p> If the given alias name identifies an entry
     * created by a call to <code>setKeyEntry</code>,
     * or created by a call to <code>setEntry</code> with a
     * <code>PrivateKeyEntry</code>,
     * then the first element of the certificate chain in that entry
     * (if a chain exists) is returned.
     *
     * @param alias the alias name
     *
     * @return the certificate, or null if the given alias does not exist or
     * does not contain a certificate.
     */
    public synchronized Certificate engineGetCertificate(String alias) {
        token.ensureValid();

        AliasInfo aliasInfo = aliasMap.get(alias);
        if (aliasInfo == null) {
            return null;
        }
        return aliasInfo.cert;
    }

    /**
     * Returns the creation date of the entry identified by the given alias.
     *
     * @param alias the alias name
     *
     * @return the creation date of this entry, or null if the given alias does
     * not exist
     */
    public Date engineGetCreationDate(String alias) {
        token.ensureValid();
        throw new ProviderException(new UnsupportedOperationException());
    }

    /**
     * Assigns the given key to the given alias, protecting it with the given
     * password.
     *
     * <p>If the given key is of type <code>java.security.PrivateKey</code>,
     * it must be accompanied by a certificate chain certifying the
     * corresponding public key.
     *
     * <p>If the given alias already exists, the keystore information
     * associated with it is overridden by the given key (and possibly
     * certificate chain).
     *
     * @param alias the alias name
     * @param key the key to be associated with the alias
     * @param password the password to protect the key
     * @param chain the certificate chain for the corresponding public
     * key (only required if the given key is of type
     * <code>java.security.PrivateKey</code>).
     *
     * @exception KeyStoreException if the given key cannot be protected, or
     * this operation fails for some other reason
     */
    public synchronized void engineSetKeyEntry(String alias, Key key,
                                   char[] password,
                                   Certificate[] chain)
                throws KeyStoreException {

        token.ensureValid();
        checkWrite();

        if (!(key instanceof PrivateKey) && !(key instanceof SecretKey)) {
            throw new KeyStoreException("key must be PrivateKey or SecretKey");
        } else if (key instanceof PrivateKey && chain == null) {
            throw new KeyStoreException
                ("PrivateKey must be accompanied by non-null chain");
        } else if (key instanceof SecretKey && chain != null) {
            throw new KeyStoreException
                ("SecretKey must be accompanied by null chain");
        } else if (password != null &&
                    !token.config.getKeyStoreCompatibilityMode()) {
            throw new KeyStoreException("Password must be null");
        }

        KeyStore.Entry entry = null;
        try {
            if (key instanceof PrivateKey) {
                entry = new KeyStore.PrivateKeyEntry((PrivateKey)key, chain);
            } else if (key instanceof SecretKey) {
                entry = new KeyStore.SecretKeyEntry((SecretKey)key);
            }
        } catch (NullPointerException | IllegalArgumentException e) {
            throw new KeyStoreException(e);
        }
        engineSetEntry(alias, entry, new KeyStore.PasswordProtection(password));
    }

    /**
     * Assigns the given key (that has already been protected) to the given
     * alias.
     *
     * <p>If the protected key is of type
     * <code>java.security.PrivateKey</code>,
     * it must be accompanied by a certificate chain certifying the
     * corresponding public key.
     *
     * <p>If the given alias already exists, the keystore information
     * associated with it is overridden by the given key (and possibly
     * certificate chain).
     *
     * @param alias the alias name
     * @param key the key (in protected format) to be associated with the alias
     * @param chain the certificate chain for the corresponding public
     * key (only useful if the protected key is of type
     * <code>java.security.PrivateKey</code>).
     *
     * @exception KeyStoreException if this operation fails.
     */
    public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain)
                throws KeyStoreException {
        token.ensureValid();
        throw new ProviderException(new UnsupportedOperationException());
    }

    /**
     * Assigns the given certificate to the given alias.
     *
     * <p> If the given alias identifies an existing entry
     * created by a call to <code>setCertificateEntry</code>,
     * or created by a call to <code>setEntry</code> with a
     * <code>TrustedCertificateEntry</code>,
     * the trusted certificate in the existing entry
     * is overridden by the given certificate.
     *
     * @param alias the alias name
     * @param cert the certificate
     *
     * @exception KeyStoreException if the given alias already exists and does
     * not identify an entry containing a trusted certificate,
     * or this operation fails for some other reason.
     */
    public synchronized void engineSetCertificateEntry
        (String alias, Certificate cert) throws KeyStoreException {

        token.ensureValid();
        checkWrite();

        if (cert == null) {
            throw new KeyStoreException("invalid null certificate");
        }

        KeyStore.Entry entry = null;
        entry = new KeyStore.TrustedCertificateEntry(cert);
        engineSetEntry(alias, entry, null);
    }

    /**
     * Deletes the entry identified by the given alias from this keystore.
     *
     * @param alias the alias name
     *
     * @exception KeyStoreException if the entry cannot be removed.
     */
    public synchronized void engineDeleteEntry(String alias)
                throws KeyStoreException {
        token.ensureValid();

        if (token.isWriteProtected()) {
            throw new KeyStoreException("token write-protected");
        }
        checkWrite();
        deleteEntry(alias);
    }

    /**
     * XXX - not sure whether to keep this
     */
    private boolean deleteEntry(String alias) throws KeyStoreException {
        AliasInfo aliasInfo = aliasMap.get(alias);
        if (aliasInfo != null) {

            aliasMap.remove(alias);

            try {
                if (aliasInfo.type == ATTR_CLASS_CERT) {
                    // trusted certificate entry
                    return destroyCert(aliasInfo.id);
                } else if (aliasInfo.type == ATTR_CLASS_PKEY) {
                    // private key entry
                    return destroyPkey(aliasInfo.id) &&
                                destroyChain(aliasInfo.id);
                } else if (aliasInfo.type == ATTR_CLASS_SKEY) {
                    // secret key entry
                    return destroySkey(alias);
                } else {
                    throw new KeyStoreException("unexpected entry type");
                }
            } catch (PKCS11Exception | CertificateException e) {
                throw new KeyStoreException(e);
            }
        }
        return false;
    }

    /**
     * Lists all the alias names of this keystore.
     *
     * @return enumeration of the alias names
     */
    public synchronized Enumeration<String> engineAliases() {
        token.ensureValid();

        // don't want returned enumeration to iterate off actual keySet -
        // otherwise applications that iterate and modify the keystore
        // may run into concurrent modification problems
        return Collections.enumeration(new HashSet<String>(aliasMap.keySet()));
    }

    /**
     * Checks if the given alias exists in this keystore.
     *
     * @param alias the alias name
     *
     * @return true if the alias exists, false otherwise
     */
    public synchronized boolean engineContainsAlias(String alias) {
        token.ensureValid();
        return aliasMap.containsKey(alias);
    }

    /**
     * Retrieves the number of entries in this keystore.
     *
     * @return the number of entries in this keystore
     */
    public synchronized int engineSize() {
        token.ensureValid();
        return aliasMap.size();
    }

    /**
     * Returns true if the entry identified by the given alias
     * was created by a call to <code>setKeyEntry</code>,
     * or created by a call to <code>setEntry</code> with a
     * <code>PrivateKeyEntry</code> or a <code>SecretKeyEntry</code>.
     *
     * @param alias the alias for the keystore entry to be checked
     *
     * @return true if the entry identified by the given alias is a
     * key-related, false otherwise.
     */
    public synchronized boolean engineIsKeyEntry(String alias) {
        token.ensureValid();

        AliasInfo aliasInfo = aliasMap.get(alias);
        if (aliasInfo == null || aliasInfo.type == ATTR_CLASS_CERT) {
            return false;
        }
        return true;
    }

    /**
     * Returns true if the entry identified by the given alias
     * was created by a call to <code>setCertificateEntry</code>,
     * or created by a call to <code>setEntry</code> with a
     * <code>TrustedCertificateEntry</code>.
     *
     * @param alias the alias for the keystore entry to be checked
     *
     * @return true if the entry identified by the given alias contains a
     * trusted certificate, false otherwise.
     */
    public synchronized boolean engineIsCertificateEntry(String alias) {
        token.ensureValid();

        AliasInfo aliasInfo = aliasMap.get(alias);
        if (aliasInfo == null || aliasInfo.type != ATTR_CLASS_CERT) {
            return false;
        }
        return true;
    }

    /**
     * Returns the (alias) name of the first keystore entry whose certificate
     * matches the given certificate.
     *
     * <p>This method attempts to match the given certificate with each
     * keystore entry. If the entry being considered was
     * created by a call to <code>setCertificateEntry</code>,
     * or created by a call to <code>setEntry</code> with a
     * <code>TrustedCertificateEntry</code>,
     * then the given certificate is compared to that entry's certificate.
     *
     * <p> If the entry being considered was
     * created by a call to <code>setKeyEntry</code>,
     * or created by a call to <code>setEntry</code> with a
     * <code>PrivateKeyEntry</code>,
     * then the given certificate is compared to the first
     * element of that entry's certificate chain.
     *
     * @param cert the certificate to match with.
     *
     * @return the alias name of the first entry with matching certificate,
     * or null if no such entry exists in this keystore.
     */
    public synchronized String engineGetCertificateAlias(Certificate cert) {
        token.ensureValid();
        Enumeration<String> e = engineAliases();
        while (e.hasMoreElements()) {
            String alias = e.nextElement();
            Certificate tokenCert = engineGetCertificate(alias);
            if (tokenCert != null && tokenCert.equals(cert)) {
                return alias;
            }
        }
        return null;
    }

    /**
     * engineStore currently is a No-op.
     * Entries are stored to the token during engineSetEntry
     *
     * @param stream this must be <code>null</code>
     * @param password this must be <code>null</code>
     */
    public synchronized void engineStore(OutputStream stream, char[] password)
        throws IOException, NoSuchAlgorithmException, CertificateException {
        token.ensureValid();
        if (stream != null && !token.config.getKeyStoreCompatibilityMode()) {
            throw new IOException("output stream must be null");
        }

        if (password != null && !token.config.getKeyStoreCompatibilityMode()) {
            throw new IOException("password must be null");
        }
    }

    /**
     * engineStore currently is a No-op.
     * Entries are stored to the token during engineSetEntry
     *
     * @param param this must be <code>null</code>
     *
     * @exception IllegalArgumentException if the given
     *          <code>KeyStore.LoadStoreParameter</code>
     *          input is not <code>null</code>
     */
    public synchronized void engineStore(KeyStore.LoadStoreParameter param)
        throws IOException, NoSuchAlgorithmException, CertificateException {
        token.ensureValid();
        if (param != null) {
            throw new IllegalArgumentException
                ("LoadStoreParameter must be null");
        }
    }

    /**
     * Loads the keystore.
     *
     * @param stream the input stream, which must be <code>null</code>
     * @param password the password used to unlock the keystore,
     *          or <code>null</code> if the token supports a
     *          CKF_PROTECTED_AUTHENTICATION_PATH
     *
     * @exception IOException if the given <code>stream</code> is not
     *          <code>null</code>, if the token supports a
     *          CKF_PROTECTED_AUTHENTICATION_PATH and a non-null
     *          password is given, of if the token login operation failed
     */
    public synchronized void engineLoad(InputStream stream, char[] password)
        throws IOException, NoSuchAlgorithmException, CertificateException {

        token.ensureValid();

        if (NSS_TEST) {
            ATTR_SKEY_TOKEN_TRUE = new CK_ATTRIBUTE(CKA_TOKEN, false);
        }

        if (stream != null && !token.config.getKeyStoreCompatibilityMode()) {
            throw new IOException("input stream must be null");
        }

        if (useSecmodTrust) {
            nssTrustType = Secmod.TrustType.ALL;
        }

        try {
            if (password == null) {
                login(null);
            } else {
                login(new PasswordCallbackHandler(password));
            }
            if (mapLabels() == true) {
                // CKA_LABELs are shared by multiple certs
                writeDisabled = true;
            }
            if (debug != null) {
                dumpTokenMap();
            }
        } catch (LoginException | KeyStoreException | PKCS11Exception e) {
            throw new IOException("load failed", e);
        }
    }

    /**
     * Loads the keystore using the given
     * <code>KeyStore.LoadStoreParameter</code>.
     *
     * <p> The <code>LoadStoreParameter.getProtectionParameter()</code>
     * method is expected to return a <code>KeyStore.PasswordProtection</code>
     * object.  The password is retrieved from that object and used
     * to unlock the PKCS#11 token.
     *
     * <p> If the token supports a CKF_PROTECTED_AUTHENTICATION_PATH
     * then the provided password must be <code>null</code>.
     *
     * @param param the <code>KeyStore.LoadStoreParameter</code>
     *
     * @exception IllegalArgumentException if the given
     *          <code>KeyStore.LoadStoreParameter</code> is <code>null</code>,
     *          or if that parameter returns a <code>null</code>
     *          <code>ProtectionParameter</code> object.
     *          input is not recognized
     * @exception IOException if the token supports a
     *          CKF_PROTECTED_AUTHENTICATION_PATH and the provided password
     *          is non-null, or if the token login operation fails
     */
    public synchronized void engineLoad(KeyStore.LoadStoreParameter param)
                throws IOException, NoSuchAlgorithmException,
                CertificateException {

        token.ensureValid();

        if (NSS_TEST) {
            ATTR_SKEY_TOKEN_TRUE = new CK_ATTRIBUTE(CKA_TOKEN, false);
        }

        // if caller wants to pass a NULL password,
        // force it to pass a non-NULL PasswordProtection that returns
        // a NULL password

        if (param == null) {
            throw new IllegalArgumentException
                        ("invalid null LoadStoreParameter");
        }
        if (useSecmodTrust) {
            if (param instanceof Secmod.KeyStoreLoadParameter) {
                nssTrustType = ((Secmod.KeyStoreLoadParameter)param).getTrustType();
            } else {
                nssTrustType = Secmod.TrustType.ALL;
            }
        }

        CallbackHandler handler;
        KeyStore.ProtectionParameter pp = param.getProtectionParameter();
        if (pp instanceof PasswordProtection) {
            char[] password = ((PasswordProtection)pp).getPassword();
            if (password == null) {
                handler = null;
            } else {
                handler = new PasswordCallbackHandler(password);
            }
        } else if (pp instanceof CallbackHandlerProtection) {
            handler = ((CallbackHandlerProtection)pp).getCallbackHandler();
        } else {
            throw new IllegalArgumentException
                        ("ProtectionParameter must be either " +
                        "PasswordProtection or CallbackHandlerProtection");
        }

        try {
            login(handler);
            if (mapLabels() == true) {
                // CKA_LABELs are shared by multiple certs
                writeDisabled = true;
            }
            if (debug != null) {
                dumpTokenMap();
            }
        } catch (LoginException | KeyStoreException | PKCS11Exception e) {
            throw new IOException("load failed", e);
        }
    }

    private void login(CallbackHandler handler) throws LoginException {
        if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {
            token.provider.login(null, handler);
        } else {
            // token supports protected authentication path
            // (external pin-pad, for example)
            if (handler != null &&
                !token.config.getKeyStoreCompatibilityMode()) {
                throw new LoginException("can not specify password if token " +
                                "supports protected authentication path");
            }

            // must rely on application-set or default handler
            // if one is necessary
            token.provider.login(null, null);
        }
    }

    /**
     * Get a <code>KeyStore.Entry</code> for the specified alias
     *
     * @param alias get the <code>KeyStore.Entry</code> for this alias
     * @param protParam this must be <code>null</code>
     *
     * @return the <code>KeyStore.Entry</code> for the specified alias,
     *          or <code>null</code> if there is no such entry
     *
     * @exception KeyStoreException if the operation failed
     * @exception NoSuchAlgorithmException if the algorithm for recovering the
     *          entry cannot be found
     * @exception UnrecoverableEntryException if the specified
     *          <code>protParam</code> were insufficient or invalid
     *
     * @since 1.5
     */
    public synchronized KeyStore.Entry engineGetEntry(String alias,
                        KeyStore.ProtectionParameter protParam)
                throws KeyStoreException, NoSuchAlgorithmException,
                UnrecoverableEntryException {

        token.ensureValid();

        if (protParam != null &&
            protParam instanceof KeyStore.PasswordProtection &&
            ((KeyStore.PasswordProtection)protParam).getPassword() != null &&
            !token.config.getKeyStoreCompatibilityMode()) {
            throw new KeyStoreException("ProtectionParameter must be null");
        }

        AliasInfo aliasInfo = aliasMap.get(alias);
        if (aliasInfo == null) {
            if (debug != null) {
                debug.println("engineGetEntry did not find alias [" +
                        alias +
                        "] in map");
            }
            return null;
        }

        Session session = null;
        try {
            session = token.getOpSession();

            if (aliasInfo.type == ATTR_CLASS_CERT) {
                // trusted certificate entry
                if (debug != null) {
                    debug.println("engineGetEntry found trusted cert entry");
                }
                return new KeyStore.TrustedCertificateEntry(aliasInfo.cert);
            } else if (aliasInfo.type == ATTR_CLASS_SKEY) {
                // secret key entry
                if (debug != null) {
                    debug.println("engineGetEntry found secret key entry");
                }

                THandle h = getTokenObject
                        (session, ATTR_CLASS_SKEY, null, aliasInfo.label);
                if (h.type != ATTR_CLASS_SKEY) {
                    throw new KeyStoreException
                        ("expected but could not find secret key");
                } else {
                    SecretKey skey = loadSkey(session, h.handle);
                    return new KeyStore.SecretKeyEntry(skey);
                }
            } else {
                // private key entry
                if (debug != null) {
                    debug.println("engineGetEntry found private key entry");
                }

                THandle h = getTokenObject
                        (session, ATTR_CLASS_PKEY, aliasInfo.id, null);
                if (h.type != ATTR_CLASS_PKEY) {
                    throw new KeyStoreException
                        ("expected but could not find private key");
                } else {
                    PrivateKey pkey = loadPkey(session, h.handle);
                    Certificate[] chain = aliasInfo.chain;
                    if ((pkey != null) && (chain != null)) {
                        return new KeyStore.PrivateKeyEntry(pkey, chain);
                    } else {
                        if (debug != null) {
                            debug.println
                                ("engineGetEntry got null cert chain or private key");
                        }
                    }
                }
            }
            return null;
        } catch (PKCS11Exception pe) {
            throw new KeyStoreException(pe);
        } finally {
            token.releaseSession(session);
        }
    }

    /**
     * Save a <code>KeyStore.Entry</code> under the specified alias.
     *
     * <p> If an entry already exists for the specified alias,
     * it is overridden.
     *
     * <p> This KeyStore implementation only supports the standard
     * entry types, and only supports X509Certificates in
     * TrustedCertificateEntries.  Also, this implementation does not support
     * protecting entries using a different password
     * from the one used for token login.
     *
     * <p> Entries are immediately stored on the token.
     *
     * @param alias save the <code>KeyStore.Entry</code> under this alias
     * @param entry the <code>Entry</code> to save
     * @param protParam this must be <code>null</code>
     *
     * @exception KeyStoreException if this operation fails
     *
     * @since 1.5
     */
    public synchronized void engineSetEntry(String alias, KeyStore.Entry entry,
                        KeyStore.ProtectionParameter protParam)
                throws KeyStoreException {

        token.ensureValid();
        checkWrite();

        if (protParam != null &&
            protParam instanceof KeyStore.PasswordProtection &&
            ((KeyStore.PasswordProtection)protParam).getPassword() != null &&
            !token.config.getKeyStoreCompatibilityMode()) {
            throw new KeyStoreException(new UnsupportedOperationException
                                ("ProtectionParameter must be null"));
        }

        if (token.isWriteProtected()) {
            throw new KeyStoreException("token write-protected");
        }

        if (entry instanceof KeyStore.TrustedCertificateEntry) {

            if (useSecmodTrust == false) {
                // PKCS #11 does not allow app to modify trusted certs -
                throw new KeyStoreException(new UnsupportedOperationException
                                    ("trusted certificates may only be set by " +
                                    "token initialization application"));
            }
            Module module = token.provider.nssModule;
            if ((module.type != ModuleType.KEYSTORE) && (module.type != ModuleType.FIPS)) {
                // XXX allow TRUSTANCHOR module
                throw new KeyStoreException("Trusted certificates can only be "
                    + "added to the NSS KeyStore module");
            }
            Certificate cert = ((TrustedCertificateEntry)entry).getTrustedCertificate();
            if (cert instanceof X509Certificate == false) {
                throw new KeyStoreException("Certificate must be an X509Certificate");
            }
            X509Certificate xcert = (X509Certificate)cert;
            AliasInfo info = aliasMap.get(alias);
            if (info != null) {
                // XXX try to update
                deleteEntry(alias);
            }
            try {
                storeCert(alias, xcert);
                module.setTrust(token, xcert);
                mapLabels();
            } catch (PKCS11Exception | CertificateException e) {
                throw new KeyStoreException(e);
            }

        } else {

            if (entry instanceof KeyStore.PrivateKeyEntry) {

                PrivateKey key =
                        ((KeyStore.PrivateKeyEntry)entry).getPrivateKey();
                if (!(key instanceof P11Key) &&
                    !(key instanceof RSAPrivateKey) &&
                    !(key instanceof DSAPrivateKey) &&
                    !(key instanceof DHPrivateKey) &&
                    !(key instanceof ECPrivateKey)) {
                    throw new KeyStoreException("unsupported key type: " +
                                                key.getClass().getName());
                }

                // only support X509Certificate chains
                Certificate[] chain =
                    ((KeyStore.PrivateKeyEntry)entry).getCertificateChain();
                if (!(chain instanceof X509Certificate[])) {
                    throw new KeyStoreException
                        (new UnsupportedOperationException
                                ("unsupported certificate array type: " +
                                chain.getClass().getName()));
                }

                try {
                    boolean updatedAlias = false;
                    Set<String> aliases = aliasMap.keySet();
                    for (String oldAlias : aliases) {

                        // see if there's an existing entry with the same info

                        AliasInfo aliasInfo = aliasMap.get(oldAlias);
                        if (aliasInfo.type == ATTR_CLASS_PKEY &&
                            aliasInfo.cert.getPublicKey().equals
                                        (chain[0].getPublicKey())) {

                            // found existing entry -
                            // caller is renaming entry or updating cert chain
                            //
                            // set new CKA_LABEL/CKA_ID
                            // and update certs if necessary

                            updatePkey(alias,
                                        aliasInfo.id,
                                        (X509Certificate[])chain,
                                        !aliasInfo.cert.equals(chain[0]));
                            updatedAlias = true;
                            break;
                        }
                    }

                    if (!updatedAlias) {
                        // caller adding new entry
                        engineDeleteEntry(alias);
                        storePkey(alias, (KeyStore.PrivateKeyEntry)entry);
                    }

                } catch (PKCS11Exception | CertificateException pe) {
                    throw new KeyStoreException(pe);
                }

            } else if (entry instanceof KeyStore.SecretKeyEntry) {

                KeyStore.SecretKeyEntry ske = (KeyStore.SecretKeyEntry)entry;
                SecretKey skey = ske.getSecretKey();

                try {
                    // first check if the key already exists
                    AliasInfo aliasInfo = aliasMap.get(alias);

                    if (aliasInfo != null) {
                        engineDeleteEntry(alias);
                    }
                    storeSkey(alias, ske);

                } catch (PKCS11Exception pe) {
                    throw new KeyStoreException(pe);
                }

            } else {
                throw new KeyStoreException(new UnsupportedOperationException
                    ("unsupported entry type: " + entry.getClass().getName()));
            }

            try {

                // XXX  NSS does not write out the CKA_ID we pass to them
                //
                // therefore we must re-map labels
                // (can not simply update aliasMap)

                mapLabels();
                if (debug != null) {
                    dumpTokenMap();
                }
            } catch (PKCS11Exception | CertificateException pe) {
                throw new KeyStoreException(pe);
            }
        }

        if (debug != null) {
            debug.println
                ("engineSetEntry added new entry for [" +
                alias +
                "] to token");
        }
    }

    /**
     * Determines if the keystore <code>Entry</code> for the specified
     * <code>alias</code> is an instance or subclass of the specified
     * <code>entryClass</code>.
     *
     * @param alias the alias name
     * @param entryClass the entry class
     *
     * @return true if the keystore <code>Entry</code> for the specified
     *          <code>alias</code> is an instance or subclass of the
     *          specified <code>entryClass</code>, false otherwise
     */
    public synchronized boolean engineEntryInstanceOf
                (String alias, Class<? extends KeyStore.Entry> entryClass) {
        token.ensureValid();
        return super.engineEntryInstanceOf(alias, entryClass);
    }

    private X509Certificate loadCert(Session session, long oHandle)
                throws PKCS11Exception, CertificateException {

        CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[]
                        { new CK_ATTRIBUTE(CKA_VALUE) };
        token.p11.C_GetAttributeValue(session.id(), oHandle, attrs);

        byte[] bytes = attrs[0].getByteArray();
        if (bytes == null) {
            throw new CertificateException
                        ("unexpectedly retrieved null byte array");
        }
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        return (X509Certificate)cf.generateCertificate
                        (new ByteArrayInputStream(bytes));
    }

    private X509Certificate[] loadChain(Session session,
                                        X509Certificate endCert)
                throws PKCS11Exception, CertificateException {

        ArrayList<X509Certificate> lChain = null;

        if (endCert.getSubjectX500Principal().equals
            (endCert.getIssuerX500Principal())) {
            // self signed
            return new X509Certificate[] { endCert };
        } else {
            lChain = new ArrayList<X509Certificate>();
            lChain.add(endCert);
        }

        // try loading remaining certs in chain by following
        // issuer->subject links

        X509Certificate next = endCert;
        while (true) {
            CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
                        ATTR_TOKEN_TRUE,
                        ATTR_CLASS_CERT,
                        new CK_ATTRIBUTE(CKA_SUBJECT,
                                next.getIssuerX500Principal().getEncoded()) };
            long[] ch = findObjects(session, attrs);

            if (ch == null || ch.length == 0) {
                // done
                break;
            } else {
                // if more than one found, use first
                if (debug != null && ch.length > 1) {
                    debug.println("engineGetEntry found " +
                                ch.length +
                                " certificate entries for subject [" +
                                next.getIssuerX500Principal().toString() +
                                "] in token - using first entry");
                }

                next = loadCert(session, ch[0]);
                lChain.add(next);
                if (next.getSubjectX500Principal().equals
                    (next.getIssuerX500Principal())) {
                    // self signed
                    break;
                }
            }
        }

        return lChain.toArray(new X509Certificate[lChain.size()]);
    }

    private SecretKey loadSkey(Session session, long oHandle)
                throws PKCS11Exception {

        CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
                        new CK_ATTRIBUTE(CKA_KEY_TYPE) };
        token.p11.C_GetAttributeValue(session.id(), oHandle, attrs);
        long kType = attrs[0].getLong();

        String keyType = null;
        int keyLength = -1;

        // XXX NSS mangles the stored key type for secret key token objects

        if (kType == CKK_DES || kType == CKK_DES3) {
            if (kType == CKK_DES) {
                keyType = "DES";
                keyLength = 64;
            } else if (kType == CKK_DES3) {
                keyType = "DESede";
                keyLength = 192;
            }
        } else {
            if (kType == CKK_AES) {
                keyType = "AES";
            } else if (kType == CKK_BLOWFISH) {
                keyType = "Blowfish";
            } else if (kType == CKK_RC4) {
                keyType = "ARCFOUR";
            } else {
                if (debug != null) {
                    debug.println("unknown key type [" +
                                kType +
                                "] - using 'Generic Secret'");
                }
                keyType = "Generic Secret";
            }

            // XXX NSS problem CKR_ATTRIBUTE_TYPE_INVALID?
            if (NSS_TEST) {
                keyLength = 128;
            } else {
                attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_VALUE_LEN) };
                token.p11.C_GetAttributeValue(session.id(), oHandle, attrs);
                keyLength = (int)attrs[0].getLong();
            }
        }

        return P11Key.secretKey(session, oHandle, keyType, keyLength, null);
    }

    private PrivateKey loadPkey(Session session, long oHandle)
        throws PKCS11Exception, KeyStoreException {

        CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
                        new CK_ATTRIBUTE(CKA_KEY_TYPE) };
        token.p11.C_GetAttributeValue(session.id(), oHandle, attrs);
        long kType = attrs[0].getLong();
        String keyType = null;
        int keyLength = 0;

        if (kType == CKK_RSA) {

            keyType = "RSA";

            attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_MODULUS) };
            token.p11.C_GetAttributeValue(session.id(), oHandle, attrs);
            BigInteger modulus = attrs[0].getBigInteger();
            keyLength = modulus.bitLength();

            // This check will combine our "don't care" values here
            // with the system-wide min/max values.
            try {
                RSAKeyFactory.checkKeyLengths(keyLength, null,
                    -1, Integer.MAX_VALUE);
            } catch (InvalidKeyException e) {
                throw new KeyStoreException(e.getMessage());
            }

            return P11Key.privateKey(session,
                                oHandle,
                                keyType,
                                keyLength,
                                null);

        } else if (kType == CKK_DSA) {

            keyType = "DSA";

            attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_PRIME) };
            token.p11.C_GetAttributeValue(session.id(), oHandle, attrs);
            BigInteger prime = attrs[0].getBigInteger();
            keyLength = prime.bitLength();

            return P11Key.privateKey(session,
                                oHandle,
                                keyType,
                                keyLength,
                                null);

        } else if (kType == CKK_DH) {

            keyType = "DH";

            attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_PRIME) };
            token.p11.C_GetAttributeValue(session.id(), oHandle, attrs);
            BigInteger prime = attrs[0].getBigInteger();
            keyLength = prime.bitLength();

            return P11Key.privateKey(session,
                                oHandle,
                                keyType,
                                keyLength,
                                null);

        } else if (kType == CKK_EC) {

            attrs = new CK_ATTRIBUTE[] {
                new CK_ATTRIBUTE(CKA_EC_PARAMS),
            };
            token.p11.C_GetAttributeValue(session.id(), oHandle, attrs);
            byte[] encodedParams = attrs[0].getByteArray();
            try {
                ECParameterSpec params =
                    ECUtil.getECParameterSpec(null, encodedParams);
                keyLength = params.getCurve().getField().getFieldSize();
            } catch (IOException e) {
                // we do not want to accept key with unsupported parameters
                throw new KeyStoreException("Unsupported parameters", e);
            }

            return P11Key.privateKey(session, oHandle, "EC", keyLength, null);

        } else {
            if (debug != null) {
                debug.println("unknown key type [" + kType + "]");
            }
            throw new KeyStoreException("unknown key type");
        }
    }


    /**
     * XXX  On ibutton, when you C_SetAttribute(CKA_ID) for a private key
     *      it not only changes the CKA_ID of the private key,
     *      it changes the CKA_ID of the corresponding cert too.
     *      And vice versa.
     *
     * XXX  On ibutton, CKR_DEVICE_ERROR if you C_SetAttribute(CKA_ID)
     *      for a private key, and then try to delete the corresponding cert.
     *      So this code reverses the order.
     *      After the cert is first destroyed (if necessary),
     *      then the CKA_ID of the private key can be changed successfully.
     *
     * @param replaceCert if true, then caller is updating alias info for
     *                  existing cert (only update CKA_ID/CKA_LABEL).
     *                  if false, then caller is updating cert chain
     *                  (delete old end cert and add new chain).
     */
    private void updatePkey(String alias,
                        byte[] cka_id,
                        X509Certificate[] chain,
                        boolean replaceCert) throws
                KeyStoreException, CertificateException, PKCS11Exception {

        // XXX
        //
        // always set replaceCert to true
        //
        // NSS does not allow resetting of CKA_LABEL on an existing cert
        // (C_SetAttribute call succeeds, but is ignored)

        replaceCert = true;

        Session session = null;
        try {
            session = token.getOpSession();

            // first get private key object handle and hang onto it

            THandle h = getTokenObject(session, ATTR_CLASS_PKEY, cka_id, null);
            long pKeyHandle;
            if (h.type == ATTR_CLASS_PKEY) {
                pKeyHandle = h.handle;
            } else {
                throw new KeyStoreException
                        ("expected but could not find private key " +
                        "with CKA_ID " +
                        getID(cka_id));
            }

            // next find existing end entity cert

            h = getTokenObject(session, ATTR_CLASS_CERT, cka_id, null);
            if (h.type != ATTR_CLASS_CERT) {
                throw new KeyStoreException
                        ("expected but could not find certificate " +
                        "with CKA_ID " +
                        getID(cka_id));
            } else {
                if (replaceCert) {
                    // replacing existing cert and chain
                    destroyChain(cka_id);
                } else {
                    // renaming alias for existing cert
                    CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
                        new CK_ATTRIBUTE(CKA_LABEL, alias),
                        new CK_ATTRIBUTE(CKA_ID, alias) };
                    token.p11.C_SetAttributeValue
                        (session.id(), h.handle, attrs);
                }
            }

            // add new chain

            if (replaceCert) {
                // add all certs in chain
                storeChain(alias, chain);
            } else {
                // already updated alias info for existing end cert -
                // just update CA certs
                storeCaCerts(chain, 1);
            }

            // finally update CKA_ID for private key
            //
            // ibutton may have already done this (that is ok)

            CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
                                new CK_ATTRIBUTE(CKA_ID, alias) };
            token.p11.C_SetAttributeValue(session.id(), pKeyHandle, attrs);

            if (debug != null) {
                debug.println("updatePkey set new alias [" +
                                alias +
                                "] for private key entry");
            }
        } finally {
            token.releaseSession(session);
        }
    }

    private void updateP11Pkey(String alias, CK_ATTRIBUTE attribute, P11Key key)
                throws PKCS11Exception {

        // if token key, update alias.
        // if session key, convert to token key.

        Session session = null;
        try {
            session = token.getOpSession();
            if (key.tokenObject == true) {

                // token key - set new CKA_ID

                CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
                                new CK_ATTRIBUTE(CKA_ID, alias) };
                token.p11.C_SetAttributeValue
                                (session.id(), key.keyID, attrs);
                if (debug != null) {
                    debug.println("updateP11Pkey set new alias [" +
                                alias +
                                "] for key entry");
                }
            } else {

                // session key - convert to token key and set CKA_ID

                CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
                    ATTR_TOKEN_TRUE,
                    new CK_ATTRIBUTE(CKA_ID, alias),
                };
                if (attribute != null) {
                    attrs = addAttribute(attrs, attribute);
                }
                token.p11.C_CopyObject(session.id(), key.keyID, attrs);
                if (debug != null) {
                    debug.println("updateP11Pkey copied private session key " +
                                "for [" +
                                alias +
                                "] to token entry");
                }
            }
        } finally {
            token.releaseSession(session);
        }
    }

    private void storeCert(String alias, X509Certificate cert)
                throws PKCS11Exception, CertificateException {

        ArrayList<CK_ATTRIBUTE> attrList = new ArrayList<CK_ATTRIBUTE>();
        attrList.add(ATTR_TOKEN_TRUE);
        attrList.add(ATTR_CLASS_CERT);
        attrList.add(ATTR_X509_CERT_TYPE);
        attrList.add(new CK_ATTRIBUTE(CKA_SUBJECT,
                                cert.getSubjectX500Principal().getEncoded()));
        attrList.add(new CK_ATTRIBUTE(CKA_ISSUER,
                                cert.getIssuerX500Principal().getEncoded()));
        attrList.add(new CK_ATTRIBUTE(CKA_SERIAL_NUMBER,
                                cert.getSerialNumber().toByteArray()));
        attrList.add(new CK_ATTRIBUTE(CKA_VALUE, cert.getEncoded()));

        if (alias != null) {
            attrList.add(new CK_ATTRIBUTE(CKA_LABEL, alias));
            attrList.add(new CK_ATTRIBUTE(CKA_ID, alias));
        } else {
            // ibutton requires something to be set
            // - alias must be unique
            attrList.add(new CK_ATTRIBUTE(CKA_ID,
                        getID(cert.getSubjectX500Principal().getName
                                        (X500Principal.CANONICAL), cert)));
        }

        Session session = null;
        try {
            session = token.getOpSession();
            token.p11.C_CreateObject(session.id(),
                        attrList.toArray(new CK_ATTRIBUTE[attrList.size()]));
        } finally {
            token.releaseSession(session);
        }
    }

    private void storeChain(String alias, X509Certificate[] chain)
                throws PKCS11Exception, CertificateException {

        // add new chain
        //
        // end cert has CKA_LABEL and CKA_ID set to alias.
        // other certs in chain have neither set.

        storeCert(alias, chain[0]);
        storeCaCerts(chain, 1);
    }

    private void storeCaCerts(X509Certificate[] chain, int start)
                throws PKCS11Exception, CertificateException {

        // do not add duplicate CA cert if already in token
        //
        // XXX   ibutton stores duplicate CA certs, NSS does not

        Session session = null;
        HashSet<X509Certificate> cacerts = new HashSet<X509Certificate>();
        try {
            session = token.getOpSession();
            CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
                        ATTR_TOKEN_TRUE,
                        ATTR_CLASS_CERT };
            long[] handles = findObjects(session, attrs);

            // load certs currently on the token
            for (long handle : handles) {
                cacerts.add(loadCert(session, handle));
            }
        } finally {
            token.releaseSession(session);
        }

        for (int i = start; i < chain.length; i++) {
            if (!cacerts.contains(chain[i])) {
                storeCert(null, chain[i]);
            } else if (debug != null) {
                debug.println("ignoring duplicate CA cert for [" +
                        chain[i].getSubjectX500Principal() +
                        "]");
            }
        }
    }

    private void storeSkey(String alias, KeyStore.SecretKeyEntry ske)
                throws PKCS11Exception, KeyStoreException {

        SecretKey skey = ske.getSecretKey();
        // No need to specify CKA_CLASS, CKA_KEY_TYPE, CKA_VALUE since
        // they are handled in P11SecretKeyFactory.createKey() method.
        CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
            ATTR_SKEY_TOKEN_TRUE,
            ATTR_PRIVATE_TRUE,
            new CK_ATTRIBUTE(CKA_LABEL, alias),
        };
        try {
            P11SecretKeyFactory.convertKey(token, skey, null, attrs);
        } catch (InvalidKeyException ike) {
            // re-throw KeyStoreException to match javadoc
            throw new KeyStoreException("Cannot convert to PKCS11 keys", ike);
        }

        // update global alias map
        aliasMap.put(alias, new AliasInfo(alias));

        if (debug != null) {
            debug.println("storeSkey created token secret key for [" +
                          alias + "]");
        }
    }

    private static CK_ATTRIBUTE[] addAttribute(CK_ATTRIBUTE[] attrs, CK_ATTRIBUTE attr) {
        int n = attrs.length;
        CK_ATTRIBUTE[] newAttrs = new CK_ATTRIBUTE[n + 1];
        System.arraycopy(attrs, 0, newAttrs, 0, n);
        newAttrs[n] = attr;
        return newAttrs;
    }

    private void storePkey(String alias, KeyStore.PrivateKeyEntry pke)
        throws PKCS11Exception, CertificateException, KeyStoreException  {

        PrivateKey key = pke.getPrivateKey();
        CK_ATTRIBUTE[] attrs = null;

        // If the key is a token object on this token, update it instead
        // of creating a duplicate key object.
        // Otherwise, treat a P11Key like any other key, if is is extractable.
        if (key instanceof P11Key) {
            P11Key p11Key = (P11Key)key;
            if (p11Key.tokenObject && (p11Key.token == this.token)) {
                updateP11Pkey(alias, null, p11Key);
                storeChain(alias, (X509Certificate[])pke.getCertificateChain());
                return;
            }
        }

        boolean useNDB = token.config.getNssNetscapeDbWorkaround();
        PublicKey publicKey = pke.getCertificate().getPublicKey();

        if (key instanceof RSAPrivateKey) {

            X509Certificate cert = (X509Certificate)pke.getCertificate();
            attrs = getRsaPrivKeyAttrs
                (alias, (RSAPrivateKey)key, cert.getSubjectX500Principal());

        } else if (key instanceof DSAPrivateKey) {

            DSAPrivateKey dsaKey = (DSAPrivateKey)key;

            CK_ATTRIBUTE[] idAttrs = getIdAttributes(key, publicKey, false, useNDB);
            if (idAttrs[0] == null) {
                idAttrs[0] = new CK_ATTRIBUTE(CKA_ID, alias);
            }

            attrs = new CK_ATTRIBUTE[] {
                ATTR_TOKEN_TRUE,
                ATTR_CLASS_PKEY,
                ATTR_PRIVATE_TRUE,
                new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DSA),
                idAttrs[0],
                new CK_ATTRIBUTE(CKA_PRIME, dsaKey.getParams().getP()),
                new CK_ATTRIBUTE(CKA_SUBPRIME, dsaKey.getParams().getQ()),
                new CK_ATTRIBUTE(CKA_BASE, dsaKey.getParams().getG()),
                new CK_ATTRIBUTE(CKA_VALUE, dsaKey.getX()),
            };
            if (idAttrs[1] != null) {
                attrs = addAttribute(attrs, idAttrs[1]);
            }

            attrs = token.getAttributes
                (TemplateManager.O_IMPORT, CKO_PRIVATE_KEY, CKK_DSA, attrs);

            if (debug != null) {
                debug.println("storePkey created DSA template");
            }

        } else if (key instanceof DHPrivateKey) {

            DHPrivateKey dhKey = (DHPrivateKey)key;

            CK_ATTRIBUTE[] idAttrs = getIdAttributes(key, publicKey, false, useNDB);
            if (idAttrs[0] == null) {
                idAttrs[0] = new CK_ATTRIBUTE(CKA_ID, alias);
            }

            attrs = new CK_ATTRIBUTE[] {
                ATTR_TOKEN_TRUE,
                ATTR_CLASS_PKEY,
                ATTR_PRIVATE_TRUE,
                new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DH),
                idAttrs[0],
                new CK_ATTRIBUTE(CKA_PRIME, dhKey.getParams().getP()),
                new CK_ATTRIBUTE(CKA_BASE, dhKey.getParams().getG()),
                new CK_ATTRIBUTE(CKA_VALUE, dhKey.getX()),
            };
            if (idAttrs[1] != null) {
                attrs = addAttribute(attrs, idAttrs[1]);
            }

            attrs = token.getAttributes
                (TemplateManager.O_IMPORT, CKO_PRIVATE_KEY, CKK_DH, attrs);

        } else if (key instanceof ECPrivateKey) {

            ECPrivateKey ecKey = (ECPrivateKey)key;

            CK_ATTRIBUTE[] idAttrs = getIdAttributes(key, publicKey, false, useNDB);
            if (idAttrs[0] == null) {
                idAttrs[0] = new CK_ATTRIBUTE(CKA_ID, alias);
            }

            byte[] encodedParams =
                ECUtil.encodeECParameterSpec(null, ecKey.getParams());
            attrs = new CK_ATTRIBUTE[] {
                ATTR_TOKEN_TRUE,
                ATTR_CLASS_PKEY,
                ATTR_PRIVATE_TRUE,
                new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_EC),
                idAttrs[0],
                new CK_ATTRIBUTE(CKA_VALUE, ecKey.getS()),
                new CK_ATTRIBUTE(CKA_EC_PARAMS, encodedParams),
            };
            if (idAttrs[1] != null) {
                attrs = addAttribute(attrs, idAttrs[1]);
            }

            attrs = token.getAttributes
                (TemplateManager.O_IMPORT, CKO_PRIVATE_KEY, CKK_EC, attrs);

            if (debug != null) {
                debug.println("storePkey created EC template");
            }

        } else if (key instanceof P11Key) {
            // sensitive/non-extractable P11Key
            P11Key p11Key = (P11Key)key;
            if (p11Key.token != this.token) {
                throw new KeyStoreException
                    ("Cannot move sensitive keys across tokens");
            }
            CK_ATTRIBUTE netscapeDB = null;
            if (useNDB) {
                // Note that this currently fails due to an NSS bug.
                // They do not allow the CKA_NETSCAPE_DB attribute to be
                // specified during C_CopyObject() and fail with
                // CKR_ATTRIBUTE_READ_ONLY.
                // But if we did not specify it, they would fail with
                // CKA_TEMPLATE_INCOMPLETE, so leave this code in here.
                CK_ATTRIBUTE[] idAttrs = getIdAttributes(key, publicKey, false, true);
                netscapeDB = idAttrs[1];
            }
            // Update the key object.
            updateP11Pkey(alias, netscapeDB, p11Key);
            storeChain(alias, (X509Certificate[])pke.getCertificateChain());
            return;

        } else {
            throw new KeyStoreException("unsupported key type: " + key);
        }

        Session session = null;
        try {
            session = token.getOpSession();

            // create private key entry
            token.p11.C_CreateObject(session.id(), attrs);
            if (debug != null) {
                debug.println("storePkey created token key for [" +
                                alias +
                                "]");
            }
        } finally {
            token.releaseSession(session);
        }

        storeChain(alias, (X509Certificate[])pke.getCertificateChain());
    }

    private CK_ATTRIBUTE[] getRsaPrivKeyAttrs(String alias,
                                RSAPrivateKey key,
                                X500Principal subject) throws PKCS11Exception {

        // subject is currently ignored - could be used to set CKA_SUBJECT

        CK_ATTRIBUTE[] attrs = null;
        if (key instanceof RSAPrivateCrtKey) {

            if (debug != null) {
                debug.println("creating RSAPrivateCrtKey attrs");
            }

            RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey)key;

            attrs = new CK_ATTRIBUTE[] {
                ATTR_TOKEN_TRUE,
                ATTR_CLASS_PKEY,
                ATTR_PRIVATE_TRUE,
                new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
                new CK_ATTRIBUTE(CKA_ID, alias),
                new CK_ATTRIBUTE(CKA_MODULUS,
                                rsaKey.getModulus()),
                new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT,
                                rsaKey.getPrivateExponent()),
                new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT,
                                rsaKey.getPublicExponent()),
                new CK_ATTRIBUTE(CKA_PRIME_1,
                                rsaKey.getPrimeP()),
                new CK_ATTRIBUTE(CKA_PRIME_2,
                                rsaKey.getPrimeQ()),
                new CK_ATTRIBUTE(CKA_EXPONENT_1,
                                rsaKey.getPrimeExponentP()),
                new CK_ATTRIBUTE(CKA_EXPONENT_2,
                                rsaKey.getPrimeExponentQ()),
                new CK_ATTRIBUTE(CKA_COEFFICIENT,
                                rsaKey.getCrtCoefficient()) };
            attrs = token.getAttributes
                (TemplateManager.O_IMPORT, CKO_PRIVATE_KEY, CKK_RSA, attrs);

        } else {

            if (debug != null) {
                debug.println("creating RSAPrivateKey attrs");
            }

            RSAPrivateKey rsaKey = key;

            attrs = new CK_ATTRIBUTE[] {
                ATTR_TOKEN_TRUE,
                ATTR_CLASS_PKEY,
                ATTR_PRIVATE_TRUE,
                new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
                new CK_ATTRIBUTE(CKA_ID, alias),
                new CK_ATTRIBUTE(CKA_MODULUS,
                                rsaKey.getModulus()),
                new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT,
                                rsaKey.getPrivateExponent()) };
            attrs = token.getAttributes
                (TemplateManager.O_IMPORT, CKO_PRIVATE_KEY, CKK_RSA, attrs);
        }

        return attrs;
    }

    /**
     * Compute the CKA_ID and/or CKA_NETSCAPE_DB attributes that should be
     * used for this private key. It uses the same algorithm to calculate the
     * values as NSS. The public and private keys MUST match for the result to
     * be correct.
     *
     * It returns a 2 element array with CKA_ID at index 0 and CKA_NETSCAPE_DB
     * at index 1. The boolean flags determine what is to be calculated.
     * If false or if we could not calculate the value, that element is null.
     *
     * NOTE that we currently do not use the CKA_ID value calculated by this
     * method.
     */
    private CK_ATTRIBUTE[] getIdAttributes(PrivateKey privateKey,
            PublicKey publicKey, boolean id, boolean netscapeDb) {
        CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[2];
        if ((id || netscapeDb) == false) {
            return attrs;
        }
        String alg = privateKey.getAlgorithm();
        if (id && alg.equals("RSA") && (publicKey instanceof RSAPublicKey)) {
            // CKA_NETSCAPE_DB not needed for RSA public keys
            BigInteger n = ((RSAPublicKey)publicKey).getModulus();
            attrs[0] = new CK_ATTRIBUTE(CKA_ID, sha1(getMagnitude(n)));
        } else if (alg.equals("DSA") && (publicKey instanceof DSAPublicKey)) {
            BigInteger y = ((DSAPublicKey)publicKey).getY();
            if (id) {
                attrs[0] = new CK_ATTRIBUTE(CKA_ID, sha1(getMagnitude(y)));
            }
            if (netscapeDb) {
                attrs[1] = new CK_ATTRIBUTE(CKA_NETSCAPE_DB, y);
            }
        } else if (alg.equals("DH") && (publicKey instanceof DHPublicKey)) {
            BigInteger y = ((DHPublicKey)publicKey).getY();
            if (id) {
                attrs[0] = new CK_ATTRIBUTE(CKA_ID, sha1(getMagnitude(y)));
            }
            if (netscapeDb) {
                attrs[1] = new CK_ATTRIBUTE(CKA_NETSCAPE_DB, y);
            }
        } else if (alg.equals("EC") && (publicKey instanceof ECPublicKey)) {
            ECPublicKey ecPub = (ECPublicKey)publicKey;
            ECPoint point = ecPub.getW();
            ECParameterSpec params = ecPub.getParams();
            byte[] encodedPoint = ECUtil.encodePoint(point, params.getCurve());
            if (id) {
                attrs[0] = new CK_ATTRIBUTE(CKA_ID, sha1(encodedPoint));
            }
            if (netscapeDb) {
                attrs[1] = new CK_ATTRIBUTE(CKA_NETSCAPE_DB, encodedPoint);
            }
        } else {
            throw new RuntimeException("Unknown key algorithm " + alg);
        }
        return attrs;
    }

    /**
     * return true if cert destroyed
     */
    private boolean destroyCert(byte[] cka_id)
                throws PKCS11Exception, KeyStoreException {
        Session session = null;
        try {
            session = token.getOpSession();
            THandle h = getTokenObject(session, ATTR_CLASS_CERT, cka_id, null);
            if (h.type != ATTR_CLASS_CERT) {
                return false;
            }

            token.p11.C_DestroyObject(session.id(), h.handle);
            if (debug != null) {
                debug.println("destroyCert destroyed cert with CKA_ID [" +
                                                getID(cka_id) +
                                                "]");
            }
            return true;
        } finally {
            token.releaseSession(session);
        }
    }

    /**
     * return true if chain destroyed
     */
    private boolean destroyChain(byte[] cka_id)
        throws PKCS11Exception, CertificateException, KeyStoreException {

        Session session = null;
        try {
            session = token.getOpSession();

            THandle h = getTokenObject(session, ATTR_CLASS_CERT, cka_id, null);
            if (h.type != ATTR_CLASS_CERT) {
                if (debug != null) {
                    debug.println("destroyChain could not find " +
                        "end entity cert with CKA_ID [0x" +
                        Functions.toHexString(cka_id) +
                        "]");
                }
                return false;
            }

            X509Certificate endCert = loadCert(session, h.handle);
            token.p11.C_DestroyObject(session.id(), h.handle);
            if (debug != null) {
                debug.println("destroyChain destroyed end entity cert " +
                        "with CKA_ID [" +
                        getID(cka_id) +
                        "]");
            }

            // build chain following issuer->subject links

            X509Certificate next = endCert;
            while (true) {

                if (next.getSubjectX500Principal().equals
                    (next.getIssuerX500Principal())) {
                    // self signed - done
                    break;
                }

                CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
                        ATTR_TOKEN_TRUE,
                        ATTR_CLASS_CERT,
                        new CK_ATTRIBUTE(CKA_SUBJECT,
                                  next.getIssuerX500Principal().getEncoded()) };
                long[] ch = findObjects(session, attrs);

                if (ch == null || ch.length == 0) {
                    // done
                    break;
                } else {
                    // if more than one found, use first
                    if (debug != null && ch.length > 1) {
                        debug.println("destroyChain found " +
                                ch.length +
                                " certificate entries for subject [" +
                                next.getIssuerX500Principal() +
                                "] in token - using first entry");
                    }

                    next = loadCert(session, ch[0]);

                    // only delete if not part of any other chain

                    attrs = new CK_ATTRIBUTE[] {
                        ATTR_TOKEN_TRUE,
                        ATTR_CLASS_CERT,
                        new CK_ATTRIBUTE(CKA_ISSUER,
                                next.getSubjectX500Principal().getEncoded()) };
                    long[] issuers = findObjects(session, attrs);

                    boolean destroyIt = false;
                    if (issuers == null || issuers.length == 0) {
                        // no other certs with this issuer -
                        // destroy it
                        destroyIt = true;
                    } else if (issuers.length == 1) {
                        X509Certificate iCert = loadCert(session, issuers[0]);
                        if (next.equals(iCert)) {
                            // only cert with issuer is itself (self-signed) -
                            // destroy it
                            destroyIt = true;
                        }
                    }

                    if (destroyIt) {
                        token.p11.C_DestroyObject(session.id(), ch[0]);
                        if (debug != null) {
                            debug.println
                                ("destroyChain destroyed cert in chain " +
                                "with subject [" +
                                next.getSubjectX500Principal() + "]");
                        }
                    } else {
                        if (debug != null) {
                            debug.println("destroyChain did not destroy " +
                                "shared cert in chain with subject [" +
                                next.getSubjectX500Principal() + "]");
                        }
                    }
                }
            }

            return true;

        } finally {
            token.releaseSession(session);
        }
    }

    /**
     * return true if secret key destroyed
     */
    private boolean destroySkey(String alias)
                throws PKCS11Exception, KeyStoreException {
        Session session = null;
        try {
            session = token.getOpSession();

            THandle h = getTokenObject(session, ATTR_CLASS_SKEY, null, alias);
            if (h.type != ATTR_CLASS_SKEY) {
                if (debug != null) {
                    debug.println("destroySkey did not find secret key " +
                        "with CKA_LABEL [" +
                        alias +
                        "]");
                }
                return false;
            }
            token.p11.C_DestroyObject(session.id(), h.handle);
            return true;
        } finally {
            token.releaseSession(session);
        }
    }

    /**
     * return true if private key destroyed
     */
    private boolean destroyPkey(byte[] cka_id)
                throws PKCS11Exception, KeyStoreException {
        Session session = null;
        try {
            session = token.getOpSession();

            THandle h = getTokenObject(session, ATTR_CLASS_PKEY, cka_id, null);
            if (h.type != ATTR_CLASS_PKEY) {
                if (debug != null) {
                    debug.println
                        ("destroyPkey did not find private key with CKA_ID [" +
                        getID(cka_id) +
                        "]");
                }
                return false;
            }
            token.p11.C_DestroyObject(session.id(), h.handle);
            return true;
        } finally {
            token.releaseSession(session);
        }
    }

    /**
     * build [alias + issuer + serialNumber] string from a cert
     */
    private String getID(String alias, X509Certificate cert) {
        X500Principal issuer = cert.getIssuerX500Principal();
        BigInteger serialNum = cert.getSerialNumber();

        return alias +
                ALIAS_SEP +
                issuer.getName(X500Principal.CANONICAL) +
                ALIAS_SEP +
                serialNum.toString();
    }

    /**
     * build CKA_ID string from bytes
     */
    private static String getID(byte[] bytes) {
        boolean printable = true;
        for (int i = 0; i < bytes.length; i++) {
            if (!DerValue.isPrintableStringChar((char)bytes[i])) {
                printable = false;
                break;
            }
        }

        if (!printable) {
            return "0x" + Functions.toHexString(bytes);
        } else {
            try {
                return new String(bytes, "UTF-8");
            } catch (UnsupportedEncodingException uee) {
                return "0x" + Functions.toHexString(bytes);
            }
        }
    }

    /**
     * find an object on the token
     *
     * @param type either ATTR_CLASS_CERT, ATTR_CLASS_PKEY, or ATTR_CLASS_SKEY
     * @param cka_id the CKA_ID if type is ATTR_CLASS_CERT or ATTR_CLASS_PKEY
     * @param cka_label the CKA_LABEL if type is ATTR_CLASS_SKEY
     */
    private THandle getTokenObject(Session session,
                                CK_ATTRIBUTE type,
                                byte[] cka_id,
                                String cka_label)
                throws PKCS11Exception, KeyStoreException {

        CK_ATTRIBUTE[] attrs;
        if (type == ATTR_CLASS_SKEY) {
            attrs = new CK_ATTRIBUTE[] {
                        ATTR_SKEY_TOKEN_TRUE,
                        new CK_ATTRIBUTE(CKA_LABEL, cka_label),
                        type };
        } else {
            attrs = new CK_ATTRIBUTE[] {
                        ATTR_TOKEN_TRUE,
                        new CK_ATTRIBUTE(CKA_ID, cka_id),
                        type };
        }
        long[] h = findObjects(session, attrs);
        if (h.length == 0) {
            if (debug != null) {
                if (type == ATTR_CLASS_SKEY) {
                    debug.println("getTokenObject did not find secret key " +
                                "with CKA_LABEL [" +
                                cka_label +
                                "]");
                } else if (type == ATTR_CLASS_CERT) {
                    debug.println
                        ("getTokenObject did not find cert with CKA_ID [" +
                        getID(cka_id) +
                        "]");
                } else {
                    debug.println("getTokenObject did not find private key " +
                        "with CKA_ID [" +
                        getID(cka_id) +
                        "]");
                }
            }
        } else if (h.length == 1) {

            // found object handle - return it
            return new THandle(h[0], type);

        } else {

            // found multiple object handles -
            // see if token ignored CKA_LABEL during search (e.g. NSS)

            if (type == ATTR_CLASS_SKEY) {

                ArrayList<THandle> list = new ArrayList<THandle>(h.length);
                for (int i = 0; i < h.length; i++) {

                    CK_ATTRIBUTE[] label = new CK_ATTRIBUTE[]
                                        { new CK_ATTRIBUTE(CKA_LABEL) };
                    token.p11.C_GetAttributeValue(session.id(), h[i], label);
                    if (label[0].pValue != null &&
                        cka_label.equals(new String(label[0].getCharArray()))) {
                        list.add(new THandle(h[i], ATTR_CLASS_SKEY));
                    }
                }
                if (list.size() == 1) {
                    // yes, there was only one CKA_LABEL that matched
                    return list.get(0);
                } else {
                    throw new KeyStoreException("invalid KeyStore state: " +
                        "found " +
                        list.size() +
                        " secret keys sharing CKA_LABEL [" +
                        cka_label +
                        "]");
                }
            } else if (type == ATTR_CLASS_CERT) {
                throw new KeyStoreException("invalid KeyStore state: " +
                        "found " +
                        h.length +
                        " certificates sharing CKA_ID " +
                        getID(cka_id));
            } else {
                throw new KeyStoreException("invalid KeyStore state: " +
                        "found " +
                        h.length +
                        " private keys sharing CKA_ID " +
                        getID(cka_id));
            }
        }
        return new THandle(NO_HANDLE, null);
    }

    /**
     * Create a mapping of all key pairs, trusted certs, and secret keys
     * on the token into logical KeyStore entries unambiguously
     * accessible via an alias.
     *
     * If the token is removed, the map may contain stale values.
     * KeyStore.load should be called to re-create the map.
     *
     * Assume all private keys and matching certs share a unique CKA_ID.
     *
     * Assume all secret keys have a unique CKA_LABEL.
     *
     * @return true if multiple certs found sharing the same CKA_LABEL
     *          (if so, write capabilities are disabled)
     */
    private boolean mapLabels() throws
                PKCS11Exception, CertificateException, KeyStoreException {

        CK_ATTRIBUTE[] trustedAttr = new CK_ATTRIBUTE[] {
                                new CK_ATTRIBUTE(CKA_TRUSTED) };

        Session session = null;
        try {
            session = token.getOpSession();

            // get all private key CKA_IDs

            ArrayList<byte[]> pkeyIDs = new ArrayList<byte[]>();
            CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
                ATTR_TOKEN_TRUE,
                ATTR_CLASS_PKEY,
            };
            long[] handles = findObjects(session, attrs);

            for (long handle : handles) {
                attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_ID) };
                token.p11.C_GetAttributeValue(session.id(), handle, attrs);

                if (attrs[0].pValue != null) {
                    pkeyIDs.add(attrs[0].getByteArray());
                }
            }

            // Get all certificates
            //
            // If cert does not have a CKA_LABEL nor CKA_ID, it is ignored.
            //
            // Get the CKA_LABEL for each cert
            // (if the cert does not have a CKA_LABEL, use the CKA_ID).
            //
            // Map each cert to the its CKA_LABEL
            // (multiple certs may be mapped to a single CKA_LABEL)

            HashMap<String, HashSet<AliasInfo>> certMap =
                                new HashMap<String, HashSet<AliasInfo>>();

            attrs = new CK_ATTRIBUTE[] {
                ATTR_TOKEN_TRUE,
                ATTR_CLASS_CERT,
            };
            handles = findObjects(session, attrs);

            for (long handle : handles) {
                attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_LABEL) };

                String cka_label = null;
                byte[] cka_id = null;
                try {
                    token.p11.C_GetAttributeValue(session.id(), handle, attrs);
                    if (attrs[0].pValue != null) {
                        // there is a CKA_LABEL
                        cka_label = new String(attrs[0].getCharArray());
                    }
                } catch (PKCS11Exception pe) {
                    if (pe.getErrorCode() != CKR_ATTRIBUTE_TYPE_INVALID) {
                        throw pe;
                    }

                    // GetAttributeValue for CKA_LABEL not supported
                    //
                    // XXX SCA1000
                }

                // get CKA_ID

                attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_ID) };
                token.p11.C_GetAttributeValue(session.id(), handle, attrs);
                if (attrs[0].pValue == null) {
                    if (cka_label == null) {
                        // no cka_label nor cka_id - ignore
                        continue;
                    }
                } else {
                    if (cka_label == null) {
                        // use CKA_ID as CKA_LABEL
                        cka_label = getID(attrs[0].getByteArray());
                    }
                    cka_id = attrs[0].getByteArray();
                }

                X509Certificate cert = loadCert(session, handle);

                // get CKA_TRUSTED

                boolean cka_trusted = false;

                if (useSecmodTrust) {
                    cka_trusted = Secmod.getInstance().isTrusted(cert, nssTrustType);
                } else {
                    if (CKA_TRUSTED_SUPPORTED) {
                        try {
                            token.p11.C_GetAttributeValue
                                    (session.id(), handle, trustedAttr);
                            cka_trusted = trustedAttr[0].getBoolean();
                        } catch (PKCS11Exception pe) {
                            if (pe.getErrorCode() == CKR_ATTRIBUTE_TYPE_INVALID) {
                                // XXX  NSS, ibutton, sca1000
                                CKA_TRUSTED_SUPPORTED = false;
                                if (debug != null) {
                                    debug.println
                                            ("CKA_TRUSTED attribute not supported");
                                }
                            }
                        }
                    }
                }

                HashSet<AliasInfo> infoSet = certMap.get(cka_label);
                if (infoSet == null) {
                    infoSet = new HashSet<AliasInfo>(2);
                    certMap.put(cka_label, infoSet);
                }

                // initially create private key entry AliasInfo entries -
                // these entries will get resolved into their true
                // entry types later

                infoSet.add(new AliasInfo
                                (cka_label,
                                cka_id,
                                cka_trusted,
                                cert));
            }

            // create list secret key CKA_LABELS -
            // if there are duplicates (either between secret keys,
            // or between a secret key and another object),
            // throw an exception
            HashMap<String, AliasInfo> sKeyMap =
                    new HashMap<String, AliasInfo>();

            attrs = new CK_ATTRIBUTE[] {
                ATTR_SKEY_TOKEN_TRUE,
                ATTR_CLASS_SKEY,
            };
            handles = findObjects(session, attrs);

            for (long handle : handles) {
                attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_LABEL) };
                token.p11.C_GetAttributeValue(session.id(), handle, attrs);
                if (attrs[0].pValue != null) {

                    // there is a CKA_LABEL
                    String cka_label = new String(attrs[0].getCharArray());
                    if (sKeyMap.get(cka_label) == null) {
                        sKeyMap.put(cka_label, new AliasInfo(cka_label));
                    } else {
                        throw new KeyStoreException("invalid KeyStore state: " +
                                "found multiple secret keys sharing same " +
                                "CKA_LABEL [" +
                                cka_label +
                                "]");
                    }
                }
            }

            // update global aliasMap with alias mappings
            ArrayList<AliasInfo> matchedCerts =
                                mapPrivateKeys(pkeyIDs, certMap);
            boolean sharedLabel = mapCerts(matchedCerts, certMap);
            mapSecretKeys(sKeyMap);

            return sharedLabel;

        } finally {
            token.releaseSession(session);
        }
    }

    /**
     * for each private key CKA_ID, find corresponding cert with same CKA_ID.
     * if found cert, see if cert CKA_LABEL is unique.
     *     if CKA_LABEL unique, map private key/cert alias to that CKA_LABEL.
     *     if CKA_LABEL not unique, map private key/cert alias to:
     *                   CKA_LABEL + ALIAS_SEP + ISSUER + ALIAS_SEP + SERIAL
     * if cert not found, ignore private key
     * (don't support private key entries without a cert chain yet)
     *
     * @return a list of AliasInfo entries that represents all matches
     */
    private ArrayList<AliasInfo> mapPrivateKeys(ArrayList<byte[]> pkeyIDs,
                        HashMap<String, HashSet<AliasInfo>> certMap)
                throws PKCS11Exception, CertificateException {

        // reset global alias map
        aliasMap = new HashMap<String, AliasInfo>();

        // list of matched certs that we will return
        ArrayList<AliasInfo> matchedCerts = new ArrayList<AliasInfo>();

        for (byte[] pkeyID : pkeyIDs) {

            // try to find a matching CKA_ID in a certificate

            boolean foundMatch = false;
            Set<String> certLabels = certMap.keySet();
            for (String certLabel : certLabels) {

                // get cert CKA_IDs (if present) for each cert

                HashSet<AliasInfo> infoSet = certMap.get(certLabel);
                for (AliasInfo aliasInfo : infoSet) {
                    if (Arrays.equals(pkeyID, aliasInfo.id)) {

                        // found private key with matching cert

                        if (infoSet.size() == 1) {
                            // unique CKA_LABEL - use certLabel as alias
                            aliasInfo.matched = true;
                            aliasMap.put(certLabel, aliasInfo);
                        } else {
                            // create new alias
                            aliasInfo.matched = true;
                            aliasMap.put(getID(certLabel, aliasInfo.cert),
                                        aliasInfo);
                        }
                        matchedCerts.add(aliasInfo);
                        foundMatch = true;
                        break;
                    }
                }
                if (foundMatch) {
                    break;
                }
            }

            if (!foundMatch) {
                if (debug != null) {
                    debug.println
                        ("did not find match for private key with CKA_ID [" +
                        getID(pkeyID) +
                        "] (ignoring entry)");
                }
            }
        }

        return matchedCerts;
    }

    /**
     * for each cert not matched with a private key but is CKA_TRUSTED:
     *     if CKA_LABEL unique, map cert to CKA_LABEL.
     *     if CKA_LABEL not unique, map cert to [label+issuer+serialNum]
     *
     * if CKA_TRUSTED not supported, treat all certs not part of a chain
     * as trusted
     *
     * @return true if multiple certs found sharing the same CKA_LABEL
     */
    private boolean mapCerts(ArrayList<AliasInfo> matchedCerts,
                        HashMap<String, HashSet<AliasInfo>> certMap)
                throws PKCS11Exception, CertificateException {

        // load all cert chains
        for (AliasInfo aliasInfo : matchedCerts) {
            Session session = null;
            try {
                session = token.getOpSession();
                aliasInfo.chain = loadChain(session, aliasInfo.cert);
            } finally {
                token.releaseSession(session);
            }
        }

        // find all certs in certMap not part of a cert chain
        // - these are trusted

        boolean sharedLabel = false;

        Set<String> certLabels = certMap.keySet();
        for (String certLabel : certLabels) {
            HashSet<AliasInfo> infoSet = certMap.get(certLabel);
            for (AliasInfo aliasInfo : infoSet) {

                if (aliasInfo.matched == true) {
                    // already found a private key match for this cert -
                    // just continue
                    aliasInfo.trusted = false;
                    continue;
                }

                // cert in this aliasInfo is not matched yet
                //
                // if CKA_TRUSTED_SUPPORTED == true,
                // then check if cert is trusted

                if (CKA_TRUSTED_SUPPORTED) {
                    if (aliasInfo.trusted) {
                        // trusted certificate
                        if (mapTrustedCert
                                (certLabel, aliasInfo, infoSet) == true) {
                            sharedLabel = true;
                        }
                    }
                    continue;
                }

                // CKA_TRUSTED_SUPPORTED == false
                //
                // XXX treat all certs not part of a chain as trusted
                // XXX
                // XXX Unsupported
                //
                // boolean partOfChain = false;
                // for (AliasInfo matchedInfo : matchedCerts) {
                //     for (int i = 0; i < matchedInfo.chain.length; i++) {
                //      if (matchedInfo.chain[i].equals(aliasInfo.cert)) {
                //          partOfChain = true;
                //          break;
                //      }
                //     }
                //     if (partOfChain) {
                //      break;
                //     }
                // }
                //
                // if (!partOfChain) {
                //     if (mapTrustedCert(certLabel,aliasInfo,infoSet) == true){
                //      sharedLabel = true;
                //     }
                // } else {
                //    if (debug != null) {
                //      debug.println("ignoring unmatched/untrusted cert " +
                //          "that is part of cert chain - cert subject is [" +
                //          aliasInfo.cert.getSubjectX500Principal().getName
                //                              (X500Principal.CANONICAL) +
                //          "]");
                //     }
                // }
            }
        }

        return sharedLabel;
    }

    private boolean mapTrustedCert(String certLabel,
                                AliasInfo aliasInfo,
                                HashSet<AliasInfo> infoSet) {

        boolean sharedLabel = false;

        aliasInfo.type = ATTR_CLASS_CERT;
        aliasInfo.trusted = true;
        if (infoSet.size() == 1) {
            // unique CKA_LABEL - use certLabel as alias
            aliasMap.put(certLabel, aliasInfo);
        } else {
            // create new alias
            sharedLabel = true;
            aliasMap.put(getID(certLabel, aliasInfo.cert), aliasInfo);
        }

        return sharedLabel;
    }

    /**
     * If the secret key shares a CKA_LABEL with another entry,
     * throw an exception
     */
    private void mapSecretKeys(HashMap<String, AliasInfo> sKeyMap)
                throws KeyStoreException {
        for (String label : sKeyMap.keySet()) {
            if (aliasMap.containsKey(label)) {
                throw new KeyStoreException("invalid KeyStore state: " +
                        "found secret key sharing CKA_LABEL [" +
                        label +
                        "] with another token object");
            }
        }
        aliasMap.putAll(sKeyMap);
    }

    private void dumpTokenMap() {
        Set<String> aliases = aliasMap.keySet();
        System.out.println("Token Alias Map:");
        if (aliases.isEmpty()) {
            System.out.println("  [empty]");
        } else {
            for (String s : aliases) {
                System.out.println("  " + s + aliasMap.get(s));
            }
        }
    }

    private void checkWrite() throws KeyStoreException {
        if (writeDisabled) {
            throw new KeyStoreException
                ("This PKCS11KeyStore does not support write capabilities");
        }
    }

    private final static long[] LONG0 = new long[0];

    private static long[] findObjects(Session session, CK_ATTRIBUTE[] attrs)
            throws PKCS11Exception {
        Token token = session.token;
        long[] handles = LONG0;
        token.p11.C_FindObjectsInit(session.id(), attrs);
        while (true) {
            long[] h = token.p11.C_FindObjects(session.id(), FINDOBJECTS_MAX);
            if (h.length == 0) {
                break;
            }
            handles = P11Util.concat(handles, h);
        }
        token.p11.C_FindObjectsFinal(session.id());
        return handles;
    }

}
