Back to index

lightning-sunbird  0.9+nobinonly
ckhelper.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #ifdef DEBUG
00038 static const char CVS_ID[] = "@(#) $RCSfile: ckhelper.c,v $ $Revision: 1.34.28.1 $ $Date: 2007/11/16 05:25:07 $";
00039 #endif /* DEBUG */
00040 
00041 #ifndef NSSCKEPV_H
00042 #include "nssckepv.h"
00043 #endif /* NSSCKEPV_H */
00044 
00045 #ifndef DEVM_H
00046 #include "devm.h"
00047 #endif /* DEVM_H */
00048 
00049 #ifndef CKHELPER_H
00050 #include "ckhelper.h"
00051 #endif /* CKHELPER_H */
00052 
00053 extern const NSSError NSS_ERROR_DEVICE_ERROR;
00054 
00055 static const CK_BBOOL s_true = CK_TRUE;
00056 NSS_IMPLEMENT_DATA const NSSItem
00057 g_ck_true = { (CK_VOID_PTR)&s_true, sizeof(s_true) };
00058 
00059 static const CK_BBOOL s_false = CK_FALSE;
00060 NSS_IMPLEMENT_DATA const NSSItem
00061 g_ck_false = { (CK_VOID_PTR)&s_false, sizeof(s_false) };
00062 
00063 static const CK_OBJECT_CLASS s_class_cert = CKO_CERTIFICATE;
00064 NSS_IMPLEMENT_DATA const NSSItem
00065 g_ck_class_cert = { (CK_VOID_PTR)&s_class_cert, sizeof(s_class_cert) };
00066 
00067 static const CK_OBJECT_CLASS s_class_pubkey = CKO_PUBLIC_KEY;
00068 NSS_IMPLEMENT_DATA const NSSItem
00069 g_ck_class_pubkey = { (CK_VOID_PTR)&s_class_pubkey, sizeof(s_class_pubkey) };
00070 
00071 static const CK_OBJECT_CLASS s_class_privkey = CKO_PRIVATE_KEY;
00072 NSS_IMPLEMENT_DATA const NSSItem
00073 g_ck_class_privkey = { (CK_VOID_PTR)&s_class_privkey, sizeof(s_class_privkey) };
00074 
00075 static PRBool
00076 is_string_attribute (
00077   CK_ATTRIBUTE_TYPE aType
00078 )
00079 {
00080     PRBool isString;
00081     switch (aType) {
00082     case CKA_LABEL:
00083     case CKA_NETSCAPE_EMAIL:
00084        isString = PR_TRUE;
00085        break;
00086     default:
00087        isString = PR_FALSE;
00088        break;
00089     }
00090     return isString;
00091 }
00092 
00093 NSS_IMPLEMENT PRStatus 
00094 nssCKObject_GetAttributes (
00095   CK_OBJECT_HANDLE object,
00096   CK_ATTRIBUTE_PTR obj_template,
00097   CK_ULONG count,
00098   NSSArena *arenaOpt,
00099   nssSession *session,
00100   NSSSlot *slot
00101 )
00102 {
00103     nssArenaMark *mark = NULL;
00104     CK_SESSION_HANDLE hSession;
00105     CK_ULONG i = 0;
00106     CK_RV ckrv;
00107     PRStatus nssrv;
00108     PRBool alloced = PR_FALSE;
00109     void *epv = nssSlot_GetCryptokiEPV(slot);
00110     hSession = session->handle; 
00111     if (arenaOpt) {
00112        mark = nssArena_Mark(arenaOpt);
00113        if (!mark) {
00114            goto loser;
00115        }
00116     }
00117     nssSession_EnterMonitor(session);
00118     /* XXX kinda hacky, if the storage size is already in the first template
00119      * item, then skip the alloc portion
00120      */
00121     if (obj_template[0].ulValueLen == 0) {
00122        /* Get the storage size needed for each attribute */
00123        ckrv = CKAPI(epv)->C_GetAttributeValue(hSession,
00124                                               object, obj_template, count);
00125        if (ckrv != CKR_OK && 
00126            ckrv != CKR_ATTRIBUTE_TYPE_INVALID &&
00127            ckrv != CKR_ATTRIBUTE_SENSITIVE) 
00128        {
00129            nssSession_ExitMonitor(session);
00130            nss_SetError(NSS_ERROR_DEVICE_ERROR);
00131            goto loser;
00132        }
00133        /* Allocate memory for each attribute. */
00134        for (i=0; i<count; i++) {
00135            CK_ULONG ulValueLen = obj_template[i].ulValueLen;
00136            if (ulValueLen == 0) continue;
00137            if (ulValueLen == (CK_ULONG) -1) {
00138               obj_template[i].ulValueLen = 0;
00139               continue;
00140            }
00141            if (is_string_attribute(obj_template[i].type)) {
00142               ulValueLen++;
00143            }
00144            obj_template[i].pValue = nss_ZAlloc(arenaOpt, ulValueLen);
00145            if (!obj_template[i].pValue) {
00146               nssSession_ExitMonitor(session);
00147               goto loser;
00148            }
00149        }
00150        alloced = PR_TRUE;
00151     }
00152     /* Obtain the actual attribute values. */
00153     ckrv = CKAPI(epv)->C_GetAttributeValue(hSession,
00154                                            object, obj_template, count);
00155     nssSession_ExitMonitor(session);
00156     if (ckrv != CKR_OK && 
00157         ckrv != CKR_ATTRIBUTE_TYPE_INVALID &&
00158         ckrv != CKR_ATTRIBUTE_SENSITIVE) 
00159     {
00160        nss_SetError(NSS_ERROR_DEVICE_ERROR);
00161        goto loser;
00162     }
00163     if (alloced && arenaOpt) {
00164        nssrv = nssArena_Unmark(arenaOpt, mark);
00165        if (nssrv != PR_SUCCESS) {
00166            goto loser;
00167        }
00168     }
00169 
00170     if (count > 1 && ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) || 
00171                                    (ckrv == CKR_ATTRIBUTE_SENSITIVE))) {
00172        /* old tokens would keep the length of '0' and not deal with any
00173         * of the attributes we passed. For those tokens read them one at
00174         * a time */
00175        for (i=0; i < count; i++) {
00176            if ((obj_template[i].ulValueLen == 0) 
00177                             || (obj_template[i].ulValueLen == -1)) {
00178               obj_template[i].ulValueLen=0;
00179               (void) nssCKObject_GetAttributes(object,&obj_template[i], 1,
00180                      arenaOpt, session, slot);
00181            }
00182        }
00183     }
00184     return PR_SUCCESS;
00185 loser:
00186     if (alloced) {
00187        if (arenaOpt) {
00188            /* release all arena memory allocated before the failure. */
00189            (void)nssArena_Release(arenaOpt, mark);
00190        } else {
00191            CK_ULONG j;
00192            /* free each heap object that was allocated before the failure. */
00193            for (j=0; j<i; j++) {
00194               nss_ZFreeIf(obj_template[j].pValue);
00195            }
00196        }
00197     }
00198     return PR_FAILURE;
00199 }
00200 
00201 NSS_IMPLEMENT PRStatus
00202 nssCKObject_GetAttributeItem (
00203   CK_OBJECT_HANDLE object,
00204   CK_ATTRIBUTE_TYPE attribute,
00205   NSSArena *arenaOpt,
00206   nssSession *session,
00207   NSSSlot *slot,
00208   NSSItem *rvItem
00209 )
00210 {
00211     CK_ATTRIBUTE attr = { 0, NULL, 0 };
00212     PRStatus nssrv;
00213     attr.type = attribute;
00214     nssrv = nssCKObject_GetAttributes(object, &attr, 1, 
00215                                       arenaOpt, session, slot);
00216     if (nssrv != PR_SUCCESS) {
00217        return nssrv;
00218     }
00219     rvItem->data = (void *)attr.pValue;
00220     rvItem->size = (PRUint32)attr.ulValueLen;
00221     return PR_SUCCESS;
00222 }
00223 
00224 NSS_IMPLEMENT PRBool
00225 nssCKObject_IsAttributeTrue (
00226   CK_OBJECT_HANDLE object,
00227   CK_ATTRIBUTE_TYPE attribute,
00228   nssSession *session,
00229   NSSSlot *slot,
00230   PRStatus *rvStatus
00231 )
00232 {
00233     CK_BBOOL bool;
00234     CK_ATTRIBUTE_PTR attr;
00235     CK_ATTRIBUTE atemplate = { 0, NULL, 0 };
00236     CK_RV ckrv;
00237     void *epv = nssSlot_GetCryptokiEPV(slot);
00238     attr = &atemplate;
00239     NSS_CK_SET_ATTRIBUTE_VAR(attr, attribute, bool);
00240     nssSession_EnterMonitor(session);
00241     ckrv = CKAPI(epv)->C_GetAttributeValue(session->handle, object, 
00242                                            &atemplate, 1);
00243     nssSession_ExitMonitor(session);
00244     if (ckrv != CKR_OK) {
00245        *rvStatus = PR_FAILURE;
00246        return PR_FALSE;
00247     }
00248     *rvStatus = PR_SUCCESS;
00249     return (PRBool)(bool == CK_TRUE);
00250 }
00251 
00252 NSS_IMPLEMENT PRStatus 
00253 nssCKObject_SetAttributes (
00254   CK_OBJECT_HANDLE object,
00255   CK_ATTRIBUTE_PTR obj_template,
00256   CK_ULONG count,
00257   nssSession *session,
00258   NSSSlot  *slot
00259 )
00260 {
00261     CK_RV ckrv;
00262     void *epv = nssSlot_GetCryptokiEPV(slot);
00263     nssSession_EnterMonitor(session);
00264     ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle, object, 
00265                                            obj_template, count);
00266     nssSession_ExitMonitor(session);
00267     if (ckrv == CKR_OK) {
00268        return PR_SUCCESS;
00269     } else {
00270        return PR_FAILURE;
00271     }
00272 }
00273 
00274 NSS_IMPLEMENT PRBool
00275 nssCKObject_IsTokenObjectTemplate (
00276   CK_ATTRIBUTE_PTR objectTemplate, 
00277   CK_ULONG otsize
00278 )
00279 {
00280     CK_ULONG ul;
00281     for (ul=0; ul<otsize; ul++) {
00282        if (objectTemplate[ul].type == CKA_TOKEN) {
00283            return (*((CK_BBOOL*)objectTemplate[ul].pValue) == CK_TRUE);
00284        }
00285     }
00286     return PR_FALSE;
00287 }
00288 
00289 static NSSCertificateType
00290 nss_cert_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib)
00291 {
00292     CK_CERTIFICATE_TYPE ckCertType;
00293     if (!attrib->pValue) {
00294        /* default to PKIX */
00295        return NSSCertificateType_PKIX;
00296     }
00297     ckCertType = *((CK_ULONG *)attrib->pValue);
00298     switch (ckCertType) {
00299     case CKC_X_509:
00300        return NSSCertificateType_PKIX;
00301     default:
00302        break;
00303     }
00304     return NSSCertificateType_Unknown;
00305 }
00306 
00307 /* incoming pointers must be valid */
00308 NSS_IMPLEMENT PRStatus
00309 nssCryptokiCertificate_GetAttributes (
00310   nssCryptokiObject *certObject,
00311   nssSession *sessionOpt,
00312   NSSArena *arenaOpt,
00313   NSSCertificateType *certTypeOpt,
00314   NSSItem *idOpt,
00315   NSSDER *encodingOpt,
00316   NSSDER *issuerOpt,
00317   NSSDER *serialOpt,
00318   NSSDER *subjectOpt
00319 )
00320 {
00321     PRStatus status;
00322     PRUint32 i;
00323     nssSession *session;
00324     NSSSlot *slot;
00325     CK_ULONG template_size;
00326     CK_ATTRIBUTE_PTR attr;
00327     CK_ATTRIBUTE cert_template[6];
00328     /* Set up a template of all options chosen by caller */
00329     NSS_CK_TEMPLATE_START(cert_template, attr, template_size);
00330     if (certTypeOpt) {
00331        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CERTIFICATE_TYPE);
00332     }
00333     if (idOpt) {
00334        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID);
00335     }
00336     if (encodingOpt) {
00337        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
00338     }
00339     if (issuerOpt) {
00340        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ISSUER);
00341     }
00342     if (serialOpt) {
00343        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SERIAL_NUMBER);
00344     }
00345     if (subjectOpt) {
00346        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT);
00347     }
00348     NSS_CK_TEMPLATE_FINISH(cert_template, attr, template_size);
00349     if (template_size == 0) {
00350        /* caller didn't want anything */
00351        return PR_SUCCESS;
00352     }
00353 
00354     status = nssToken_GetCachedObjectAttributes(certObject->token, arenaOpt,
00355                                                 certObject, CKO_CERTIFICATE,
00356                                                 cert_template, template_size);
00357     if (status != PR_SUCCESS) {
00358 
00359        session = sessionOpt ? 
00360                  sessionOpt : 
00361                  nssToken_GetDefaultSession(certObject->token);
00362 
00363        slot = nssToken_GetSlot(certObject->token);
00364        status = nssCKObject_GetAttributes(certObject->handle, 
00365                                           cert_template, template_size,
00366                                           arenaOpt, session, slot);
00367        nssSlot_Destroy(slot);
00368        if (status != PR_SUCCESS) {
00369            return status;
00370        }
00371     }
00372 
00373     i=0;
00374     if (certTypeOpt) {
00375        *certTypeOpt = nss_cert_type_from_ck_attrib(&cert_template[i]); i++;
00376     }
00377     if (idOpt) {
00378        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], idOpt); i++;
00379     }
00380     if (encodingOpt) {
00381        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], encodingOpt); i++;
00382     }
00383     if (issuerOpt) {
00384        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], issuerOpt); i++;
00385     }
00386     if (serialOpt) {
00387        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], serialOpt); i++;
00388     }
00389     if (subjectOpt) {
00390        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], subjectOpt); i++;
00391     }
00392     return PR_SUCCESS;
00393 }
00394 
00395 static nssTrustLevel 
00396 get_nss_trust (
00397   CK_TRUST ckt
00398 )
00399 {
00400     nssTrustLevel t;
00401     switch (ckt) {
00402     case CKT_NETSCAPE_UNTRUSTED: t = nssTrustLevel_NotTrusted; break;
00403     case CKT_NETSCAPE_TRUSTED_DELEGATOR: t = nssTrustLevel_TrustedDelegator; 
00404        break;
00405     case CKT_NETSCAPE_VALID_DELEGATOR: t = nssTrustLevel_ValidDelegator; break;
00406     case CKT_NETSCAPE_TRUSTED: t = nssTrustLevel_Trusted; break;
00407     case CKT_NETSCAPE_VALID: t = nssTrustLevel_Valid; break;
00408     case CKT_NETSCAPE_MUST_VERIFY:
00409     case CKT_NETSCAPE_TRUST_UNKNOWN:
00410     default:
00411        t = nssTrustLevel_Unknown; break;
00412     }
00413     return t;
00414 }
00415 
00416 NSS_IMPLEMENT PRStatus
00417 nssCryptokiTrust_GetAttributes (
00418   nssCryptokiObject *trustObject,
00419   nssSession *sessionOpt,
00420   NSSItem *sha1_hash,
00421   nssTrustLevel *serverAuth,
00422   nssTrustLevel *clientAuth,
00423   nssTrustLevel *codeSigning,
00424   nssTrustLevel *emailProtection,
00425   PRBool *stepUpApproved
00426 )
00427 {
00428     PRStatus status;
00429     NSSSlot *slot;
00430     nssSession *session;
00431     CK_BBOOL isToken = PR_FALSE;
00432     CK_BBOOL stepUp = PR_FALSE;
00433     CK_TRUST saTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
00434     CK_TRUST caTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
00435     CK_TRUST epTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
00436     CK_TRUST csTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
00437     CK_ATTRIBUTE_PTR attr;
00438     CK_ATTRIBUTE trust_template[7];
00439     CK_ULONG trust_size;
00440 
00441     /* Use the trust object to find the trust settings */
00442     NSS_CK_TEMPLATE_START(trust_template, attr, trust_size);
00443     NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN,                  isToken);
00444     NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH,      saTrust);
00445     NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH,      caTrust);
00446     NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, epTrust);
00447     NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING,     csTrust);
00448     NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_STEP_UP_APPROVED, stepUp);
00449     NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH,     sha1_hash);
00450     NSS_CK_TEMPLATE_FINISH(trust_template, attr, trust_size);
00451 
00452     status = nssToken_GetCachedObjectAttributes(trustObject->token, NULL,
00453                                                 trustObject, 
00454                                                 CKO_NETSCAPE_TRUST,
00455                                                 trust_template, trust_size);
00456     if (status != PR_SUCCESS) {
00457        session = sessionOpt ? 
00458                  sessionOpt : 
00459                  nssToken_GetDefaultSession(trustObject->token);
00460 
00461        slot = nssToken_GetSlot(trustObject->token);
00462        status = nssCKObject_GetAttributes(trustObject->handle,
00463                                           trust_template, trust_size,
00464                                           NULL, session, slot);
00465        nssSlot_Destroy(slot);
00466        if (status != PR_SUCCESS) {
00467            return status;
00468        }
00469     }
00470 
00471     *serverAuth = get_nss_trust(saTrust);
00472     *clientAuth = get_nss_trust(caTrust);
00473     *emailProtection = get_nss_trust(epTrust);
00474     *codeSigning = get_nss_trust(csTrust);
00475     *stepUpApproved = stepUp;
00476     return PR_SUCCESS;
00477 }
00478 
00479 NSS_IMPLEMENT PRStatus
00480 nssCryptokiCRL_GetAttributes (
00481   nssCryptokiObject *crlObject,
00482   nssSession *sessionOpt,
00483   NSSArena *arenaOpt,
00484   NSSItem *encodingOpt,
00485   NSSItem *subjectOpt,
00486   CK_ULONG* crl_class,
00487   NSSUTF8 **urlOpt,
00488   PRBool *isKRLOpt
00489 )
00490 {
00491     PRStatus status;
00492     NSSSlot *slot;
00493     nssSession *session;
00494     CK_ATTRIBUTE_PTR attr;
00495     CK_ATTRIBUTE crl_template[7];
00496     CK_ULONG crl_size;
00497     PRUint32 i;
00498 
00499     NSS_CK_TEMPLATE_START(crl_template, attr, crl_size);
00500     if (crl_class) {
00501         NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CLASS);
00502     }
00503     if (encodingOpt) {
00504        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
00505     }
00506     if (urlOpt) {
00507        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_URL);
00508     }
00509     if (isKRLOpt) {
00510        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_KRL);
00511     }
00512     if (subjectOpt) {
00513        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT);
00514     }
00515     NSS_CK_TEMPLATE_FINISH(crl_template, attr, crl_size);
00516 
00517     status = nssToken_GetCachedObjectAttributes(crlObject->token, NULL,
00518                                                 crlObject, 
00519                                                 CKO_NETSCAPE_CRL,
00520                                                 crl_template, crl_size);
00521     if (status != PR_SUCCESS) {
00522        session = sessionOpt ? 
00523                  sessionOpt : 
00524                  nssToken_GetDefaultSession(crlObject->token);
00525 
00526        slot = nssToken_GetSlot(crlObject->token);
00527        status = nssCKObject_GetAttributes(crlObject->handle, 
00528                                           crl_template, crl_size,
00529                                           arenaOpt, session, slot);
00530        nssSlot_Destroy(slot);
00531        if (status != PR_SUCCESS) {
00532            return status;
00533        }
00534     }
00535 
00536     i=0;
00537     if (crl_class) {
00538         NSS_CK_ATTRIBUTE_TO_ULONG(&crl_template[i], *crl_class); i++;
00539     }
00540     if (encodingOpt) {
00541        NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], encodingOpt); i++;
00542     }
00543     if (urlOpt) {
00544        NSS_CK_ATTRIBUTE_TO_UTF8(&crl_template[i], *urlOpt); i++;
00545     }
00546     if (isKRLOpt) {
00547        NSS_CK_ATTRIBUTE_TO_BOOL(&crl_template[i], *isKRLOpt); i++;
00548     }
00549     if (subjectOpt) {
00550        NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], subjectOpt); i++;
00551     }
00552     return PR_SUCCESS;
00553 }
00554 
00555 NSS_IMPLEMENT PRStatus
00556 nssCryptokiPrivateKey_SetCertificate (
00557   nssCryptokiObject *keyObject,
00558   nssSession *sessionOpt,
00559   NSSUTF8 *nickname,
00560   NSSItem *id,
00561   NSSDER *subject
00562 )
00563 {
00564     CK_RV ckrv;
00565     CK_ATTRIBUTE_PTR attr;
00566     CK_ATTRIBUTE key_template[3];
00567     CK_ULONG key_size;
00568     void *epv = nssToken_GetCryptokiEPV(keyObject->token);
00569     nssSession *session;
00570     NSSToken *token = keyObject->token;
00571     nssSession *defaultSession = nssToken_GetDefaultSession(token);
00572     PRBool createdSession = PR_FALSE;
00573 
00574     NSS_CK_TEMPLATE_START(key_template, attr, key_size);
00575     NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname);
00576     NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
00577     NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
00578     NSS_CK_TEMPLATE_FINISH(key_template, attr, key_size);
00579 
00580     if (sessionOpt) {
00581        if (!nssSession_IsReadWrite(sessionOpt)) {
00582            return PR_FAILURE;
00583        } else {
00584            session = sessionOpt;
00585        }
00586     } else if (nssSession_IsReadWrite(defaultSession)) {
00587        session = defaultSession;
00588     } else {
00589        NSSSlot *slot = nssToken_GetSlot(token);
00590        session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE);
00591        createdSession = PR_TRUE;
00592        nssSlot_Destroy(slot);
00593     }
00594 
00595     ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle,
00596                                            keyObject->handle,
00597                                            key_template,
00598                                            key_size);
00599 
00600     if (createdSession) {
00601        nssSession_Destroy(session);
00602     }
00603 
00604     return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
00605 }
00606