iaik.pkcs.pkcs11.Module Maven / Gradle / Ivy
Show all versions of sunpkcs11-wrapper Show documentation
// Copyright (c) 2002 Graz University of Technology. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. The end-user documentation included with the redistribution, if any, must
// include the following acknowledgment:
//
// "This product includes software developed by IAIK of Graz University of
// Technology."
//
// Alternately, this acknowledgment may appear in the software itself, if and
// wherever such third-party acknowledgments normally appear.
//
// 4. The names "Graz University of Technology" and "IAIK of Graz University of
// Technology" must not be used to endorse or promote products derived from
// this software without prior written permission.
//
// 5. Products derived from this software may not be called "IAIK PKCS Wrapper",
// nor may "IAIK" appear in their name, without prior written permission of
// Graz University of Technology.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
package iaik.pkcs.pkcs11;
import iaik.pkcs.pkcs11.objects.Key;
import iaik.pkcs.pkcs11.wrapper.PKCS11Constants;
import iaik.pkcs.pkcs11.wrapper.PKCS11Exception;
import sun.security.pkcs11.wrapper.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Caution:
* Unlike the original PKCS#11 wrapper, we only call initialize() once per
* native .so/.dll. Once finalize(Object) has been called, the module cannot
* be initialized anymore.
*
*
* Objects of this class represent a PKCS#11 module. The application should
* create an instance by calling getInstance and passing the name of the
* PKCS#11 module of the desired token; e.g. "slbck.dll". The application
* must give the full path of the PKCS#11 module unless the module is in the
* system's search path or in the path of the java.library.path system
* property.
*
* According to the specification, the application must call the initialize
* method before calling any other method of the module.
* This class contains slot and token management functions as defined by the
* PKCS#11 standard.
*
* All applications using this library will contain the following code.
*
* Module pkcs11Module = Module.getInstance("cryptoki.dll");
* pkcs11Module.initialize(null);
*
* // ... work with the module
*
* pkcs11Module.finalize(null);
*
* Instead of cryptoki.dll
, the application will use the name of
* the PKCS#11 module of the installed crypto hardware.
* After the application initialized the module, it can get a list of all
* available slots. A slot is an object that represents a physical or logical
* device that can accept a cryptographic token; for instance, the card slot of
* a smart card reader. The application can call
*
* Slot[] slots = pkcs11Module.getSlotList(Module.SlotRequirement.ALL_SLOTS);
*
* to get a list of all available slots or
*
* Slot[] slotsWithToken = pkcs11Module.getSlotList(
* Module.SlotRequirement.TOKEN_PRESENT);
*
* to get a list of all those slots in which there is a currently a token
* present.
*
* To wait for the insertion of a token, the application can use the
* waitForSlotEvent
method. For example, the method call
*
* Slot eventSlot = pkcs11Module.waitForSlotEvent(
* Module.WaitingBehavior.DONT_BLOCK, null);
*
* will block until an event for any slot of this module occurred. Usually such
* an event is the insertion of a token. However, the application should check
* if the event occurred in the slot of interest and if there is really a token
* present in the slot.
*
* @see iaik.pkcs.pkcs11.Info
* @see iaik.pkcs.pkcs11.Slot
* @author Karl Scheibelhofer
* @version 1.0
*/
public class Module {
/**
* This interface defines the required properties for a slot. The
* application uses one of the defined constants as parameter when calling
* getSlotList.
*
* @version 1.0
*/
public interface SlotRequirement {
/**
* Causes getSlotList to return all slots of the system that the
* respective module supports.
*/
boolean ALL_SLOTS = false;
/**
* Causes getSlotList to return only those slots in which there is
* currently a token present; e.g. there is a smart card in the reader's
* slot.
*/
boolean TOKEN_PRESENT = true;
}
/**
* This interface defines the allowed constants for the wanted waiting
* behavior when calling waitForSlotEvent.
*
* @version 1.0
*/
public interface WaitingBehavior {
/**
* Tells waitForSlotEvent to block until an event occurs.
*/
boolean BLOCK = false;
/**
* Tells waitForSlotEvent to return immediately.
*/
boolean DONT_BLOCK = true;
}
/**
* Interface to the underlying PKCS#11 module.
*/
private PKCS11 pkcs11Module;
private final String pkcs11ModuleName;
private VendorCodeConverter vendorCodeConverter;
/**
* The currently set vendor defined key builder, or null.
*/
private Key.VendorDefinedKeyBuilder vendorKeyBuilder;
/**
* Create a new module that uses the given PKCS11 interface to interact with
* the token.
*
* @param pkcs11ModuleName
* The interface to interact with the token.
*/
public Module(String pkcs11ModuleName) {
this.pkcs11ModuleName = pkcs11ModuleName;
}
/**
* Get an instance of this class by giving the name of the PKCS#11 module;
* e.g. "slbck.dll".
*
* @param pkcs11ModuleName
* The name of the module; e.g. "slbck.dll".
* @return An instance of Module that is connected to the given PKCS#11
* module.
* @exception IOException
* If connecting to the named module fails.
*/
public static Module getInstance(String pkcs11ModuleName) throws IOException {
Util.requireNonNull("pkcs11ModuleName", pkcs11ModuleName);
File file = new File(pkcs11ModuleName);
if (!file.exists()) {
throw new FileNotFoundException(
"File " + pkcs11ModuleName + " does not exist");
}
if (!file.isFile()) {
throw new IOException(pkcs11ModuleName + " is not a file");
}
if (!file.canRead()) {
throw new IOException("Can not read file " + pkcs11ModuleName + "");
}
return new Module(pkcs11ModuleName);
}
public VendorCodeConverter getVendorCodeConverter() {
return vendorCodeConverter;
}
public void setVendorCodeConverter(VendorCodeConverter vendorCodeConverter) {
this.vendorCodeConverter = vendorCodeConverter;
}
/**
* Set a vendor-defined key builder that should be called to create an
* instance of an vendor-defined PKCS#11 key; i.e. an instance of a
* vendor defined sub-class of this class.
*
* @param builder
* The vendor-defined key builder. Null to clear any previously
* installed vendor-defined builder.
*/
public void setVendorDefinedKeyBuilder(
Key.VendorDefinedKeyBuilder builder) {
vendorKeyBuilder = builder;
}
/**
* Get the currently set vendor-defined key builder.
*
* @return The currently set vendor-defined key builder or null if
* none is set.
*/
public Key.VendorDefinedKeyBuilder getVendorDefinedKeyBuilder() {
return vendorKeyBuilder;
}
/**
* Get an instance of this class by giving the name of the PKCS#11 module,
* e.g. "slbck.dll" and the absolute path to the PKCS#11-wrapper native
* library.
*
* @param pkcs11ModuleName
* The name of the module; e.g. "slbck.dll".
* @param pkcs11WrapperPath
* The absolute path to the PKCS#11-wrapper native library.
* @return An instance of Module that is connected to the given PKCS#11
* module using the specified PKCS#11-wrapper native library.
* @exception IOException
* If connecting to the named module fails.
*/
/*
public static Module getInstance(String pkcs11ModuleName,
String pkcs11WrapperPath)
throws IOException {
Util.requireNotNull("pkcs11ModuleName", pkcs11ModuleName);
PKCS11 pkcs11Module = PKCS11Connector.connectToPKCS11Module(
pkcs11ModuleName, pkcs11WrapperPath);
return new Module(pkcs11Module);
}*/
/**
* Gets information about the module; i.e. the PKCS#11 module behind.
*
* @return A object holding information about the module.
* @exception TokenException
* If getting the information fails.
*/
public Info getInfo() throws TokenException {
assertInitialized();
CK_INFO ckInfo;
try {
ckInfo = pkcs11Module.C_GetInfo();
} catch (sun.security.pkcs11.wrapper.PKCS11Exception ex) {
throw new PKCS11Exception(ex);
}
return new Info(ckInfo);
}
/**
* Initializes the module. The application must call this method before
* calling any other method of the module.
*
* @param initArgs
* The initialization arguments for the module as defined in
* PKCS#11. May be null.
* @exception TokenException
* If initialization fails.
*/
public void initialize(InitializeArgs initArgs) throws TokenException {
CK_C_INITIALIZE_ARGS wrapperInitArgs = null;
if (initArgs != null) {
InitializeArgs castedInitArgs = initArgs;
final MutexHandler mutexHandler = castedInitArgs.getMutexHandler();
wrapperInitArgs = new CK_C_INITIALIZE_ARGS();
if (mutexHandler != null) {
wrapperInitArgs.CreateMutex = new CK_CREATEMUTEX() {
// CHECKSTYLE:SKIP
public Object CK_CREATEMUTEX()
throws sun.security.pkcs11.wrapper.PKCS11Exception {
return mutexHandler.createMutex();
}
};
wrapperInitArgs.DestroyMutex = new CK_DESTROYMUTEX() {
// CHECKSTYLE:SKIP
public void CK_DESTROYMUTEX(Object pMutex)
throws sun.security.pkcs11.wrapper.PKCS11Exception {
mutexHandler.destroyMutex(pMutex);
}
};
wrapperInitArgs.LockMutex = new CK_LOCKMUTEX() {
// CHECKSTYLE:SKIP
public void CK_LOCKMUTEX(Object pMutex)
throws sun.security.pkcs11.wrapper.PKCS11Exception {
mutexHandler.lockMutex(pMutex);
}
};
wrapperInitArgs.UnlockMutex = new CK_UNLOCKMUTEX() {
// CHECKSTYLE:SKIP
public void CK_UNLOCKMUTEX(Object pMutex)
throws sun.security.pkcs11.wrapper.PKCS11Exception {
mutexHandler.unlockMutex(pMutex);
}
};
} else {
wrapperInitArgs.CreateMutex = null;
wrapperInitArgs.DestroyMutex = null;
wrapperInitArgs.LockMutex = null;
wrapperInitArgs.UnlockMutex = null;
}
if (castedInitArgs.isLibraryCantCreateOsThreads()) {
wrapperInitArgs.flags |=
PKCS11Constants.CKF_LIBRARY_CANT_CREATE_OS_THREADS;
}
if (castedInitArgs.isOsLockingOk()) {
wrapperInitArgs.flags |= PKCS11Constants.CKF_OS_LOCKING_OK;
}
wrapperInitArgs.pReserved = castedInitArgs.getReserved();
}
// pReserved of CK_C_INITIALIZE_ARGS not used yet, just set to standard
// conform UTF8
final String functionList = "C_GetFunctionList";
final boolean omitInitialize = false;
try {
pkcs11Module = PKCS11.getInstance(pkcs11ModuleName, functionList,
wrapperInitArgs, omitInitialize);
} catch (IOException ex) {
throw new TokenException(ex.getMessage(), ex);
} catch (sun.security.pkcs11.wrapper.PKCS11Exception ex) {
throw new PKCS11Exception(ex);
} catch (NoSuchMethodError ex) {
// In some JDKs like red hat, the getInstance is extended by fipsKeyImporter as follows:
// getInstance(String pkcs11ModulePath, String functionList, CK_C_INITIALIZE_ARGS pInitArgs,
// boolean omitInitialize, MethodHandle fipsKeyImporter)
try {
Method getInstanceMethod = PKCS11.class.getMethod("getInstance",
String.class, String.class,
CK_C_INITIALIZE_ARGS.class, boolean.class, MethodHandle.class);
pkcs11Module = (PKCS11) getInstanceMethod.invoke(null, pkcs11ModuleName, functionList,
wrapperInitArgs, omitInitialize, null);
} catch (NoSuchMethodException | SecurityException
| IllegalAccessException | IllegalArgumentException | InvocationTargetException ex1) {
throw new TokenException(ex1.getMessage(), ex1);
}
}
}
/**
* Gets a list of slots that can accept tokens that are compatible with this
* module; e.g. a list of PC/SC smart card readers. The parameter determines
* if the method returns all compatible slots or only those in which there
* is a compatible token present.
*
* @param tokenPresent
* Can be SlotRequirement.ALL_SLOTS or
* SlotRequirement.TOKEN_PRESENT.
* @return An array of Slot objects. May be an empty array but not null.
* @exception TokenException
* If .
*/
public Slot[] getSlotList(boolean tokenPresent) throws TokenException {
assertInitialized();
long[] slotIDs;
try {
slotIDs = pkcs11Module.C_GetSlotList(tokenPresent);
} catch (sun.security.pkcs11.wrapper.PKCS11Exception ex) {
throw new PKCS11Exception(ex);
}
Slot[] slots = new Slot[slotIDs.length];
for (int i = 0; i < slots.length; i++) {
slots[i] = new Slot(this, slotIDs[i]);
}
return slots;
}
/**
* Waits for an slot event. That can be that a token was inserted or
* removed. It returns the Slot for which an event occurred. The dontBlock
* parameter can have the value WaitingBehavior.BLOCK or
* WaitingBehavior.DONT_BLOCK.
* If there is no event present and the method is called with
* WaitingBehavior.DONT_BLOCK this method throws an exception with the error
* code PKCS11Constants.CKR_NO_EVENT (0x00000008).
*
* @param dontBlock
* Can be WaitingBehavior.BLOCK or WaitingBehavior.DONT_BLOCK.
* @param reserved
* Should be null for this version.
* @return The slot for which an event occurred.
* @exception TokenException
* If the method was called with WaitingBehavior.DONT_BLOCK but
* there was no event available, or if an error occurred.
*/
/*
public Slot waitForSlotEvent(boolean dontBlock, PKCS11Object reserved)
throws TokenException {
long flags = (dontBlock) ? PKCS11Constants.CKF_DONT_BLOCK : 0L;
long slotID = pkcs11Module_.C_WaitForSlotEvent(flags, reserved);
return new Slot(this, slotID);
}*/
/**
* Gets the PKCS#11 module of the wrapper package behind this object.
*
* @return The PKCS#11 module behind this object.
*/
// CHECKSTYLE:SKIP
public PKCS11 getPKCS11Module() {
assertInitialized();
return pkcs11Module;
}
/**
* Returns the string representation of this object.
*
* @return The string representation of object
*/
public String toString() {
return (pkcs11Module != null) ? pkcs11Module.toString() : null;
}
/**
* Caution:
* Unlike the original PKCS#11 wrapper, we only call initialize() once per
* native .so/.dll. Once finalize(Object) has been called, the module cannot
* be initialized anymore.
*
*
* Finalizes this module. The application should call this method when it
* finished using the module.
* Note that this method is different from the finalize
method,
* which is the reserved Java method called by the garbage collector.
* This method calls the C_Finalize(PKCS11Object)
method of the
* underlying PKCS11 module.
*
* @param args
* Must be null in version 2.x of PKCS#11.
* @exception TokenException
* If finalization fails.
*/
public void finalize(Object args) throws TokenException {
if (pkcs11Module == null) {
return;
}
try {
pkcs11Module.C_Finalize(args);
} catch (sun.security.pkcs11.wrapper.PKCS11Exception ex) {
throw new PKCS11Exception(ex);
}
}
/**
* Compares the pkcs11Module_ this object with the other object.
* Returns only true, if those are equal in both objects.
*
* @param otherObject
* The other Module object.
* @return True, if other is an instance of Module and the pkcs11Module_ of
* both objects are equal. False, otherwise.
*/
@Override
public boolean equals(Object otherObject) {
if (this == otherObject) {
return true;
} else if (!(otherObject instanceof Module)) {
return false;
}
Module other = (Module) otherObject;
return Util.objEquals(this.pkcs11Module, other.pkcs11Module);
}
/**
* The overriding of this method should ensure that the objects of this
* class work correctly in a hashtable.
*
* @return The hash code of this object. Gained from the sessionHandle.
*/
@Override
public int hashCode() {
return pkcs11Module == null ? 0 : pkcs11Module.hashCode();
}
private void assertInitialized() {
if (pkcs11Module == null) {
throw new IllegalStateException(
"Module not initialized yet, please call initialize() first");
}
}
}