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