All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cesecore.keys.token.PKCS11CryptoToken Maven / Gradle / Ivy

/*************************************************************************
 *                                                                       *
 *  CESeCore: CE Security Core                                           *
 *                                                                       *
 *  This software is free software; you can redistribute it and/or       *
 *  modify it under the terms of the GNU Lesser General Public           *
 *  License as published by the Free Software Foundation; either         *
 *  version 2.1 of the License, or any later version.                    *
 *                                                                       *
 *  See terms of license at gnu.org.                                     *
 *                                                                       *
 *************************************************************************/
package org.cesecore.keys.token;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.cert.CertificateException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Properties;

import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.cesecore.internal.InternalResources;
import org.cesecore.keys.token.p11.P11Slot;
import org.cesecore.keys.token.p11.P11SlotUser;
import org.cesecore.keys.token.p11.Pkcs11SlotLabel;
import org.cesecore.keys.token.p11.Pkcs11SlotLabelType;
import org.cesecore.keys.token.p11.exception.NoSuchSlotException;
import org.cesecore.keys.util.KeyStoreTools;

/**
 * Class implementing a keystore on PKCS11 tokens.
 * 
 * @version $Id: PKCS11CryptoToken.java 31320 2019-01-25 10:35:32Z anatom $
 */
public class PKCS11CryptoToken extends BaseCryptoToken implements P11SlotUser {

    private static final long serialVersionUID = 7719014139640717867L;

    /** Log4j instance */
    private static final Logger log = Logger.getLogger(PKCS11CryptoToken.class);
    /** Internal localization of logs and errors */
    private static final InternalResources intres = InternalResources.getInstance();

    /** Keys, specific to PKCS#11, that can be defined in CA token properties */
    public static final String SLOT_LABEL_VALUE = "slotLabelValue";
    public static final String SLOT_LABEL_TYPE = "slotLabelType";
    public static final String SHLIB_LABEL_KEY = "sharedLibrary";
    public static final String ATTRIB_LABEL_KEY = "attributesFile";
    public static final String PASSWORD_LABEL_KEY = "pin";
    /** Flag that if set, prevent adding the P11 provider with Security.addProvider.
     * Can be used to create a crypto token without actually installing it in Java Security, so it
     * can be created temporarily */
    public static final String DO_NOT_ADD_P11_PROVIDER = "doNotAddP11Provider";
    
    @Deprecated //Remove once upgrading from 5.0->6.0 is no longer supported
    public static final String SLOT_LIST_INDEX_KEY = "slotListIndex";
    @Deprecated //Remove once upgrading from 5.0->6.0 is no longer supported
    public static final String SLOT_LABEL_KEY = "slot";

    
    /** A user defined name of the slot provider. Used in order to be able to have two different providers
     * (with different PKCS#11 attributes) for the same slot. If this is not set (null), the default
     * java provider name is used (SunPKCS11-pkcs11LibName-slotNr for example SunPKCS11-libcryptoki.so-slot1).
     */
    public final static String TOKEN_FRIENDLY_NAME = "tokenFriendlyName";
    
    private transient P11Slot p11slot;

    private String sSlotLabel = null;
    
    /**
     * @param providerClass
     * @throws InstantiationException
     */
    public PKCS11CryptoToken() throws InstantiationException {
        super();
        try {
            Thread.currentThread().getContextClassLoader().loadClass(Pkcs11SlotLabel.SUN_PKCS11_CLASS);
        } catch (ClassNotFoundException t) {
            throw new InstantiationException("PKCS11 provider class " + Pkcs11SlotLabel.SUN_PKCS11_CLASS + " not found.");
        }
    }

    @Override
    public void init(final Properties properties, final byte[] data, final int id) throws CryptoTokenOfflineException, NoSuchSlotException {
        if (log.isDebugEnabled()) {
            log.debug(">init: id=" + id);
        }
        // Don't autoactivate this right away, we must dynamically create the auth-provider with a slot
        setProperties(properties);
        init(properties, false, id);
        sSlotLabel = getSlotLabel(SLOT_LABEL_VALUE, properties);
        Pkcs11SlotLabelType type = Pkcs11SlotLabelType.getFromKey(getSlotLabel(SLOT_LABEL_TYPE, properties));
        String sharedLibrary = properties.getProperty(PKCS11CryptoToken.SHLIB_LABEL_KEY);
        String attributesFile = properties.getProperty(PKCS11CryptoToken.ATTRIB_LABEL_KEY);
        // If doNotAddP11Provider is set to true, this boolean is set to false
        Boolean addProvider = !BooleanUtils.toBoolean(properties.getProperty(PKCS11CryptoToken.DO_NOT_ADD_P11_PROVIDER));

        String friendlyName = properties.getProperty(TOKEN_FRIENDLY_NAME);

        if(friendlyName != null){
            p11slot = P11Slot.getInstance(friendlyName, sSlotLabel, sharedLibrary, type, attributesFile, this, id, addProvider);
        } else {
            // getInstance will run autoActivate()
            p11slot = P11Slot.getInstance(sSlotLabel, sharedLibrary, type, attributesFile, this, id, addProvider);
            
        }
        final Provider provider = p11slot.getProvider();
        if (addProvider) {
            setJCAProvider(provider);
        } else {
            setJCAProviderName(provider.getName());
            log.info("Configured to not add PKCS#11 Provider: "+provider.getName());
        }
        if (log.isDebugEnabled()) {
            log.debug(" 6.0.x 
    public static Properties upgradePropertiesFileFrom5_0_x(final Properties properties) {
        Properties returnValue = new Properties();
        
        for (Object key : properties.keySet()) {
            final String keyString = (String) key;
            if (log.isDebugEnabled()) {
                log.debug(">upgradePropertiesFileFrom5_0_x, keyString: "+key);
            }
            if (keyString.equalsIgnoreCase(SLOT_LABEL_KEY)) {
                String keyValue = properties.getProperty(keyString);
                if (log.isDebugEnabled()) {
                    log.debug(">upgradePropertiesFileFrom5_0_x, keyValue: "+keyValue);
                }
                // In 5.0.11, the "slot" value may contain just an integer, but may also encode an integer, an index
                // a token label or a config file. 
                final String oldLabelPrefix = "TOKEN_LABEL:";
                final String oldIndexPrefix = "SLOT_LIST_IX:";
                final String oldSlotNumberPrefix = "SLOT_ID:";
                final String oldSunFilePrefix = "SUN_FILE:";
                final String delimiter = ":";
                if(Pkcs11SlotLabelType.SLOT_NUMBER.validate(keyValue)) {
                    //If it was a straight integer, then save as is
                    returnValue.setProperty(SLOT_LABEL_VALUE, keyValue);
                    returnValue.setProperty(SLOT_LABEL_TYPE, Pkcs11SlotLabelType.SLOT_NUMBER.getKey());
                } else if(keyValue.startsWith(oldSlotNumberPrefix)) {
                   //If not, check with the rest of the values 
                    returnValue.setProperty(SLOT_LABEL_VALUE, keyValue.split(delimiter, 2)[1]);
                    returnValue.setProperty(SLOT_LABEL_TYPE, Pkcs11SlotLabelType.SLOT_NUMBER.getKey());
                } else if(keyValue.startsWith(oldIndexPrefix)) {
                    returnValue.setProperty(SLOT_LABEL_VALUE, keyValue.split(delimiter, 2)[1]);
                    returnValue.setProperty(SLOT_LABEL_TYPE, Pkcs11SlotLabelType.SLOT_INDEX.getKey());
                } else if(keyValue.startsWith(oldLabelPrefix)) {
                    returnValue.setProperty(SLOT_LABEL_VALUE, keyValue.split(delimiter, 2)[1]);
                    returnValue.setProperty(SLOT_LABEL_TYPE, Pkcs11SlotLabelType.SLOT_LABEL.getKey());
                } else if(keyValue.startsWith(oldSunFilePrefix)) {
                    returnValue.setProperty(SLOT_LABEL_TYPE, Pkcs11SlotLabelType.SUN_FILE.getKey());
                }
                
            } else if (keyString.equalsIgnoreCase(SLOT_LIST_INDEX_KEY)) {
                String indexValue = properties.getProperty(keyString);
                if (indexValue.charAt(0) != 'i') {
                    indexValue = "i" + indexValue;
                }
                if (log.isDebugEnabled()) {
                    log.debug(">upgradePropertiesFileFrom5_0_x, indexValue: "+indexValue);
                }
                returnValue.setProperty(SLOT_LABEL_VALUE, indexValue);
                returnValue.setProperty(SLOT_LABEL_TYPE, Pkcs11SlotLabelType.SLOT_INDEX.getKey());
            } else {
                if (log.isDebugEnabled()) {
                    log.debug(">upgradePropertiesFileFrom5_0_x, keyString is neither "+SLOT_LABEL_KEY+" or "+SLOT_LIST_INDEX_KEY+", just setting the property without SLOT_LABEL_TYPE.");
                }
                returnValue.setProperty(keyString, properties.getProperty(keyString));
            }
        }
        return returnValue;
    }

    @Override
    public boolean permitExtractablePrivateKeyForTest() {
        return doPermitExtractablePrivateKey();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy