/* * Copyright Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms specified in the COPYING file * distributed with the Net-SNMP package. */ /* * pkcs.c */ #include #ifdef NETSNMP_USE_PKCS11 #include #include #include #include #include #include #include #include #include typedef struct netsnmp_pkcs_slot_session_s { CK_SLOT_ID sid; CK_SESSION_HANDLE hdl; } netsnmp_pkcs_slot_session; typedef struct netsnmp_pkcs_slot_info_s { int count; netsnmp_pkcs_slot_session *pSession; } netsnmp_pkcs_slot_info; static CK_RV get_session_handle(CK_MECHANISM_TYPE, CK_FLAGS,\ CK_SESSION_HANDLE_PTR); static CK_RV get_slot_session_handle(netsnmp_pkcs_slot_session *,\ CK_SESSION_HANDLE_PTR); static char *pkcserr_string(CK_RV); static int free_slots(int, int, void *, void *); static netsnmp_pkcs_slot_info *pSlot = NULL; /* * initialize the Cryptoki library. */ int pkcs_init(void) { CK_RV rv; CK_ULONG slotcount; CK_SLOT_ID_PTR pSlotList = NULL; netsnmp_pkcs_slot_session *tmp; int i, rval = SNMPERR_SUCCESS; /* Initialize pkcs */ if ((rv = C_Initialize(NULL)) != CKR_OK) { DEBUGMSGTL(("pkcs_init", "C_Initialize failed: %s", pkcserr_string(rv))); return SNMPERR_SC_NOT_CONFIGURED; } /* Get slot count */ rv = C_GetSlotList(1, NULL_PTR, &slotcount); if (rv != CKR_OK || slotcount == 0) { DEBUGMSGTL(("pkcs_init", "C_GetSlotList failed: %s", pkcserr_string(rv))); QUITFUN(SNMPERR_GENERR, pkcs_init_quit); } /* Found at least one slot, allocate memory for slot list */ pSlotList = malloc(slotcount * sizeof (CK_SLOT_ID)); pSlot = malloc(sizeof (netsnmp_pkcs_slot_info)); pSlot->pSession = malloc(slotcount * sizeof (netsnmp_pkcs_slot_session)); if (pSlotList == NULL_PTR || pSlot == NULL_PTR || pSlot->pSession == NULL_PTR) { DEBUGMSGTL(("pkcs_init","malloc failed.")); QUITFUN(SNMPERR_GENERR, pkcs_init_quit); } /* Get the list of slots */ if ((rv = C_GetSlotList(1, pSlotList, &slotcount)) != CKR_OK) { DEBUGMSGTL(("pkcs_init", "C_GetSlotList failed: %s", pkcserr_string(rv))); QUITFUN(SNMPERR_GENERR, pkcs_init_quit); } /* initialize Slots structure */ pSlot->count = slotcount; for (i = 0, tmp = pSlot->pSession; i < slotcount; i++, tmp++) { tmp->sid = pSlotList[i]; tmp->hdl = NULL; } snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SHUTDOWN, free_slots, NULL); pkcs_init_quit: SNMP_FREE(pSlotList); return rval; } /* * close all the opened sessions when finished with Cryptoki library. */ static int free_slots(int majorID, int minorID, void *serverarg, void *clientarg) { int slotcount, i; if (pSlot != NULL) { slotcount = pSlot->count; for (i = 0; i < slotcount; i++) { if (pSlot->pSession->hdl != NULL) { free(pSlot->pSession->hdl); } } free(pSlot); } (void) C_Finalize(NULL); return 0; } /* * generate random data */ int pkcs_random(u_char * buf, size_t buflen) { CK_SESSION_HANDLE hSession; if (pSlot != NULL && get_slot_session_handle(pSlot->pSession, &hSession) == CKR_OK && C_GenerateRandom(hSession, buf, buflen) == CKR_OK) { return SNMPERR_SUCCESS; } return SNMPERR_GENERR; } /* * retrieve the session handle from the first slot that supports the specified * mechanism. */ static CK_RV get_session_handle(CK_MECHANISM_TYPE mech_type, CK_FLAGS flag, CK_SESSION_HANDLE_PTR sess) { CK_RV rv = CKR_OK; CK_MECHANISM_INFO info; netsnmp_pkcs_slot_session *p = NULL; int i, slotcount = 0; if (pSlot) { slotcount = pSlot->count; p = pSlot->pSession; } /* Find a slot with matching mechanism */ for (i = 0; i < slotcount; i++, p++) { rv = C_GetMechanismInfo(p->sid, mech_type, &info); if (rv != CKR_OK) { continue; /* to the next slot */ } else { if (info.flags & flag) { rv = get_slot_session_handle(p, sess); break; /* found */ } } } /* Show error if no matching mechanism found */ if (i == slotcount) { DEBUGMSGTL(("pkcs_init","No cryptographic provider for %s", mech_type)); return CKR_SESSION_HANDLE_INVALID; } return rv; } /* * retrieve the session handle from the specified slot. */ static CK_RV get_slot_session_handle(netsnmp_pkcs_slot_session *p, CK_SESSION_HANDLE_PTR sess) { CK_RV rv = CKR_OK; if (p == NULL) { *sess = NULL; return CKR_SESSION_HANDLE_INVALID; } if (p->hdl == NULL) { /* Open a session */ rv = C_OpenSession(p->sid, CKF_SERIAL_SESSION, NULL_PTR, NULL, &p->hdl); if (rv != CKR_OK) { DEBUGMSGTL(("get_slot_session_handle","can not open PKCS #11 session: %s", pkcserr_string(rv))); } } *sess = p->hdl; return rv; } /* * perform a signature operation to generate MAC. */ int pkcs_sign(CK_MECHANISM_TYPE mech_type, u_char * key, u_int keylen, u_char * msg, u_int msglen, u_char * mac, size_t * maclen) { /* * Key template */ CK_OBJECT_CLASS class = CKO_SECRET_KEY; CK_KEY_TYPE keytype = CKK_GENERIC_SECRET; CK_BBOOL truevalue = TRUE; CK_BBOOL falsevalue= FALSE; CK_ATTRIBUTE template[] = { {CKA_CLASS, &class, sizeof (class)}, {CKA_KEY_TYPE, &keytype, sizeof (keytype)}, {CKA_SIGN, &truevalue, sizeof (truevalue)}, {CKA_TOKEN, &falsevalue, sizeof (falsevalue)}, {CKA_VALUE, key, keylen} }; CK_SESSION_HANDLE hSession; CK_MECHANISM mech; CK_OBJECT_HANDLE hkey = (CK_OBJECT_HANDLE) 0; int rval = SNMPERR_SUCCESS; if (get_session_handle(mech_type, CKF_SIGN, &hSession) != CKR_OK || hSession == NULL) { QUITFUN(SNMPERR_GENERR, pkcs_sign_quit); } /* create a key object */ if (C_CreateObject(hSession, template, (sizeof (template) / sizeof (CK_ATTRIBUTE)), &hkey) != CKR_OK) { QUITFUN(SNMPERR_GENERR, pkcs_sign_quit); } mech.mechanism = mech_type; mech.pParameter = NULL_PTR; mech.ulParameterLen = 0; /* initialize a signature operation */ if (C_SignInit(hSession, &mech, hkey) != CKR_OK ) { QUITFUN(SNMPERR_GENERR, pkcs_sign_quit); } /* continue a multiple-part signature operation */ if (C_SignUpdate(hSession, msg, msglen) != CKR_OK) { QUITFUN(SNMPERR_GENERR, pkcs_sign_quit); } /* finish a multiple-part signature operation */ if (C_SignFinal(hSession, mac, maclen) != CKR_OK) { QUITFUN(SNMPERR_GENERR, pkcs_sign_quit); } pkcs_sign_quit: if (key != (CK_OBJECT_HANDLE) 0) { (void) C_DestroyObject(hSession, hkey); } return rval; } /* * perform a message-digesting operation. */ int pkcs_digest(CK_MECHANISM_TYPE mech_type, u_char * msg, u_int msglen, u_char * digest, size_t * digestlen) { int rval = SNMPERR_SUCCESS; CK_SESSION_HANDLE hSession; CK_MECHANISM mech; if (get_session_handle(mech_type, CKF_DIGEST, &hSession) != CKR_OK || hSession == NULL) { QUITFUN(SNMPERR_GENERR, pkcs_digest_quit); } mech.mechanism = mech_type; mech.pParameter = NULL_PTR; mech.ulParameterLen = 0; /* initialize a message-digesting operation */ if (C_DigestInit(hSession, &mech)!= CKR_OK ) { QUITFUN(SNMPERR_GENERR, pkcs_digest_quit); } /* continue a multiple-part message-digesting operation */ if (C_DigestUpdate(hSession, msg, msglen) != CKR_OK ) { QUITFUN(SNMPERR_GENERR, pkcs_digest_quit); } /* finish a multiple-part message-digesting operation */ if (C_DigestFinal(hSession, digest, digestlen) != CKR_OK) { QUITFUN(SNMPERR_GENERR, pkcs_digest_quit); } pkcs_digest_quit: return rval; } /* * encrypt plaintext into ciphertext using key and iv. */ int pkcs_encrpyt(CK_MECHANISM_TYPE mech_type, u_char * key, u_int keylen, u_char * iv, u_int ivlen, u_char * plaintext, u_int ptlen, u_char * ciphertext, size_t * ctlen) { int rval = SNMPERR_SUCCESS; int pad_size, offset; /* * Key template */ CK_OBJECT_CLASS class = CKO_SECRET_KEY; CK_KEY_TYPE keytype = CKK_DES; /* CK_KEY_TYPE AESkeytype = CKK_AES; */ CK_BBOOL truevalue = TRUE; CK_BBOOL falsevalue = FALSE; CK_ATTRIBUTE template[] = { {CKA_CLASS, &class, sizeof (class)}, {CKA_KEY_TYPE, &keytype, sizeof (keytype)}, {CKA_ENCRYPT, &truevalue, sizeof (truevalue)}, {CKA_TOKEN, &falsevalue, sizeof (falsevalue)}, {CKA_VALUE, key, keylen} }; CK_SESSION_HANDLE hSession; CK_MECHANISM mech; CK_OBJECT_HANDLE hkey = (CK_OBJECT_HANDLE) 0; if (get_session_handle(mech_type, CKF_ENCRYPT, &hSession) != CKR_OK || hSession == NULL) { QUITFUN(SNMPERR_GENERR, pkcs_encrypt_quit); } if (C_CreateObject(hSession, template, (sizeof (template) / sizeof (CK_ATTRIBUTE)), &hkey) != CKR_OK) { QUITFUN(SNMPERR_GENERR, pkcs_encrypt_quit); } mech.mechanism = mech_type; mech.pParameter = iv; mech.ulParameterLen = ivlen; /* initialize an encryption operation */ if (C_EncryptInit(hSession, &mech, hkey) != CKR_OK ) { QUITFUN(SNMPERR_GENERR, pkcs_encrypt_quit); } /* for DES */ pad_size = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES); if (ptlen + pad_size - ptlen % pad_size > *ctlen) { QUITFUN(SNMPERR_GENERR, pkcs_encrypt_quit); } for (offset = 0; offset < ptlen; offset += pad_size) { /* continue a multiple-part encryption operation */ if (C_EncryptUpdate(hSession, plaintext + offset, pad_size, ciphertext + offset, ctlen) != CKR_OK) { QUITFUN(SNMPERR_GENERR, pkcs_encrypt_quit); } } /* finish a multiple-part encryption operation */ if (C_EncryptFinal(hSession, ciphertext + offset, ctlen) != CKR_OK) { QUITFUN(SNMPERR_GENERR, pkcs_encrypt_quit); } *ctlen = offset; pkcs_encrypt_quit: if (key != (CK_OBJECT_HANDLE) 0) { (void) C_DestroyObject(hSession, hkey); } return rval; } /* * decrypt ciphertext into plaintext using key and iv. */ int pkcs_decrpyt(CK_MECHANISM_TYPE mech_type, u_char * key, u_int keylen, u_char * iv, u_int ivlen, u_char * ciphertext, u_int ctlen, u_char * plaintext, size_t * ptlen) { int rval = SNMPERR_SUCCESS; /* * Key template */ CK_OBJECT_CLASS class = CKO_SECRET_KEY; CK_KEY_TYPE keytype = CKK_DES; /* CK_KEY_TYPE AESkeytype = CKK_AES; */ CK_BBOOL truevalue = TRUE; CK_BBOOL falsevalue= FALSE; CK_ATTRIBUTE template[] = { {CKA_CLASS, &class, sizeof (class)}, {CKA_KEY_TYPE, &keytype, sizeof (keytype)}, {CKA_DECRYPT, &truevalue, sizeof (truevalue)}, {CKA_TOKEN, &falsevalue, sizeof (falsevalue)}, {CKA_VALUE, key, keylen} }; CK_SESSION_HANDLE hSession; CK_MECHANISM mech; CK_OBJECT_HANDLE hkey = (CK_OBJECT_HANDLE) 0; if (get_session_handle(mech_type, CKF_DECRYPT, &hSession) != CKR_OK || hSession == NULL) { QUITFUN(SNMPERR_GENERR, pkcs_decrypt_quit); } if (C_CreateObject(hSession, template, (sizeof (template) / sizeof (CK_ATTRIBUTE)), &hkey) != CKR_OK) { QUITFUN(SNMPERR_GENERR, pkcs_decrypt_quit); } mech.mechanism = mech_type; mech.pParameter = iv; mech.ulParameterLen = ivlen; /* initialize a decryption operation */ if (C_DecryptInit(hSession, &mech, hkey) != CKR_OK ) { QUITFUN(SNMPERR_GENERR, pkcs_decrypt_quit); } /* continue a multiple-part decryption operation */ if (C_DecryptUpdate(hSession, ciphertext, ctlen, plaintext, ptlen) != CKR_OK) { QUITFUN(SNMPERR_GENERR, pkcs_decrypt_quit); } /* finish a multiple-part decryption operation */ if (C_DecryptFinal(hSession, plaintext, ptlen) != CKR_OK) { QUITFUN(SNMPERR_GENERR, pkcs_decrypt_quit); } pkcs_decrypt_quit: if (key != (CK_OBJECT_HANDLE) 0) { (void) C_DestroyObject(hSession, hkey); } return rval; } /* * Convert a passphrase into a master user key, Ku, according to the * algorithm given in RFC 2274 concerning the SNMPv3 User Security Model (USM) */ int pkcs_generate_Ku(CK_MECHANISM_TYPE mech_type, u_char * passphrase, u_int pplen, u_char * Ku, size_t * kulen) { int rval = SNMPERR_SUCCESS, nbytes = USM_LENGTH_EXPANDED_PASSPHRASE; CK_SESSION_HANDLE hSession; CK_MECHANISM mech; u_int i, pindex = 0; u_char buf[USM_LENGTH_KU_HASHBLOCK], *bufp; if (get_session_handle(mech_type, CKF_DIGEST, &hSession) != CKR_OK || hSession == NULL) { QUITFUN(SNMPERR_GENERR, pkcs_generate_Ku_quit); } mech.mechanism = mech_type; mech.pParameter = NULL_PTR; mech.ulParameterLen = 0; /* initialize a message-digesting operation */ if (C_DigestInit(hSession, &mech)!= CKR_OK ) { QUITFUN(SNMPERR_GENERR, pkcs_generate_Ku_quit); } while (nbytes > 0) { bufp = buf; for (i = 0; i < USM_LENGTH_KU_HASHBLOCK; i++) { /* * fill a buffer with the supplied passphrase. When the end * of the passphrase is reachedcycle back to the beginning. */ *bufp++ = passphrase[pindex++ % pplen]; } /* continue a multiple-part message-digesting operation */ if (C_DigestUpdate(hSession, buf, USM_LENGTH_KU_HASHBLOCK) != CKR_OK ) { QUITFUN(SNMPERR_GENERR, pkcs_generate_Ku_quit); } nbytes -= USM_LENGTH_KU_HASHBLOCK; } /* finish a multiple-part message-digesting operation */ if (C_DigestFinal(hSession, Ku, kulen) != CKR_OK) { QUITFUN(SNMPERR_GENERR, pkcs_generate_Ku_quit); } pkcs_generate_Ku_quit: return rval; } /* * pkcserr_stringor: returns a string representation of the given * return code. */ static char * pkcserr_string(CK_RV rv) { static char errstr[128]; switch (rv) { case CKR_OK: return ("CKR_OK"); break; case CKR_CANCEL: return ("CKR_CANCEL"); break; case CKR_HOST_MEMORY: return ("CKR_HOST_MEMORY"); break; case CKR_SLOT_ID_INVALID: return ("CKR_SLOT_ID_INVALID"); break; case CKR_GENERAL_ERROR: return ("CKR_GENERAL_ERROR"); break; case CKR_FUNCTION_FAILED: return ("CKR_FUNCTION_FAILED"); break; case CKR_ARGUMENTS_BAD: return ("CKR_ARGUMENTS_BAD"); break; case CKR_NO_EVENT: return ("CKR_NO_EVENT"); break; case CKR_NEED_TO_CREATE_THREADS: return ("CKR_NEED_TO_CREATE_THREADS"); break; case CKR_CANT_LOCK: return ("CKR_CANT_LOCK"); break; case CKR_ATTRIBUTE_READ_ONLY: return ("CKR_ATTRIBUTE_READ_ONLY"); break; case CKR_ATTRIBUTE_SENSITIVE: return ("CKR_ATTRIBUTE_SENSITIVE"); break; case CKR_ATTRIBUTE_TYPE_INVALID: return ("CKR_ATTRIBUTE_TYPE_INVALID"); break; case CKR_ATTRIBUTE_VALUE_INVALID: return ("CKR_ATTRIBUTE_VALUE_INVALID"); break; case CKR_DATA_INVALID: return ("CKR_DATA_INVALID"); break; case CKR_DATA_LEN_RANGE: return ("CKR_DATA_LEN_RANGE"); break; case CKR_DEVICE_ERROR: return ("CKR_DEVICE_ERROR"); break; case CKR_DEVICE_MEMORY: return ("CKR_DEVICE_MEMORY"); break; case CKR_DEVICE_REMOVED: return ("CKR_DEVICE_REMOVED"); break; case CKR_ENCRYPTED_DATA_INVALID: return ("CKR_ENCRYPTED_DATA_INVALID"); break; case CKR_ENCRYPTED_DATA_LEN_RANGE: return ("CKR_ENCRYPTED_DATA_LEN_RANGE"); break; case CKR_FUNCTION_CANCELED: return ("CKR_FUNCTION_CANCELED"); break; case CKR_FUNCTION_NOT_PARALLEL: return ("CKR_FUNCTION_NOT_PARALLEL"); break; case CKR_FUNCTION_NOT_SUPPORTED: return ("CKR_FUNCTION_NOT_SUPPORTED"); break; case CKR_KEY_HANDLE_INVALID: return ("CKR_KEY_HANDLE_INVALID"); break; case CKR_KEY_SIZE_RANGE: return ("CKR_KEY_SIZE_RANGE"); break; case CKR_KEY_TYPE_INCONSISTENT: return ("CKR_KEY_TYPE_INCONSISTENT"); break; case CKR_KEY_NOT_NEEDED: return ("CKR_KEY_NOT_NEEDED"); break; case CKR_KEY_CHANGED: return ("CKR_KEY_CHANGED"); break; case CKR_KEY_NEEDED: return ("CKR_KEY_NEEDED"); break; case CKR_KEY_INDIGESTIBLE: return ("CKR_KEY_INDIGESTIBLE"); break; case CKR_KEY_FUNCTION_NOT_PERMITTED: return ("CKR_KEY_FUNCTION_NOT_PERMITTED"); break; case CKR_KEY_NOT_WRAPPABLE: return ("CKR_KEY_NOT_WRAPPABLE"); break; case CKR_KEY_UNEXTRACTABLE: return ("CKR_KEY_UNEXTRACTABLE"); break; case CKR_MECHANISM_INVALID: return ("CKR_MECHANISM_INVALID"); break; case CKR_MECHANISM_PARAM_INVALID: return ("CKR_MECHANISM_PARAM_INVALID"); break; case CKR_OBJECT_HANDLE_INVALID: return ("CKR_OBJECT_HANDLE_INVALID"); break; case CKR_OPERATION_ACTIVE: return ("CKR_OPERATION_ACTIVE"); break; case CKR_OPERATION_NOT_INITIALIZED: return ("CKR_OPERATION_NOT_INITIALIZED"); break; case CKR_PIN_INCORRECT: return ("CKR_PIN_INCORRECT"); break; case CKR_PIN_INVALID: return ("CKR_PIN_INVALID"); break; case CKR_PIN_LEN_RANGE: return ("CKR_PIN_LEN_RANGE"); break; case CKR_PIN_EXPIRED: return ("CKR_PIN_EXPIRED"); break; case CKR_PIN_LOCKED: return ("CKR_PIN_LOCKED"); break; case CKR_SESSION_CLOSED: return ("CKR_SESSION_CLOSED"); break; case CKR_SESSION_COUNT: return ("CKR_SESSION_COUNT"); break; case CKR_SESSION_HANDLE_INVALID: return ("CKR_SESSION_HANDLE_INVALID"); break; case CKR_SESSION_PARALLEL_NOT_SUPPORTED: return ("CKR_SESSION_PARALLEL_NOT_SUPPORTED"); break; case CKR_SESSION_READ_ONLY: return ("CKR_SESSION_READ_ONLY"); break; case CKR_SESSION_EXISTS: return ("CKR_SESSION_EXISTS"); break; case CKR_SESSION_READ_ONLY_EXISTS: return ("CKR_SESSION_READ_ONLY_EXISTS"); break; case CKR_SESSION_READ_WRITE_SO_EXISTS: return ("CKR_SESSION_READ_WRITE_SO_EXISTS"); break; case CKR_SIGNATURE_INVALID: return ("CKR_SIGNATURE_INVALID"); break; case CKR_SIGNATURE_LEN_RANGE: return ("CKR_SIGNATURE_LEN_RANGE"); break; case CKR_TEMPLATE_INCOMPLETE: return ("CKR_TEMPLATE_INCOMPLETE"); break; case CKR_TEMPLATE_INCONSISTENT: return ("CKR_TEMPLATE_INCONSISTENT"); break; case CKR_TOKEN_NOT_PRESENT: return ("CKR_TOKEN_NOT_PRESENT"); break; case CKR_TOKEN_NOT_RECOGNIZED: return ("CKR_TOKEN_NOT_RECOGNIZED"); break; case CKR_TOKEN_WRITE_PROTECTED: return ("CKR_TOKEN_WRITE_PROTECTED"); break; case CKR_UNWRAPPING_KEY_HANDLE_INVALID: return ("CKR_UNWRAPPING_KEY_HANDLE_INVALID"); break; case CKR_UNWRAPPING_KEY_SIZE_RANGE: return ("CKR_UNWRAPPING_KEY_SIZE_RANGE"); break; case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT: return ("CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"); break; case CKR_USER_ALREADY_LOGGED_IN: return ("CKR_USER_ALREADY_LOGGED_IN"); break; case CKR_USER_NOT_LOGGED_IN: return ("CKR_USER_NOT_LOGGED_IN"); break; case CKR_USER_PIN_NOT_INITIALIZED: return ("CKR_USER_PIN_NOT_INITIALIZED"); break; case CKR_USER_TYPE_INVALID: return ("CKR_USER_TYPE_INVALID"); break; case CKR_USER_ANOTHER_ALREADY_LOGGED_IN: return ("CKR_USER_ANOTHER_ALREADY_LOGGED_IN"); break; case CKR_USER_TOO_MANY_TYPES: return ("CKR_USER_TOO_MANY_TYPES"); break; case CKR_WRAPPED_KEY_INVALID: return ("CKR_WRAPPED_KEY_INVALID"); break; case CKR_WRAPPED_KEY_LEN_RANGE: return ("CKR_WRAPPED_KEY_LEN_RANGE"); break; case CKR_WRAPPING_KEY_HANDLE_INVALID: return ("CKR_WRAPPING_KEY_HANDLE_INVALID"); break; case CKR_WRAPPING_KEY_SIZE_RANGE: return ("CKR_WRAPPING_KEY_SIZE_RANGE"); break; case CKR_WRAPPING_KEY_TYPE_INCONSISTENT: return ("CKR_WRAPPING_KEY_TYPE_INCONSISTENT"); break; case CKR_RANDOM_SEED_NOT_SUPPORTED: return ("CKR_RANDOM_SEED_NOT_SUPPORTED"); break; case CKR_RANDOM_NO_RNG: return ("CKR_RANDOM_NO_RNG"); break; case CKR_DOMAIN_PARAMS_INVALID: return ("CKR_DOMAIN_PARAMS_INVALID"); break; case CKR_BUFFER_TOO_SMALL: return ("CKR_BUFFER_TOO_SMALL"); break; case CKR_SAVED_STATE_INVALID: return ("CKR_SAVED_STATE_INVALID"); break; case CKR_INFORMATION_SENSITIVE: return ("CKR_INFORMATION_SENSITIVE"); break; case CKR_STATE_UNSAVEABLE: return ("CKR_STATE_UNSAVEABLE"); break; case CKR_CRYPTOKI_NOT_INITIALIZED: return ("CKR_CRYPTOKI_NOT_INITIALIZED"); break; case CKR_CRYPTOKI_ALREADY_INITIALIZED: return ("CKR_CRYPTOKI_ALREADY_INITIALIZED"); break; case CKR_MUTEX_BAD: return ("CKR_MUTEX_BAD"); break; case CKR_MUTEX_NOT_LOCKED: return ("CKR_MUTEX_NOT_LOCKED"); break; case CKR_VENDOR_DEFINED: return ("CKR_VENDOR_DEFINED"); break; default: /* rv not found */ snprintf(errstr, sizeof (errstr), "Unknown return code: 0x%x", rv); return (errstr); break; } } #else int pkcs_unused; /* Suppress "empty translation unit" warning */ #endif