Previous section.

Common Security: CDSA and CSSM
Copyright © 1997 The Open Group

Add-In Module Administration

Besides security services, there are several additional steps that must be performed by the module developer in order to insure access to the module via CSSM.

To insure system integrity, a module developer must create a set of digital credentials to be verified by CSSM when the module is attached.

The module developer will need to create an installation program to inform CSSM and applications of the module's identity and capabilities.

Finally, the module developer will need to insure that the appropriate sequence of component verification and module initialization steps occur prior to dynamic binding of the module with CSSM.

Manufacturing an Add-In Module

A complete set of credentials must be created for each CSSM add-in security service module as part of the module manufacturing process. These credentials are required by CSSM in order to maintain the integrity of the CDSA system. A full set of credentials are shown in Credentials of an Add-In Service Module and Certificate Chain for an Add-In Service Module . The set includes:

These three objects must be zipped to form a single set of credentials. Multiple implementations of standard zip algorithms interoperate on one or more platforms, hence a zipped, signed manifest retains a substantial degree of interoperability.

Figure: Credentials of an Add-In Service Module

The module's certificate is the leaf in one or more certificate chains. Each chain is rooted at one of a small number of known, trusted public keys. A single chain is shown in Certificate Chain for an Add-In Service Module . A CSSM vendor issues a certificate to the module vendor, signed with the private key of the CSSM vendor's certificate. The module vendor issues a certificate for each of its products, signing the product certificate with the module vendor's certificate. The CSSM Embedded Integrity Services Library (EISL) embeds a set of CSSM vendor public root keys. These keys are recognized roots of trust and are used when verifying a module's certificate. At runtime, EISL can also accepts additional public root keys as points of trust.

Figure: Certificate Chain for an Add-In Service Module

The manifest forms a complete description of an add-in module. A manifest includes a manifest section for each object code file that is part of a module's implementation. Each manifest section contains:

The object code files are standard OS-managed entities. Object files do not embed their digital signatures, instead, signatures are stored in a manifest separate from, but related to, the object files.

A digest of each manifest section is then computed and stored in the signature info file.

The signature file contains the PKCS#7 signature computed over the signature info file.

This set of credentials must be manufactured when the module is manufactured. Assuming a module manufacturer already has a certificate from a CSSM manufacturer, the module manufacturing process proceeds as follows:

  1. Generate an X.509 product certificate for the module and sign it with the manufacturer's certificate.

  2. Create a SHA-1 digest of each implementation component (object code file) used in the module.

  3. Build a manifest which describes the module by referencing all object code files, digests of those files and the cryptographic capabilities (attributes) embedded in those files.

  4. Build a signature info file which contains a SHA-1 digest of each manifest section.

  5. Sign a SHA-1 digest of the signature info file using the private key of the product's certificate.

  6. Create a PKCS #7 signature containing the signature info file digest, the product certificate and the signature.

  7. Place the PKCS #7 signature in a signature file.

It is of the utmost importance that the object code files and the manifest be signed using the private key associated with the product certificate. This tightly binds the identity in the certificate with "what the module is" (that is, the object code files themselves) and with "what the module claims it is" (that is, the capability descriptions in the manifest).

Authenticating to Multiple CSSM Vendors

A single add-in module can authenticate with and attach to different instances of CSSM, even if these instances require add-in module credentials based on difference roots of trust. Signature File for an Add-In Module . shows a complete set of credentials for an add-in module that can authenticate with a CSSM that accepts any one of three roots of trust. The credentials include three certificate chains. Each chain has a distinct root, but all chains share a common leaf certificate. This leaf certificate is used to sign the add-in module product. All three certificate chains are included in the signature file containing the credentials for this add-in module. When CSSM1 attempts to verify the add-in module's credential, a verified certificate chain will be constructed from the add-in module's leaf certificate to the root certificate containing public Key PK1, which is recognized as a point of trust by CSSM1. Hence the ad-in module's credentials will be successfully verified.
Figure: Signature File for an Add-In Module
that can authenticate with three distinct roots of trust

Obtaining an Add-In Module Manufacturing Certificate

Every add-in module must have an associated set of credentials, including a product certificate signed by the module manufacturer's certificate. If the module must be fully authenticated by the CSSM, then the module manufacturer must obtain a manufacturing certificate from each CSSM vendor it wishes to work with. The specific procedure for obtaining a manufacturing certificate depends on the CSSM vendor. The manufacturing certificate must be signed with the CSSM vendor's certificate and returned to the add-in module vendor.

Issuing an Add-In Module Product Certificate

A product certificate should be issued for each distinct product. What constitutes a distinct product is defined by the add-in module vendor. The product certificate must be directly or indirectly signed by the add-in module vendor's manufacturing certificate. Issuing a product certificate incorporates some of the processes of a Certificate Authority.

Manufacturing Add-In Modules

Manufacturing an add-in module is a three step process:

  1. Incorporating integrity-checking facilities and roots of trust in the product software

  2. Compiling the software components of the product

  3. Generating integrity credentials for the add-in module product

An add-in module that performs self-check and/or authenticates CSSM during module attach must:

The root of trust for self-check is the public key of the product certificate. The root of trust for authenticating a CSSM is the public root key of the CSSM vendor. Roots of trust can be presented as certificates or as keys. The add-in module should include the roots for all CSSM vendors that it trusts. This knowledge can be embedded as part of the module manufacturing process. Once the roots of trust are known, attach-time integrity checking is performed by invoking the Embedded Integrity Services Library (EISL).

CSSM invokes the module's AddInAuthenticate function to initiate the module's integrity check of CSSM. Although CSSM cannot determine that the add-in module has performed self-check and verified CSSM's credentials it is highly recommended that modules use EISL to perform these checks at attach-time and periodically during execution based on elapsed time or usage. Failure to perform these verifications during module attach processing compromises the integrity of the entire runtime environment.

After the roots of trust have been incorporated into the software component of the product and all product software components have been compiled and linked with EISL, the add-in module credentials should be created. These credentials are partitioned and persistently stored in three files:

The manifest file contains:

The capability description is mandatory for add-in modules that provide cryptographic services. It is highly recommended that all add-in modules, regardless of service type, include their capability description in their manifest file. The description is a flattened representation of the information defined by the CSSM_MODULE_INFO structure. This information is stored as an attribute value in the manifest. The hashes must be computed and included in the manifest file.

After the manifest file is created, the signer information file is created. The signer's information file must contain:

Finally the signature block file is created. The signature block file must contain:

The signing operation must be performed using the private key associated with the product certificate.

These credentials (three files) must be included with the add-in module that will be installed using CSSM_ModuleInstall. During installation these files should be placed in a subdirectory of the file system directory containing the add-in module object code files.

Installing an Add-In Module

Before an application can use a module, the module's name, location and description must be registered with CSSM by an installation application. The name given to a module includes both a logical name and a globally-unique identifier (GUID). The logical name is a string chosen by the module developer to describe the module. The GUID is a structure used to differentiate between library modules in the CSSM registry. GUIDs are discussed in more detail below. The location of the module is required at installation time so the CSSM can locate the module and its credentials when an application requests an attach. The module description indicates to CSSM the security services available within this module. The module description is clarified below.

Global Unique Identifiers (GUIDs)

Each module must have a globally-unique identifier (GUID) that the CSSM, applications, and the module itself use to uniquely identify a given module. The GUID is used by the CSSM registry to expose add-in module availability and capabilities to applications. A module uses its GUID to identify itself when it sets an error. When attaching the library, the application uses the GUID to identify the requested module.

A GUID is defined as:

typedef struct cssm_guid {
    uint32 Data1;
    uint16 Data2;
    uint16 Data3;
    uint8 Data4[8];
} CSSM_GUID, *CSSM_GUID_PTR;

GUID generators are publicly available for Windows* 95, Windows NT*, and on many UNIX* platforms.

The Module Description

At install time, the installation program must inform CSSM of the ways in which this module can be used. The module usage information includes indicators of the overall module capabilities and descriptions of the security services available from this module. The overall module capabilities include indicators such as the module's threading properties or exportability. The security service descriptions include information on each service, its sub-services, and any embedded products or services. For example, a module description might indicate that this is an exportable module containing a DL service and a CSP service, where the CSP service provides one sub-service to access a software token and a second sub-service to access a hardware token. The module description is made available to applications via queries to the CSSM registry.

Attaching an Add-In Module

Before an application can use the functions of a specific module sub-service, it must use the CSSM_ModuleAttach function to request that CSSM attach to the module's sub-service. On the first attach, CSSM verifies the integrity of the add-in module prior to loading the module. Loading the module initiates a call to an OS-specific main entry point in the module. The module must perform self-check and return to CSSM. CSSM invokes the AddInAuthenticate function implemented by the add-in module. Within that function, the add-in module must verify the integrity of CSSM.

The Embedded Integrity Services Library (EISL) must be used to perform this verification. If verification fails, the add-in module is responsible for terminating the attach process. When EISL returns a failure condition, then either the CSSM has been tampered or the attaching add-in module does not recognize the certificate of the CSSM that is attempting to attach the add-in module. The add-in module must terminate the attach. The module should not register it service function table with the suspect CSSM. The add-in module should perform clean-up operations and exit voluntarily. The module has refused to provide service in an environment that it could not verify. If verification succeeds, then the add-in module should proceed to register with CSSM.

On registration, the add-in module registers its tables of service function pointers with CSSM and receives the application's memory management upcalls. CSSM then uses the module function table to call the module's Initialize function to confirm version compatibility and calls the module's EventNotify function to indicate that an attach operation is occurring. Once these steps have successfully completed, CSSM returns a handle to the calling application which will identify the application to module sub-service pairing in future function calls. CSSM will notify the module of subsequent attach requests from the application by using the module's EventNotify function. Subsequent attach operations do not require integrity verification.

Module Entry Point

When CSSM first attaches to or last detaches from a module, it initiates an OS-specific entry point. For the Windows NT* operating system, DLLMain is the entry point. For SunOS, _init and _fini are the entry points. On attach, this function will be responsible for authenticating CSSM and then calling CSSM_RegisterServices. On detach, it will be responsible for calling CSSM_DeregisterServices. To avoid OS-related conflicts, any setup or cleanup operations should be performed in the module's Initialize and Terminate functions.

Bilateral Authentication

On attach, CSSM and the add-in module verify their own and each other's credentials by following CSSM's bilateral authentication protocol. These practices of self-checking and cross-checking by other parties increases the level of tamper detection provided by CDSA. This bilateral authentication protocol is supported by the services of the CSSM Embedded Integrity Services Library (EISL).

The basic steps in bilateral authentication during module attach are defined as follows:

  1. CSSM performs a self integrity check

  2. CSSM performs an integrity check of the attaching module

  3. CSSM verifies secure linkage by checking that the initiation point is within the verified module

  4. CSSM invokes the add-in module

  5. The add-in module performs a self integrity check

  6. The add-in module performs an integrity check of CSSM

  7. The add-in module verifies secure linkage by checking that the function call originated from the verified CSSM

Each authenticating entity invokes ISL functions to carry out the steps in this process. The following ISL functions are used to carry out the seven step bilateral authentication protocol:

The ISL Verify functions check all aspects of a module's credentials, including the certificate chain, the signature on the manifest, the signature on the capability descriptions, and the signature on each object code file. The ISL Verify functions cannot check for secure linkage. CSSM and the add-in module must use the ISL address checking functions to verify secure linkage with the party being verified. The purpose of the secure linkage check is to verify that the object code just verified is either the code you are about to invoke or the code that invoked you. To free the data structures used in bilateral authentication, the ISL provides a Recycle function.

Module Function Table Registration

On attach, a module must register its function tables with CSSM by calling CSSM_RegisterServices. Its function tables will consist of a table of module management function pointers, plus one table of service provider interface function pointers for each (service, sub-service) pair contained in this module. The module management functions include Initialize, EventNotify, and Terminate. The service provider interface functions reflect the CSSM API for each security service. The function prototypes and their descriptions are given in the Service Provider Interface Specifications, the CSSM Cryptographic Service Provider Interface Specification, CSSM Trust Policy Interface Specification, CSSM Certificate Library Interface Specification, CSSM Data Storage Library Interface Specification, CSSM Key Recovery Interface Specification. If a sub-service does not support a given function in its service provider interface, the pointer to that function should be set to NULL. These structures are specified in the CSSM header files, <cssmspi.h>, <cssmcspi.h>, <cssmtpi.h>, <cssmcli.h>, and <cssmdli.h>.

Memory Management Upcalls

All memory allocation and de-allocation for data passed between the application and a module via CSSM is ultimately the responsibility of the calling application. Since a module needs to allocate memory to return data to the application, the application must provide the module with a means of allocating memory that the application has the ability to free. It does this by providing the module with memory management upcalls.

Memory management upcalls are pointers to the memory management functions used by the calling application. They are provided to a module via CSSM as a structure of function pointers. The functions will be the calling application's equivalent of malloc, free, calloc, and re-alloc and will be expected to have the same behavior as those functions. The function parameters will consist of the normal parameters for that function. The function return values should be interpreted in the standard manner. A module is responsible for making the memory management functions available to all of its internal functions.

Error Handling

When an error occurs inside a module, the function should call CSSM_SetError. The CSSM_SetError function takes the module's GUID and an error number as inputs. The module's GUID is used to identify where the error occurred. The error number will be used to describe the error.

The error number set by a module sub-service should fall into one of two ranges. The first range of error numbers is pre-defined by CSSM. These are errors that are common to all modules implementing a given sub-service function. They are described in the CSSM Cryptographic Service Provider Interface Specification as part of the function definitions. They are defined in the header file <cssmerr.h>, which is distributed as part of CSSM. The second range of error numbers is used to define module-specific error codes. These module-specific error codes should be in the range of CSSM_XX_PRIVATE_ERROR to CSSM_XX_END_ERROR, where XX stands for the service category abbreviation (CSP, TP, CL, DL). CSSM_XX_PRIVATE_ERROR and CSSM_XX_END_ERROR are also defined in the header file <cssmerr.h>. A module developer is responsible for making the definition and interpretation of their module-specific error codes available to applications.

When no error has occurred, but the appropriate return value from a function is CSSM_FALSE, that function should call CSSM_ClearError before returning. When the application receives a CSSM_FALSE return value, it is responsible for checking whether an error has occurred by calling CSSM_GetError. If the module function has called CSSM_ClearError, the calling application receives a CSSM_OK response from the CSSM_GetError function, indicating no error has occurred.

Install Example

An installation program is responsible for registering a module's capabilities with CSSM. A sample code-segment for the installation of a CL Module is shown in the example below.

CL Module Install

#include "cssm.h"
CSSM_GUID clm_guid =
{ 0x5fc43dc1, 0x732, 0x11d0, { 0xbb, 0x14, 0x0, 0xaa, 0x0,
                                           0x36, 0x67, 0x2d } };
CSSM_BOOL CLModuleInstall()
{
    CSSM_VERSION      cssm_version = { CSSM_MAJOR, CSSM_MINOR };
    CSSM_VERSION  cl_version = { CLM_MAJOR_VER, CLM_MINOR_VER };
    CSSM_GUID           cl_guid = clm_guid;
    CSSM_CLSUBSERVICE   sub_service;
    CSSM_SERVICE_INFO   service_info;
    CSSM_MODULE_INFO    module_info;
    char                SysDir[_MAX_PATH];

        /* fill sub-service information */
    sub_service.SubServiceId = 0;
    strcpy(sub_service.Description, "X509v3 SubService");
    sub_service.CertType = CSSM_CERT_X_509v3;
    sub_service.CertEncoding = CSSM_CERT_ENCODING_DER;
    sub_service.AuthenticationMechanism = CSSM_AUTHENTICATION_NONE;
    sub_service.NumberOfTemplateFields = NUMBER_X509_CERT_OIDS;
    sub_service.CertTemplates = X509_CERT_OIDS_ARRAY;
    sub_service.NumberOfTranslationTypes = 0;
    sub_service.CertTranslationTypes = NULL;
    sub_service.WrappedProduct.EmbeddedEncoderProducts = NULL;
    sub_service.WrappedProduct.NumberOfEncoderProducts = 0;
    sub_service.WrappedProduct.AccessibleCAProducts = NULL;
    sub_service.WrappedProduct.NumberOfCAProducts = 0;

        /* fill service information */
    strcpy(service_info.Description, "CL Service");
    service_info.Type = CSSM_SERVICE_CL;
    service_info.Flags = 0;
    service_info.NumberOfSubServices = 1;
    service_info.ClSubServiceList = &sub_service;
    service_info.Reserved = NULL;

        /* fill module information */
    module_info.Version = cl_version;
    module_info.CompatibleCSSMVersion = cssm_version;
    strcpy(module_info.Description, "Vendor Module");
    strcpy(module_info.Vendor, "Vendor Name");
    module_info.Flags = 0;
    module_info.ServiceMask = CSSM_SERVICE_CL;
    module_info.NumberOfServices = 1;
    module_info.ServiceList = &service_info;
    module_info.Reserved = NULL;

        /* get system dir path */
    GetSystemDirectory(SysDir, _MAX_PATH);

        /* Install the module */
    if (CSSM_ModuleInstall(clm_fullname_string,
                clm_filename_string,
                SysDir,
                &clm_guid,
                &module_info,
                NULL,
                NULL) == CSSM_FAIL)
    {
        return CSSM_FALSE;
    }

    return CSSM_TRUE;
}

Attach/Detach and AddInAuthenticate Example

A module is responsible for performing certain operations when CSSM attaches to and detaches from it. Modules that have been developed for Windows-based systems use the DllMain routine to perform those operations, as shown in the DL Module example below.

DLLMain

#include "cssm.h"
CSSM_GUID dl_guid =
{ 0x5fc43dc1, 0x732, 0x11d0, { 0xbb, 0x14, 0x0, 0xaa, 0x0,
                                           0x36, 0x67, 0x2d } };
CSSM_SPI_DL_FUNCS FunctionTable;
CSSM_REGISTRATION_INFO  DLRegInfo;
CSSM_MODULE_FUNCS       Services;
CSSM_SPI_MEMORY_FUNCS   DLMemoryFunctions;

BOOL WINAPI DllMain ( HANDLE hInstance, DWORD dwReason,
                                              LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
    ISL_VERIFIED_MODULE_PTR VerifiedDLModulePtr = NULL;
    VerifiedDLModulePtr = ISL_SelfCheck();
    if(VerifiedDLModulePtr == NULL) return FALSE;
    ISL_RecycleVerifiedModuleCredentials
                                 (VerifiedDLModulePtr);

    break;
}
    case DLL_THREAD_ATTACH:
    break;

    case DLL_THREAD_DETACH:
    break;

    case DLL_PROCESS_DETACH:
          if (CSSM_DeregisterServices (&dl_guid) != CSSM_OK)
          return FALSE;
    break;
}
    return TRUE;
}

CSSM_RETURN CSSMAPI AddInAuthenticate 
    (char* cssmCredentialPath,
    char* cssmSection
    char* appFileName,
    char* appPathName)
{

    ISL_VERIFIED_MODULE_PTR VerifiedCLModulePtr = NULL;
    ISL_STATUS islret;
    void* retAddress;
    ISL_CONST_DATA ConstData = {0, NULL};
    ISL_CONST_DATA ConstPathData = {0, NULL};
    ISL_CONST_DATA ConstSectionData = {0, NULL};

    ConstPathData.Length = strlen(cssmCredentialPath);
    ConstPathData.Data = (uint8*) cssmCredentialPath;
    ConstSectionData.Length = strlen(cssmSection);
    ConstSectionData.Data = (uint8*) cssmSection;

    /* Verify CSSM's static and dynamic footprint based on its 
                                                   manifest */
    VerifiedCSSMModulePtr = 
                         ISL_VerifyLoadedModuleAndCredentials
           (ConstPathDataConstSectionData,ConstData,ConstData);
    if(VerifiedCSSMModulePtr == NULL)
        return CSSM_FAIL;

    /* Verify secure linkage with CSSM */
    ISL_GetReturnAddress(retAddress);
    islret = ISL_CheckAddressWithinModule
                            (VerifiedCSSMModulePtr, retAddress);
    if(islret == ISL_FAIL)
    {
        ISL_RecycleVerifiedModuleCredentials(VerifiedCSSMModulePtr);
        VerifiedCSSMModulePtr = NULL;
        return CSSM_FAIL;
    }

    ISL_RecycleVerifiedModuleCredentials(VerifiedCSSMModulePtr);

    /* Authenticate application credentials directly if required*/
    if((appFileName == NULL) ]] (appPathName == NULL))
     return CSSM_FAIL;
    else 
    {
     /* Verify the application's credentials */
    }

    /* Fill in Registration information and register services
                                                        with CSSM*/
    DLRegInfo.Initialize            = DL_Initialize;  
    DLRegInfo.Terminate             = DL_Uninitialize;
    DLRegInfo.EventNotify           = DL_EventNotify;
    DLRegInfo.GetModuleInfo         = NULL;
    DLRegInfo.FreeModuleInfo        = NULL;
    DLRegInfo.ThreadSafe            = CSSM_TRUE;
    DLRegInfo.ServiceSummary        = CSSM_SERVICE_DL;
    DLRegInfo.NumberOfServiceTables = 1;
    DLRegInfo.Services              = &Services;

    /* Fill in Services */

    Services.ServiceType  = CSSM_SERVICE_DL;
    Services.DlFuncs = &FunctionTable;

    /* Fill in FunctionTable with function pointers */
    FunctionTable.Authenticate = DL_Authenticate;
    FunctionTable.DbOpen = DL_DbOpen;
    FunctionTable.DbClose = DL_DbClose;
    /* initialize all the other function pointers */
    FunctionTable.PassThrough = DL_PassThrough;

    /* Call CSSM_RegisterServices to
                        register the FunctionTable */
    /* with CSSM and to receive the application's
                                memory upcall table*/
    if (CSSM_RegisterServices (&dl_guid, &DLRegInfo,  
                     &DLMemoryFunctions,NULL) != CSSM_OK)
    return FALSE;

    /* Make the upcall table available to all
    functions in this library */

}


Why not acquire a nicely bound hard copy?
Click here to return to the publication details or order a copy of this publication.
You should also read the legal notice explaining the terms and conditions relating to the CDSA documentation.

Contents Next section Index