tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

fipstokn.c (70640B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 /*
      5 * This file implements PKCS 11 on top of our existing security modules
      6 *
      7 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
      8 *   This implementation has two slots:
      9 *  slot 1 is our generic crypto support. It does not require login
     10 *   (unless you've enabled FIPS). It supports Public Key ops, and all they
     11 *   bulk ciphers and hashes. It can also support Private Key ops for imported
     12 *   Private keys. It does not have any token storage.
     13 *  slot 2 is our private key support. It requires a login before use. It
     14 *   can store Private Keys and Certs as token objects. Currently only private
     15 *   keys and their associated Certificates are saved on the token.
     16 *
     17 *   In this implementation, session objects are only visible to the session
     18 *   that created or generated them.
     19 */
     20 #include "seccomon.h"
     21 #include "softoken.h"
     22 #include "lowkeyi.h"
     23 #include "pkcs11.h"
     24 #include "pkcs11i.h"
     25 #include "prenv.h"
     26 #include "prprf.h"
     27 
     28 #include <ctype.h>
     29 
     30 #ifdef XP_UNIX
     31 #define NSS_AUDIT_WITH_SYSLOG 1
     32 #include <syslog.h>
     33 #include <unistd.h>
     34 #endif
     35 
     36 #ifdef LINUX
     37 #include <pthread.h>
     38 #include <dlfcn.h>
     39 #define LIBAUDIT_NAME "libaudit.so.1"
     40 #ifndef AUDIT_CRYPTO_TEST_USER
     41 #define AUDIT_CRYPTO_TEST_USER 2400         /* Crypto test results */
     42 #define AUDIT_CRYPTO_PARAM_CHANGE_USER 2401 /* Crypto attribute change */
     43 #define AUDIT_CRYPTO_LOGIN 2402             /* Logged in as crypto officer */
     44 #define AUDIT_CRYPTO_LOGOUT 2403            /* Logged out from crypto */
     45 #define AUDIT_CRYPTO_KEY_USER 2404          /* Create,delete,negotiate */
     46 #define AUDIT_CRYPTO_FAILURE_USER 2405      /* Fail decrypt,encrypt,randomize */
     47 #endif
     48 static void *libaudit_handle;
     49 static int (*audit_open_func)(void);
     50 static void (*audit_close_func)(int fd);
     51 static int (*audit_log_user_message_func)(int audit_fd, int type,
     52                                          const char *message, const char *hostname, const char *addr,
     53                                          const char *tty, int result);
     54 static int (*audit_send_user_message_func)(int fd, int type,
     55                                           const char *message);
     56 
     57 static pthread_once_t libaudit_once_control = PTHREAD_ONCE_INIT;
     58 
     59 static void
     60 libaudit_init(void)
     61 {
     62    libaudit_handle = dlopen(LIBAUDIT_NAME, RTLD_LAZY);
     63    if (!libaudit_handle) {
     64        return;
     65    }
     66    audit_open_func = dlsym(libaudit_handle, "audit_open");
     67    audit_close_func = dlsym(libaudit_handle, "audit_close");
     68    /*
     69     * audit_send_user_message is the older function.
     70     * audit_log_user_message, if available, is preferred.
     71     */
     72    audit_log_user_message_func = dlsym(libaudit_handle,
     73                                        "audit_log_user_message");
     74    if (!audit_log_user_message_func) {
     75        audit_send_user_message_func = dlsym(libaudit_handle,
     76                                             "audit_send_user_message");
     77    }
     78    if (!audit_open_func || !audit_close_func ||
     79        (!audit_log_user_message_func && !audit_send_user_message_func)) {
     80        dlclose(libaudit_handle);
     81        libaudit_handle = NULL;
     82        audit_open_func = NULL;
     83        audit_close_func = NULL;
     84        audit_log_user_message_func = NULL;
     85        audit_send_user_message_func = NULL;
     86    }
     87 }
     88 #endif /* LINUX */
     89 
     90 /*
     91 * ******************** Password Utilities *******************************
     92 */
     93 static PRBool isLoggedIn = PR_FALSE;
     94 static PRBool isLevel2 = PR_TRUE;
     95 PRBool sftk_fatalError = PR_FALSE;
     96 
     97 /*
     98 * This function returns
     99 *   - CKR_PIN_INVALID if the password/PIN is not a legal UTF8 string
    100 *   - CKR_PIN_LEN_RANGE if the password/PIN is too short or does not
    101 *     consist of characters from three or more character classes.
    102 *   - CKR_OK otherwise
    103 *
    104 * The minimum password/PIN length is FIPS_MIN_PIN Unicode characters.
    105 * We define five character classes: digits (0-9), ASCII lowercase letters,
    106 * ASCII uppercase letters, ASCII non-alphanumeric characters (such as
    107 * space and punctuation marks), and non-ASCII characters.  If an ASCII
    108 * uppercase letter is the first character of the password/PIN, the
    109 * uppercase letter is not counted toward its character class.  Similarly,
    110 * if a digit is the last character of the password/PIN, the digit is not
    111 * counted toward its character class.
    112 *
    113 * Although NSC_SetPIN and NSC_InitPIN already do the maximum and minimum
    114 * password/PIN length checks, they check the length in bytes as opposed
    115 * to characters.  To meet the minimum password/PIN guessing probability
    116 * requirements in FIPS 140-2, we need to check the length in characters.
    117 */
    118 static CK_RV
    119 sftk_newPinCheck(CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
    120 {
    121    unsigned int i;
    122    int nchar = 0;     /* number of characters */
    123    int ntrail = 0;    /* number of trailing bytes to follow */
    124    int ndigit = 0;    /* number of decimal digits */
    125    int nlower = 0;    /* number of ASCII lowercase letters */
    126    int nupper = 0;    /* number of ASCII uppercase letters */
    127    int nnonalnum = 0; /* number of ASCII non-alphanumeric characters */
    128    int nnonascii = 0; /* number of non-ASCII characters */
    129    int nclass;        /* number of character classes */
    130 
    131    for (i = 0; i < ulPinLen; i++) {
    132        unsigned int byte = pPin[i];
    133 
    134        if (ntrail) {
    135            if ((byte & 0xc0) != 0x80) {
    136                /* illegal */
    137                nchar = -1;
    138                break;
    139            }
    140            if (--ntrail == 0) {
    141                nchar++;
    142                nnonascii++;
    143            }
    144            continue;
    145        }
    146        if ((byte & 0x80) == 0x00) {
    147            /* single-byte (ASCII) character */
    148            nchar++;
    149            if (isdigit(byte)) {
    150                if (i < ulPinLen - 1) {
    151                    ndigit++;
    152                }
    153            } else if (islower(byte)) {
    154                nlower++;
    155            } else if (isupper(byte)) {
    156                if (i > 0) {
    157                    nupper++;
    158                }
    159            } else {
    160                nnonalnum++;
    161            }
    162        } else if ((byte & 0xe0) == 0xc0) {
    163            /* leading byte of two-byte character */
    164            ntrail = 1;
    165        } else if ((byte & 0xf0) == 0xe0) {
    166            /* leading byte of three-byte character */
    167            ntrail = 2;
    168        } else if ((byte & 0xf8) == 0xf0) {
    169            /* leading byte of four-byte character */
    170            ntrail = 3;
    171        } else {
    172            /* illegal */
    173            nchar = -1;
    174            break;
    175        }
    176    }
    177    if (nchar == -1) {
    178        /* illegal UTF8 string */
    179        return CKR_PIN_INVALID;
    180    }
    181    if (nchar < FIPS_MIN_PIN) {
    182        return CKR_PIN_LEN_RANGE;
    183    }
    184    nclass = (ndigit != 0) + (nlower != 0) + (nupper != 0) +
    185             (nnonalnum != 0) + (nnonascii != 0);
    186    if (nclass < 3) {
    187        return CKR_PIN_LEN_RANGE;
    188    }
    189    return CKR_OK;
    190 }
    191 
    192 /* FIPS required checks before any useful cryptographic services */
    193 static CK_RV
    194 sftk_fipsCheck(void)
    195 {
    196    if (sftk_fatalError)
    197        return CKR_DEVICE_ERROR;
    198    if (isLevel2 && !isLoggedIn)
    199        return CKR_USER_NOT_LOGGED_IN;
    200    return CKR_OK;
    201 }
    202 
    203 #define SFTK_FIPSCHECK()                   \
    204    CK_RV rv;                              \
    205    if ((rv = sftk_fipsCheck()) != CKR_OK) \
    206        return rv;
    207 
    208 #define SFTK_FIPSFATALCHECK() \
    209    if (sftk_fatalError)      \
    210        return CKR_DEVICE_ERROR;
    211 
    212 /* grab an attribute out of a raw template */
    213 void *
    214 fc_getAttribute(CK_ATTRIBUTE_PTR pTemplate,
    215                CK_ULONG ulCount, CK_ATTRIBUTE_TYPE type)
    216 {
    217    int i;
    218 
    219    for (i = 0; i < (int)ulCount; i++) {
    220        if (pTemplate[i].type == type) {
    221            return pTemplate[i].pValue;
    222        }
    223    }
    224    return NULL;
    225 }
    226 
    227 #define __PASTE(x, y) x##y
    228 
    229 /* ------------- forward declare all the NSC_ functions ------------- */
    230 #undef CK_NEED_ARG_LIST
    231 #undef CK_PKCS11_FUNCTION_INFO
    232 
    233 #define CK_PKCS11_3_2 1
    234 #define CK_PKCS11_3_0 1
    235 
    236 #define CK_PKCS11_FUNCTION_INFO(name) CK_RV __PASTE(NS, name)
    237 #define CK_NEED_ARG_LIST 1
    238 
    239 #include "pkcs11f.h"
    240 
    241 /* ------------- forward declare all the FIPS functions ------------- */
    242 #undef CK_NEED_ARG_LIST
    243 #undef CK_PKCS11_FUNCTION_INFO
    244 
    245 #define CK_PKCS11_FUNCTION_INFO(name) CK_RV __PASTE(F, name)
    246 #define CK_NEED_ARG_LIST 1
    247 
    248 #include "pkcs11f.h"
    249 
    250 /* ------------- build the CK_CRYPTO_TABLE ------------------------- */
    251 static CK_FUNCTION_LIST_3_2 sftk_fipsTable_v32 = {
    252    { 3, 2 },
    253 
    254 #undef CK_NEED_ARG_LIST
    255 #undef CK_PKCS11_FUNCTION_INFO
    256 
    257 #define CK_PKCS11_3_2_ONLY 1
    258 #define CK_PKCS11_FUNCTION_INFO(name) \
    259    __PASTE(F, name)                  \
    260    ,
    261 
    262 #include "pkcs11f.h"
    263 
    264 };
    265 #undef CK_PKCS11_3_2_ONLY
    266 
    267 static CK_FUNCTION_LIST_3_0 sftk_fipsTable_v30 = {
    268    { 3, 0 },
    269 
    270 #undef CK_NEED_ARG_LIST
    271 #undef CK_PKCS11_FUNCTION_INFO
    272 
    273 #define CK_PKCS11_3_0_ONLY 1
    274 #define CK_PKCS11_FUNCTION_INFO(name) \
    275    __PASTE(F, name)                  \
    276    ,
    277 
    278 #include "pkcs11f.h"
    279 
    280 };
    281 #undef CK_PKCS11_3_0_ONLY
    282 
    283 /* forward declaration of special GetInfo functions */
    284 CK_RV FC_GetInfoV2(CK_INFO_PTR pInfo);
    285 CK_RV NSC_GetInfoV2(CK_INFO_PTR pInfo);
    286 CK_RV FC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
    287                            CK_MECHANISM_INFO_PTR pInfo);
    288 CK_RV NSC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
    289                             CK_MECHANISM_INFO_PTR pInfo);
    290 
    291 static CK_FUNCTION_LIST sftk_fipsTable_v2 = {
    292    { 2, 40 },
    293 
    294 #undef CK_PKCS11_3_0
    295 #define CK_PKCS11_2_0_ONLY 1
    296 #undef CK_NEED_ARG_LIST
    297 #undef CK_PKCS11_FUNCTION_INFO
    298 #define C_GetInfo C_GetInfoV2
    299 #define C_GetMechanismInfo C_GetMechanismInfoV2
    300 
    301 #define CK_PKCS11_FUNCTION_INFO(name) \
    302    __PASTE(F, name)                  \
    303    ,
    304 
    305 #include "pkcs11f.h"
    306 
    307 };
    308 
    309 #undef C_GetInfo
    310 #undef C_GetMechanismInfo
    311 #undef CK_NEED_ARG_LIST
    312 #undef CK_PKCS11_FUNCTION_INFO
    313 #undef CK_PKCS11_2_0_ONLY
    314 
    315 #undef __PASTE
    316 
    317 /*
    318 * Array is orderd by default first
    319 */
    320 static CK_INTERFACE fips_interfaces[] = {
    321    { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_fipsTable_v32, NSS_INTERFACE_FLAGS },
    322    { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_fipsTable_v30, NSS_INTERFACE_FLAGS },
    323    { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_fipsTable_v2, NSS_INTERFACE_FLAGS },
    324    { (CK_UTF8CHAR_PTR) "Vendor NSS Module Interface", &sftk_module_funcList, NSS_INTERFACE_FLAGS },
    325    { (CK_UTF8CHAR_PTR) "Vendor NSS FIPS Interface", &sftk_fips_funcList, NSS_INTERFACE_FLAGS }
    326 };
    327 /* must match the count of interfaces in fips_interfaces above*/
    328 #define FIPS_INTERFACE_COUNT PR_ARRAY_SIZE(fips_interfaces)
    329 
    330 /* CKO_NOT_A_KEY can be any object class that's not a key object. */
    331 #define CKO_NOT_A_KEY CKO_DATA
    332 
    333 #define SFTK_IS_KEY_OBJECT(objClass)    \
    334    (((objClass) == CKO_PUBLIC_KEY) ||  \
    335     ((objClass) == CKO_PRIVATE_KEY) || \
    336     ((objClass) == CKO_SECRET_KEY))
    337 
    338 #define SFTK_IS_NONPUBLIC_KEY_OBJECT(objClass) \
    339    (((objClass) == CKO_PRIVATE_KEY) || ((objClass) == CKO_SECRET_KEY))
    340 
    341 static CK_RV
    342 sftk_get_object_class_and_fipsCheck(CK_SESSION_HANDLE hSession,
    343                                    CK_OBJECT_HANDLE hObject, CK_OBJECT_CLASS *pObjClass)
    344 {
    345    CK_RV rv;
    346    CK_ATTRIBUTE class;
    347    class.type = CKA_CLASS;
    348    class.pValue = pObjClass;
    349    class.ulValueLen = sizeof(*pObjClass);
    350    rv = NSC_GetAttributeValue(hSession, hObject, &class, 1);
    351    if ((rv == CKR_OK) && SFTK_IS_NONPUBLIC_KEY_OBJECT(*pObjClass)) {
    352        rv = sftk_fipsCheck();
    353    }
    354    return rv;
    355 }
    356 
    357 #ifdef LINUX
    358 
    359 int
    360 sftk_mapLinuxAuditType(NSSAuditSeverity severity, NSSAuditType auditType)
    361 {
    362    switch (auditType) {
    363        case NSS_AUDIT_ACCESS_KEY:
    364        case NSS_AUDIT_CHANGE_KEY:
    365        case NSS_AUDIT_COPY_KEY:
    366        case NSS_AUDIT_DERIVE_KEY:
    367        case NSS_AUDIT_DESTROY_KEY:
    368        case NSS_AUDIT_DIGEST_KEY:
    369        case NSS_AUDIT_GENERATE_KEY:
    370        case NSS_AUDIT_LOAD_KEY:
    371        case NSS_AUDIT_UNWRAP_KEY:
    372        case NSS_AUDIT_WRAP_KEY:
    373        case NSS_AUDIT_ENCAPSULATE_KEY:
    374        case NSS_AUDIT_DECAPSULATE_KEY:
    375            return AUDIT_CRYPTO_KEY_USER;
    376        case NSS_AUDIT_CRYPT:
    377            return (severity == NSS_AUDIT_ERROR) ? AUDIT_CRYPTO_FAILURE_USER : AUDIT_CRYPTO_KEY_USER;
    378        case NSS_AUDIT_FIPS_STATE:
    379        case NSS_AUDIT_INIT_PIN:
    380        case NSS_AUDIT_INIT_TOKEN:
    381        case NSS_AUDIT_SET_PIN:
    382            return AUDIT_CRYPTO_PARAM_CHANGE_USER;
    383        case NSS_AUDIT_SELF_TEST:
    384            return AUDIT_CRYPTO_TEST_USER;
    385        case NSS_AUDIT_LOGIN:
    386            return AUDIT_CRYPTO_LOGIN;
    387        case NSS_AUDIT_LOGOUT:
    388            return AUDIT_CRYPTO_LOGOUT;
    389            /* we skip the fault case here so we can get compiler
    390             * warnings if new 'NSSAuditType's are added without
    391             * added them to this list, defaults fall through */
    392    }
    393    /* default */
    394    return AUDIT_CRYPTO_PARAM_CHANGE_USER;
    395 }
    396 #endif
    397 
    398 /**********************************************************************
    399 *
    400 *     FIPS 140 auditable event logging
    401 *
    402 **********************************************************************/
    403 
    404 PRBool sftk_audit_enabled = PR_FALSE;
    405 
    406 /*
    407 * Each audit record must have the following information:
    408 * - Date and time of the event
    409 * - Type of event
    410 * - user (subject) identity
    411 * - outcome (success or failure) of the event
    412 * - process ID
    413 * - name (ID) of the object
    414 * - for changes to data (except for authentication data and CSPs), the new
    415 *   and old values of the data
    416 * - for authentication attempts, the origin of the attempt (e.g., terminal
    417 *   identifier)
    418 * - for assuming a role, the type of role, and the location of the request
    419 */
    420 void
    421 sftk_LogAuditMessage(NSSAuditSeverity severity, NSSAuditType auditType,
    422                     const char *msg)
    423 {
    424 #ifdef NSS_AUDIT_WITH_SYSLOG
    425    int level;
    426 
    427    switch (severity) {
    428        case NSS_AUDIT_ERROR:
    429            level = LOG_ERR;
    430            break;
    431        case NSS_AUDIT_WARNING:
    432            level = LOG_WARNING;
    433            break;
    434        default:
    435            level = LOG_INFO;
    436            break;
    437    }
    438    /* timestamp is provided by syslog in the message header */
    439    syslog(level | LOG_USER /* facility */,
    440           "NSS " SOFTOKEN_LIB_NAME "[pid=%d uid=%d]: %s",
    441           (int)getpid(), (int)getuid(), msg);
    442 #ifdef LINUX
    443    if (pthread_once(&libaudit_once_control, libaudit_init) != 0) {
    444        return;
    445    }
    446    if (libaudit_handle) {
    447        int audit_fd;
    448        int linuxAuditType;
    449        int result = (severity != NSS_AUDIT_ERROR); /* 1=success; 0=failed */
    450        char *message = PR_smprintf("NSS " SOFTOKEN_LIB_NAME ": %s", msg);
    451        if (!message) {
    452            return;
    453        }
    454        audit_fd = audit_open_func();
    455        if (audit_fd < 0) {
    456            PR_smprintf_free(message);
    457            return;
    458        }
    459        linuxAuditType = sftk_mapLinuxAuditType(severity, auditType);
    460        if (audit_log_user_message_func) {
    461            audit_log_user_message_func(audit_fd, linuxAuditType, message,
    462                                        NULL, NULL, NULL, result);
    463        } else {
    464            audit_send_user_message_func(audit_fd, linuxAuditType, message);
    465        }
    466        audit_close_func(audit_fd);
    467        PR_smprintf_free(message);
    468    }
    469 #endif /* LINUX */
    470 #else
    471 /* do nothing */
    472 #endif
    473 }
    474 
    475 /**********************************************************************
    476 *
    477 *     Start of PKCS 11 functions
    478 *
    479 **********************************************************************/
    480 /* return the function list */
    481 CK_RV
    482 FC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList)
    483 {
    484 
    485    CHECK_FORK();
    486 
    487    *pFunctionList = &sftk_fipsTable_v2;
    488    return CKR_OK;
    489 }
    490 
    491 CK_RV
    492 FC_GetInterfaceList(CK_INTERFACE_PTR interfaces, CK_ULONG_PTR pulCount)
    493 {
    494    CK_ULONG count = *pulCount;
    495    *pulCount = FIPS_INTERFACE_COUNT;
    496    if (interfaces == NULL) {
    497        return CKR_OK;
    498    }
    499    if (count < FIPS_INTERFACE_COUNT) {
    500        return CKR_BUFFER_TOO_SMALL;
    501    }
    502    PORT_Memcpy(interfaces, fips_interfaces, sizeof(fips_interfaces));
    503    return CKR_OK;
    504 }
    505 
    506 /*
    507 * Get the requested interface, use the fips_interfaces array so we can
    508 * easily add new interfaces as they occur.
    509 */
    510 CK_RV
    511 FC_GetInterface(CK_UTF8CHAR_PTR pInterfaceName, CK_VERSION_PTR pVersion,
    512                CK_INTERFACE_PTR_PTR ppInterface, CK_FLAGS flags)
    513 {
    514    int i;
    515    for (i = 0; i < FIPS_INTERFACE_COUNT; i++) {
    516        CK_INTERFACE_PTR interface = &fips_interfaces[i];
    517        if (pInterfaceName && PORT_Strcmp((char *)pInterfaceName, (char *)interface->pInterfaceName) != 0) {
    518            continue;
    519        }
    520        if (pVersion && PORT_Memcmp(pVersion, (CK_VERSION *)interface->pFunctionList, sizeof(CK_VERSION)) != 0) {
    521            continue;
    522        }
    523        if (flags & ((interface->flags & flags) != flags)) {
    524            continue;
    525        }
    526        *ppInterface = interface;
    527        return CKR_OK;
    528    }
    529    return CKR_ARGUMENTS_BAD;
    530 }
    531 
    532 /* sigh global so pkcs11 can read it */
    533 PRBool nsf_init = PR_FALSE;
    534 
    535 void
    536 fc_log_init_error(CK_RV crv)
    537 {
    538    if (sftk_audit_enabled) {
    539        char msg[128];
    540        PR_snprintf(msg, sizeof msg,
    541                    "C_Initialize()=0x%08lX "
    542                    "power-up self-tests failed",
    543                    (PRUint32)crv);
    544        sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg);
    545    }
    546 }
    547 
    548 /* FC_Initialize initializes the PKCS #11 library. */
    549 CK_RV
    550 FC_Initialize(CK_VOID_PTR pReserved)
    551 {
    552    const char *envp;
    553    CK_RV crv;
    554    PRBool rerun;
    555 
    556    if ((envp = PR_GetEnv("NSS_ENABLE_AUDIT")) != NULL) {
    557        sftk_audit_enabled = (atoi(envp) == 1);
    558    }
    559 
    560    /* if we have the forcePOST flag on, rerun the integrity checks */
    561    /* we need to know this before we fully parse the arguments in
    562     * nsc_CommonInitialize, so read it now */
    563    rerun = sftk_RawArgHasFlag("flags", "forcePost", pReserved);
    564 
    565    /* At this point we should have already done post and integrity checks.
    566     * if we haven't, it probably means the FIPS product has not been installed
    567     * or the tests failed. Don't let an application try to enter FIPS mode. This
    568     * also forces the tests to be rerun if forcePOST is set. */
    569    crv = sftk_FIPSEntryOK(rerun);
    570    if (crv != CKR_OK) {
    571        sftk_fatalError = PR_TRUE;
    572        fc_log_init_error(crv);
    573        return crv;
    574    }
    575 
    576    sftk_ForkReset(pReserved, &crv);
    577 
    578    if (nsf_init) {
    579        return CKR_CRYPTOKI_ALREADY_INITIALIZED;
    580    }
    581 
    582    crv = nsc_CommonInitialize(pReserved, PR_TRUE);
    583 
    584    /* not an 'else' rv can be set by either SFTK_LowInit or SFTK_SlotInit*/
    585    if (crv != CKR_OK) {
    586        sftk_fatalError = PR_TRUE;
    587        return crv;
    588    }
    589 
    590    sftk_fatalError = PR_FALSE; /* any error has been reset */
    591    nsf_init = PR_TRUE;
    592    isLevel2 = PR_TRUE; /* assume level 2 unless we learn otherwise */
    593 
    594    return CKR_OK;
    595 }
    596 
    597 /*FC_Finalize indicates that an application is done with the PKCS #11 library.*/
    598 CK_RV
    599 FC_Finalize(CK_VOID_PTR pReserved)
    600 {
    601    CK_RV crv;
    602 
    603    if (sftk_ForkReset(pReserved, &crv)) {
    604        return crv;
    605    }
    606 
    607    if (!nsf_init) {
    608        return CKR_OK;
    609    }
    610 
    611    crv = nsc_CommonFinalize(pReserved, PR_TRUE);
    612 
    613    nsf_init = (PRBool) !(crv == CKR_OK);
    614    return crv;
    615 }
    616 
    617 /* FC_GetInfo returns general information about PKCS #11. */
    618 CK_RV
    619 FC_GetInfo(CK_INFO_PTR pInfo)
    620 {
    621    CHECK_FORK();
    622 
    623    return NSC_GetInfo(pInfo);
    624 }
    625 
    626 /* FC_GetInfo returns general information about PKCS #11. */
    627 CK_RV
    628 FC_GetInfoV2(CK_INFO_PTR pInfo)
    629 {
    630    CHECK_FORK();
    631 
    632    return NSC_GetInfoV2(pInfo);
    633 }
    634 
    635 /* FC_GetSlotList obtains a list of slots in the system. */
    636 CK_RV
    637 FC_GetSlotList(CK_BBOOL tokenPresent,
    638               CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
    639 {
    640    CHECK_FORK();
    641 
    642    return nsc_CommonGetSlotList(tokenPresent, pSlotList, pulCount,
    643                                 NSC_FIPS_MODULE);
    644 }
    645 
    646 /* FC_GetSlotInfo obtains information about a particular slot in the system. */
    647 CK_RV
    648 FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
    649 {
    650    CHECK_FORK();
    651 
    652    return NSC_GetSlotInfo(slotID, pInfo);
    653 }
    654 
    655 /*FC_GetTokenInfo obtains information about a particular token in the system.*/
    656 CK_RV
    657 FC_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
    658 {
    659    CK_RV crv;
    660 
    661    CHECK_FORK();
    662 
    663    crv = NSC_GetTokenInfo(slotID, pInfo);
    664    if (crv == CKR_OK) {
    665        /* use the global database to figure out if we are running in
    666         * FIPS 140 Level 1 or Level 2 */
    667        if (slotID == FIPS_SLOT_ID &&
    668            (pInfo->flags & CKF_LOGIN_REQUIRED) == 0) {
    669            isLevel2 = PR_FALSE;
    670        }
    671    }
    672    return crv;
    673 }
    674 
    675 /*FC_GetMechanismList obtains a list of mechanism types supported by a token.*/
    676 CK_RV
    677 FC_GetMechanismList(CK_SLOT_ID slotID,
    678                    CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pusCount)
    679 {
    680    CHECK_FORK();
    681 
    682    SFTK_FIPSFATALCHECK();
    683    if (sftk_isFIPS(slotID)) {
    684        slotID = NETSCAPE_SLOT_ID;
    685    }
    686    /* FIPS Slots support all functions */
    687    return NSC_GetMechanismList(slotID, pMechanismList, pusCount);
    688 }
    689 
    690 /* FC_GetMechanismInfo obtains information about a particular mechanism
    691 * possibly supported by a token. */
    692 CK_RV
    693 FC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
    694                    CK_MECHANISM_INFO_PTR pInfo)
    695 {
    696    CHECK_FORK();
    697 
    698    SFTK_FIPSFATALCHECK();
    699    if (sftk_isFIPS(slotID)) {
    700        slotID = NETSCAPE_SLOT_ID;
    701    }
    702    /* FIPS Slots support all functions */
    703    return NSC_GetMechanismInfo(slotID, type, pInfo);
    704 }
    705 
    706 /* FC_GetMechanismInfoV2 same as FC_GetMechanismInfo except the Message
    707 * flags have been stripped out */
    708 CK_RV
    709 FC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
    710                      CK_MECHANISM_INFO_PTR pInfo)
    711 {
    712    CHECK_FORK();
    713 
    714    SFTK_FIPSFATALCHECK();
    715    if (sftk_isFIPS(slotID)) {
    716        slotID = NETSCAPE_SLOT_ID;
    717    }
    718    /* FIPS Slots support all functions */
    719    return NSC_GetMechanismInfoV2(slotID, type, pInfo);
    720 }
    721 
    722 /* FC_InitToken initializes a token. */
    723 CK_RV
    724 FC_InitToken(CK_SLOT_ID slotID, CK_CHAR_PTR pPin,
    725             CK_ULONG usPinLen, CK_CHAR_PTR pLabel)
    726 {
    727    CK_RV crv;
    728 
    729    CHECK_FORK();
    730 
    731    crv = NSC_InitToken(slotID, pPin, usPinLen, pLabel);
    732    if (sftk_audit_enabled) {
    733        char msg[128];
    734        NSSAuditSeverity severity = (crv == CKR_OK) ? NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
    735        /* pLabel points to a 32-byte label, which is not null-terminated */
    736        PR_snprintf(msg, sizeof msg,
    737                    "C_InitToken(slotID=%lu, pLabel=\"%.32s\")=0x%08lX",
    738                    (PRUint32)slotID, pLabel, (PRUint32)crv);
    739        sftk_LogAuditMessage(severity, NSS_AUDIT_INIT_TOKEN, msg);
    740    }
    741    return crv;
    742 }
    743 
    744 /* FC_InitPIN initializes the normal user's PIN. */
    745 CK_RV
    746 FC_InitPIN(CK_SESSION_HANDLE hSession,
    747           CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
    748 {
    749    CK_RV rv;
    750 
    751    CHECK_FORK();
    752 
    753    if (sftk_fatalError)
    754        return CKR_DEVICE_ERROR;
    755    /* NSC_InitPIN will only work once per database. We can either initialize
    756     * it to level1 (pin len == 0) or level2. If we initialize to level 2, then
    757     * we need to make sure the pin meets FIPS requirements */
    758    if ((ulPinLen == 0) || ((rv = sftk_newPinCheck(pPin, ulPinLen)) == CKR_OK)) {
    759        rv = NSC_InitPIN(hSession, pPin, ulPinLen);
    760        if ((rv == CKR_OK) &&
    761            (sftk_SlotIDFromSessionHandle(hSession) == FIPS_SLOT_ID)) {
    762            isLevel2 = (ulPinLen > 0) ? PR_TRUE : PR_FALSE;
    763        }
    764    }
    765    if (sftk_audit_enabled) {
    766        char msg[128];
    767        NSSAuditSeverity severity = (rv == CKR_OK) ? NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
    768        PR_snprintf(msg, sizeof msg,
    769                    "C_InitPIN(hSession=0x%08lX)=0x%08lX",
    770                    (PRUint32)hSession, (PRUint32)rv);
    771        sftk_LogAuditMessage(severity, NSS_AUDIT_INIT_PIN, msg);
    772    }
    773    return rv;
    774 }
    775 
    776 /* FC_SetPIN modifies the PIN of user that is currently logged in. */
    777 /* NOTE: This is only valid for the PRIVATE_KEY_SLOT */
    778 CK_RV
    779 FC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
    780          CK_ULONG usOldLen, CK_CHAR_PTR pNewPin, CK_ULONG usNewLen)
    781 {
    782    CK_RV rv;
    783 
    784    CHECK_FORK();
    785 
    786    rv = sftk_fipsCheck();
    787    if (rv != CKR_OK) {
    788        goto loser;
    789    }
    790 
    791    if (isLevel2 || usNewLen > 0) {
    792        rv = sftk_newPinCheck(pNewPin, usNewLen);
    793        if (rv != CKR_OK) {
    794            goto loser;
    795        }
    796        rv = NSC_SetPIN(hSession, pOldPin, usOldLen, pNewPin, usNewLen);
    797        if (rv != CKR_OK) {
    798            goto loser;
    799        }
    800        if (sftk_SlotIDFromSessionHandle(hSession) == FIPS_SLOT_ID) {
    801            /* if we set the password in level1 we now go
    802             * to level2. NOTE: we don't allow the user to
    803             * go from level2 to level1 */
    804            isLevel2 = PR_TRUE;
    805        }
    806    } else {
    807        /* here both old and new passwords are empty, but we need to
    808         * call NSC_SetPIN to force rekey the database entries */
    809        PORT_Assert(usNewLen == 0);
    810        rv = NSC_SetPIN(hSession, pOldPin, usOldLen, pNewPin, usNewLen);
    811        if (rv != CKR_OK) {
    812            goto loser;
    813        }
    814    }
    815 
    816 loser:
    817    if (sftk_audit_enabled) {
    818        char msg[128];
    819        NSSAuditSeverity severity = (rv == CKR_OK) ? NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
    820        PR_snprintf(msg, sizeof msg,
    821                    "C_SetPIN(hSession=0x%08lX)=0x%08lX",
    822                    (PRUint32)hSession, (PRUint32)rv);
    823        sftk_LogAuditMessage(severity, NSS_AUDIT_SET_PIN, msg);
    824    }
    825    return rv;
    826 }
    827 
    828 /* FC_OpenSession opens a session between an application and a token. */
    829 CK_RV
    830 FC_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags,
    831               CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession)
    832 {
    833    SFTK_FIPSFATALCHECK();
    834 
    835    CHECK_FORK();
    836 
    837    return NSC_OpenSession(slotID, flags, pApplication, Notify, phSession);
    838 }
    839 
    840 /* FC_CloseSession closes a session between an application and a token. */
    841 CK_RV
    842 FC_CloseSession(CK_SESSION_HANDLE hSession)
    843 {
    844    CHECK_FORK();
    845 
    846    return NSC_CloseSession(hSession);
    847 }
    848 
    849 /* FC_CloseAllSessions closes all sessions with a token. */
    850 CK_RV
    851 FC_CloseAllSessions(CK_SLOT_ID slotID)
    852 {
    853 
    854    CHECK_FORK();
    855 
    856    return NSC_CloseAllSessions(slotID);
    857 }
    858 
    859 CK_RV
    860 FC_SessionCancel(CK_SESSION_HANDLE hSession, CK_FLAGS flags)
    861 {
    862    SFTK_FIPSFATALCHECK();
    863 
    864    CHECK_FORK();
    865 
    866    return NSC_SessionCancel(hSession, flags);
    867 }
    868 
    869 /* FC_GetSessionInfo obtains information about the session. */
    870 CK_RV
    871 FC_GetSessionInfo(CK_SESSION_HANDLE hSession,
    872                  CK_SESSION_INFO_PTR pInfo)
    873 {
    874    CK_RV rv;
    875    SFTK_FIPSFATALCHECK();
    876 
    877    CHECK_FORK();
    878 
    879    rv = NSC_GetSessionInfo(hSession, pInfo);
    880    if (rv == CKR_OK) {
    881        /* handle the case where the auxilary slot doesn't require login.
    882         * piggy back on the main token's login state */
    883        if (isLoggedIn &&
    884            ((pInfo->state == CKS_RO_PUBLIC_SESSION) ||
    885             (pInfo->state == CKS_RW_PUBLIC_SESSION))) {
    886            CK_RV crv;
    887            CK_TOKEN_INFO tInfo;
    888            crv = NSC_GetTokenInfo(sftk_SlotIDFromSessionHandle(hSession),
    889                                   &tInfo);
    890            /* if the token doesn't login, use our global login state */
    891            if ((crv == CKR_OK) && ((tInfo.flags & CKF_LOGIN_REQUIRED) == 0)) {
    892                if (pInfo->state == CKS_RO_PUBLIC_SESSION) {
    893                    pInfo->state = CKS_RO_USER_FUNCTIONS;
    894                } else {
    895                    pInfo->state = CKS_RW_USER_FUNCTIONS;
    896                }
    897            }
    898        }
    899    }
    900    return rv;
    901 }
    902 
    903 /* FC_Login logs a user into a token. */
    904 CK_RV
    905 FC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
    906         CK_CHAR_PTR pPin, CK_ULONG usPinLen)
    907 {
    908    CK_RV rv;
    909    PRBool successful;
    910    if (sftk_fatalError)
    911        return CKR_DEVICE_ERROR;
    912    rv = NSC_Login(hSession, userType, pPin, usPinLen);
    913    successful = (rv == CKR_OK) || (rv == CKR_USER_ALREADY_LOGGED_IN);
    914    if (successful)
    915        isLoggedIn = PR_TRUE;
    916    if (sftk_audit_enabled) {
    917        char msg[128];
    918        NSSAuditSeverity severity;
    919        severity = successful ? NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
    920        PR_snprintf(msg, sizeof msg,
    921                    "C_Login(hSession=0x%08lX, userType=%lu)=0x%08lX",
    922                    (PRUint32)hSession, (PRUint32)userType, (PRUint32)rv);
    923        sftk_LogAuditMessage(severity, NSS_AUDIT_LOGIN, msg);
    924    }
    925    return rv;
    926 }
    927 
    928 CK_RV
    929 FC_LoginUser(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
    930             CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pUsername,
    931             CK_ULONG ulUsernameLen)
    932 {
    933    CK_RV rv;
    934    PRBool successful;
    935    if (sftk_fatalError)
    936        return CKR_DEVICE_ERROR;
    937    rv = NSC_LoginUser(hSession, userType, pPin, ulPinLen,
    938                       pUsername, ulUsernameLen);
    939    successful = (rv == CKR_OK) || (rv == CKR_USER_ALREADY_LOGGED_IN);
    940    if (successful)
    941        isLoggedIn = PR_TRUE;
    942    if (sftk_audit_enabled) {
    943        char msg[128];
    944        char user[61];
    945        int len = PR_MIN(ulUsernameLen, sizeof(user) - 1);
    946        PORT_Memcpy(user, pUsername, len);
    947        user[len] = 0;
    948        NSSAuditSeverity severity;
    949        severity = successful ? NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
    950        PR_snprintf(msg, sizeof msg,
    951                    "C_LoginUser(hSession=0x%08lX, userType=%lu username=%s)=0x%08lX",
    952                    (PRUint32)hSession, (PRUint32)userType, user, (PRUint32)rv);
    953        sftk_LogAuditMessage(severity, NSS_AUDIT_LOGIN, msg);
    954    }
    955    return rv;
    956 }
    957 
    958 /* FC_Logout logs a user out from a token. */
    959 CK_RV
    960 FC_Logout(CK_SESSION_HANDLE hSession)
    961 {
    962    CK_RV rv;
    963 
    964    CHECK_FORK();
    965 
    966    if ((rv = sftk_fipsCheck()) == CKR_OK) {
    967        rv = NSC_Logout(hSession);
    968        isLoggedIn = PR_FALSE;
    969    }
    970    if (sftk_audit_enabled) {
    971        char msg[128];
    972        NSSAuditSeverity severity = (rv == CKR_OK) ? NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
    973        PR_snprintf(msg, sizeof msg,
    974                    "C_Logout(hSession=0x%08lX)=0x%08lX",
    975                    (PRUint32)hSession, (PRUint32)rv);
    976        sftk_LogAuditMessage(severity, NSS_AUDIT_LOGOUT, msg);
    977    }
    978    return rv;
    979 }
    980 
    981 /* FC_CreateObject creates a new object. */
    982 CK_RV
    983 FC_CreateObject(CK_SESSION_HANDLE hSession,
    984                CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
    985                CK_OBJECT_HANDLE_PTR phObject)
    986 {
    987    CK_OBJECT_CLASS *classptr;
    988    CK_RV rv = CKR_OK;
    989 
    990    CHECK_FORK();
    991 
    992    classptr = (CK_OBJECT_CLASS *)fc_getAttribute(pTemplate, ulCount, CKA_CLASS);
    993    if (classptr == NULL)
    994        return CKR_TEMPLATE_INCOMPLETE;
    995 
    996    if (*classptr == CKO_NSS_NEWSLOT || *classptr == CKO_NSS_DELSLOT) {
    997        if (sftk_fatalError)
    998            return CKR_DEVICE_ERROR;
    999    } else {
   1000        rv = sftk_fipsCheck();
   1001        if (rv != CKR_OK)
   1002            return rv;
   1003    }
   1004 
   1005    /* FIPS can't create keys from raw key material */
   1006    if (SFTK_IS_NONPUBLIC_KEY_OBJECT(*classptr)) {
   1007        rv = CKR_ATTRIBUTE_VALUE_INVALID;
   1008    } else {
   1009        rv = NSC_CreateObject(hSession, pTemplate, ulCount, phObject);
   1010    }
   1011    if (sftk_audit_enabled && SFTK_IS_KEY_OBJECT(*classptr)) {
   1012        sftk_AuditCreateObject(hSession, pTemplate, ulCount, phObject, rv);
   1013    }
   1014    return rv;
   1015 }
   1016 
   1017 /* FC_CopyObject copies an object, creating a new object for the copy. */
   1018 CK_RV
   1019 FC_CopyObject(CK_SESSION_HANDLE hSession,
   1020              CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
   1021              CK_OBJECT_HANDLE_PTR phNewObject)
   1022 {
   1023    CK_RV rv;
   1024    CK_OBJECT_CLASS objClass = CKO_NOT_A_KEY;
   1025 
   1026    CHECK_FORK();
   1027 
   1028    SFTK_FIPSFATALCHECK();
   1029    rv = sftk_get_object_class_and_fipsCheck(hSession, hObject, &objClass);
   1030    if (rv == CKR_OK) {
   1031        rv = NSC_CopyObject(hSession, hObject, pTemplate, ulCount, phNewObject);
   1032    }
   1033    if (sftk_audit_enabled && SFTK_IS_KEY_OBJECT(objClass)) {
   1034        sftk_AuditCopyObject(hSession,
   1035                             hObject, pTemplate, ulCount, phNewObject, rv);
   1036    }
   1037    return rv;
   1038 }
   1039 
   1040 /* FC_DestroyObject destroys an object. */
   1041 CK_RV
   1042 FC_DestroyObject(CK_SESSION_HANDLE hSession,
   1043                 CK_OBJECT_HANDLE hObject)
   1044 {
   1045    CK_RV rv;
   1046    CK_OBJECT_CLASS objClass = CKO_NOT_A_KEY;
   1047 
   1048    CHECK_FORK();
   1049 
   1050    SFTK_FIPSFATALCHECK();
   1051    rv = sftk_get_object_class_and_fipsCheck(hSession, hObject, &objClass);
   1052    if (rv == CKR_OK) {
   1053        rv = NSC_DestroyObject(hSession, hObject);
   1054    }
   1055    if (sftk_audit_enabled && SFTK_IS_KEY_OBJECT(objClass)) {
   1056        sftk_AuditDestroyObject(hSession, hObject, rv);
   1057    }
   1058    return rv;
   1059 }
   1060 
   1061 /* FC_GetObjectSize gets the size of an object in bytes. */
   1062 CK_RV
   1063 FC_GetObjectSize(CK_SESSION_HANDLE hSession,
   1064                 CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize)
   1065 {
   1066    CK_RV rv;
   1067    CK_OBJECT_CLASS objClass = CKO_NOT_A_KEY;
   1068 
   1069    CHECK_FORK();
   1070 
   1071    SFTK_FIPSFATALCHECK();
   1072    rv = sftk_get_object_class_and_fipsCheck(hSession, hObject, &objClass);
   1073    if (rv == CKR_OK) {
   1074        rv = NSC_GetObjectSize(hSession, hObject, pulSize);
   1075    }
   1076    if (sftk_audit_enabled && SFTK_IS_KEY_OBJECT(objClass)) {
   1077        sftk_AuditGetObjectSize(hSession, hObject, pulSize, rv);
   1078    }
   1079    return rv;
   1080 }
   1081 
   1082 /* FC_GetAttributeValue obtains the value of one or more object attributes. */
   1083 CK_RV
   1084 FC_GetAttributeValue(CK_SESSION_HANDLE hSession,
   1085                     CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
   1086 {
   1087    CK_RV rv;
   1088    CK_OBJECT_CLASS objClass = CKO_NOT_A_KEY;
   1089 
   1090    CHECK_FORK();
   1091 
   1092    SFTK_FIPSFATALCHECK();
   1093    rv = sftk_get_object_class_and_fipsCheck(hSession, hObject, &objClass);
   1094    if (rv == CKR_OK) {
   1095        rv = NSC_GetAttributeValue(hSession, hObject, pTemplate, ulCount);
   1096    }
   1097    if (sftk_audit_enabled && SFTK_IS_KEY_OBJECT(objClass)) {
   1098        sftk_AuditGetAttributeValue(hSession, hObject, pTemplate, ulCount, rv);
   1099    }
   1100    return rv;
   1101 }
   1102 
   1103 /* FC_SetAttributeValue modifies the value of one or more object attributes */
   1104 CK_RV
   1105 FC_SetAttributeValue(CK_SESSION_HANDLE hSession,
   1106                     CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
   1107 {
   1108    CK_RV rv;
   1109    CK_OBJECT_CLASS objClass = CKO_NOT_A_KEY;
   1110 
   1111    CHECK_FORK();
   1112 
   1113    SFTK_FIPSFATALCHECK();
   1114    rv = sftk_get_object_class_and_fipsCheck(hSession, hObject, &objClass);
   1115    if (rv == CKR_OK) {
   1116        rv = NSC_SetAttributeValue(hSession, hObject, pTemplate, ulCount);
   1117    }
   1118    if (sftk_audit_enabled && SFTK_IS_KEY_OBJECT(objClass)) {
   1119        sftk_AuditSetAttributeValue(hSession, hObject, pTemplate, ulCount, rv);
   1120    }
   1121    return rv;
   1122 }
   1123 
   1124 /* FC_FindObjectsInit initializes a search for token and session objects
   1125 * that match a template. */
   1126 CK_RV
   1127 FC_FindObjectsInit(CK_SESSION_HANDLE hSession,
   1128                   CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount)
   1129 {
   1130    /* let publically readable object be found */
   1131    unsigned int i;
   1132    CK_RV rv;
   1133    PRBool needLogin = PR_FALSE;
   1134 
   1135    CHECK_FORK();
   1136 
   1137    SFTK_FIPSFATALCHECK();
   1138 
   1139    for (i = 0; i < usCount; i++) {
   1140        CK_OBJECT_CLASS class;
   1141        if (pTemplate[i].type != CKA_CLASS) {
   1142            continue;
   1143        }
   1144        if (pTemplate[i].ulValueLen != sizeof(CK_OBJECT_CLASS)) {
   1145            continue;
   1146        }
   1147        if (pTemplate[i].pValue == NULL) {
   1148            continue;
   1149        }
   1150        class = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
   1151        if ((class == CKO_PRIVATE_KEY) || (class == CKO_SECRET_KEY)) {
   1152            needLogin = PR_TRUE;
   1153            break;
   1154        }
   1155    }
   1156    if (needLogin) {
   1157        if ((rv = sftk_fipsCheck()) != CKR_OK)
   1158            return rv;
   1159    }
   1160    return NSC_FindObjectsInit(hSession, pTemplate, usCount);
   1161 }
   1162 
   1163 /* FC_FindObjects continues a search for token and session objects
   1164 * that match a template, obtaining additional object handles. */
   1165 CK_RV
   1166 FC_FindObjects(CK_SESSION_HANDLE hSession,
   1167               CK_OBJECT_HANDLE_PTR phObject, CK_ULONG usMaxObjectCount,
   1168               CK_ULONG_PTR pusObjectCount)
   1169 {
   1170    CHECK_FORK();
   1171 
   1172    /* let publically readable object be found */
   1173    SFTK_FIPSFATALCHECK();
   1174    return NSC_FindObjects(hSession, phObject, usMaxObjectCount,
   1175                           pusObjectCount);
   1176 }
   1177 
   1178 /*
   1179 ************** Crypto Functions:     Encrypt ************************
   1180 */
   1181 
   1182 /* FC_EncryptInit initializes an encryption operation. */
   1183 CK_RV
   1184 FC_EncryptInit(CK_SESSION_HANDLE hSession,
   1185               CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
   1186 {
   1187    SFTK_FIPSCHECK();
   1188    CHECK_FORK();
   1189 
   1190    rv = NSC_EncryptInit(hSession, pMechanism, hKey);
   1191    if (sftk_audit_enabled) {
   1192        sftk_AuditCryptInit("Encrypt", hSession, pMechanism, hKey, rv);
   1193    }
   1194    return rv;
   1195 }
   1196 
   1197 /* FC_Encrypt encrypts single-part data. */
   1198 CK_RV
   1199 FC_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
   1200           CK_ULONG usDataLen, CK_BYTE_PTR pEncryptedData,
   1201           CK_ULONG_PTR pusEncryptedDataLen)
   1202 {
   1203    SFTK_FIPSCHECK();
   1204    CHECK_FORK();
   1205 
   1206    return NSC_Encrypt(hSession, pData, usDataLen, pEncryptedData,
   1207                       pusEncryptedDataLen);
   1208 }
   1209 
   1210 /* FC_EncryptUpdate continues a multiple-part encryption operation. */
   1211 CK_RV
   1212 FC_EncryptUpdate(CK_SESSION_HANDLE hSession,
   1213                 CK_BYTE_PTR pPart, CK_ULONG usPartLen, CK_BYTE_PTR pEncryptedPart,
   1214                 CK_ULONG_PTR pusEncryptedPartLen)
   1215 {
   1216    SFTK_FIPSCHECK();
   1217    CHECK_FORK();
   1218 
   1219    return NSC_EncryptUpdate(hSession, pPart, usPartLen, pEncryptedPart,
   1220                             pusEncryptedPartLen);
   1221 }
   1222 
   1223 /* FC_EncryptFinal finishes a multiple-part encryption operation. */
   1224 CK_RV
   1225 FC_EncryptFinal(CK_SESSION_HANDLE hSession,
   1226                CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pusLastEncryptedPartLen)
   1227 {
   1228    SFTK_FIPSCHECK();
   1229    CHECK_FORK();
   1230 
   1231    return NSC_EncryptFinal(hSession, pLastEncryptedPart,
   1232                            pusLastEncryptedPartLen);
   1233 }
   1234 
   1235 /*
   1236 ************** Crypto Functions:     Decrypt ************************
   1237 */
   1238 
   1239 /* FC_DecryptInit initializes a decryption operation. */
   1240 CK_RV
   1241 FC_DecryptInit(CK_SESSION_HANDLE hSession,
   1242               CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
   1243 {
   1244    SFTK_FIPSCHECK();
   1245    CHECK_FORK();
   1246 
   1247    rv = NSC_DecryptInit(hSession, pMechanism, hKey);
   1248    if (sftk_audit_enabled) {
   1249        sftk_AuditCryptInit("Decrypt", hSession, pMechanism, hKey, rv);
   1250    }
   1251    return rv;
   1252 }
   1253 
   1254 /* FC_Decrypt decrypts encrypted data in a single part. */
   1255 CK_RV
   1256 FC_Decrypt(CK_SESSION_HANDLE hSession,
   1257           CK_BYTE_PTR pEncryptedData, CK_ULONG usEncryptedDataLen, CK_BYTE_PTR pData,
   1258           CK_ULONG_PTR pusDataLen)
   1259 {
   1260    SFTK_FIPSCHECK();
   1261    CHECK_FORK();
   1262 
   1263    return NSC_Decrypt(hSession, pEncryptedData, usEncryptedDataLen, pData,
   1264                       pusDataLen);
   1265 }
   1266 
   1267 /* FC_DecryptUpdate continues a multiple-part decryption operation. */
   1268 CK_RV
   1269 FC_DecryptUpdate(CK_SESSION_HANDLE hSession,
   1270                 CK_BYTE_PTR pEncryptedPart, CK_ULONG usEncryptedPartLen,
   1271                 CK_BYTE_PTR pPart, CK_ULONG_PTR pusPartLen)
   1272 {
   1273    SFTK_FIPSCHECK();
   1274    CHECK_FORK();
   1275 
   1276    return NSC_DecryptUpdate(hSession, pEncryptedPart, usEncryptedPartLen,
   1277                             pPart, pusPartLen);
   1278 }
   1279 
   1280 /* FC_DecryptFinal finishes a multiple-part decryption operation. */
   1281 CK_RV
   1282 FC_DecryptFinal(CK_SESSION_HANDLE hSession,
   1283                CK_BYTE_PTR pLastPart, CK_ULONG_PTR pusLastPartLen)
   1284 {
   1285    SFTK_FIPSCHECK();
   1286    CHECK_FORK();
   1287 
   1288    return NSC_DecryptFinal(hSession, pLastPart, pusLastPartLen);
   1289 }
   1290 
   1291 /*
   1292 ************** Crypto Functions:     Digest (HASH)  ************************
   1293 */
   1294 
   1295 /* FC_DigestInit initializes a message-digesting operation. */
   1296 CK_RV
   1297 FC_DigestInit(CK_SESSION_HANDLE hSession,
   1298              CK_MECHANISM_PTR pMechanism)
   1299 {
   1300    SFTK_FIPSFATALCHECK();
   1301    CHECK_FORK();
   1302 
   1303    return NSC_DigestInit(hSession, pMechanism);
   1304 }
   1305 
   1306 /* FC_Digest digests data in a single part. */
   1307 CK_RV
   1308 FC_Digest(CK_SESSION_HANDLE hSession,
   1309          CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pDigest,
   1310          CK_ULONG_PTR pusDigestLen)
   1311 {
   1312    SFTK_FIPSFATALCHECK();
   1313    CHECK_FORK();
   1314 
   1315    return NSC_Digest(hSession, pData, usDataLen, pDigest, pusDigestLen);
   1316 }
   1317 
   1318 /* FC_DigestUpdate continues a multiple-part message-digesting operation. */
   1319 CK_RV
   1320 FC_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
   1321                CK_ULONG usPartLen)
   1322 {
   1323    SFTK_FIPSFATALCHECK();
   1324    CHECK_FORK();
   1325 
   1326    return NSC_DigestUpdate(hSession, pPart, usPartLen);
   1327 }
   1328 
   1329 /* FC_DigestFinal finishes a multiple-part message-digesting operation. */
   1330 CK_RV
   1331 FC_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
   1332               CK_ULONG_PTR pusDigestLen)
   1333 {
   1334    SFTK_FIPSFATALCHECK();
   1335    CHECK_FORK();
   1336 
   1337    return NSC_DigestFinal(hSession, pDigest, pusDigestLen);
   1338 }
   1339 
   1340 /*
   1341 ************** Crypto Functions:     Sign  ************************
   1342 */
   1343 
   1344 /* FC_SignInit initializes a signature (private key encryption) operation,
   1345 * where the signature is (will be) an appendix to the data,
   1346 * and plaintext cannot be recovered from the signature */
   1347 CK_RV
   1348 FC_SignInit(CK_SESSION_HANDLE hSession,
   1349            CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
   1350 {
   1351    SFTK_FIPSCHECK();
   1352    CHECK_FORK();
   1353 
   1354    rv = NSC_SignInit(hSession, pMechanism, hKey);
   1355    if (sftk_audit_enabled) {
   1356        sftk_AuditCryptInit("Sign", hSession, pMechanism, hKey, rv);
   1357    }
   1358    return rv;
   1359 }
   1360 
   1361 /* FC_Sign signs (encrypts with private key) data in a single part,
   1362 * where the signature is (will be) an appendix to the data,
   1363 * and plaintext cannot be recovered from the signature */
   1364 CK_RV
   1365 FC_Sign(CK_SESSION_HANDLE hSession,
   1366        CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pSignature,
   1367        CK_ULONG_PTR pusSignatureLen)
   1368 {
   1369    SFTK_FIPSCHECK();
   1370    CHECK_FORK();
   1371 
   1372    return NSC_Sign(hSession, pData, usDataLen, pSignature, pusSignatureLen);
   1373 }
   1374 
   1375 /* FC_SignUpdate continues a multiple-part signature operation,
   1376 * where the signature is (will be) an appendix to the data,
   1377 * and plaintext cannot be recovered from the signature */
   1378 CK_RV
   1379 FC_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
   1380              CK_ULONG usPartLen)
   1381 {
   1382    SFTK_FIPSCHECK();
   1383    CHECK_FORK();
   1384 
   1385    return NSC_SignUpdate(hSession, pPart, usPartLen);
   1386 }
   1387 
   1388 /* FC_SignFinal finishes a multiple-part signature operation,
   1389 * returning the signature. */
   1390 CK_RV
   1391 FC_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
   1392             CK_ULONG_PTR pusSignatureLen)
   1393 {
   1394    SFTK_FIPSCHECK();
   1395    CHECK_FORK();
   1396 
   1397    return NSC_SignFinal(hSession, pSignature, pusSignatureLen);
   1398 }
   1399 
   1400 /*
   1401 ************** Crypto Functions:     Sign Recover  ************************
   1402 */
   1403 /* FC_SignRecoverInit initializes a signature operation,
   1404 * where the (digest) data can be recovered from the signature.
   1405 * E.g. encryption with the user's private key */
   1406 CK_RV
   1407 FC_SignRecoverInit(CK_SESSION_HANDLE hSession,
   1408                   CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
   1409 {
   1410    SFTK_FIPSCHECK();
   1411    CHECK_FORK();
   1412 
   1413    rv = NSC_SignRecoverInit(hSession, pMechanism, hKey);
   1414    if (sftk_audit_enabled) {
   1415        sftk_AuditCryptInit("SignRecover", hSession, pMechanism, hKey, rv);
   1416    }
   1417    return rv;
   1418 }
   1419 
   1420 /* FC_SignRecover signs data in a single operation
   1421 * where the (digest) data can be recovered from the signature.
   1422 * E.g. encryption with the user's private key */
   1423 CK_RV
   1424 FC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
   1425               CK_ULONG usDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pusSignatureLen)
   1426 {
   1427    SFTK_FIPSCHECK();
   1428    CHECK_FORK();
   1429 
   1430    return NSC_SignRecover(hSession, pData, usDataLen, pSignature, pusSignatureLen);
   1431 }
   1432 
   1433 /*
   1434 ************** Crypto Functions:     verify  ************************
   1435 */
   1436 
   1437 /* FC_VerifyInit initializes a verification operation,
   1438 * where the signature is an appendix to the data,
   1439 * and plaintext cannot be recovered from the signature (e.g. DSA) */
   1440 CK_RV
   1441 FC_VerifyInit(CK_SESSION_HANDLE hSession,
   1442              CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
   1443 {
   1444    SFTK_FIPSCHECK();
   1445    CHECK_FORK();
   1446 
   1447    rv = NSC_VerifyInit(hSession, pMechanism, hKey);
   1448    if (sftk_audit_enabled) {
   1449        sftk_AuditCryptInit("Verify", hSession, pMechanism, hKey, rv);
   1450    }
   1451    return rv;
   1452 }
   1453 
   1454 /* FC_Verify verifies a signature in a single-part operation,
   1455 * where the signature is an appendix to the data,
   1456 * and plaintext cannot be recovered from the signature */
   1457 CK_RV
   1458 FC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
   1459          CK_ULONG usDataLen, CK_BYTE_PTR pSignature, CK_ULONG usSignatureLen)
   1460 {
   1461    /* make sure we're legal */
   1462    SFTK_FIPSCHECK();
   1463    CHECK_FORK();
   1464 
   1465    return NSC_Verify(hSession, pData, usDataLen, pSignature, usSignatureLen);
   1466 }
   1467 
   1468 /* FC_VerifyUpdate continues a multiple-part verification operation,
   1469 * where the signature is an appendix to the data,
   1470 * and plaintext cannot be recovered from the signature */
   1471 CK_RV
   1472 FC_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
   1473                CK_ULONG usPartLen)
   1474 {
   1475    SFTK_FIPSCHECK();
   1476    CHECK_FORK();
   1477 
   1478    return NSC_VerifyUpdate(hSession, pPart, usPartLen);
   1479 }
   1480 
   1481 /* FC_VerifyFinal finishes a multiple-part verification operation,
   1482 * checking the signature. */
   1483 CK_RV
   1484 FC_VerifyFinal(CK_SESSION_HANDLE hSession,
   1485               CK_BYTE_PTR pSignature, CK_ULONG usSignatureLen)
   1486 {
   1487    SFTK_FIPSCHECK();
   1488    CHECK_FORK();
   1489 
   1490    return NSC_VerifyFinal(hSession, pSignature, usSignatureLen);
   1491 }
   1492 
   1493 /*
   1494 ************** Crypto Functions:     Verify  Signature ************************
   1495 * some algorithms need the signature at the beginning of the verification,
   1496 * VerifySignature provides such and API. For algorithms that don't need
   1497 * the signature first, we stash the signature and just pass it to
   1498 * NSC_VerifyXXX.
   1499 */
   1500 CK_RV
   1501 FC_VerifySignatureInit(CK_SESSION_HANDLE hSession,
   1502                       CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey,
   1503                       CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
   1504 {
   1505    SFTK_FIPSCHECK();
   1506    CHECK_FORK();
   1507 
   1508    rv = NSC_VerifySignatureInit(hSession, pMechanism, hKey,
   1509                                 pSignature, ulSignatureLen);
   1510    if (sftk_audit_enabled) {
   1511        sftk_AuditCryptInit("VerifySignature", hSession, pMechanism, hKey, rv);
   1512    }
   1513    return rv;
   1514 }
   1515 
   1516 CK_RV
   1517 FC_VerifySignature(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
   1518                   CK_ULONG ulDataLen)
   1519 {
   1520    SFTK_FIPSCHECK();
   1521    CHECK_FORK();
   1522 
   1523    return NSC_VerifySignature(hSession, pData, ulDataLen);
   1524 }
   1525 
   1526 CK_RV
   1527 FC_VerifySignatureUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
   1528                         CK_ULONG ulPartLen)
   1529 {
   1530    SFTK_FIPSCHECK();
   1531    CHECK_FORK();
   1532 
   1533    return NSC_VerifySignatureUpdate(hSession, pPart, ulPartLen);
   1534 }
   1535 
   1536 CK_RV
   1537 FC_VerifySignatureFinal(CK_SESSION_HANDLE hSession)
   1538 {
   1539    SFTK_FIPSCHECK();
   1540    CHECK_FORK();
   1541 
   1542    return NSC_VerifySignatureFinal(hSession);
   1543 }
   1544 
   1545 /*
   1546 ************** Crypto Functions:     Verify  Recover ************************
   1547 */
   1548 
   1549 /* FC_VerifyRecoverInit initializes a signature verification operation,
   1550 * where the data is recovered from the signature.
   1551 * E.g. Decryption with the user's public key */
   1552 CK_RV
   1553 FC_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
   1554                     CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
   1555 {
   1556    SFTK_FIPSCHECK();
   1557    CHECK_FORK();
   1558 
   1559    rv = NSC_VerifyRecoverInit(hSession, pMechanism, hKey);
   1560    if (sftk_audit_enabled) {
   1561        sftk_AuditCryptInit("VerifyRecover", hSession, pMechanism, hKey, rv);
   1562    }
   1563    return rv;
   1564 }
   1565 
   1566 /* FC_VerifyRecover verifies a signature in a single-part operation,
   1567 * where the data is recovered from the signature.
   1568 * E.g. Decryption with the user's public key */
   1569 CK_RV
   1570 FC_VerifyRecover(CK_SESSION_HANDLE hSession,
   1571                 CK_BYTE_PTR pSignature, CK_ULONG usSignatureLen,
   1572                 CK_BYTE_PTR pData, CK_ULONG_PTR pusDataLen)
   1573 {
   1574    SFTK_FIPSCHECK();
   1575    CHECK_FORK();
   1576 
   1577    return NSC_VerifyRecover(hSession, pSignature, usSignatureLen, pData,
   1578                             pusDataLen);
   1579 }
   1580 
   1581 /*
   1582 **************************** Key Functions:  ************************
   1583 */
   1584 
   1585 /* FC_GenerateKey generates a secret key, creating a new key object. */
   1586 CK_RV
   1587 FC_GenerateKey(CK_SESSION_HANDLE hSession,
   1588               CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
   1589               CK_OBJECT_HANDLE_PTR phKey)
   1590 {
   1591    CK_BBOOL *boolptr;
   1592 
   1593    SFTK_FIPSCHECK();
   1594    CHECK_FORK();
   1595 
   1596    /* all secret keys must be sensitive, if the upper level code tries to say
   1597     * otherwise, reject it. */
   1598    boolptr = (CK_BBOOL *)fc_getAttribute(pTemplate, ulCount, CKA_SENSITIVE);
   1599    if (boolptr != NULL) {
   1600        if (!(*boolptr)) {
   1601            return CKR_ATTRIBUTE_VALUE_INVALID;
   1602        }
   1603    }
   1604 
   1605    rv = NSC_GenerateKey(hSession, pMechanism, pTemplate, ulCount, phKey);
   1606    if (sftk_audit_enabled) {
   1607        sftk_AuditGenerateKey(hSession, pMechanism, pTemplate, ulCount, phKey, rv);
   1608    }
   1609    return rv;
   1610 }
   1611 
   1612 /* FC_GenerateKeyPair generates a public-key/private-key pair,
   1613 * creating new key objects. */
   1614 CK_RV
   1615 FC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
   1616                   CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,
   1617                   CK_ULONG usPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
   1618                   CK_ULONG usPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey,
   1619                   CK_OBJECT_HANDLE_PTR phPrivateKey)
   1620 {
   1621    CK_BBOOL *boolptr;
   1622    CK_RV crv;
   1623 
   1624    SFTK_FIPSCHECK();
   1625    CHECK_FORK();
   1626 
   1627    /* all private keys must be sensitive, if the upper level code tries to say
   1628     * otherwise, reject it. */
   1629    boolptr = (CK_BBOOL *)fc_getAttribute(pPrivateKeyTemplate,
   1630                                          usPrivateKeyAttributeCount, CKA_SENSITIVE);
   1631    if (boolptr != NULL) {
   1632        if (!(*boolptr)) {
   1633            return CKR_ATTRIBUTE_VALUE_INVALID;
   1634        }
   1635    }
   1636    crv = NSC_GenerateKeyPair(hSession, pMechanism, pPublicKeyTemplate,
   1637                              usPublicKeyAttributeCount, pPrivateKeyTemplate,
   1638                              usPrivateKeyAttributeCount, phPublicKey, phPrivateKey);
   1639    if (crv == CKR_GENERAL_ERROR) {
   1640        /* pairwise consistency check failed. */
   1641        sftk_fatalError = PR_TRUE;
   1642    }
   1643    if (sftk_audit_enabled) {
   1644        sftk_AuditGenerateKeyPair(hSession, pMechanism, pPublicKeyTemplate,
   1645                                  usPublicKeyAttributeCount, pPrivateKeyTemplate,
   1646                                  usPrivateKeyAttributeCount, phPublicKey, phPrivateKey, crv);
   1647    }
   1648    return crv;
   1649 }
   1650 
   1651 /* FC_WrapKey wraps (i.e., encrypts) a key. */
   1652 CK_RV
   1653 FC_WrapKey(CK_SESSION_HANDLE hSession,
   1654           CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey,
   1655           CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
   1656           CK_ULONG_PTR pulWrappedKeyLen)
   1657 {
   1658    SFTK_FIPSCHECK();
   1659    CHECK_FORK();
   1660 
   1661    rv = NSC_WrapKey(hSession, pMechanism, hWrappingKey, hKey, pWrappedKey,
   1662                     pulWrappedKeyLen);
   1663    if (sftk_audit_enabled) {
   1664        sftk_AuditWrapKey(hSession, pMechanism, hWrappingKey, hKey, pWrappedKey,
   1665                          pulWrappedKeyLen, rv);
   1666    }
   1667    return rv;
   1668 }
   1669 
   1670 /* FC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
   1671 CK_RV
   1672 FC_UnwrapKey(CK_SESSION_HANDLE hSession,
   1673             CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
   1674             CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
   1675             CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
   1676             CK_OBJECT_HANDLE_PTR phKey)
   1677 {
   1678    CK_BBOOL *boolptr;
   1679 
   1680    SFTK_FIPSCHECK();
   1681    CHECK_FORK();
   1682 
   1683    /* all secret keys must be sensitive, if the upper level code tries to say
   1684     * otherwise, reject it. */
   1685    boolptr = (CK_BBOOL *)fc_getAttribute(pTemplate,
   1686                                          ulAttributeCount, CKA_SENSITIVE);
   1687    if (boolptr != NULL) {
   1688        if (!(*boolptr)) {
   1689            return CKR_ATTRIBUTE_VALUE_INVALID;
   1690        }
   1691    }
   1692    rv = NSC_UnwrapKey(hSession, pMechanism, hUnwrappingKey, pWrappedKey,
   1693                       ulWrappedKeyLen, pTemplate, ulAttributeCount, phKey);
   1694    if (sftk_audit_enabled) {
   1695        sftk_AuditUnwrapKey(hSession, pMechanism, hUnwrappingKey, pWrappedKey,
   1696                            ulWrappedKeyLen, pTemplate, ulAttributeCount, phKey, rv);
   1697    }
   1698    return rv;
   1699 }
   1700 
   1701 /* FC_DeriveKey derives a key from a base key, creating a new key object. */
   1702 CK_RV
   1703 FC_DeriveKey(CK_SESSION_HANDLE hSession,
   1704             CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
   1705             CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
   1706             CK_OBJECT_HANDLE_PTR phKey)
   1707 {
   1708    CK_BBOOL *boolptr;
   1709 
   1710    SFTK_FIPSCHECK();
   1711    CHECK_FORK();
   1712 
   1713    /* all secret keys must be sensitive, if the upper level code tries to say
   1714     * otherwise, reject it. */
   1715    boolptr = (CK_BBOOL *)fc_getAttribute(pTemplate,
   1716                                          ulAttributeCount, CKA_SENSITIVE);
   1717    if (boolptr != NULL) {
   1718        if (!(*boolptr)) {
   1719            return CKR_ATTRIBUTE_VALUE_INVALID;
   1720        }
   1721    }
   1722    rv = NSC_DeriveKey(hSession, pMechanism, hBaseKey, pTemplate,
   1723                       ulAttributeCount, phKey);
   1724    if (sftk_audit_enabled) {
   1725        sftk_AuditDeriveKey(hSession, pMechanism, hBaseKey, pTemplate,
   1726                            ulAttributeCount, phKey, rv);
   1727    }
   1728    return rv;
   1729 }
   1730 
   1731 /*
   1732 **************************** Radom Functions:  ************************
   1733 */
   1734 
   1735 /* FC_SeedRandom mixes additional seed material into the token's random number
   1736 * generator. */
   1737 CK_RV
   1738 FC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
   1739              CK_ULONG usSeedLen)
   1740 {
   1741    CK_RV crv;
   1742 
   1743    SFTK_FIPSFATALCHECK();
   1744    CHECK_FORK();
   1745 
   1746    crv = NSC_SeedRandom(hSession, pSeed, usSeedLen);
   1747    if (crv != CKR_OK) {
   1748        sftk_fatalError = PR_TRUE;
   1749    }
   1750    return crv;
   1751 }
   1752 
   1753 /* FC_GenerateRandom generates random data. */
   1754 CK_RV
   1755 FC_GenerateRandom(CK_SESSION_HANDLE hSession,
   1756                  CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
   1757 {
   1758    CK_RV crv;
   1759 
   1760    CHECK_FORK();
   1761 
   1762    SFTK_FIPSFATALCHECK();
   1763    crv = NSC_GenerateRandom(hSession, pRandomData, ulRandomLen);
   1764    if (crv != CKR_OK) {
   1765        sftk_fatalError = PR_TRUE;
   1766        if (sftk_audit_enabled) {
   1767            char msg[128];
   1768            PR_snprintf(msg, sizeof msg,
   1769                        "C_GenerateRandom(hSession=0x%08lX, pRandomData=%p, "
   1770                        "ulRandomLen=%lu)=0x%08lX "
   1771                        "self-test: continuous RNG test failed",
   1772                        (PRUint32)hSession, pRandomData,
   1773                        (PRUint32)ulRandomLen, (PRUint32)crv);
   1774            sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg);
   1775        }
   1776    }
   1777    return crv;
   1778 }
   1779 
   1780 /* FC_GetFunctionStatus obtains an updated status of a function running
   1781 * in parallel with an application. */
   1782 CK_RV
   1783 FC_GetFunctionStatus(CK_SESSION_HANDLE hSession)
   1784 {
   1785    SFTK_FIPSCHECK();
   1786    CHECK_FORK();
   1787 
   1788    return NSC_GetFunctionStatus(hSession);
   1789 }
   1790 
   1791 /* FC_CancelFunction cancels a function running in parallel */
   1792 CK_RV
   1793 FC_CancelFunction(CK_SESSION_HANDLE hSession)
   1794 {
   1795    SFTK_FIPSCHECK();
   1796    CHECK_FORK();
   1797 
   1798    return NSC_CancelFunction(hSession);
   1799 }
   1800 
   1801 /*
   1802 ****************************  Version 1.1 Functions:  ************************
   1803 */
   1804 
   1805 /* FC_GetOperationState saves the state of the cryptographic
   1806 *operation in a session. */
   1807 CK_RV
   1808 FC_GetOperationState(CK_SESSION_HANDLE hSession,
   1809                     CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
   1810 {
   1811    SFTK_FIPSFATALCHECK();
   1812    CHECK_FORK();
   1813 
   1814    return NSC_GetOperationState(hSession, pOperationState, pulOperationStateLen);
   1815 }
   1816 
   1817 /* FC_SetOperationState restores the state of the cryptographic operation
   1818 * in a session. */
   1819 CK_RV
   1820 FC_SetOperationState(CK_SESSION_HANDLE hSession,
   1821                     CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen,
   1822                     CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
   1823 {
   1824    SFTK_FIPSFATALCHECK();
   1825    CHECK_FORK();
   1826 
   1827    return NSC_SetOperationState(hSession, pOperationState, ulOperationStateLen,
   1828                                 hEncryptionKey, hAuthenticationKey);
   1829 }
   1830 
   1831 /* FC_FindObjectsFinal finishes a search for token and session objects. */
   1832 CK_RV
   1833 FC_FindObjectsFinal(CK_SESSION_HANDLE hSession)
   1834 {
   1835    /* let publically readable object be found */
   1836    SFTK_FIPSFATALCHECK();
   1837    CHECK_FORK();
   1838 
   1839    return NSC_FindObjectsFinal(hSession);
   1840 }
   1841 
   1842 /* Dual-function cryptographic operations */
   1843 
   1844 /* FC_DigestEncryptUpdate continues a multiple-part digesting and encryption
   1845 * operation. */
   1846 CK_RV
   1847 FC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
   1848                       CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
   1849                       CK_ULONG_PTR pulEncryptedPartLen)
   1850 {
   1851    SFTK_FIPSCHECK();
   1852    CHECK_FORK();
   1853 
   1854    return NSC_DigestEncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart,
   1855                                   pulEncryptedPartLen);
   1856 }
   1857 
   1858 /* FC_DecryptDigestUpdate continues a multiple-part decryption and digesting
   1859 * operation. */
   1860 CK_RV
   1861 FC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
   1862                       CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
   1863                       CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
   1864 {
   1865    SFTK_FIPSCHECK();
   1866    CHECK_FORK();
   1867 
   1868    return NSC_DecryptDigestUpdate(hSession, pEncryptedPart, ulEncryptedPartLen,
   1869                                   pPart, pulPartLen);
   1870 }
   1871 
   1872 /* FC_SignEncryptUpdate continues a multiple-part signing and encryption
   1873 * operation. */
   1874 CK_RV
   1875 FC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
   1876                     CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
   1877                     CK_ULONG_PTR pulEncryptedPartLen)
   1878 {
   1879    SFTK_FIPSCHECK();
   1880    CHECK_FORK();
   1881 
   1882    return NSC_SignEncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart,
   1883                                 pulEncryptedPartLen);
   1884 }
   1885 
   1886 /* FC_DecryptVerifyUpdate continues a multiple-part decryption and verify
   1887 * operation. */
   1888 CK_RV
   1889 FC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,
   1890                       CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
   1891                       CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
   1892 {
   1893    SFTK_FIPSCHECK();
   1894    CHECK_FORK();
   1895 
   1896    return NSC_DecryptVerifyUpdate(hSession, pEncryptedData, ulEncryptedDataLen,
   1897                                   pData, pulDataLen);
   1898 }
   1899 
   1900 /* FC_DigestKey continues a multi-part message-digesting operation,
   1901 * by digesting the value of a secret key as part of the data already digested.
   1902 */
   1903 CK_RV
   1904 FC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
   1905 {
   1906    SFTK_FIPSCHECK();
   1907    CHECK_FORK();
   1908 
   1909    rv = NSC_DigestKey(hSession, hKey);
   1910    if (sftk_audit_enabled) {
   1911        sftk_AuditDigestKey(hSession, hKey, rv);
   1912    }
   1913    return rv;
   1914 }
   1915 
   1916 CK_RV
   1917 FC_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot,
   1918                    CK_VOID_PTR pReserved)
   1919 {
   1920    CHECK_FORK();
   1921 
   1922    return NSC_WaitForSlotEvent(flags, pSlot, pReserved);
   1923 }
   1924 
   1925 CK_RV
   1926 FC_MessageEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
   1927                      CK_OBJECT_HANDLE hKey)
   1928 {
   1929    SFTK_FIPSCHECK();
   1930    CHECK_FORK();
   1931 
   1932    rv = NSC_MessageEncryptInit(hSession, pMechanism, hKey);
   1933    if (sftk_audit_enabled) {
   1934        sftk_AuditCryptInit("MessageEncrypt", hSession, pMechanism, hKey, rv);
   1935    }
   1936    return rv;
   1937 }
   1938 
   1939 CK_RV
   1940 FC_EncryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
   1941                  CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
   1942                  CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pPlaintext,
   1943                  CK_ULONG ulPlaintextLen, CK_BYTE_PTR pCiphertext,
   1944                  CK_ULONG_PTR pulCiphertextLen)
   1945 {
   1946    SFTK_FIPSCHECK();
   1947    CHECK_FORK();
   1948    return NSC_EncryptMessage(hSession, pParameter, ulParameterLen,
   1949                              pAssociatedData, ulAssociatedDataLen,
   1950                              pPlaintext, ulPlaintextLen, pCiphertext,
   1951                              pulCiphertextLen);
   1952 }
   1953 
   1954 CK_RV
   1955 FC_EncryptMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
   1956                       CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
   1957                       CK_ULONG ulAssociatedDataLen)
   1958 {
   1959    SFTK_FIPSCHECK();
   1960    CHECK_FORK();
   1961    return NSC_EncryptMessageBegin(hSession, pParameter, ulParameterLen,
   1962                                   pAssociatedData, ulAssociatedDataLen);
   1963 }
   1964 
   1965 CK_RV
   1966 FC_EncryptMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
   1967                      CK_ULONG ulParameterLen, CK_BYTE_PTR pPlaintextPart,
   1968                      CK_ULONG ulPlaintextPartLen, CK_BYTE_PTR pCiphertextPart,
   1969                      CK_ULONG_PTR pulCiphertextPartLen, CK_FLAGS flags)
   1970 {
   1971    SFTK_FIPSCHECK();
   1972    CHECK_FORK();
   1973    return NSC_EncryptMessageNext(hSession, pParameter, ulParameterLen,
   1974                                  pPlaintextPart, ulPlaintextPartLen,
   1975                                  pCiphertextPart, pulCiphertextPartLen, flags);
   1976 }
   1977 
   1978 CK_RV
   1979 FC_MessageEncryptFinal(CK_SESSION_HANDLE hSession)
   1980 {
   1981    SFTK_FIPSCHECK();
   1982    CHECK_FORK();
   1983    return NSC_MessageEncryptFinal(hSession);
   1984 }
   1985 
   1986 CK_RV
   1987 FC_MessageDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
   1988                      CK_OBJECT_HANDLE hKey)
   1989 {
   1990    SFTK_FIPSCHECK();
   1991    CHECK_FORK();
   1992 
   1993    rv = NSC_MessageDecryptInit(hSession, pMechanism, hKey);
   1994    if (sftk_audit_enabled) {
   1995        sftk_AuditCryptInit("MessageDecrypt", hSession, pMechanism, hKey, rv);
   1996    }
   1997    return rv;
   1998 }
   1999 
   2000 CK_RV
   2001 FC_DecryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
   2002                  CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
   2003                  CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pCiphertext,
   2004                  CK_ULONG ulCiphertextLen, CK_BYTE_PTR pPlaintext,
   2005                  CK_ULONG_PTR pulPlaintextLen)
   2006 {
   2007    SFTK_FIPSCHECK();
   2008    CHECK_FORK();
   2009    return NSC_DecryptMessage(hSession, pParameter, ulParameterLen,
   2010                              pAssociatedData, ulAssociatedDataLen,
   2011                              pCiphertext, ulCiphertextLen, pPlaintext,
   2012                              pulPlaintextLen);
   2013 }
   2014 
   2015 CK_RV
   2016 FC_DecryptMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
   2017                       CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
   2018                       CK_ULONG ulAssociatedDataLen)
   2019 {
   2020    SFTK_FIPSCHECK();
   2021    CHECK_FORK();
   2022    return NSC_DecryptMessageBegin(hSession, pParameter, ulParameterLen,
   2023                                   pAssociatedData, ulAssociatedDataLen);
   2024 }
   2025 
   2026 CK_RV
   2027 FC_DecryptMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
   2028                      CK_ULONG ulParameterLen, CK_BYTE_PTR pCiphertextPart,
   2029                      CK_ULONG ulCiphertextPartLen, CK_BYTE_PTR pPlaintextPart,
   2030                      CK_ULONG_PTR pulPlaintextPartLen, CK_FLAGS flags)
   2031 {
   2032    SFTK_FIPSCHECK();
   2033    CHECK_FORK();
   2034    return NSC_DecryptMessageNext(hSession, pParameter, ulParameterLen,
   2035                                  pCiphertextPart, ulCiphertextPartLen,
   2036                                  pPlaintextPart, pulPlaintextPartLen, flags);
   2037 }
   2038 
   2039 CK_RV
   2040 FC_MessageDecryptFinal(CK_SESSION_HANDLE hSession)
   2041 {
   2042    SFTK_FIPSCHECK();
   2043    CHECK_FORK();
   2044    return NSC_MessageDecryptFinal(hSession);
   2045 }
   2046 
   2047 CK_RV
   2048 FC_MessageSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
   2049                   CK_OBJECT_HANDLE hKey)
   2050 {
   2051    SFTK_FIPSCHECK();
   2052    CHECK_FORK();
   2053 
   2054    rv = NSC_MessageSignInit(hSession, pMechanism, hKey);
   2055    if (sftk_audit_enabled) {
   2056        sftk_AuditCryptInit("MessageSign", hSession, pMechanism, hKey, rv);
   2057    }
   2058    return rv;
   2059 }
   2060 
   2061 CK_RV
   2062 FC_SignMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
   2063               CK_ULONG ulParameterLen, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
   2064               CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
   2065 {
   2066    SFTK_FIPSCHECK();
   2067    CHECK_FORK();
   2068    return NSC_SignMessage(hSession, pParameter, ulParameterLen, pData,
   2069                           ulDataLen, pSignature, pulSignatureLen);
   2070 }
   2071 
   2072 CK_RV
   2073 FC_SignMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
   2074                    CK_ULONG ulParameterLen)
   2075 {
   2076    SFTK_FIPSCHECK();
   2077    CHECK_FORK();
   2078    return NSC_SignMessageBegin(hSession, pParameter, ulParameterLen);
   2079 }
   2080 
   2081 CK_RV
   2082 FC_SignMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
   2083                   CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
   2084                   CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
   2085                   CK_ULONG_PTR pulSignatureLen)
   2086 {
   2087    SFTK_FIPSCHECK();
   2088    CHECK_FORK();
   2089    return NSC_SignMessageNext(hSession, pParameter, ulParameterLen, pData,
   2090                               ulDataLen, pSignature, pulSignatureLen);
   2091 }
   2092 
   2093 CK_RV
   2094 FC_MessageSignFinal(CK_SESSION_HANDLE hSession)
   2095 {
   2096    SFTK_FIPSCHECK();
   2097    CHECK_FORK();
   2098    return NSC_MessageSignFinal(hSession);
   2099 }
   2100 
   2101 CK_RV
   2102 FC_MessageVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
   2103                     CK_OBJECT_HANDLE hKey)
   2104 {
   2105    SFTK_FIPSCHECK();
   2106    CHECK_FORK();
   2107 
   2108    rv = NSC_MessageVerifyInit(hSession, pMechanism, hKey);
   2109    if (sftk_audit_enabled) {
   2110        sftk_AuditCryptInit("MessageVerify", hSession, pMechanism, hKey, rv);
   2111    }
   2112    return rv;
   2113 }
   2114 
   2115 CK_RV
   2116 FC_VerifyMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
   2117                 CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
   2118                 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
   2119                 CK_ULONG ulSignatureLen)
   2120 {
   2121    SFTK_FIPSCHECK();
   2122    CHECK_FORK();
   2123    return NSC_VerifyMessage(hSession, pParameter, ulParameterLen, pData,
   2124                             ulDataLen, pSignature, ulSignatureLen);
   2125 }
   2126 
   2127 CK_RV
   2128 FC_VerifyMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
   2129                      CK_ULONG ulParameterLen)
   2130 {
   2131    SFTK_FIPSCHECK();
   2132    CHECK_FORK();
   2133    return NSC_VerifyMessageBegin(hSession, pParameter, ulParameterLen);
   2134 }
   2135 
   2136 CK_RV
   2137 FC_VerifyMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
   2138                     CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
   2139                     CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
   2140                     CK_ULONG ulSignatureLen)
   2141 {
   2142    SFTK_FIPSCHECK();
   2143    CHECK_FORK();
   2144    return NSC_VerifyMessageNext(hSession, pParameter, ulParameterLen,
   2145                                 pData, ulDataLen, pSignature, ulSignatureLen);
   2146 }
   2147 
   2148 CK_RV
   2149 FC_MessageVerifyFinal(CK_SESSION_HANDLE hSession)
   2150 {
   2151    SFTK_FIPSCHECK();
   2152    CHECK_FORK();
   2153    return NSC_MessageVerifyFinal(hSession);
   2154 }
   2155 
   2156 CK_RV
   2157 FC_EncapsulateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
   2158                  CK_OBJECT_HANDLE hPublicKey, CK_ATTRIBUTE_PTR pTemplate,
   2159                  CK_ULONG ulAttributeCount, CK_BYTE_PTR pCiphertext,
   2160                  CK_ULONG_PTR pulCiphertextLen, CK_OBJECT_HANDLE_PTR phKey)
   2161 {
   2162    CK_BBOOL *boolptr;
   2163 
   2164    SFTK_FIPSCHECK();
   2165    CHECK_FORK();
   2166 
   2167    /* all secret keys must be sensitive, if the upper level code tries to say
   2168     * otherwise, reject it. */
   2169    boolptr = (CK_BBOOL *)fc_getAttribute(pTemplate,
   2170                                          ulAttributeCount, CKA_SENSITIVE);
   2171    if (boolptr != NULL) {
   2172        if (!(*boolptr)) {
   2173            return CKR_ATTRIBUTE_VALUE_INVALID;
   2174        }
   2175    }
   2176    rv = NSC_EncapsulateKey(hSession, pMechanism, hPublicKey,
   2177                            pTemplate, ulAttributeCount,
   2178                            pCiphertext, pulCiphertextLen, phKey);
   2179    if (sftk_audit_enabled) {
   2180        sftk_AuditEncapsulateKey(hSession, pMechanism, hPublicKey,
   2181                                 pTemplate, ulAttributeCount,
   2182                                 pCiphertext, pulCiphertextLen, phKey, rv);
   2183    }
   2184    return rv;
   2185 }
   2186 
   2187 CK_RV
   2188 FC_DecapsulateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
   2189                  CK_OBJECT_HANDLE hPrivateKey, CK_ATTRIBUTE_PTR pTemplate,
   2190                  CK_ULONG ulAttributeCount, CK_BYTE_PTR pCiphertext,
   2191                  CK_ULONG ulCiphertextLen, CK_OBJECT_HANDLE_PTR phKey)
   2192 {
   2193    CK_BBOOL *boolptr;
   2194 
   2195    SFTK_FIPSCHECK();
   2196    CHECK_FORK();
   2197 
   2198    /* all secret keys must be sensitive, if the upper level code tries to say
   2199     * otherwise, reject it. */
   2200    boolptr = (CK_BBOOL *)fc_getAttribute(pTemplate,
   2201                                          ulAttributeCount, CKA_SENSITIVE);
   2202    if (boolptr != NULL) {
   2203        if (!(*boolptr)) {
   2204            return CKR_ATTRIBUTE_VALUE_INVALID;
   2205        }
   2206    }
   2207    rv = NSC_DecapsulateKey(hSession, pMechanism, hPrivateKey,
   2208                            pTemplate, ulAttributeCount,
   2209                            pCiphertext, ulCiphertextLen, phKey);
   2210    if (sftk_audit_enabled) {
   2211        sftk_AuditDecapsulateKey(hSession, pMechanism, hPrivateKey,
   2212                                 pTemplate, ulAttributeCount,
   2213                                 pCiphertext, ulCiphertextLen, phKey, rv);
   2214    }
   2215    return rv;
   2216 }
   2217 
   2218 CK_RV
   2219 FC_GetSessionValidationFlags(CK_SESSION_HANDLE hSession,
   2220                             CK_SESSION_VALIDATION_FLAGS_TYPE type,
   2221                             CK_FLAGS_PTR pFlags)
   2222 {
   2223    SFTK_FIPSCHECK();
   2224    CHECK_FORK();
   2225 
   2226    return NSC_GetSessionValidationFlags(hSession, type, pFlags);
   2227 }
   2228 
   2229 CK_RV
   2230 FC_AsyncComplete(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pFunctionName,
   2231                 CK_ASYNC_DATA_PTR pResult)
   2232 {
   2233    SFTK_FIPSCHECK();
   2234    CHECK_FORK();
   2235 
   2236    return NSC_AsyncComplete(hSession, pFunctionName, pResult);
   2237 }
   2238 
   2239 CK_RV
   2240 FC_AsyncGetID(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pFunctionName,
   2241              CK_ULONG_PTR pulID)
   2242 {
   2243    SFTK_FIPSCHECK();
   2244    CHECK_FORK();
   2245 
   2246    return NSC_AsyncGetID(hSession, pFunctionName, pulID);
   2247 }
   2248 
   2249 CK_RV
   2250 FC_AsyncJoin(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pFunctionName,
   2251             CK_ULONG ulID, CK_BYTE_PTR pData, CK_ULONG ulData)
   2252 {
   2253    SFTK_FIPSCHECK();
   2254    CHECK_FORK();
   2255 
   2256    return FC_AsyncJoin(hSession, pFunctionName, ulID, pData, ulData);
   2257 }
   2258 
   2259 CK_RV
   2260 FC_WrapKeyAuthenticated(CK_SESSION_HANDLE hSession,
   2261                        CK_MECHANISM_PTR pMechanism,
   2262                        CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey,
   2263                        CK_BYTE_PTR pAssociatedData,
   2264                        CK_ULONG ulAssociatedDataLen,
   2265                        CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen)
   2266 {
   2267    SFTK_FIPSCHECK();
   2268    CHECK_FORK();
   2269 
   2270    /* Before we support FC_WrapKeyAuthenticated, we'll have to add
   2271     * logging here, so just return CKR_FUNCTION_NOT_SUPPORTED until logging
   2272     * is added */
   2273    return CKR_FUNCTION_NOT_SUPPORTED;
   2274 }
   2275 
   2276 CK_RV
   2277 FC_UnwrapKeyAuthenticated(CK_SESSION_HANDLE hSession,
   2278                          CK_MECHANISM_PTR pMechanism,
   2279                          CK_OBJECT_HANDLE hUnwrappingKey,
   2280                          CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
   2281                          CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
   2282                          CK_BYTE_PTR pAssociatedData,
   2283                          CK_ULONG ulAssociatedDataLen,
   2284                          CK_OBJECT_HANDLE_PTR phKey)
   2285 {
   2286    SFTK_FIPSCHECK();
   2287    CHECK_FORK();
   2288 
   2289    /* Before we support FC_UnwrapKeyAuthenticated, we'll have to add
   2290     * logging here, so just return CKR_FUNCTION_NOT_SUPPORTED until logging
   2291     * is added */
   2292    return CKR_FUNCTION_NOT_SUPPORTED;
   2293 }