net-snmp  5.4.1
pkcs.c
00001 /*
00002  * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
00003  * Use is subject to license terms specified in the COPYING file
00004  * distributed with the Net-SNMP package.
00005  */
00006 
00007 /*
00008  * pkcs.c
00009  */
00010 
00011 #include <net-snmp/net-snmp-config.h>
00012 #ifdef NETSNMP_USE_PKCS11
00013 #include <net-snmp/types.h>
00014 #include <net-snmp/output_api.h>
00015 #include <net-snmp/config_api.h>
00016 #include <net-snmp/library/snmp_api.h>
00017 #include <net-snmp/library/tools.h>
00018 #include <net-snmp/library/keytools.h>
00019 #include <net-snmp/library/scapi.h>
00020 #include <net-snmp/library/callback.h>
00021 #include <security/cryptoki.h>
00022 
00023 typedef struct netsnmp_pkcs_slot_session_s {
00024     CK_SLOT_ID        sid;
00025     CK_SESSION_HANDLE hdl;
00026 } netsnmp_pkcs_slot_session; 
00027 
00028 typedef struct netsnmp_pkcs_slot_info_s {
00029     int count;
00030     netsnmp_pkcs_slot_session *pSession; 
00031 } netsnmp_pkcs_slot_info;
00032 
00033 static CK_RV get_session_handle(CK_MECHANISM_TYPE, CK_FLAGS,\
00034                                 CK_SESSION_HANDLE_PTR);
00035 static CK_RV get_slot_session_handle(netsnmp_pkcs_slot_session *,\
00036                                      CK_SESSION_HANDLE_PTR);
00037 static char *pkcserr_string(CK_RV);
00038 static int free_slots(int, int, void *, void *);
00039 
00040 static netsnmp_pkcs_slot_info *pSlot = NULL;
00041 
00042 /*
00043  * initialize the Cryptoki library.
00044  */
00045 int
00046 pkcs_init(void)
00047 {
00048     CK_RV          rv;
00049     CK_ULONG       slotcount;
00050     CK_SLOT_ID_PTR pSlotList = NULL;
00051     netsnmp_pkcs_slot_session    *tmp;
00052     int            i, rval = SNMPERR_SUCCESS;
00053     /* Initialize pkcs */
00054     if ((rv = C_Initialize(NULL)) != CKR_OK) {
00055         DEBUGMSGTL(("pkcs_init", "C_Initialize failed: %s",
00056                 pkcserr_string(rv)));
00057         return SNMPERR_SC_NOT_CONFIGURED;
00058     }
00059 
00060     /* Get slot count */
00061     rv = C_GetSlotList(1, NULL_PTR, &slotcount);
00062     if (rv != CKR_OK || slotcount == 0) {
00063         DEBUGMSGTL(("pkcs_init", "C_GetSlotList failed: %s", 
00064                 pkcserr_string(rv)));
00065         QUITFUN(SNMPERR_GENERR, pkcs_init_quit);
00066     }
00067 
00068     /* Found at least one slot, allocate memory for slot list */
00069     pSlotList = malloc(slotcount * sizeof (CK_SLOT_ID));
00070     pSlot = malloc(sizeof (netsnmp_pkcs_slot_info));
00071     pSlot->pSession = malloc(slotcount * sizeof (netsnmp_pkcs_slot_session));
00072 
00073     if (pSlotList == NULL_PTR ||
00074         pSlot == NULL_PTR ||
00075         pSlot->pSession == NULL_PTR) {
00076         DEBUGMSGTL(("pkcs_init","malloc failed.")); 
00077         QUITFUN(SNMPERR_GENERR, pkcs_init_quit);
00078     }
00079 
00080     /* Get the list of slots */
00081     if ((rv = C_GetSlotList(1, pSlotList, &slotcount)) != CKR_OK) {
00082         DEBUGMSGTL(("pkcs_init", "C_GetSlotList failed: %s", 
00083                 pkcserr_string(rv)));
00084         QUITFUN(SNMPERR_GENERR, pkcs_init_quit);
00085     }
00086 
00087     /* initialize Slots structure */
00088     pSlot->count = slotcount;
00089     for (i = 0, tmp = pSlot->pSession; i < slotcount; i++, tmp++) {
00090         tmp->sid = pSlotList[i]; 
00091         tmp->hdl = NULL;
00092     }
00093 
00094     snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SHUTDOWN,
00095                         free_slots, NULL);
00096 
00097   pkcs_init_quit:
00098     SNMP_FREE(pSlotList);
00099     return rval;
00100 }
00101 
00102 /*
00103  * close all the opened sessions when finished with Cryptoki library.
00104  */
00105 static int
00106 free_slots(int majorID, int minorID, void *serverarg, void *clientarg)
00107 {
00108     (void) C_Finalize(NULL);
00109 
00110     if (pSlot != NULL) {
00111         SNMP_FREE(pSlot->pSession);
00112         SNMP_FREE(pSlot);
00113     }
00114 
00115     return 0;
00116 }
00117 
00118 /*
00119  * generate random data
00120  */
00121 int
00122 pkcs_random(u_char * buf, size_t buflen)
00123 {
00124     CK_SESSION_HANDLE hSession;
00125 
00126     if (pSlot != NULL &&
00127         get_slot_session_handle(pSlot->pSession, &hSession) == CKR_OK &&
00128         C_GenerateRandom(hSession, buf, buflen) == CKR_OK) {
00129         return SNMPERR_SUCCESS;
00130     }
00131 
00132     return SNMPERR_GENERR;
00133 }
00134 
00135 /*
00136  * retrieve the session handle from the first slot that supports the specified
00137  * mechanism.
00138  */
00139 static CK_RV
00140 get_session_handle(CK_MECHANISM_TYPE mech_type, CK_FLAGS flag,
00141                 CK_SESSION_HANDLE_PTR sess)
00142 {
00143     CK_RV             rv = CKR_OK;
00144     CK_MECHANISM_INFO info;
00145     netsnmp_pkcs_slot_session       *p = NULL;
00146     int               i, slotcount = 0;
00147             
00148     if (pSlot) {
00149         slotcount = pSlot->count;
00150         p = pSlot->pSession;
00151     }
00152 
00153     /* Find a slot with matching mechanism */
00154     for (i = 0; i < slotcount; i++, p++) {
00155         rv = C_GetMechanismInfo(p->sid, mech_type, &info);
00156 
00157         if (rv != CKR_OK) {
00158             continue; /* to the next slot */
00159         } else {
00160             if (info.flags & flag) {
00161                 rv = get_slot_session_handle(p, sess);
00162                 break; /* found */
00163             }
00164         }
00165     }
00166 
00167     /* Show error if no matching mechanism found */
00168     if (i == slotcount) {
00169         DEBUGMSGTL(("pkcs_init","No cryptographic provider for %s",
00170                 mech_type)); 
00171         return CKR_SESSION_HANDLE_INVALID;
00172     }
00173 
00174     return rv;
00175 }
00176 
00177 /*
00178  * retrieve the session handle from the specified slot.
00179  */
00180 static CK_RV
00181 get_slot_session_handle(netsnmp_pkcs_slot_session *p,
00182                         CK_SESSION_HANDLE_PTR sess)
00183 {
00184     CK_RV rv = CKR_OK;
00185     if (p == NULL) {
00186         *sess = NULL;
00187         return CKR_SESSION_HANDLE_INVALID;
00188     }
00189 
00190     if (p->hdl == NULL) {
00191         /* Open a session */
00192         rv = C_OpenSession(p->sid, CKF_SERIAL_SESSION,
00193                 NULL_PTR, NULL, &p->hdl);
00194 
00195         if (rv != CKR_OK) {
00196             DEBUGMSGTL(("get_slot_session_handle","can not open PKCS #11 session: %s",
00197                         pkcserr_string(rv)));
00198         }
00199     }
00200     *sess = p->hdl;
00201 
00202     return rv;
00203 }
00204 
00205 /*
00206  * perform a signature operation to generate MAC.
00207  */
00208 int
00209 pkcs_sign(CK_MECHANISM_TYPE mech_type, u_char * key, u_int keylen,
00210           u_char * msg, u_int msglen, u_char * mac, size_t * maclen)
00211 {
00212     /*
00213      * Key template 
00214      */
00215     CK_OBJECT_CLASS class = CKO_SECRET_KEY;
00216     CK_KEY_TYPE keytype = CKK_GENERIC_SECRET;
00217     CK_BBOOL truevalue = TRUE;
00218     CK_BBOOL falsevalue= FALSE;
00219     CK_ATTRIBUTE template[] = {
00220         {CKA_CLASS, &class, sizeof (class)},
00221         {CKA_KEY_TYPE, &keytype, sizeof (keytype)},
00222         {CKA_SIGN, &truevalue, sizeof (truevalue)},
00223         {CKA_TOKEN, &falsevalue, sizeof (falsevalue)},
00224         {CKA_VALUE, key, keylen}
00225     };
00226     CK_SESSION_HANDLE hSession;
00227     CK_MECHANISM mech;
00228     CK_OBJECT_HANDLE hkey = (CK_OBJECT_HANDLE) 0;
00229     int                rval = SNMPERR_SUCCESS;
00230     if (get_session_handle(mech_type, CKF_SIGN, &hSession) != CKR_OK ||
00231         hSession == NULL) {
00232         QUITFUN(SNMPERR_GENERR, pkcs_sign_quit);
00233     }
00234 
00235     /* create a key object */
00236     if (C_CreateObject(hSession, template,
00237         (sizeof (template) / sizeof (CK_ATTRIBUTE)), &hkey) != CKR_OK) {
00238         QUITFUN(SNMPERR_GENERR, pkcs_sign_quit);
00239     }
00240 
00241     mech.mechanism = mech_type;
00242     mech.pParameter = NULL_PTR;
00243     mech.ulParameterLen = 0;
00244 
00245     /* initialize a signature operation */
00246     if (C_SignInit(hSession, &mech, hkey) != CKR_OK ) {
00247         QUITFUN(SNMPERR_GENERR, pkcs_sign_quit);
00248     }
00249     /* continue a multiple-part signature operation */
00250     if (C_SignUpdate(hSession, msg, msglen) != CKR_OK) {
00251         QUITFUN(SNMPERR_GENERR, pkcs_sign_quit);
00252     }
00253     /* finish a multiple-part signature operation */
00254     if (C_SignFinal(hSession, mac, maclen) != CKR_OK) {
00255         QUITFUN(SNMPERR_GENERR, pkcs_sign_quit);
00256     }
00257 
00258   pkcs_sign_quit:
00259 
00260     if (key != (CK_OBJECT_HANDLE) 0) {
00261         (void) C_DestroyObject(hSession, hkey);
00262     }
00263     return rval;
00264 }
00265 
00266 /*
00267  * perform a message-digesting operation.
00268  */
00269 int
00270 pkcs_digest(CK_MECHANISM_TYPE mech_type, u_char * msg, u_int msglen,
00271             u_char * digest, size_t * digestlen)
00272 {
00273     int               rval = SNMPERR_SUCCESS;
00274     CK_SESSION_HANDLE hSession;
00275     CK_MECHANISM      mech;
00276     if (get_session_handle(mech_type, CKF_DIGEST, &hSession) != CKR_OK ||
00277         hSession == NULL) {
00278         QUITFUN(SNMPERR_GENERR, pkcs_digest_quit);
00279     }
00280 
00281     mech.mechanism = mech_type;
00282     mech.pParameter = NULL_PTR;
00283     mech.ulParameterLen = 0;
00284 
00285     /* initialize a message-digesting operation */
00286     if (C_DigestInit(hSession, &mech)!= CKR_OK ) {
00287         QUITFUN(SNMPERR_GENERR, pkcs_digest_quit);
00288     }
00289     /* continue a multiple-part message-digesting operation */
00290     if (C_DigestUpdate(hSession, msg, msglen) != CKR_OK ) {
00291         QUITFUN(SNMPERR_GENERR, pkcs_digest_quit);
00292     }
00293     /* finish a multiple-part message-digesting operation */
00294     if (C_DigestFinal(hSession, digest, digestlen) != CKR_OK) {
00295         QUITFUN(SNMPERR_GENERR, pkcs_digest_quit);
00296     }
00297 
00298   pkcs_digest_quit:
00299     return rval;
00300 }
00301 
00302 /*
00303  * encrypt plaintext into ciphertext using key and iv.   
00304  */
00305 int
00306 pkcs_encrpyt(CK_MECHANISM_TYPE mech_type, u_char * key, u_int keylen,
00307              u_char * iv, u_int ivlen,
00308              u_char * plaintext, u_int ptlen,
00309              u_char * ciphertext, size_t * ctlen)
00310 {
00311     int                rval = SNMPERR_SUCCESS;
00312     int                pad_size, offset;
00313     /*
00314      * Key template 
00315      */
00316     CK_OBJECT_CLASS class = CKO_SECRET_KEY;
00317     CK_KEY_TYPE keytype = CKK_DES;
00318     /* CK_KEY_TYPE AESkeytype = CKK_AES; */
00319     CK_BBOOL truevalue = TRUE;
00320     CK_BBOOL falsevalue = FALSE;
00321 
00322     CK_ATTRIBUTE template[] = {
00323         {CKA_CLASS, &class, sizeof (class)},
00324         {CKA_KEY_TYPE, &keytype, sizeof (keytype)},
00325         {CKA_ENCRYPT, &truevalue, sizeof (truevalue)},
00326         {CKA_TOKEN, &falsevalue, sizeof (falsevalue)},
00327         {CKA_VALUE, key, keylen} 
00328     };
00329 
00330     CK_SESSION_HANDLE hSession;
00331     CK_MECHANISM mech;
00332     CK_OBJECT_HANDLE hkey = (CK_OBJECT_HANDLE) 0;
00333 
00334     if (get_session_handle(mech_type, CKF_ENCRYPT,
00335                            &hSession) != CKR_OK ||
00336         hSession == NULL) {
00337         QUITFUN(SNMPERR_GENERR, pkcs_encrypt_quit);
00338     }
00339 
00340     if (C_CreateObject(hSession, template,
00341         (sizeof (template) / sizeof (CK_ATTRIBUTE)),
00342                                 &hkey) != CKR_OK) {
00343         QUITFUN(SNMPERR_GENERR, pkcs_encrypt_quit);
00344     }
00345 
00346     mech.mechanism = mech_type;
00347     mech.pParameter = iv;
00348     mech.ulParameterLen = ivlen;
00349 
00350     /* initialize an encryption operation */
00351     if (C_EncryptInit(hSession, &mech, hkey) != CKR_OK ) {
00352         QUITFUN(SNMPERR_GENERR, pkcs_encrypt_quit);
00353     }
00354 
00355     /* for DES */
00356     pad_size = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES);
00357 
00358     if (ptlen + pad_size - ptlen % pad_size > *ctlen) {
00359         QUITFUN(SNMPERR_GENERR, pkcs_encrypt_quit);    
00360     }
00361 
00362     for (offset = 0; offset < ptlen; offset += pad_size) {
00363         /* continue a multiple-part encryption operation */
00364         if (C_EncryptUpdate(hSession, plaintext + offset, pad_size,
00365                             ciphertext + offset, ctlen) != CKR_OK) {
00366             QUITFUN(SNMPERR_GENERR, pkcs_encrypt_quit);
00367         }
00368     }
00369 
00370     /* finish a multiple-part encryption operation */
00371     if (C_EncryptFinal(hSession, ciphertext + offset, ctlen) != CKR_OK) {
00372         QUITFUN(SNMPERR_GENERR, pkcs_encrypt_quit);
00373     }
00374     *ctlen = offset;
00375 
00376   pkcs_encrypt_quit:
00377     if (key != (CK_OBJECT_HANDLE) 0) {
00378         (void) C_DestroyObject(hSession, hkey);
00379     }
00380     return rval;
00381 }
00382 
00383 /* 
00384  * decrypt ciphertext into plaintext using key and iv.
00385  */
00386 int
00387 pkcs_decrpyt(CK_MECHANISM_TYPE mech_type, u_char * key, u_int keylen,
00388              u_char * iv, u_int ivlen,
00389              u_char * ciphertext, u_int ctlen,
00390              u_char * plaintext, size_t * ptlen)
00391 {
00392     int            rval = SNMPERR_SUCCESS;
00393     /*
00394      * Key template 
00395      */
00396     CK_OBJECT_CLASS class = CKO_SECRET_KEY;
00397     CK_KEY_TYPE keytype = CKK_DES;
00398     /* CK_KEY_TYPE AESkeytype = CKK_AES; */
00399     CK_BBOOL truevalue = TRUE;
00400     CK_BBOOL falsevalue= FALSE;
00401     CK_ATTRIBUTE template[] = {
00402         {CKA_CLASS, &class, sizeof (class)},
00403         {CKA_KEY_TYPE, &keytype, sizeof (keytype)},
00404         {CKA_DECRYPT, &truevalue, sizeof (truevalue)},
00405         {CKA_TOKEN, &falsevalue, sizeof (falsevalue)},
00406         {CKA_VALUE, key, keylen}
00407     };
00408     CK_SESSION_HANDLE hSession;
00409     CK_MECHANISM mech;
00410     CK_OBJECT_HANDLE hkey = (CK_OBJECT_HANDLE) 0;
00411 
00412     if (get_session_handle(mech_type, CKF_DECRYPT, &hSession) != CKR_OK ||
00413         hSession == NULL) {
00414         QUITFUN(SNMPERR_GENERR, pkcs_decrypt_quit);
00415     }
00416 
00417     if (C_CreateObject(hSession, template,
00418         (sizeof (template) / sizeof (CK_ATTRIBUTE)), &hkey) != CKR_OK) {
00419         QUITFUN(SNMPERR_GENERR, pkcs_decrypt_quit);
00420     }
00421 
00422     mech.mechanism = mech_type;
00423     mech.pParameter = iv;
00424     mech.ulParameterLen = ivlen;
00425 
00426     /* initialize a decryption operation */
00427     if (C_DecryptInit(hSession, &mech, hkey) != CKR_OK ) {
00428         QUITFUN(SNMPERR_GENERR, pkcs_decrypt_quit);
00429     }
00430     /* continue a multiple-part decryption operation */
00431     if (C_DecryptUpdate(hSession, ciphertext, ctlen, plaintext,
00432                                         ptlen) != CKR_OK) {
00433         QUITFUN(SNMPERR_GENERR, pkcs_decrypt_quit);
00434     }
00435     /* finish a multiple-part decryption operation */
00436     if (C_DecryptFinal(hSession, plaintext, ptlen) != CKR_OK) {
00437         QUITFUN(SNMPERR_GENERR, pkcs_decrypt_quit);
00438     }
00439 
00440   pkcs_decrypt_quit:
00441     if (key != (CK_OBJECT_HANDLE) 0) {
00442         (void) C_DestroyObject(hSession, hkey);
00443     }
00444     return rval;
00445 }
00446 
00447 /*
00448  * Convert a passphrase into a master user key, Ku, according to the
00449  * algorithm given in RFC 2274 concerning the SNMPv3 User Security Model (USM)
00450  */
00451 int
00452 pkcs_generate_Ku(CK_MECHANISM_TYPE mech_type, u_char * passphrase, u_int pplen,
00453                  u_char * Ku, size_t * kulen)
00454 {
00455     int                rval = SNMPERR_SUCCESS, nbytes = USM_LENGTH_EXPANDED_PASSPHRASE;
00456     CK_SESSION_HANDLE hSession;
00457     CK_MECHANISM mech;
00458     u_int        i, pindex = 0;
00459     u_char        buf[USM_LENGTH_KU_HASHBLOCK], *bufp;
00460 
00461     if (get_session_handle(mech_type, CKF_DIGEST, &hSession) != CKR_OK ||
00462         hSession == NULL) {
00463         QUITFUN(SNMPERR_GENERR, pkcs_generate_Ku_quit);
00464     }
00465 
00466     mech.mechanism = mech_type;
00467     mech.pParameter = NULL_PTR;
00468     mech.ulParameterLen = 0;
00469 
00470     /* initialize a message-digesting operation */
00471     if (C_DigestInit(hSession, &mech)!= CKR_OK ) {
00472         QUITFUN(SNMPERR_GENERR, pkcs_generate_Ku_quit);
00473     }
00474 
00475     while (nbytes > 0) {
00476         bufp = buf;
00477         for (i = 0; i < USM_LENGTH_KU_HASHBLOCK; i++) {
00478            /*
00479             * fill a buffer with the supplied passphrase.  When the end
00480             * of the passphrase is reachedcycle back to the beginning.
00481             */
00482             *bufp++ = passphrase[pindex++ % pplen];
00483         }
00484         /* continue a multiple-part message-digesting operation */
00485         if (C_DigestUpdate(hSession, buf, USM_LENGTH_KU_HASHBLOCK) != CKR_OK ) {
00486             QUITFUN(SNMPERR_GENERR, pkcs_generate_Ku_quit);
00487         }
00488         nbytes -= USM_LENGTH_KU_HASHBLOCK;
00489     }
00490     /* finish a multiple-part message-digesting operation */
00491     if (C_DigestFinal(hSession, Ku, kulen) != CKR_OK) {
00492         QUITFUN(SNMPERR_GENERR, pkcs_generate_Ku_quit);
00493     }
00494 
00495   pkcs_generate_Ku_quit:
00496     return rval;
00497 }
00498    
00499 /*
00500  * pkcserr_stringor: returns a string representation of the given 
00501  * return code.
00502  */
00503 static char *
00504 pkcserr_string(CK_RV rv)
00505 {
00506     static char errstr[128];
00507     switch (rv) {
00508     case CKR_OK:
00509         return ("CKR_OK");
00510         break;
00511     case CKR_CANCEL:
00512         return ("CKR_CANCEL");
00513         break;
00514     case CKR_HOST_MEMORY:
00515         return ("CKR_HOST_MEMORY");
00516         break;
00517     case CKR_SLOT_ID_INVALID:
00518         return ("CKR_SLOT_ID_INVALID");
00519         break;
00520     case CKR_GENERAL_ERROR:
00521         return ("CKR_GENERAL_ERROR");
00522         break;
00523     case CKR_FUNCTION_FAILED:
00524         return ("CKR_FUNCTION_FAILED");
00525         break;
00526     case CKR_ARGUMENTS_BAD:
00527         return ("CKR_ARGUMENTS_BAD");
00528         break;
00529     case CKR_NO_EVENT:
00530         return ("CKR_NO_EVENT");
00531         break;
00532     case CKR_NEED_TO_CREATE_THREADS:
00533         return ("CKR_NEED_TO_CREATE_THREADS");
00534         break;
00535     case CKR_CANT_LOCK:
00536         return ("CKR_CANT_LOCK");
00537         break;
00538     case CKR_ATTRIBUTE_READ_ONLY:
00539         return ("CKR_ATTRIBUTE_READ_ONLY");
00540         break;
00541     case CKR_ATTRIBUTE_SENSITIVE:
00542         return ("CKR_ATTRIBUTE_SENSITIVE");
00543         break;
00544     case CKR_ATTRIBUTE_TYPE_INVALID:
00545         return ("CKR_ATTRIBUTE_TYPE_INVALID");
00546         break;
00547     case CKR_ATTRIBUTE_VALUE_INVALID:
00548         return ("CKR_ATTRIBUTE_VALUE_INVALID");
00549         break;
00550     case CKR_DATA_INVALID:
00551         return ("CKR_DATA_INVALID");
00552         break;
00553     case CKR_DATA_LEN_RANGE:
00554         return ("CKR_DATA_LEN_RANGE");
00555         break;
00556     case CKR_DEVICE_ERROR:
00557         return ("CKR_DEVICE_ERROR");
00558         break;
00559     case CKR_DEVICE_MEMORY:
00560         return ("CKR_DEVICE_MEMORY");
00561         break;
00562     case CKR_DEVICE_REMOVED:
00563         return ("CKR_DEVICE_REMOVED");
00564         break;
00565     case CKR_ENCRYPTED_DATA_INVALID:
00566         return ("CKR_ENCRYPTED_DATA_INVALID");
00567         break;
00568     case CKR_ENCRYPTED_DATA_LEN_RANGE:
00569         return ("CKR_ENCRYPTED_DATA_LEN_RANGE");
00570         break;
00571     case CKR_FUNCTION_CANCELED:
00572         return ("CKR_FUNCTION_CANCELED");
00573         break;
00574     case CKR_FUNCTION_NOT_PARALLEL:
00575         return ("CKR_FUNCTION_NOT_PARALLEL");
00576         break;
00577     case CKR_FUNCTION_NOT_SUPPORTED:
00578         return ("CKR_FUNCTION_NOT_SUPPORTED");
00579         break;
00580     case CKR_KEY_HANDLE_INVALID:
00581         return ("CKR_KEY_HANDLE_INVALID");
00582         break;
00583     case CKR_KEY_SIZE_RANGE:
00584         return ("CKR_KEY_SIZE_RANGE");
00585         break;
00586     case CKR_KEY_TYPE_INCONSISTENT:
00587         return ("CKR_KEY_TYPE_INCONSISTENT");
00588         break;
00589     case CKR_KEY_NOT_NEEDED:
00590         return ("CKR_KEY_NOT_NEEDED");
00591         break;
00592     case CKR_KEY_CHANGED:
00593         return ("CKR_KEY_CHANGED");
00594         break;
00595     case CKR_KEY_NEEDED:
00596         return ("CKR_KEY_NEEDED");
00597         break;
00598     case CKR_KEY_INDIGESTIBLE:
00599         return ("CKR_KEY_INDIGESTIBLE");
00600         break;
00601     case CKR_KEY_FUNCTION_NOT_PERMITTED:
00602         return ("CKR_KEY_FUNCTION_NOT_PERMITTED");
00603         break;
00604     case CKR_KEY_NOT_WRAPPABLE:
00605         return ("CKR_KEY_NOT_WRAPPABLE");
00606         break;
00607     case CKR_KEY_UNEXTRACTABLE:
00608         return ("CKR_KEY_UNEXTRACTABLE");
00609         break;
00610     case CKR_MECHANISM_INVALID:
00611         return ("CKR_MECHANISM_INVALID");
00612         break;
00613     case CKR_MECHANISM_PARAM_INVALID:
00614         return ("CKR_MECHANISM_PARAM_INVALID");
00615         break;
00616     case CKR_OBJECT_HANDLE_INVALID:
00617         return ("CKR_OBJECT_HANDLE_INVALID");
00618         break;
00619     case CKR_OPERATION_ACTIVE:
00620         return ("CKR_OPERATION_ACTIVE");
00621         break;
00622     case CKR_OPERATION_NOT_INITIALIZED:
00623         return ("CKR_OPERATION_NOT_INITIALIZED");
00624         break;
00625     case CKR_PIN_INCORRECT:
00626         return ("CKR_PIN_INCORRECT");
00627         break;
00628     case CKR_PIN_INVALID:
00629         return ("CKR_PIN_INVALID");
00630         break;
00631     case CKR_PIN_LEN_RANGE:
00632         return ("CKR_PIN_LEN_RANGE");
00633         break;
00634     case CKR_PIN_EXPIRED:
00635         return ("CKR_PIN_EXPIRED");
00636         break;
00637     case CKR_PIN_LOCKED:
00638         return ("CKR_PIN_LOCKED");
00639         break;
00640     case CKR_SESSION_CLOSED:
00641         return ("CKR_SESSION_CLOSED");
00642         break;
00643     case CKR_SESSION_COUNT:
00644         return ("CKR_SESSION_COUNT");
00645         break;
00646     case CKR_SESSION_HANDLE_INVALID:
00647         return ("CKR_SESSION_HANDLE_INVALID");
00648         break;
00649     case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
00650         return ("CKR_SESSION_PARALLEL_NOT_SUPPORTED");
00651         break;
00652     case CKR_SESSION_READ_ONLY:
00653         return ("CKR_SESSION_READ_ONLY");
00654         break;
00655     case CKR_SESSION_EXISTS:
00656         return ("CKR_SESSION_EXISTS");
00657         break;
00658     case CKR_SESSION_READ_ONLY_EXISTS:
00659         return ("CKR_SESSION_READ_ONLY_EXISTS");
00660         break;
00661     case CKR_SESSION_READ_WRITE_SO_EXISTS:
00662         return ("CKR_SESSION_READ_WRITE_SO_EXISTS");
00663         break;
00664     case CKR_SIGNATURE_INVALID:
00665         return ("CKR_SIGNATURE_INVALID");
00666         break;
00667     case CKR_SIGNATURE_LEN_RANGE:
00668         return ("CKR_SIGNATURE_LEN_RANGE");
00669         break;
00670     case CKR_TEMPLATE_INCOMPLETE:
00671         return ("CKR_TEMPLATE_INCOMPLETE");
00672         break;
00673     case CKR_TEMPLATE_INCONSISTENT:
00674         return ("CKR_TEMPLATE_INCONSISTENT");
00675         break;
00676     case CKR_TOKEN_NOT_PRESENT:
00677         return ("CKR_TOKEN_NOT_PRESENT");
00678         break;
00679     case CKR_TOKEN_NOT_RECOGNIZED:
00680         return ("CKR_TOKEN_NOT_RECOGNIZED");
00681         break;
00682     case CKR_TOKEN_WRITE_PROTECTED:
00683         return ("CKR_TOKEN_WRITE_PROTECTED");
00684         break;
00685     case CKR_UNWRAPPING_KEY_HANDLE_INVALID:
00686         return ("CKR_UNWRAPPING_KEY_HANDLE_INVALID");
00687         break;
00688     case CKR_UNWRAPPING_KEY_SIZE_RANGE:
00689         return ("CKR_UNWRAPPING_KEY_SIZE_RANGE");
00690         break;
00691     case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT:
00692         return ("CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT");
00693         break;
00694     case CKR_USER_ALREADY_LOGGED_IN:
00695         return ("CKR_USER_ALREADY_LOGGED_IN");
00696         break;
00697     case CKR_USER_NOT_LOGGED_IN:
00698         return ("CKR_USER_NOT_LOGGED_IN");
00699         break;
00700     case CKR_USER_PIN_NOT_INITIALIZED:
00701         return ("CKR_USER_PIN_NOT_INITIALIZED");
00702         break;
00703     case CKR_USER_TYPE_INVALID:
00704         return ("CKR_USER_TYPE_INVALID");
00705         break;
00706     case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
00707         return ("CKR_USER_ANOTHER_ALREADY_LOGGED_IN");
00708         break;
00709     case CKR_USER_TOO_MANY_TYPES:
00710         return ("CKR_USER_TOO_MANY_TYPES");
00711         break;
00712     case CKR_WRAPPED_KEY_INVALID:
00713         return ("CKR_WRAPPED_KEY_INVALID");
00714         break;
00715     case CKR_WRAPPED_KEY_LEN_RANGE:
00716         return ("CKR_WRAPPED_KEY_LEN_RANGE");
00717         break;
00718     case CKR_WRAPPING_KEY_HANDLE_INVALID:
00719         return ("CKR_WRAPPING_KEY_HANDLE_INVALID");
00720         break;
00721     case CKR_WRAPPING_KEY_SIZE_RANGE:
00722         return ("CKR_WRAPPING_KEY_SIZE_RANGE");
00723         break;
00724     case CKR_WRAPPING_KEY_TYPE_INCONSISTENT:
00725         return ("CKR_WRAPPING_KEY_TYPE_INCONSISTENT");
00726         break;
00727     case CKR_RANDOM_SEED_NOT_SUPPORTED:
00728         return ("CKR_RANDOM_SEED_NOT_SUPPORTED");
00729         break;
00730     case CKR_RANDOM_NO_RNG:
00731         return ("CKR_RANDOM_NO_RNG");
00732         break;
00733     case CKR_DOMAIN_PARAMS_INVALID:
00734         return ("CKR_DOMAIN_PARAMS_INVALID");
00735         break;
00736     case CKR_BUFFER_TOO_SMALL:
00737         return ("CKR_BUFFER_TOO_SMALL");
00738         break;
00739     case CKR_SAVED_STATE_INVALID:
00740         return ("CKR_SAVED_STATE_INVALID");
00741         break;
00742     case CKR_INFORMATION_SENSITIVE:
00743         return ("CKR_INFORMATION_SENSITIVE");
00744         break;
00745     case CKR_STATE_UNSAVEABLE:
00746         return ("CKR_STATE_UNSAVEABLE");
00747         break;
00748     case CKR_CRYPTOKI_NOT_INITIALIZED:
00749         return ("CKR_CRYPTOKI_NOT_INITIALIZED");
00750         break;
00751     case CKR_CRYPTOKI_ALREADY_INITIALIZED:
00752         return ("CKR_CRYPTOKI_ALREADY_INITIALIZED");
00753         break;
00754     case CKR_MUTEX_BAD:
00755         return ("CKR_MUTEX_BAD");
00756         break;
00757     case CKR_MUTEX_NOT_LOCKED:
00758         return ("CKR_MUTEX_NOT_LOCKED");
00759         break;
00760     case CKR_VENDOR_DEFINED:
00761         return ("CKR_VENDOR_DEFINED");
00762         break;
00763     default:
00764         /* rv not found */
00765         snprintf(errstr, sizeof (errstr),
00766             "Unknown return code: 0x%x", rv);
00767         return (errstr);
00768         break;
00769     }
00770 }
00771 #endif