IAIK PKCS#11 Provider API Documentation
version 1.6

iaik.pkcs.pkcs11.provider
Class IAIKPkcs11

java.lang.Object
  extended by java.util.Dictionary<K,V>
      extended by java.util.Hashtable<java.lang.Object,java.lang.Object>
          extended by java.util.Properties
              extended by java.security.Provider
                  extended by iaik.pkcs.pkcs11.provider.IAIKPkcs11
All Implemented Interfaces:
java.io.Serializable, java.lang.Cloneable, java.util.Map<java.lang.Object,java.lang.Object>
Direct Known Subclasses:
IAIKPkcs112, IAIKPkcs113, IAIKPkcs114

public class IAIKPkcs11
extends java.security.Provider

This is a JCE provider implementation that uses a PKCS#11 library to perform cryptographic operations. This includes ciphers, signatures, message digests, key generation, key-pair generation, random generation, MACs and key agreements. The list of algorithms that this provider offers depends on the configured list of algorithms. Before you can use this provider, you have to install it. You can install it at runtime like this:

 
   IAIKPkcs11 smartCardProvider = new IAIKPkcs11();
   Security.addProvider(smartCardProvider);
 
 
or use static installation.

Despite its standard functionality of a JCE provider, this implementation offers some additional features.
The methods

 
   getGlobalProperties()
   getProperties()
 
 
provide access to the provider's global and the provider's instance configuration. The application can use the handler for creating delegate objects using
 
   getGlobalDelegateProvider()
   getDelegateProvider()
   setGlobalDelegateProvider(DelegateProvider)
   setDelegateProvider(DelegateProvider)
 
 
With the
 
   getLoginManager()
   setLoginManager(LoginManager)
 
 
methods, the application can provide its own handler for login operations.

Further details can be found on the product's page on our website or in the JCA specification.

Author:
Karl Scheibelhofer
See Also:
Provider, Security, Serialized Form
Invariants
(tokenManager_ <> null) and (properties_ <> null)

Nested Class Summary
 
Nested classes/interfaces inherited from class java.security.Provider
java.security.Provider.Service
 
Field Summary
static java.io.PrintStream debugStream_
          The output stream for debug messages.
static java.io.PrintStream errorStream_
          The output stream for error messages.
static java.lang.String PROVIDER_BASE_NAME
          The name the provider is registered to Java.
static java.lang.String PROVIDER_INFO_BASE
          The info for this provider that is registered to Java.
static double PROVIDER_VERSION
          The version of this implementation.
 
Constructor Summary
IAIKPkcs11()
          Default constructor.
IAIKPkcs11(java.util.Properties configuration)
          Constructor for the provider that takes its configuration as a argument.
 
Method Summary
 void disableCleanerThread()
          removes the cleanerThread_ from the shutdown hook
static void discardProviderInstance(IAIKPkcs11 provider)
          Discards the given provider instance.
 boolean equals(java.lang.Object other)
          We override this method to check for reference equality, because we use several instances of the same class, which may be considered equal otherwise.
static IAIKPkcs11 getCurrentProviderInstance()
          Gets the current provider instance.
 DelegateProvider getDelegateProvider()
          Get the current delegate provider.
static DelegateProvider getGlobalDelegateProvider()
          Get the current delegate provider.
static KeyHandler getGlobalKeyHandler()
          Get the current global key handler.
static java.util.Properties getGlobalProperties()
          Get the global configuration of provider class.
 java.lang.String getInfo()
          Returns a human-readable description of the provider and its services.
 java.lang.String getKeystoreSupportProvider()
          Get the keystore support provider.
 LoginManager getLoginManager()
          Get the login manager used by this provider to login the user, to change the user PIN and to logout.
static iaik.pkcs.pkcs11.Module getModule()
          Get the PKCS#11 module of the static configuration.
static iaik.pkcs.pkcs11.Module getModule(java.util.Properties configuration)
          Get the PKCS#11 module of the given configuration properties.
 java.lang.String getModuleAlreadyInitialized()
          Get the behavior in case of a CKR_CRYPTOKI_ALREADY_INITIALIZED error upon module initialization.
 java.lang.String getModuleInitializationParameters()
          Get the current delegate provider.
static IAIKPkcs11 getNewProviderInstance()
          Gets a new provider instance.
static IAIKPkcs11 getNewProviderInstance(java.util.Properties properties)
          Gets a new provider instance.
 java.util.Properties getProperties()
          Get the configuration of this provider.
 java.lang.String getProperty(java.lang.String key)
          We override this method to check if the requested algorithm is supported by the current token.
 java.lang.String getProperty(java.lang.String key, java.lang.String defaultValue)
          Overridden to ensure thread-safety, because we also synchronized getProperty(String).
static IAIKPkcs11 getProviderInstance(int instanceNumber)
          Get a reference to the already instantiated provider with the given number.
static int getProviderInstanceCount()
          Get the number of instances that have already been created.
static int getProviderInstanceNumber(java.lang.String providerName)
          Get the instance number of the IAIKPkcs11 provider with the given name.
 int getSessionPoolMaxSize()
          Get the maximum number of sessions to keep in the session pool of the token manager.
 TokenManager getTokenManager()
          Get the token manager of this provider.
 char[] getUserPIN()
          Get the user PIN, which has been set for this provider.
 double getVersion()
          Returns the version number for this provider.
 int hashCode()
          Override to ensure consistency with equals(Object).
 void initialize()
          Initializes this provider based on its current configuration.
static void insertProviderAtForJDK14(java.security.Provider provider, int position)
          Adds the give JCE provider to the Security class of JCA/JCE using a workaround that enables the provider to be added in the first position in JDK 1.4 and later.
 boolean isCheckMechanismSupported()
          Get if the provider checks, if a requested algorithm is supported by the underlying PKCS#11 token.
static boolean isEnableSoftwareDelegation()
          Check, if the software delegation feature of the PKCS#11 provider is enabled.
static boolean isIAIKPkcs11Provider(java.security.Provider provider)
          Check, if the given provider is a IAIKPkcs11 provider.
 boolean isLoginKeystoreOnDemand()
          Enable or disable login on demand for the keystore.
 boolean isMultiThreadInit()
          Check, if the provider initializes the underlying PKCS#11 module for multi-threaded operation or not.
 void setCheckMechanismSupported(boolean checkMechanismSupported)
          Set if the provider should check, if a requested algorithm is supported by the underlying PKCS#11 token.
 void setDelegateProvider(DelegateProvider delegateProvider)
          Set the delegate provider.
static void setEnableSoftwareDelegation(boolean enableSoftwareDelegation)
          Enable or disable the software delegation feature of the PKCS#11 provider.
static void setGlobalDelegateProvider(DelegateProvider globalDelegateProvider)
          Set the global delegate provider.
static void setGlobalKeyHandler(KeyHandler keyHandler)
          Set the key handler.
 void setKeystoreSupportProvider(java.lang.String providerName)
          Set the keystore support provider.
 void setLoginKeystoreOnDemand(boolean loginOnDemand)
          Enable or disable login on demand for the keystore.
 void setLoginManager(LoginManager loginManager)
          Set the login manager used by this provider to login the user, to change the user PIN and to logout.
 void setModuleAlreadyInitialized(java.lang.String value)
          Set the behavior in case of a CKR_CRYPTOKI_ALREADY_INITIALIZED error upon module initialization.
 void setModuleInitializationParameters(java.lang.String initializationParameters)
          Set an initialization parameter string to be passed to the underlying PKCS#11 module during initialization.
 void setMultiThreadInit(boolean multiThread)
          Set, if the provider initializes the underlying PKCS#11 module for multi-threaded operation or not.
 void setSessionPoolMaxSize(int sessionPoolMaxSize)
          Set the maximum number of sessions to keep in the session pool of the token manager.
 void setUserPIN(char[] userPIN)
          Set the user PIN this provider shall use.
 java.lang.String toString()
          Returns a string with the name and the version number of this provider.
 
Methods inherited from class java.security.Provider
clear, elements, entrySet, get, getName, getService, getServices, keys, keySet, load, put, putAll, remove, values
 
Methods inherited from class java.util.Properties
list, list, load, loadFromXML, propertyNames, save, setProperty, store, store, storeToXML, storeToXML, stringPropertyNames
 
Methods inherited from class java.util.Hashtable
clone, contains, containsKey, containsValue, isEmpty, size
 
Methods inherited from class java.lang.Object
getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

PROVIDER_BASE_NAME

public static final java.lang.String PROVIDER_BASE_NAME
The name the provider is registered to Java.

See Also:
Constant Field Values

PROVIDER_VERSION

public static final double PROVIDER_VERSION
The version of this implementation.

See Also:
Constant Field Values

PROVIDER_INFO_BASE

public static final java.lang.String PROVIDER_INFO_BASE
The info for this provider that is registered to Java.

See Also:
Constant Field Values

debugStream_

public static java.io.PrintStream debugStream_
The output stream for debug messages.


errorStream_

public static java.io.PrintStream errorStream_
The output stream for error messages.

Constructor Detail

IAIKPkcs11

public IAIKPkcs11()
           throws IAIKPkcs11Exception
Default constructor. Reads configuration and algorithm info, and instantiates the configured token manager object. Use getInstance() if possible.

Throws:
IAIKPkcs11Exception - If the provider is not appropriately configured.
Postconditions
(properties_ <> null) and (tokenManager_ <> null)

IAIKPkcs11

public IAIKPkcs11(java.util.Properties configuration)
           throws IAIKPkcs11Exception
Constructor for the provider that takes its configuration as a argument. The given configuration has higher priority than any default configuration or any configuration done in a statically configured property file. Any property missing in the given properties are taken from the defaults. Currently, from the given properties, only the first level properties are taken into account, its defaults are ignored.

Parameters:
configuration - The configuration properties to use for this provider instance.
Throws:
IAIKPkcs11Exception - If the initialization fails.
Method Detail

isIAIKPkcs11Provider

public static boolean isIAIKPkcs11Provider(java.security.Provider provider)
Check, if the given provider is a IAIKPkcs11 provider.

Parameters:
provider - The provider to check.
Returns:
True, if the given provider is a IAIKPkcs11 provider, false otherwise.

getNewProviderInstance

public static IAIKPkcs11 getNewProviderInstance()
Gets a new provider instance. Equals new IAIKPkcs11().

Returns:
the new provider instance

getNewProviderInstance

public static IAIKPkcs11 getNewProviderInstance(java.util.Properties properties)
Gets a new provider instance. Equals new IAIKPkcs11(properties).

Parameters:
properties - the properties
Returns:
the new provider instance

discardProviderInstance

public static void discardProviderInstance(IAIKPkcs11 provider)
Discards the given provider instance.

Parameters:
provider - the provider

getProviderInstance

public static IAIKPkcs11 getProviderInstance(int instanceNumber)
Get a reference to the already instantiated provider with the given number. This method does not instantiate any provider, it only returns a reference to an existing provider.

Parameters:
instanceNumber - The number (index) of the provider to get (Starting at index 1).
Returns:
A reference to the provider with the given index or null, if there is no provider with this index.

getCurrentProviderInstance

public static IAIKPkcs11 getCurrentProviderInstance()
Gets the current provider instance. FIXME does just return the first available instance. There is no way in Sun's JCE to access the own provider.

Returns:
the current provider instance

getProviderInstanceNumber

public static int getProviderInstanceNumber(java.lang.String providerName)
Get the instance number of the IAIKPkcs11 provider with the given name. The given name may also be just the instance number of the provider.

Parameters:
providerName - The name of the IAIKPkcs11 provider instance.
Returns:
The instance number, or -1 if there is no such IAIKPkcs11 provider.

getProviderInstanceCount

public static int getProviderInstanceCount()
Get the number of instances that have already been created.

Returns:
The number of instances that have already been created.
Postconditions
(result >= 0)

insertProviderAtForJDK14

public static void insertProviderAtForJDK14(java.security.Provider provider,
                                            int position)
Adds the give JCE provider to the Security class of JCA/JCE using a workaround that enables the provider to be added in the first position in JDK 1.4 and later. These JDKs have a bug hat prevents installing some providers in the first position in the normal way. The usage is pretty much the same as that of Security.insertProviderAt(Provider, int).

Parameters:
provider - The provider to add.
position - The position where to install the provider. 1 to become the first provider.
See Also:
Security.insertProviderAt(Provider, int)
Preconditions
(provider <> null)

isEnableSoftwareDelegation

public static boolean isEnableSoftwareDelegation()
Check, if the software delegation feature of the PKCS#11 provider is enabled. This is a global feature for all instances of this provider.

Returns:
enable True, if the software delegation feature is enabled; false, otherwise.

setEnableSoftwareDelegation

public static void setEnableSoftwareDelegation(boolean enableSoftwareDelegation)
Enable or disable the software delegation feature of the PKCS#11 provider. This can only be set globally for all instances of this provider.

Parameters:
enableSoftwareDelegation - True, to enable software delegation, false to disable it.

getGlobalDelegateProvider

public static DelegateProvider getGlobalDelegateProvider()
Get the current delegate provider. This is used, if an engine class cannot determine to which provider instance it belongs. This situation occurs for message digest objects and engine classes that have not been initialized with a key of their provider, because the key objects carry a reference to their provider instance.

Returns:
The current delegate provider.
Postconditions
(result <> null)

setGlobalDelegateProvider

public static void setGlobalDelegateProvider(DelegateProvider globalDelegateProvider)
Set the global delegate provider. This is used, if an engine class cannot determine to which provider instance it belongs. This situation occurs for message digest objects and engine classes that have not been initialized with a key of their provider, because the key objects carry a reference to their provider instance.

Parameters:
globalDelegateProvider - The new delegate provider. If this is null, the default delegate provider is used.

getGlobalProperties

public static java.util.Properties getGlobalProperties()
Get the global configuration of provider class.

Returns:
The global configuration as properties.
Postconditions
(result <> null)

getGlobalKeyHandler

public static KeyHandler getGlobalKeyHandler()
Get the current global key handler.

Returns:
The current global key handler.
Postconditions
(result <> null)

setGlobalKeyHandler

public static void setGlobalKeyHandler(KeyHandler keyHandler)
Set the key handler.

Parameters:
keyHandler - The new key handler. If this is null, the default key handler is used.

getModule

public static iaik.pkcs.pkcs11.Module getModule()
Get the PKCS#11 module of the static configuration. It only uses the value of the PKCS11_NATIVE_MODULE property.

Returns:
The module or null if no module has been configured.

getModule

public static iaik.pkcs.pkcs11.Module getModule(java.util.Properties configuration)
                                         throws IAIKPkcs11Exception
Get the PKCS#11 module of the given configuration properties. It only uses the value of the PKCS11_NATIVE_MODULE property. If the given properties do not contain this property, the property of the configure properties file is used.

Parameters:
configuration - The configuration properties.
Returns:
The module or null if no module has been configured.
Throws:
IAIKPkcs11Exception - If the configuration is incorrect.

getDelegateProvider

public DelegateProvider getDelegateProvider()
Get the current delegate provider.

Returns:
The current delegate provider.
Postconditions
(result <> null)

setDelegateProvider

public void setDelegateProvider(DelegateProvider delegateProvider)
Set the delegate provider.

Parameters:
delegateProvider - The new delegate provider. If this is null, the default delegate provider is used.

setModuleInitializationParameters

public void setModuleInitializationParameters(java.lang.String initializationParameters)
Set an initialization parameter string to be passed to the underlying PKCS#11 module during initialization. For instance, this can be used to access a Netscape/Mozilla software PKCS#11 module (e.g. softokn3.dll on Windows). For a Mozilla module, this string may look like this configdir='/user/home/dummy/.mozilla' certPrefix='' keyPrefix='' secmod='secmod.db'

Parameters:
initializationParameters - The parameter string for the PKCS#11 module.

getModuleInitializationParameters

public java.lang.String getModuleInitializationParameters()
Get the current delegate provider.

Returns:
The current delegate provider.
Postconditions
(result <> null)

getLoginManager

public LoginManager getLoginManager()
Get the login manager used by this provider to login the user, to change the user PIN and to logout.

Returns:
The current login manager.
Postconditions
(result <> null)

setLoginManager

public void setLoginManager(LoginManager loginManager)
Set the login manager used by this provider to login the user, to change the user PIN and to logout. If this is set to null, the configured default manager will be used.

Parameters:
loginManager - The login manager to use or null to use the configured default.

getUserPIN

public char[] getUserPIN()
Get the user PIN, which has been set for this provider. Every time that provider needs to login the user and no PIN has been provided by other means, it passes this PIN to the login manager when calling its LoginManager.loginUser(TokenManager, Session, char[]) method. However, it is then up to the concrete login manager, if it uses this PIN. The default login manager will use it.

Returns:
The currently set user PIN or null if none has been set.

setUserPIN

public void setUserPIN(char[] userPIN)
Set the user PIN this provider shall use. Every time that provider needs to login the user and no PIN has been provided by other means, it passes this PIN to the login manager when calling its LoginManager.loginUser(TokenManager, Session, char[]) method. However, it is then up to the concrete login manager, if it uses this PIN. The default login manager will use it.

Parameters:
userPIN - The user PIN to pass to the login manager.

getProperties

public java.util.Properties getProperties()
Get the configuration of this provider.

Returns:
The configuration as properties.
Postconditions
(result <> null)

getProperty

public java.lang.String getProperty(java.lang.String key)
We override this method to check if the requested algorithm is supported by the current token. This is only done, if this feature is enabled in the configuration properties.

Overrides:
getProperty in class java.security.Provider
Parameters:
key - The name of the requested algorithm.
Returns:
The class name of the implementing class or null if unsupported.
Preconditions
(key <> null)

getProperty

public java.lang.String getProperty(java.lang.String key,
                                    java.lang.String defaultValue)
Overridden to ensure thread-safety, because we also synchronized getProperty(String).

Overrides:
getProperty in class java.util.Properties
Parameters:
key - The properties key.
defaultValue - The default value.
Returns:
The class name of the implementing class or null if unsupported.
Preconditions
(key <> null)

getKeystoreSupportProvider

public java.lang.String getKeystoreSupportProvider()
Get the keystore support provider. The key store uses this provider to hash certificates and generate key specs.

Returns:
The name of the keystore support provider or null if the provider defaults are used.

setKeystoreSupportProvider

public void setKeystoreSupportProvider(java.lang.String providerName)
Set the keystore support provider. The key store uses this provider to hash certificates and generate key specs.

Parameters:
providerName - The name of the keystore support provider or null to use the default provider order.

isLoginKeystoreOnDemand

public boolean isLoginKeystoreOnDemand()
Enable or disable login on demand for the keystore. If this is set to true, the keystore will operate using a public session as long as possible. This will help preventing a PIN-prompt before the actual crypto operation starts.

Returns:
True, if login on demand is enabled, false otherwise.

setLoginKeystoreOnDemand

public void setLoginKeystoreOnDemand(boolean loginOnDemand)
Enable or disable login on demand for the keystore. If this is set to true, the keystore will operate using a public session as long as possible. This will help preventing a PIN-prompt before the actual crypto operation starts.

Parameters:
loginOnDemand - True, to enable login on demand, false to disable it.

isCheckMechanismSupported

public boolean isCheckMechanismSupported()
Get if the provider checks, if a requested algorithm is supported by the underlying PKCS#11 token. If enabled, it does not report the JCE algorithm as provided. If disabled, the provider always reports all algorithms which are configured in the iaik.pkcs.pkcs11.provider.IAIKPkcs11Algorithm.proprties. However, the provider will never report an algorithm as being supported which is not listed in this properties file.

Returns:
True, if the provider checks, if a requested algorithm is supported by the underlying PKCS#11 token, false otherwise.

setCheckMechanismSupported

public void setCheckMechanismSupported(boolean checkMechanismSupported)
Set if the provider should check, if a requested algorithm is supported by the underlying PKCS#11 token. If enabled, it does not report the JCE algorithm as provided. If disabled, the provider always reports all algorithms which are configured in the iaik.pkcs.pkcs11.provider.IAIKPkcs11Algorithm.proprties. However, the provider will never report an algorithm as being supported which is not listed in this properties file.

Parameters:
checkMechanismSupported - True, to check if an algorithm is supported by the token, false to not check it.

isMultiThreadInit

public boolean isMultiThreadInit()
Check, if the provider initializes the underlying PKCS#11 module for multi-threaded operation or not. If this is set to true, the provider will initialize the module with the CKF_OS_LOCKING_OK set to true. If set to false, the provider will initialize the module without any argument (NULL_PTR). To safely use a PKCS#11 module with multiple threads concurrently, this must be set to true.

Returns:
true, if the provider initializes the underlying PKCS#11 module for multi-threaded operation; false, otherwise.

setMultiThreadInit

public void setMultiThreadInit(boolean multiThread)
Set, if the provider initializes the underlying PKCS#11 module for multi-threaded operation or not. If this is set to true, the provider will initialize the module with the CKF_OS_LOCKING_OK set to true. If set to false, the provider will initialize the module without any argument (NULL_PTR). To safely use a PKCS#11 module with multiple threads concurrently, this must be set to true.

Parameters:
multiThread - true, if the provider initializes the underlying PKCS#11 module for multi-threaded operation; false, otherwise.

getModuleAlreadyInitialized

public java.lang.String getModuleAlreadyInitialized()
Get the behavior in case of a CKR_CRYPTOKI_ALREADY_INITIALIZED error upon module initialization. This corresponds to the MODULE_ALREADY_INITIALIZED property.

Returns:
The property value; e.g. ignore or exception.
Postconditions
(result <> null)

setModuleAlreadyInitialized

public void setModuleAlreadyInitialized(java.lang.String value)
Set the behavior in case of a CKR_CRYPTOKI_ALREADY_INITIALIZED error upon module initialization. This corresponds to the MODULE_ALREADY_INITIALIZED property.

Parameters:
value - The property value; e.g. ignore or exception.

getSessionPoolMaxSize

public int getSessionPoolMaxSize()
Get the maximum number of sessions to keep in the session pool of the token manager. The token manager creates sessions on demand and not in advance. That means the session pool is empty after start. Only open sessions that are currently unused are kept in the pool to be able to reuse them on demand.

Returns:
Set the maximum number of sessions to keep in the pool.

setSessionPoolMaxSize

public void setSessionPoolMaxSize(int sessionPoolMaxSize)
Set the maximum number of sessions to keep in the session pool of the token manager. The token manager creates sessions on demand and not in advance. That means the session pool is empty after start. Only open sessions that are currently unused are kept in the pool to be able to reuse them on demand.

Parameters:
sessionPoolMaxSize - Set the maximum number of sessions to keep in the pool.
Preconditions
(sessionPoolMaxSize >= 1)

getTokenManager

public TokenManager getTokenManager()
Get the token manager of this provider. Used for all token related operations.

Returns:
The token manager of this provider.
Postconditions
(result <> null)

getVersion

public double getVersion()
Returns the version number for this provider.

Overrides:
getVersion in class java.security.Provider
Returns:
the version number for this provider.

getInfo

public java.lang.String getInfo()
Returns a human-readable description of the provider and its services. This may return an HTML page, with relevant links.

Overrides:
getInfo in class java.security.Provider
Returns:
a description of the provider and its services.

toString

public java.lang.String toString()
Returns a string with the name and the version number of this provider.

Overrides:
toString in class java.security.Provider
Returns:
the string with the name and the version number for this provider.

initialize

public void initialize()
                throws IAIKPkcs11Exception
Initializes this provider based on its current configuration. Please take care when calling this method, because it changes substantial settings of this provider instance, which may cause those running operations to fail if they are associated with this provider.

Throws:
IAIKPkcs11Exception - If the provider is not appropriately configured.

disableCleanerThread

public void disableCleanerThread()
removes the cleanerThread_ from the shutdown hook


equals

public boolean equals(java.lang.Object other)
We override this method to check for reference equality, because we use several instances of the same class, which may be considered equal otherwise. This would cause the provider table of the framework to work incorrectly.

Specified by:
equals in interface java.util.Map<java.lang.Object,java.lang.Object>
Overrides:
equals in class java.util.Hashtable<java.lang.Object,java.lang.Object>
Parameters:
other - The other provider to compare to.
Returns:
true if this object refers to the same object instance than the other object.
Postconditions
(this == other)

hashCode

public int hashCode()
Override to ensure consistency with equals(Object).

Specified by:
hashCode in interface java.util.Map<java.lang.Object,java.lang.Object>
Overrides:
hashCode in class java.util.Hashtable<java.lang.Object,java.lang.Object>
Returns:
The hash code for this object, which is the identity hash code for tis object in the VM.
Postconditions
(result <> null)

IAIK PKCS#11 Provider API Documentation
version 1.6

IAIK JavaSecurity Website http://jce.iaik.tugraz.at/

IAIK at Graz University of Technology, Austria, Europe
Copyright 2001-2004, IAIK, Graz University of Technology, Inffeldgasse 16a, 8010 Graz, Austria. All Rights Reserved.
version 1.6