Application IDs

Within Chrystoki, each application has an application ID that is generated when the application starts, but which can also be specified in the configuration file. An application ID was historically a 64-bit integer, normally specified in two 32-bit parts. When an application invokes C_Initialize, the Chrystoki library automatically generates a default application ID. The default value is based on the application's process ID, so different applications will always have different application IDs. The application ID is also associated with each session created by the application.

Shared Login State and Application IDs

PKCS#11 specifies that sessions within an application (a single address space and all threads that execute within it) share a login state, meaning that if one session is logged in, all are logged in. If one logs out, all are logged out. Thus, if process A spawns multiple threads, and all of those threads open sessions on Token #1, then all of those sessions share a login state. If process B also has sessions open on Token #1, they are independent from the sessions of process A. The login state of process B sessions does not affect process A sessions, unless they conflict with one another (e.g. process A logs in as USER when process B is already logged in as SO).

Within Chrystoki and SafeNet tokens, login states are shared by sessions with the same application ID. This means that sessions within an application share a login state, but sessions across separate applications do not. However, Chrystoki does provides functionality allowing applications to alter their application IDs, so that separate applications can share a login state.

CAUTION!   The ability to share login states through the use of application IDs is a legacy feature. It can eliminate the need for repeated PED authentication across multiple applications, but this is not ideal for security reasons. To avoid these risks, it is recommended to use auto-activation in conjunction with a PED challenge password instead (see Activation and Auto-activation on Multi-factor- (PED-) Authenticated Partitions).

To change application IDs manually using the LunaCM appid command, see appid.

Why Share Login State Between Applications?

For most applications, this is unnecessary. If an application consists of a single perpetual process, unshared session states are sufficient. If the application supports multiple, separately-validated processes, unshared session states are also sufficient. Generally, applications that validate (login) separately are more secure.

It is only necessary to share login state between processes if all of the following conditions are true:

>the application designer wants to require only one login action by the user

>the application consists of multiple processes, each with their own sessions

> the system uses SafeNet CA3 tokens

The SafeNet CA3 token provides FIPS 140-1 level 3 security by using a separate port for password entry (where PINs take the form of special data keys). Use of these keys prevents an application from caching a password and using it to log in with multiple sessions. To log in to separate processes simultaneously, login state between those processes must be shared.

Login State Sharing Overview

The simplest form of the Chrystoki state-sharing functionality is the CA_SetApplicationID function. This function should be invoked after C_Initialize, but before any sessions are opened. Two separate applications can use this function to set their application IDs to the same value, and thus allow them to share login states between their sessions.

Alternatively, set the AppIdMajor and AppIdMinor fields in the Misc section of the Chrystoki configuration file. This causes default application IDs for all applications to be generated from these fields, rather than from each application's process ID. When these fields are set, all applications on a host system will share login state between their sessions, unless individual applications use the CA_SetApplicationID function.

Example

A sample configuration file (crystoki.ini for Windows) using explicit application IDs is duplicated here:

[Chrystoki2]
LibNT=D:\Program Files\SafeNet\LunaClient\cryptoki.dl
[Luna]
DefaultTimeOut=500000
PEDTimeout1=100000
PEDTimeout2=200000
[CardReader]
RemoteCommand=1
[Misc]
AppIdMajor=2
AppIdMinor=4

Problems may still arise. When all sessions of a particular application ID are closed, that application ID reverts to a dormant state. When another session for that application ID is created, the application ID is recreated, but always in the logged-out state, regardless of the state it was in when it went dormant.

For example, consider an application where a parent process sets its application ID, opens a session, logs the session in, then closes the session and terminates. Several child processes then set their application IDs, open sessions and try to use them. However, since the application ID went dormant when the parent process closed its session, the child processes find their sessions logged out. The logged-in state of the parent process's session was lost when it closed its session.

The CA_OpenApplicationID function can ensure that the login state of an application ID is maintained, even when no sessions belonging to that application ID exist. When CA_OpenApplicationID is invoked, the application ID is tagged so that it never goes dormant, even if no open sessions exist.

NOTE   Running CA_OpenApplication_ID does not set the application ID for the current process. You must first explicitly run CA_SetApplicationID to do this.

Login State Sharing Functions

Use the following functions to configure and manage login state sharing:

CA_SetApplicationID
CK_RV CK_ENTRY CA_SetApplicationID(
        CK_ULONG ulHigh,
        CK_ULONG ulLow
);

The CA_SetApplicationID function allows an application to set its own application ID, rather than letting the application ID be generated automatically from the application's process ID. CA_SetApplicationID should be invoked after C_Initialize, but before any session manipulation functions are invoked. If CA_SetApplicationID is invoked after sessions have been opened, results will be unpredictable.

CA_SetApplicationID always returns CKR_OK.

CA_OpenApplicationID
CK_RV CK_ENTRY CA_OpenApplicationID(
        CK_SLOT_ID slotID,
        CK_ULONG ulHigh,
        CK_ULONG ulLow
);

The CA_OpenApplicationID function forces a given application ID on a given token to remain active, even when all sessions belonging to the application ID have been closed. Normally, an application ID on a token goes dormant when the last session that belongs to the application ID is closed. When an application ID goes dormant, login state is lost, so when a new session is created within the application ID, it starts in the logged-out state. However, if CA_OpenApplicationID is used, the application ID is prevented from going dormant, so login state is maintained even when all sessions for an application ID are closed.

NOTE   Running CA_OpenApplication_ID does not set the application ID for the current process. You must first explicitly run CA_SetApplicationID to do this.

CA_OpenApplicationID can return CKR_SLOT_ID_INVALID or CKR_TOKEN_NOT_PRESENT.

CA_CloseApplicationID
CK_RV CK_ENTRY CA_CloseApplicationID(
        CK_SLOT_ID slotID,
        CK_ULONG ulHigh,
        CK_ULONG ulLow
);

The CA_CloseApplicationID function removes the property of an application ID that prevents it from going dormant. CA_CloseApplicationID also closes any open sessions owned by the given application ID. Thus, when CA_CloseApplicationID returns, all open sessions owned by the given application ID have been closed and the application ID has gone dormant.

CA_CloseApplicationID can return CKR_SLOT_ID_INVALID or CKR_TOKEN_NOT_PRESENT.

Application ID Examples

The following code fragments show how two separate applications might share a single application ID:

app 1:        app 2:
C_Initialize()
CA_SetApplicationID(3,4)
C_OpenSession()
C_Login() 
              C_Initialize()
              CA_SetApplicationID(3,4)
              C_OpenSession()
              C_GetSessionInfo()
              // Session info shows session
              // already logged in.         
              <perform work, no login 
              necessary>

C_Logout()
              C_GetSessionInfo()
              // Session info shows session
              // logged out.

C_CloseSession() 
              C_CloseSession()
C_Finalize() 
              C_Finalize()

The following code fragments show how one process might login for others:

Setup app:

C_Initialize()
CA_SetApplicationID(7,9)
CA_OpenApplicationID(slot,7,9)
C_OpenSession(slot)
C_Login()
C_CloseSession()

Spawn many child applications:

C_Finalize()

Terminate each child app:

              C_Initialize()
              CA_SetApplicationID(7,9)
              C_OpenSession(slot)
              <perform work, no login necessary>

Takedown app:

Terminate child applications:

              C_CloseSession()
              C_Finalize()
C_Initialize()
CA_CloseApplicationID(slot,7,9)
C_Finalize()