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

xades4j.providers.impl.PKCS11KeyStoreKeyingDataProvider Maven / Gradle / Ivy

/*
 * XAdES4j - A Java library for generation and verification of XAdES signatures.
 * Copyright (C) 2010 Luis Goncalves.
 *
 * XAdES4j 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 3 of the License, or any later version.
 *
 * XAdES4j 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 Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License along
 * with XAdES4j. If not, see .
 */
package xades4j.providers.impl;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.KeyStore;
import java.security.KeyStore.Builder;
import java.security.KeyStore.ProtectionParameter;
import java.security.KeyStoreException;
import java.security.Provider;
import java.security.ProviderException;
import java.security.Security;
import java.security.cert.X509Certificate;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;

/**
 * A specification of {@code KeyStoreKeyingDataProvider} for PKCS#11 keystores.
 * This class uses the SUN's PKCS#11 provider, which brigdes with the native PKCS#11
 * library. Note that this provider is not included in some versions of the JRE,
 * namely the 64 bits Windows version. On those scenarios this class will fail at
 * runtime.
 * 

* The {@code KeyStorePasswordProvider} and {@code KeyEntryPasswordProvider} may * be {@code null}. In that case the keystore protection has to be handled by the * native library. If the {@code KeyEntryPasswordProvider} is supplied, the protection * used to access an entry is a {@code CallbackHandlerProtection} that invokes the * {@code KeyEntryPasswordProvider} exactly when when the password is requested. * @see xades4j.providers.impl.KeyStoreKeyingDataProvider * @author Luís */ public class PKCS11KeyStoreKeyingDataProvider extends KeyStoreKeyingDataProvider { /** * The provider name is used has a key to search for installed providers. If a * provider exists with the same name, it will be used even if it relies on a * different native library. * @param nativeLibraryPath the path for the native library of the specific PKCS#11 provider * @param providerName this string is concatenated with the prefix SunPKCS11- to produce this provider instance's name * @param certificateSelector the selector of signing certificate * @param keyStorePasswordProvider the provider of the keystore loading password (may be {@code null}) * @param entryPasswordProvider the provider of entry passwords (may be {@code null}) * @param returnFullChain indicates of the full certificate chain should be returned, if available * @throws KeyStoreException */ public PKCS11KeyStoreKeyingDataProvider( final String nativeLibraryPath, final String providerName, SigningCertSelector certificateSelector, KeyStorePasswordProvider keyStorePasswordProvider, KeyEntryPasswordProvider entryPasswordProvider, boolean returnFullChain) throws KeyStoreException { this(nativeLibraryPath, providerName, null, certificateSelector, keyStorePasswordProvider, entryPasswordProvider, returnFullChain); } /** * The provider name is used as a key to search for installed providers. If a * provider exists with the same name, it will be used even if it relies on a * different native library. * @param nativeLibraryPath the path for the native library of the specific PKCS#11 provider * @param providerName this string is concatenated with the prefix SunPKCS11- to produce this provider instance's name * @param slotId the id of the slot that this provider instance is to be associated with (can be {@code null}) * @param certificateSelector the selector of signing certificate * @param keyStorePasswordProvider the provider of the keystore loading password (can be {@code null}) * @param entryPasswordProvider the provider of entry passwords (may be {@code null}) * @param returnFullChain indicates of the full certificate chain should be returned, if available * @throws KeyStoreException */ public PKCS11KeyStoreKeyingDataProvider( final String nativeLibraryPath, final String providerName, final Integer slotId, SigningCertSelector certificateSelector, KeyStorePasswordProvider keyStorePasswordProvider, KeyEntryPasswordProvider entryPasswordProvider, boolean returnFullChain) throws KeyStoreException { super(new KeyStoreBuilderCreator() { @Override public Builder getBuilder(ProtectionParameter loadProtection) { Provider p = getInstalledProvider(providerName); if (p == null) { StringBuilder config = new StringBuilder("name = ").append(providerName); config.append(System.getProperty("line.separator")); config.append("library = ").append(nativeLibraryPath); if(slotId != null) { config.append(System.getProperty("line.separator")); config.append("slot = ").append(slotId); } ByteArrayInputStream configStream = new ByteArrayInputStream(config.toString().getBytes()); p = createPkcs11Provider(configStream); Security.addProvider(p); } return KeyStore.Builder.newInstance("PKCS11", p, loadProtection); } }, certificateSelector, keyStorePasswordProvider, entryPasswordProvider, returnFullChain); } /** * Shortcut constructor using {@code null} for the password providers and slot * and {@code false} for the {@code returnFullChain} parameter. * @param nativeLibraryPath * @param providerName * @param slotId * @param certificateSelector * @throws KeyStoreException */ public PKCS11KeyStoreKeyingDataProvider( String nativeLibraryPath, String providerName, Integer slotId, SigningCertSelector certificateSelector) throws KeyStoreException { this(nativeLibraryPath, providerName, slotId, certificateSelector, null, null, false); } /** * Shortcut constructor using {@code null} for the password providers and slot, * and {@code false} for the {@code returnFullChain} parameter. * @param nativeLibraryPath * @param providerName * @param certificateSelector * @throws KeyStoreException */ public PKCS11KeyStoreKeyingDataProvider( final String nativeLibraryPath, final String providerName, SigningCertSelector certificateSelector) throws KeyStoreException { this(nativeLibraryPath, providerName, null, certificateSelector); } @Override protected final KeyStore.ProtectionParameter getKeyProtection( final String entryAlias, final X509Certificate entryCert, final KeyEntryPasswordProvider entryPasswordProvider) { if (null == entryPasswordProvider) { return null; } return new KeyStore.CallbackHandlerProtection(new CallbackHandler() { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { PasswordCallback c = (PasswordCallback) callbacks[0]; c.setPassword(entryPasswordProvider.getPassword(entryAlias, entryCert)); } }); } private static Provider getInstalledProvider(String providerName) { Class pkcs11Class = getPkcs11ProviderClass(); Provider p = Security.getProvider("SunPKCS11-" + providerName); // Throws expcetion if the provider is not of the expected type return pkcs11Class.cast(p); } private static Provider createPkcs11Provider(InputStream configStream) { try { Class providerClass = getPkcs11ProviderClass(); Constructor ctor = providerClass.getConstructor(InputStream.class); return ctor.newInstance(configStream); } // Since the provider class was loaded, these exceptions are unexpected catch (IllegalAccessException ex) { throw new ProviderException(ex); } catch (IllegalArgumentException ex) { throw new ProviderException(ex); } catch (InvocationTargetException ex) { throw new ProviderException(ex); } catch (NoSuchMethodException ex) { throw new ProviderException(ex); } catch(InstantiationException ex) { throw new ProviderException(ex); } } private static Class getPkcs11ProviderClass() { try { return Class.forName("sun.security.pkcs11.SunPKCS11"); } catch (ClassNotFoundException ex) { throw new ProviderException("Cannot find SunPKCS11 provider", ex); } } public static boolean isProviderAvailable() { try { getPkcs11ProviderClass(); return true; } catch(ProviderException ex) { return false; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy