iaik.pkcs.pkcs11.Module Maven / Gradle / Ivy
// 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 java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Method;
import iaik.pkcs.pkcs11.wrapper.PKCS11Constants;
import iaik.pkcs.pkcs11.wrapper.PKCS11Exception;
import sun.security.pkcs11.wrapper.CK_CREATEMUTEX;
import sun.security.pkcs11.wrapper.CK_C_INITIALIZE_ARGS;
import sun.security.pkcs11.wrapper.CK_DESTROYMUTEX;
import sun.security.pkcs11.wrapper.CK_INFO;
import sun.security.pkcs11.wrapper.CK_LOCKMUTEX;
import sun.security.pkcs11.wrapper.CK_UNLOCKMUTEX;
import sun.security.pkcs11.wrapper.PKCS11;
//FIXME: check if pkcs11module_ is not null.
/**
* 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.
* By default, it is assumed that the required PKCS#11-wrapper-library
* is named "pkcs11wrapper" and is located in the system path. The name of the
* library with the absolute path can also be passed as parameter.
* 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
* @invariants (pkcs11Module_ <> null)
*/
@SuppressWarnings("restriction")
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.
*
* @author Karl
* Scheibelhofer
* @version 1.0
* @invariants
*/
public interface SlotRequirement {
/**
* Causes getSlotList to return all slots of the system that the
* respective module supports.
*/
public static 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.
*/
public static boolean TOKEN_PRESENT = true;
}
/**
* This interface defines the allowed constants for the wanted waiting
* behavior when calling waitForSlotEvent.
*
* @author Karl
* Scheibelhofer
* @version 1.0
* @invariants
*/
public interface WaitingBehavior {
/**
* Tells waitForSlotEvent to block until an event occurs.
*/
public static boolean BLOCK = false;
/**
* Tells waitForSlotEvent to return immediately.
*/
public static boolean DONT_BLOCK = true;
}
/**
* Interface to the underlying PKCS#11 module.
*/
protected PKCS11 pkcs11Module_;
protected String pkcs11ModuleName_;
/**
* Create a new module that uses the given PKCS11 interface to interact with
* the token.
*
* @param pkcs11Module
* The interface to interact with the token.
* @preconditions
* @postconditions
*/
protected Module(String pkcs11ModuleName) {
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.
* @preconditions (pkcs11ModuleName <> null)
* and (pkcs11ModuleName is a valid PKCS#11 module name)
* @postconditions
*/
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 not a file");
}
if (!file.canRead()) {
throw new IOException("Can not read file " + pkcs11ModuleName + "");
}
return new Module(pkcs11ModuleName);
}
/**
* 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.
* @preconditions (pkcs11ModuleName <> null)
* and (pkcs11ModuleName is a valid PKCS#11 module name)
* @postconditions
*/
/*
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.
* @preconditions
* @postconditions (result <> null)
*/
public Info getInfo()
throws TokenException {
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.
* @preconditions
* @postconditions
*/
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() {
public Object CK_CREATEMUTEX()
throws sun.security.pkcs11.wrapper.PKCS11Exception {
return mutexHandler.createMutex();
}
};
wrapperInitArgs.DestroyMutex = new CK_DESTROYMUTEX() {
public void CK_DESTROYMUTEX(Object pMutex)
throws sun.security.pkcs11.wrapper.PKCS11Exception {
mutexHandler.destroyMutex(pMutex);
}
};
wrapperInitArgs.LockMutex = new CK_LOCKMUTEX() {
public void CK_LOCKMUTEX(Object pMutex)
throws sun.security.pkcs11.wrapper.PKCS11Exception
{
mutexHandler.lockMutex(pMutex);
}
};
wrapperInitArgs.UnlockMutex = new CK_UNLOCKMUTEX() {
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);
}
}
/**
* 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(Object)
method of the
* underlying PKCS11 module.
*
* @param args
* Must be null in version 2.x of PKCS#11.
* @exception TokenException
* If finalization fails.
* @preconditions (args == null)
* @postconditions
*/
public void finalize(Object args)
throws TokenException {
try {
pkcs11Module_.C_Finalize(args);
} catch (sun.security.pkcs11.wrapper.PKCS11Exception ex) {
throw new PKCS11Exception(ex);
}
}
/**
* 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 .
* @preconditions
* @postconditions (result <> null)
*/
public Slot[] getSlotList(boolean tokenPresent)
throws TokenException {
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.
* @preconditions (reserved == null)
* @postconditions (result <> null)
*/
/*
public Slot waitForSlotEvent(boolean dontBlock, Object 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.
* @preconditions
* @postconditions (result <> null)
*/
public PKCS11 getPKCS11Module() {
return pkcs11Module_;
}
/**
* Returns the string representation of this object.
*
* @return The string representation of object
*/
public String toString() {
return (pkcs11Module_ != null) ? pkcs11Module_.toString() : null;
}
/**
* This finalize method tries to finalize the module by calling
* finalize()
of the Java object of the PKCS11 module.
* Note that this method does not call the finalize(Object)
* (C_Finalize(Object)
) method of the PKCS11 module!
* This method is the reserved Java method called by the garbage collector.
* Don't get confused by the same name.
*
* @exception Throwable
* If finalization fails.
* @preconditions
* @postconditions
* @see #finalize(Object)
*/
public void finalize()
throws Throwable {
// pkcs11Module_.finalize();
Method method = PKCS11.class.getDeclaredMethod("finalize");
method.setAccessible(true);
method.invoke(pkcs11Module_);
super.finalize();
}
/**
* 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.
* @preconditions
* @postconditions
*/
@Override
public boolean equals(java.lang.Object otherObject) {
if (this == otherObject) {
return true;
}
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.
* @preconditions
* @postconditions
*/
@Override
public int hashCode() {
return pkcs11Module_.hashCode();
}
}