1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/dev/ckhelper.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,588 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "pkcs11.h" 1.9 + 1.10 +#ifndef DEVM_H 1.11 +#include "devm.h" 1.12 +#endif /* DEVM_H */ 1.13 + 1.14 +#ifndef CKHELPER_H 1.15 +#include "ckhelper.h" 1.16 +#endif /* CKHELPER_H */ 1.17 + 1.18 +extern const NSSError NSS_ERROR_DEVICE_ERROR; 1.19 + 1.20 +static const CK_BBOOL s_true = CK_TRUE; 1.21 +NSS_IMPLEMENT_DATA const NSSItem 1.22 +g_ck_true = { (CK_VOID_PTR)&s_true, sizeof(s_true) }; 1.23 + 1.24 +static const CK_BBOOL s_false = CK_FALSE; 1.25 +NSS_IMPLEMENT_DATA const NSSItem 1.26 +g_ck_false = { (CK_VOID_PTR)&s_false, sizeof(s_false) }; 1.27 + 1.28 +static const CK_OBJECT_CLASS s_class_cert = CKO_CERTIFICATE; 1.29 +NSS_IMPLEMENT_DATA const NSSItem 1.30 +g_ck_class_cert = { (CK_VOID_PTR)&s_class_cert, sizeof(s_class_cert) }; 1.31 + 1.32 +static const CK_OBJECT_CLASS s_class_pubkey = CKO_PUBLIC_KEY; 1.33 +NSS_IMPLEMENT_DATA const NSSItem 1.34 +g_ck_class_pubkey = { (CK_VOID_PTR)&s_class_pubkey, sizeof(s_class_pubkey) }; 1.35 + 1.36 +static const CK_OBJECT_CLASS s_class_privkey = CKO_PRIVATE_KEY; 1.37 +NSS_IMPLEMENT_DATA const NSSItem 1.38 +g_ck_class_privkey = { (CK_VOID_PTR)&s_class_privkey, sizeof(s_class_privkey) }; 1.39 + 1.40 +static PRBool 1.41 +is_string_attribute ( 1.42 + CK_ATTRIBUTE_TYPE aType 1.43 +) 1.44 +{ 1.45 + PRBool isString; 1.46 + switch (aType) { 1.47 + case CKA_LABEL: 1.48 + case CKA_NSS_EMAIL: 1.49 + isString = PR_TRUE; 1.50 + break; 1.51 + default: 1.52 + isString = PR_FALSE; 1.53 + break; 1.54 + } 1.55 + return isString; 1.56 +} 1.57 + 1.58 +NSS_IMPLEMENT PRStatus 1.59 +nssCKObject_GetAttributes ( 1.60 + CK_OBJECT_HANDLE object, 1.61 + CK_ATTRIBUTE_PTR obj_template, 1.62 + CK_ULONG count, 1.63 + NSSArena *arenaOpt, 1.64 + nssSession *session, 1.65 + NSSSlot *slot 1.66 +) 1.67 +{ 1.68 + nssArenaMark *mark = NULL; 1.69 + CK_SESSION_HANDLE hSession; 1.70 + CK_ULONG i = 0; 1.71 + CK_RV ckrv; 1.72 + PRStatus nssrv; 1.73 + PRBool alloced = PR_FALSE; 1.74 + void *epv = nssSlot_GetCryptokiEPV(slot); 1.75 + hSession = session->handle; 1.76 + if (arenaOpt) { 1.77 + mark = nssArena_Mark(arenaOpt); 1.78 + if (!mark) { 1.79 + goto loser; 1.80 + } 1.81 + } 1.82 + nssSession_EnterMonitor(session); 1.83 + /* XXX kinda hacky, if the storage size is already in the first template 1.84 + * item, then skip the alloc portion 1.85 + */ 1.86 + if (obj_template[0].ulValueLen == 0) { 1.87 + /* Get the storage size needed for each attribute */ 1.88 + ckrv = CKAPI(epv)->C_GetAttributeValue(hSession, 1.89 + object, obj_template, count); 1.90 + if (ckrv != CKR_OK && 1.91 + ckrv != CKR_ATTRIBUTE_TYPE_INVALID && 1.92 + ckrv != CKR_ATTRIBUTE_SENSITIVE) 1.93 + { 1.94 + nssSession_ExitMonitor(session); 1.95 + nss_SetError(NSS_ERROR_DEVICE_ERROR); 1.96 + goto loser; 1.97 + } 1.98 + /* Allocate memory for each attribute. */ 1.99 + for (i=0; i<count; i++) { 1.100 + CK_ULONG ulValueLen = obj_template[i].ulValueLen; 1.101 + if (ulValueLen == 0 || ulValueLen == (CK_ULONG) -1) { 1.102 + obj_template[i].pValue = NULL; 1.103 + obj_template[i].ulValueLen = 0; 1.104 + continue; 1.105 + } 1.106 + if (is_string_attribute(obj_template[i].type)) { 1.107 + ulValueLen++; 1.108 + } 1.109 + obj_template[i].pValue = nss_ZAlloc(arenaOpt, ulValueLen); 1.110 + if (!obj_template[i].pValue) { 1.111 + nssSession_ExitMonitor(session); 1.112 + goto loser; 1.113 + } 1.114 + } 1.115 + alloced = PR_TRUE; 1.116 + } 1.117 + /* Obtain the actual attribute values. */ 1.118 + ckrv = CKAPI(epv)->C_GetAttributeValue(hSession, 1.119 + object, obj_template, count); 1.120 + nssSession_ExitMonitor(session); 1.121 + if (ckrv != CKR_OK && 1.122 + ckrv != CKR_ATTRIBUTE_TYPE_INVALID && 1.123 + ckrv != CKR_ATTRIBUTE_SENSITIVE) 1.124 + { 1.125 + nss_SetError(NSS_ERROR_DEVICE_ERROR); 1.126 + goto loser; 1.127 + } 1.128 + if (alloced && arenaOpt) { 1.129 + nssrv = nssArena_Unmark(arenaOpt, mark); 1.130 + if (nssrv != PR_SUCCESS) { 1.131 + goto loser; 1.132 + } 1.133 + } 1.134 + 1.135 + if (count > 1 && ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) || 1.136 + (ckrv == CKR_ATTRIBUTE_SENSITIVE))) { 1.137 + /* old tokens would keep the length of '0' and not deal with any 1.138 + * of the attributes we passed. For those tokens read them one at 1.139 + * a time */ 1.140 + for (i=0; i < count; i++) { 1.141 + if ((obj_template[i].ulValueLen == 0) 1.142 + || (obj_template[i].ulValueLen == -1)) { 1.143 + obj_template[i].ulValueLen=0; 1.144 + (void) nssCKObject_GetAttributes(object,&obj_template[i], 1, 1.145 + arenaOpt, session, slot); 1.146 + } 1.147 + } 1.148 + } 1.149 + return PR_SUCCESS; 1.150 +loser: 1.151 + if (alloced) { 1.152 + if (arenaOpt) { 1.153 + /* release all arena memory allocated before the failure. */ 1.154 + (void)nssArena_Release(arenaOpt, mark); 1.155 + } else { 1.156 + CK_ULONG j; 1.157 + /* free each heap object that was allocated before the failure. */ 1.158 + for (j=0; j<i; j++) { 1.159 + nss_ZFreeIf(obj_template[j].pValue); 1.160 + } 1.161 + } 1.162 + } 1.163 + return PR_FAILURE; 1.164 +} 1.165 + 1.166 +NSS_IMPLEMENT PRStatus 1.167 +nssCKObject_GetAttributeItem ( 1.168 + CK_OBJECT_HANDLE object, 1.169 + CK_ATTRIBUTE_TYPE attribute, 1.170 + NSSArena *arenaOpt, 1.171 + nssSession *session, 1.172 + NSSSlot *slot, 1.173 + NSSItem *rvItem 1.174 +) 1.175 +{ 1.176 + CK_ATTRIBUTE attr = { 0, NULL, 0 }; 1.177 + PRStatus nssrv; 1.178 + attr.type = attribute; 1.179 + nssrv = nssCKObject_GetAttributes(object, &attr, 1, 1.180 + arenaOpt, session, slot); 1.181 + if (nssrv != PR_SUCCESS) { 1.182 + return nssrv; 1.183 + } 1.184 + rvItem->data = (void *)attr.pValue; 1.185 + rvItem->size = (PRUint32)attr.ulValueLen; 1.186 + return PR_SUCCESS; 1.187 +} 1.188 + 1.189 +NSS_IMPLEMENT PRBool 1.190 +nssCKObject_IsAttributeTrue ( 1.191 + CK_OBJECT_HANDLE object, 1.192 + CK_ATTRIBUTE_TYPE attribute, 1.193 + nssSession *session, 1.194 + NSSSlot *slot, 1.195 + PRStatus *rvStatus 1.196 +) 1.197 +{ 1.198 + CK_BBOOL bool; 1.199 + CK_ATTRIBUTE_PTR attr; 1.200 + CK_ATTRIBUTE atemplate = { 0, NULL, 0 }; 1.201 + CK_RV ckrv; 1.202 + void *epv = nssSlot_GetCryptokiEPV(slot); 1.203 + attr = &atemplate; 1.204 + NSS_CK_SET_ATTRIBUTE_VAR(attr, attribute, bool); 1.205 + nssSession_EnterMonitor(session); 1.206 + ckrv = CKAPI(epv)->C_GetAttributeValue(session->handle, object, 1.207 + &atemplate, 1); 1.208 + nssSession_ExitMonitor(session); 1.209 + if (ckrv != CKR_OK) { 1.210 + *rvStatus = PR_FAILURE; 1.211 + return PR_FALSE; 1.212 + } 1.213 + *rvStatus = PR_SUCCESS; 1.214 + return (PRBool)(bool == CK_TRUE); 1.215 +} 1.216 + 1.217 +NSS_IMPLEMENT PRStatus 1.218 +nssCKObject_SetAttributes ( 1.219 + CK_OBJECT_HANDLE object, 1.220 + CK_ATTRIBUTE_PTR obj_template, 1.221 + CK_ULONG count, 1.222 + nssSession *session, 1.223 + NSSSlot *slot 1.224 +) 1.225 +{ 1.226 + CK_RV ckrv; 1.227 + void *epv = nssSlot_GetCryptokiEPV(slot); 1.228 + nssSession_EnterMonitor(session); 1.229 + ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle, object, 1.230 + obj_template, count); 1.231 + nssSession_ExitMonitor(session); 1.232 + if (ckrv == CKR_OK) { 1.233 + return PR_SUCCESS; 1.234 + } else { 1.235 + return PR_FAILURE; 1.236 + } 1.237 +} 1.238 + 1.239 +NSS_IMPLEMENT PRBool 1.240 +nssCKObject_IsTokenObjectTemplate ( 1.241 + CK_ATTRIBUTE_PTR objectTemplate, 1.242 + CK_ULONG otsize 1.243 +) 1.244 +{ 1.245 + CK_ULONG ul; 1.246 + for (ul=0; ul<otsize; ul++) { 1.247 + if (objectTemplate[ul].type == CKA_TOKEN) { 1.248 + return (*((CK_BBOOL*)objectTemplate[ul].pValue) == CK_TRUE); 1.249 + } 1.250 + } 1.251 + return PR_FALSE; 1.252 +} 1.253 + 1.254 +static NSSCertificateType 1.255 +nss_cert_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib) 1.256 +{ 1.257 + CK_CERTIFICATE_TYPE ckCertType; 1.258 + if (!attrib->pValue) { 1.259 + /* default to PKIX */ 1.260 + return NSSCertificateType_PKIX; 1.261 + } 1.262 + ckCertType = *((CK_ULONG *)attrib->pValue); 1.263 + switch (ckCertType) { 1.264 + case CKC_X_509: 1.265 + return NSSCertificateType_PKIX; 1.266 + default: 1.267 + break; 1.268 + } 1.269 + return NSSCertificateType_Unknown; 1.270 +} 1.271 + 1.272 +/* incoming pointers must be valid */ 1.273 +NSS_IMPLEMENT PRStatus 1.274 +nssCryptokiCertificate_GetAttributes ( 1.275 + nssCryptokiObject *certObject, 1.276 + nssSession *sessionOpt, 1.277 + NSSArena *arenaOpt, 1.278 + NSSCertificateType *certTypeOpt, 1.279 + NSSItem *idOpt, 1.280 + NSSDER *encodingOpt, 1.281 + NSSDER *issuerOpt, 1.282 + NSSDER *serialOpt, 1.283 + NSSDER *subjectOpt 1.284 +) 1.285 +{ 1.286 + PRStatus status; 1.287 + PRUint32 i; 1.288 + nssSession *session; 1.289 + NSSSlot *slot; 1.290 + CK_ULONG template_size; 1.291 + CK_ATTRIBUTE_PTR attr; 1.292 + CK_ATTRIBUTE cert_template[6]; 1.293 + /* Set up a template of all options chosen by caller */ 1.294 + NSS_CK_TEMPLATE_START(cert_template, attr, template_size); 1.295 + if (certTypeOpt) { 1.296 + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CERTIFICATE_TYPE); 1.297 + } 1.298 + if (idOpt) { 1.299 + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID); 1.300 + } 1.301 + if (encodingOpt) { 1.302 + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE); 1.303 + } 1.304 + if (issuerOpt) { 1.305 + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ISSUER); 1.306 + } 1.307 + if (serialOpt) { 1.308 + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SERIAL_NUMBER); 1.309 + } 1.310 + if (subjectOpt) { 1.311 + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT); 1.312 + } 1.313 + NSS_CK_TEMPLATE_FINISH(cert_template, attr, template_size); 1.314 + if (template_size == 0) { 1.315 + /* caller didn't want anything */ 1.316 + return PR_SUCCESS; 1.317 + } 1.318 + 1.319 + status = nssToken_GetCachedObjectAttributes(certObject->token, arenaOpt, 1.320 + certObject, CKO_CERTIFICATE, 1.321 + cert_template, template_size); 1.322 + if (status != PR_SUCCESS) { 1.323 + 1.324 + session = sessionOpt ? 1.325 + sessionOpt : 1.326 + nssToken_GetDefaultSession(certObject->token); 1.327 + if (!session) { 1.328 + nss_SetError(NSS_ERROR_INVALID_ARGUMENT); 1.329 + return PR_FAILURE; 1.330 + } 1.331 + 1.332 + slot = nssToken_GetSlot(certObject->token); 1.333 + status = nssCKObject_GetAttributes(certObject->handle, 1.334 + cert_template, template_size, 1.335 + arenaOpt, session, slot); 1.336 + nssSlot_Destroy(slot); 1.337 + if (status != PR_SUCCESS) { 1.338 + return status; 1.339 + } 1.340 + } 1.341 + 1.342 + i=0; 1.343 + if (certTypeOpt) { 1.344 + *certTypeOpt = nss_cert_type_from_ck_attrib(&cert_template[i]); i++; 1.345 + } 1.346 + if (idOpt) { 1.347 + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], idOpt); i++; 1.348 + } 1.349 + if (encodingOpt) { 1.350 + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], encodingOpt); i++; 1.351 + } 1.352 + if (issuerOpt) { 1.353 + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], issuerOpt); i++; 1.354 + } 1.355 + if (serialOpt) { 1.356 + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], serialOpt); i++; 1.357 + } 1.358 + if (subjectOpt) { 1.359 + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], subjectOpt); i++; 1.360 + } 1.361 + return PR_SUCCESS; 1.362 +} 1.363 + 1.364 +static nssTrustLevel 1.365 +get_nss_trust ( 1.366 + CK_TRUST ckt 1.367 +) 1.368 +{ 1.369 + nssTrustLevel t; 1.370 + switch (ckt) { 1.371 + case CKT_NSS_NOT_TRUSTED: t = nssTrustLevel_NotTrusted; break; 1.372 + case CKT_NSS_TRUSTED_DELEGATOR: t = nssTrustLevel_TrustedDelegator; 1.373 + break; 1.374 + case CKT_NSS_VALID_DELEGATOR: t = nssTrustLevel_ValidDelegator; break; 1.375 + case CKT_NSS_TRUSTED: t = nssTrustLevel_Trusted; break; 1.376 + case CKT_NSS_MUST_VERIFY_TRUST: t = nssTrustLevel_MustVerify; break; 1.377 + case CKT_NSS_TRUST_UNKNOWN: 1.378 + default: 1.379 + t = nssTrustLevel_Unknown; break; 1.380 + } 1.381 + return t; 1.382 +} 1.383 + 1.384 +NSS_IMPLEMENT PRStatus 1.385 +nssCryptokiTrust_GetAttributes ( 1.386 + nssCryptokiObject *trustObject, 1.387 + nssSession *sessionOpt, 1.388 + NSSItem *sha1_hash, 1.389 + nssTrustLevel *serverAuth, 1.390 + nssTrustLevel *clientAuth, 1.391 + nssTrustLevel *codeSigning, 1.392 + nssTrustLevel *emailProtection, 1.393 + PRBool *stepUpApproved 1.394 +) 1.395 +{ 1.396 + PRStatus status; 1.397 + NSSSlot *slot; 1.398 + nssSession *session; 1.399 + CK_BBOOL isToken = PR_FALSE; 1.400 + CK_BBOOL stepUp = PR_FALSE; 1.401 + CK_TRUST saTrust = CKT_NSS_TRUST_UNKNOWN; 1.402 + CK_TRUST caTrust = CKT_NSS_TRUST_UNKNOWN; 1.403 + CK_TRUST epTrust = CKT_NSS_TRUST_UNKNOWN; 1.404 + CK_TRUST csTrust = CKT_NSS_TRUST_UNKNOWN; 1.405 + CK_ATTRIBUTE_PTR attr; 1.406 + CK_ATTRIBUTE trust_template[7]; 1.407 + CK_ATTRIBUTE_PTR sha1_hash_attr; 1.408 + CK_ULONG trust_size; 1.409 + 1.410 + /* Use the trust object to find the trust settings */ 1.411 + NSS_CK_TEMPLATE_START(trust_template, attr, trust_size); 1.412 + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN, isToken); 1.413 + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, saTrust); 1.414 + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, caTrust); 1.415 + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, epTrust); 1.416 + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, csTrust); 1.417 + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_STEP_UP_APPROVED, stepUp); 1.418 + sha1_hash_attr = attr; 1.419 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, sha1_hash); 1.420 + NSS_CK_TEMPLATE_FINISH(trust_template, attr, trust_size); 1.421 + 1.422 + status = nssToken_GetCachedObjectAttributes(trustObject->token, NULL, 1.423 + trustObject, 1.424 + CKO_NSS_TRUST, 1.425 + trust_template, trust_size); 1.426 + if (status != PR_SUCCESS) { 1.427 + session = sessionOpt ? 1.428 + sessionOpt : 1.429 + nssToken_GetDefaultSession(trustObject->token); 1.430 + if (!session) { 1.431 + nss_SetError(NSS_ERROR_INVALID_ARGUMENT); 1.432 + return PR_FAILURE; 1.433 + } 1.434 + 1.435 + slot = nssToken_GetSlot(trustObject->token); 1.436 + status = nssCKObject_GetAttributes(trustObject->handle, 1.437 + trust_template, trust_size, 1.438 + NULL, session, slot); 1.439 + nssSlot_Destroy(slot); 1.440 + if (status != PR_SUCCESS) { 1.441 + return status; 1.442 + } 1.443 + } 1.444 + 1.445 + if (sha1_hash_attr->ulValueLen == -1) { 1.446 + /* The trust object does not have the CKA_CERT_SHA1_HASH attribute. */ 1.447 + sha1_hash_attr->ulValueLen = 0; 1.448 + } 1.449 + sha1_hash->size = sha1_hash_attr->ulValueLen; 1.450 + *serverAuth = get_nss_trust(saTrust); 1.451 + *clientAuth = get_nss_trust(caTrust); 1.452 + *emailProtection = get_nss_trust(epTrust); 1.453 + *codeSigning = get_nss_trust(csTrust); 1.454 + *stepUpApproved = stepUp; 1.455 + return PR_SUCCESS; 1.456 +} 1.457 + 1.458 +NSS_IMPLEMENT PRStatus 1.459 +nssCryptokiCRL_GetAttributes ( 1.460 + nssCryptokiObject *crlObject, 1.461 + nssSession *sessionOpt, 1.462 + NSSArena *arenaOpt, 1.463 + NSSItem *encodingOpt, 1.464 + NSSItem *subjectOpt, 1.465 + CK_ULONG* crl_class, 1.466 + NSSUTF8 **urlOpt, 1.467 + PRBool *isKRLOpt 1.468 +) 1.469 +{ 1.470 + PRStatus status; 1.471 + NSSSlot *slot; 1.472 + nssSession *session; 1.473 + CK_ATTRIBUTE_PTR attr; 1.474 + CK_ATTRIBUTE crl_template[7]; 1.475 + CK_ULONG crl_size; 1.476 + PRUint32 i; 1.477 + 1.478 + NSS_CK_TEMPLATE_START(crl_template, attr, crl_size); 1.479 + if (crl_class) { 1.480 + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CLASS); 1.481 + } 1.482 + if (encodingOpt) { 1.483 + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE); 1.484 + } 1.485 + if (urlOpt) { 1.486 + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NSS_URL); 1.487 + } 1.488 + if (isKRLOpt) { 1.489 + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NSS_KRL); 1.490 + } 1.491 + if (subjectOpt) { 1.492 + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT); 1.493 + } 1.494 + NSS_CK_TEMPLATE_FINISH(crl_template, attr, crl_size); 1.495 + 1.496 + status = nssToken_GetCachedObjectAttributes(crlObject->token, NULL, 1.497 + crlObject, 1.498 + CKO_NSS_CRL, 1.499 + crl_template, crl_size); 1.500 + if (status != PR_SUCCESS) { 1.501 + session = sessionOpt ? 1.502 + sessionOpt : 1.503 + nssToken_GetDefaultSession(crlObject->token); 1.504 + if (session == NULL) { 1.505 + nss_SetError(NSS_ERROR_INVALID_ARGUMENT); 1.506 + return PR_FAILURE; 1.507 + } 1.508 + 1.509 + slot = nssToken_GetSlot(crlObject->token); 1.510 + status = nssCKObject_GetAttributes(crlObject->handle, 1.511 + crl_template, crl_size, 1.512 + arenaOpt, session, slot); 1.513 + nssSlot_Destroy(slot); 1.514 + if (status != PR_SUCCESS) { 1.515 + return status; 1.516 + } 1.517 + } 1.518 + 1.519 + i=0; 1.520 + if (crl_class) { 1.521 + NSS_CK_ATTRIBUTE_TO_ULONG(&crl_template[i], *crl_class); i++; 1.522 + } 1.523 + if (encodingOpt) { 1.524 + NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], encodingOpt); i++; 1.525 + } 1.526 + if (urlOpt) { 1.527 + NSS_CK_ATTRIBUTE_TO_UTF8(&crl_template[i], *urlOpt); i++; 1.528 + } 1.529 + if (isKRLOpt) { 1.530 + NSS_CK_ATTRIBUTE_TO_BOOL(&crl_template[i], *isKRLOpt); i++; 1.531 + } 1.532 + if (subjectOpt) { 1.533 + NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], subjectOpt); i++; 1.534 + } 1.535 + return PR_SUCCESS; 1.536 +} 1.537 + 1.538 +NSS_IMPLEMENT PRStatus 1.539 +nssCryptokiPrivateKey_SetCertificate ( 1.540 + nssCryptokiObject *keyObject, 1.541 + nssSession *sessionOpt, 1.542 + const NSSUTF8 *nickname, 1.543 + NSSItem *id, 1.544 + NSSDER *subject 1.545 +) 1.546 +{ 1.547 + CK_RV ckrv; 1.548 + CK_ATTRIBUTE_PTR attr; 1.549 + CK_ATTRIBUTE key_template[3]; 1.550 + CK_ULONG key_size; 1.551 + void *epv = nssToken_GetCryptokiEPV(keyObject->token); 1.552 + nssSession *session; 1.553 + NSSToken *token = keyObject->token; 1.554 + nssSession *defaultSession = nssToken_GetDefaultSession(token); 1.555 + PRBool createdSession = PR_FALSE; 1.556 + 1.557 + NSS_CK_TEMPLATE_START(key_template, attr, key_size); 1.558 + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); 1.559 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); 1.560 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); 1.561 + NSS_CK_TEMPLATE_FINISH(key_template, attr, key_size); 1.562 + 1.563 + if (sessionOpt) { 1.564 + if (!nssSession_IsReadWrite(sessionOpt)) { 1.565 + return PR_FAILURE; 1.566 + } 1.567 + session = sessionOpt; 1.568 + } else if (defaultSession && nssSession_IsReadWrite(defaultSession)) { 1.569 + session = defaultSession; 1.570 + } else { 1.571 + NSSSlot *slot = nssToken_GetSlot(token); 1.572 + session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE); 1.573 + nssSlot_Destroy(slot); 1.574 + if (!session) { 1.575 + return PR_FAILURE; 1.576 + } 1.577 + createdSession = PR_TRUE; 1.578 + } 1.579 + 1.580 + ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle, 1.581 + keyObject->handle, 1.582 + key_template, 1.583 + key_size); 1.584 + 1.585 + if (createdSession) { 1.586 + nssSession_Destroy(session); 1.587 + } 1.588 + 1.589 + return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE; 1.590 +} 1.591 +