/*
* 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
* 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