PageRenderTime 55ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/security/nss/lib/dev/ckhelper.c

https://bitbucket.org/soko/mozilla-central
C | 624 lines | 531 code | 41 blank | 52 comment | 106 complexity | 50f748c512d8ceef693c339b722081b4 MD5 | raw file
Possible License(s): GPL-2.0, JSON, 0BSD, LGPL-3.0, AGPL-1.0, MIT, MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.1, Apache-2.0
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the Netscape security libraries.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. *
  23. * Alternatively, the contents of this file may be used under the terms of
  24. * either the GNU General Public License Version 2 or later (the "GPL"), or
  25. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  26. * in which case the provisions of the GPL or the LGPL are applicable instead
  27. * of those above. If you wish to allow use of your version of this file only
  28. * under the terms of either the GPL or the LGPL, and not to allow others to
  29. * use your version of this file under the terms of the MPL, indicate your
  30. * decision by deleting the provisions above and replace them with the notice
  31. * and other provisions required by the GPL or the LGPL. If you do not delete
  32. * the provisions above, a recipient may use your version of this file under
  33. * the terms of any one of the MPL, the GPL or the LGPL.
  34. *
  35. * ***** END LICENSE BLOCK ***** */
  36. #ifdef DEBUG
  37. static const char CVS_ID[] = "@(#) $RCSfile: ckhelper.c,v $ $Revision: 1.42 $ $Date: 2011/09/14 00:28:48 $";
  38. #endif /* DEBUG */
  39. #include "pkcs11.h"
  40. #ifndef DEVM_H
  41. #include "devm.h"
  42. #endif /* DEVM_H */
  43. #ifndef CKHELPER_H
  44. #include "ckhelper.h"
  45. #endif /* CKHELPER_H */
  46. extern const NSSError NSS_ERROR_DEVICE_ERROR;
  47. static const CK_BBOOL s_true = CK_TRUE;
  48. NSS_IMPLEMENT_DATA const NSSItem
  49. g_ck_true = { (CK_VOID_PTR)&s_true, sizeof(s_true) };
  50. static const CK_BBOOL s_false = CK_FALSE;
  51. NSS_IMPLEMENT_DATA const NSSItem
  52. g_ck_false = { (CK_VOID_PTR)&s_false, sizeof(s_false) };
  53. static const CK_OBJECT_CLASS s_class_cert = CKO_CERTIFICATE;
  54. NSS_IMPLEMENT_DATA const NSSItem
  55. g_ck_class_cert = { (CK_VOID_PTR)&s_class_cert, sizeof(s_class_cert) };
  56. static const CK_OBJECT_CLASS s_class_pubkey = CKO_PUBLIC_KEY;
  57. NSS_IMPLEMENT_DATA const NSSItem
  58. g_ck_class_pubkey = { (CK_VOID_PTR)&s_class_pubkey, sizeof(s_class_pubkey) };
  59. static const CK_OBJECT_CLASS s_class_privkey = CKO_PRIVATE_KEY;
  60. NSS_IMPLEMENT_DATA const NSSItem
  61. g_ck_class_privkey = { (CK_VOID_PTR)&s_class_privkey, sizeof(s_class_privkey) };
  62. static PRBool
  63. is_string_attribute (
  64. CK_ATTRIBUTE_TYPE aType
  65. )
  66. {
  67. PRBool isString;
  68. switch (aType) {
  69. case CKA_LABEL:
  70. case CKA_NSS_EMAIL:
  71. isString = PR_TRUE;
  72. break;
  73. default:
  74. isString = PR_FALSE;
  75. break;
  76. }
  77. return isString;
  78. }
  79. NSS_IMPLEMENT PRStatus
  80. nssCKObject_GetAttributes (
  81. CK_OBJECT_HANDLE object,
  82. CK_ATTRIBUTE_PTR obj_template,
  83. CK_ULONG count,
  84. NSSArena *arenaOpt,
  85. nssSession *session,
  86. NSSSlot *slot
  87. )
  88. {
  89. nssArenaMark *mark = NULL;
  90. CK_SESSION_HANDLE hSession;
  91. CK_ULONG i = 0;
  92. CK_RV ckrv;
  93. PRStatus nssrv;
  94. PRBool alloced = PR_FALSE;
  95. void *epv = nssSlot_GetCryptokiEPV(slot);
  96. hSession = session->handle;
  97. if (arenaOpt) {
  98. mark = nssArena_Mark(arenaOpt);
  99. if (!mark) {
  100. goto loser;
  101. }
  102. }
  103. nssSession_EnterMonitor(session);
  104. /* XXX kinda hacky, if the storage size is already in the first template
  105. * item, then skip the alloc portion
  106. */
  107. if (obj_template[0].ulValueLen == 0) {
  108. /* Get the storage size needed for each attribute */
  109. ckrv = CKAPI(epv)->C_GetAttributeValue(hSession,
  110. object, obj_template, count);
  111. if (ckrv != CKR_OK &&
  112. ckrv != CKR_ATTRIBUTE_TYPE_INVALID &&
  113. ckrv != CKR_ATTRIBUTE_SENSITIVE)
  114. {
  115. nssSession_ExitMonitor(session);
  116. nss_SetError(NSS_ERROR_DEVICE_ERROR);
  117. goto loser;
  118. }
  119. /* Allocate memory for each attribute. */
  120. for (i=0; i<count; i++) {
  121. CK_ULONG ulValueLen = obj_template[i].ulValueLen;
  122. if (ulValueLen == 0 || ulValueLen == (CK_ULONG) -1) {
  123. obj_template[i].pValue = NULL;
  124. obj_template[i].ulValueLen = 0;
  125. continue;
  126. }
  127. if (is_string_attribute(obj_template[i].type)) {
  128. ulValueLen++;
  129. }
  130. obj_template[i].pValue = nss_ZAlloc(arenaOpt, ulValueLen);
  131. if (!obj_template[i].pValue) {
  132. nssSession_ExitMonitor(session);
  133. goto loser;
  134. }
  135. }
  136. alloced = PR_TRUE;
  137. }
  138. /* Obtain the actual attribute values. */
  139. ckrv = CKAPI(epv)->C_GetAttributeValue(hSession,
  140. object, obj_template, count);
  141. nssSession_ExitMonitor(session);
  142. if (ckrv != CKR_OK &&
  143. ckrv != CKR_ATTRIBUTE_TYPE_INVALID &&
  144. ckrv != CKR_ATTRIBUTE_SENSITIVE)
  145. {
  146. nss_SetError(NSS_ERROR_DEVICE_ERROR);
  147. goto loser;
  148. }
  149. if (alloced && arenaOpt) {
  150. nssrv = nssArena_Unmark(arenaOpt, mark);
  151. if (nssrv != PR_SUCCESS) {
  152. goto loser;
  153. }
  154. }
  155. if (count > 1 && ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) ||
  156. (ckrv == CKR_ATTRIBUTE_SENSITIVE))) {
  157. /* old tokens would keep the length of '0' and not deal with any
  158. * of the attributes we passed. For those tokens read them one at
  159. * a time */
  160. for (i=0; i < count; i++) {
  161. if ((obj_template[i].ulValueLen == 0)
  162. || (obj_template[i].ulValueLen == -1)) {
  163. obj_template[i].ulValueLen=0;
  164. (void) nssCKObject_GetAttributes(object,&obj_template[i], 1,
  165. arenaOpt, session, slot);
  166. }
  167. }
  168. }
  169. return PR_SUCCESS;
  170. loser:
  171. if (alloced) {
  172. if (arenaOpt) {
  173. /* release all arena memory allocated before the failure. */
  174. (void)nssArena_Release(arenaOpt, mark);
  175. } else {
  176. CK_ULONG j;
  177. /* free each heap object that was allocated before the failure. */
  178. for (j=0; j<i; j++) {
  179. nss_ZFreeIf(obj_template[j].pValue);
  180. }
  181. }
  182. }
  183. return PR_FAILURE;
  184. }
  185. NSS_IMPLEMENT PRStatus
  186. nssCKObject_GetAttributeItem (
  187. CK_OBJECT_HANDLE object,
  188. CK_ATTRIBUTE_TYPE attribute,
  189. NSSArena *arenaOpt,
  190. nssSession *session,
  191. NSSSlot *slot,
  192. NSSItem *rvItem
  193. )
  194. {
  195. CK_ATTRIBUTE attr = { 0, NULL, 0 };
  196. PRStatus nssrv;
  197. attr.type = attribute;
  198. nssrv = nssCKObject_GetAttributes(object, &attr, 1,
  199. arenaOpt, session, slot);
  200. if (nssrv != PR_SUCCESS) {
  201. return nssrv;
  202. }
  203. rvItem->data = (void *)attr.pValue;
  204. rvItem->size = (PRUint32)attr.ulValueLen;
  205. return PR_SUCCESS;
  206. }
  207. NSS_IMPLEMENT PRBool
  208. nssCKObject_IsAttributeTrue (
  209. CK_OBJECT_HANDLE object,
  210. CK_ATTRIBUTE_TYPE attribute,
  211. nssSession *session,
  212. NSSSlot *slot,
  213. PRStatus *rvStatus
  214. )
  215. {
  216. CK_BBOOL bool;
  217. CK_ATTRIBUTE_PTR attr;
  218. CK_ATTRIBUTE atemplate = { 0, NULL, 0 };
  219. CK_RV ckrv;
  220. void *epv = nssSlot_GetCryptokiEPV(slot);
  221. attr = &atemplate;
  222. NSS_CK_SET_ATTRIBUTE_VAR(attr, attribute, bool);
  223. nssSession_EnterMonitor(session);
  224. ckrv = CKAPI(epv)->C_GetAttributeValue(session->handle, object,
  225. &atemplate, 1);
  226. nssSession_ExitMonitor(session);
  227. if (ckrv != CKR_OK) {
  228. *rvStatus = PR_FAILURE;
  229. return PR_FALSE;
  230. }
  231. *rvStatus = PR_SUCCESS;
  232. return (PRBool)(bool == CK_TRUE);
  233. }
  234. NSS_IMPLEMENT PRStatus
  235. nssCKObject_SetAttributes (
  236. CK_OBJECT_HANDLE object,
  237. CK_ATTRIBUTE_PTR obj_template,
  238. CK_ULONG count,
  239. nssSession *session,
  240. NSSSlot *slot
  241. )
  242. {
  243. CK_RV ckrv;
  244. void *epv = nssSlot_GetCryptokiEPV(slot);
  245. nssSession_EnterMonitor(session);
  246. ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle, object,
  247. obj_template, count);
  248. nssSession_ExitMonitor(session);
  249. if (ckrv == CKR_OK) {
  250. return PR_SUCCESS;
  251. } else {
  252. return PR_FAILURE;
  253. }
  254. }
  255. NSS_IMPLEMENT PRBool
  256. nssCKObject_IsTokenObjectTemplate (
  257. CK_ATTRIBUTE_PTR objectTemplate,
  258. CK_ULONG otsize
  259. )
  260. {
  261. CK_ULONG ul;
  262. for (ul=0; ul<otsize; ul++) {
  263. if (objectTemplate[ul].type == CKA_TOKEN) {
  264. return (*((CK_BBOOL*)objectTemplate[ul].pValue) == CK_TRUE);
  265. }
  266. }
  267. return PR_FALSE;
  268. }
  269. static NSSCertificateType
  270. nss_cert_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib)
  271. {
  272. CK_CERTIFICATE_TYPE ckCertType;
  273. if (!attrib->pValue) {
  274. /* default to PKIX */
  275. return NSSCertificateType_PKIX;
  276. }
  277. ckCertType = *((CK_ULONG *)attrib->pValue);
  278. switch (ckCertType) {
  279. case CKC_X_509:
  280. return NSSCertificateType_PKIX;
  281. default:
  282. break;
  283. }
  284. return NSSCertificateType_Unknown;
  285. }
  286. /* incoming pointers must be valid */
  287. NSS_IMPLEMENT PRStatus
  288. nssCryptokiCertificate_GetAttributes (
  289. nssCryptokiObject *certObject,
  290. nssSession *sessionOpt,
  291. NSSArena *arenaOpt,
  292. NSSCertificateType *certTypeOpt,
  293. NSSItem *idOpt,
  294. NSSDER *encodingOpt,
  295. NSSDER *issuerOpt,
  296. NSSDER *serialOpt,
  297. NSSDER *subjectOpt
  298. )
  299. {
  300. PRStatus status;
  301. PRUint32 i;
  302. nssSession *session;
  303. NSSSlot *slot;
  304. CK_ULONG template_size;
  305. CK_ATTRIBUTE_PTR attr;
  306. CK_ATTRIBUTE cert_template[6];
  307. /* Set up a template of all options chosen by caller */
  308. NSS_CK_TEMPLATE_START(cert_template, attr, template_size);
  309. if (certTypeOpt) {
  310. NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CERTIFICATE_TYPE);
  311. }
  312. if (idOpt) {
  313. NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID);
  314. }
  315. if (encodingOpt) {
  316. NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
  317. }
  318. if (issuerOpt) {
  319. NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ISSUER);
  320. }
  321. if (serialOpt) {
  322. NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SERIAL_NUMBER);
  323. }
  324. if (subjectOpt) {
  325. NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT);
  326. }
  327. NSS_CK_TEMPLATE_FINISH(cert_template, attr, template_size);
  328. if (template_size == 0) {
  329. /* caller didn't want anything */
  330. return PR_SUCCESS;
  331. }
  332. status = nssToken_GetCachedObjectAttributes(certObject->token, arenaOpt,
  333. certObject, CKO_CERTIFICATE,
  334. cert_template, template_size);
  335. if (status != PR_SUCCESS) {
  336. session = sessionOpt ?
  337. sessionOpt :
  338. nssToken_GetDefaultSession(certObject->token);
  339. if (!session) {
  340. nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
  341. return PR_FAILURE;
  342. }
  343. slot = nssToken_GetSlot(certObject->token);
  344. status = nssCKObject_GetAttributes(certObject->handle,
  345. cert_template, template_size,
  346. arenaOpt, session, slot);
  347. nssSlot_Destroy(slot);
  348. if (status != PR_SUCCESS) {
  349. return status;
  350. }
  351. }
  352. i=0;
  353. if (certTypeOpt) {
  354. *certTypeOpt = nss_cert_type_from_ck_attrib(&cert_template[i]); i++;
  355. }
  356. if (idOpt) {
  357. NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], idOpt); i++;
  358. }
  359. if (encodingOpt) {
  360. NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], encodingOpt); i++;
  361. }
  362. if (issuerOpt) {
  363. NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], issuerOpt); i++;
  364. }
  365. if (serialOpt) {
  366. NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], serialOpt); i++;
  367. }
  368. if (subjectOpt) {
  369. NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], subjectOpt); i++;
  370. }
  371. return PR_SUCCESS;
  372. }
  373. static nssTrustLevel
  374. get_nss_trust (
  375. CK_TRUST ckt
  376. )
  377. {
  378. nssTrustLevel t;
  379. switch (ckt) {
  380. case CKT_NSS_NOT_TRUSTED: t = nssTrustLevel_NotTrusted; break;
  381. case CKT_NSS_TRUSTED_DELEGATOR: t = nssTrustLevel_TrustedDelegator;
  382. break;
  383. case CKT_NSS_VALID_DELEGATOR: t = nssTrustLevel_ValidDelegator; break;
  384. case CKT_NSS_TRUSTED: t = nssTrustLevel_Trusted; break;
  385. case CKT_NSS_MUST_VERIFY_TRUST: t = nssTrustLevel_MustVerify; break;
  386. case CKT_NSS_TRUST_UNKNOWN:
  387. default:
  388. t = nssTrustLevel_Unknown; break;
  389. }
  390. return t;
  391. }
  392. NSS_IMPLEMENT PRStatus
  393. nssCryptokiTrust_GetAttributes (
  394. nssCryptokiObject *trustObject,
  395. nssSession *sessionOpt,
  396. NSSItem *sha1_hash,
  397. nssTrustLevel *serverAuth,
  398. nssTrustLevel *clientAuth,
  399. nssTrustLevel *codeSigning,
  400. nssTrustLevel *emailProtection,
  401. PRBool *stepUpApproved
  402. )
  403. {
  404. PRStatus status;
  405. NSSSlot *slot;
  406. nssSession *session;
  407. CK_BBOOL isToken = PR_FALSE;
  408. CK_BBOOL stepUp = PR_FALSE;
  409. CK_TRUST saTrust = CKT_NSS_TRUST_UNKNOWN;
  410. CK_TRUST caTrust = CKT_NSS_TRUST_UNKNOWN;
  411. CK_TRUST epTrust = CKT_NSS_TRUST_UNKNOWN;
  412. CK_TRUST csTrust = CKT_NSS_TRUST_UNKNOWN;
  413. CK_ATTRIBUTE_PTR attr;
  414. CK_ATTRIBUTE trust_template[7];
  415. CK_ATTRIBUTE_PTR sha1_hash_attr;
  416. CK_ULONG trust_size;
  417. /* Use the trust object to find the trust settings */
  418. NSS_CK_TEMPLATE_START(trust_template, attr, trust_size);
  419. NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN, isToken);
  420. NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, saTrust);
  421. NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, caTrust);
  422. NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, epTrust);
  423. NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, csTrust);
  424. NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_STEP_UP_APPROVED, stepUp);
  425. sha1_hash_attr = attr;
  426. NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, sha1_hash);
  427. NSS_CK_TEMPLATE_FINISH(trust_template, attr, trust_size);
  428. status = nssToken_GetCachedObjectAttributes(trustObject->token, NULL,
  429. trustObject,
  430. CKO_NSS_TRUST,
  431. trust_template, trust_size);
  432. if (status != PR_SUCCESS) {
  433. session = sessionOpt ?
  434. sessionOpt :
  435. nssToken_GetDefaultSession(trustObject->token);
  436. if (!session) {
  437. nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
  438. return PR_FAILURE;
  439. }
  440. slot = nssToken_GetSlot(trustObject->token);
  441. status = nssCKObject_GetAttributes(trustObject->handle,
  442. trust_template, trust_size,
  443. NULL, session, slot);
  444. nssSlot_Destroy(slot);
  445. if (status != PR_SUCCESS) {
  446. return status;
  447. }
  448. }
  449. if (sha1_hash_attr->ulValueLen == -1) {
  450. /* The trust object does not have the CKA_CERT_SHA1_HASH attribute. */
  451. sha1_hash_attr->ulValueLen = 0;
  452. }
  453. sha1_hash->size = sha1_hash_attr->ulValueLen;
  454. *serverAuth = get_nss_trust(saTrust);
  455. *clientAuth = get_nss_trust(caTrust);
  456. *emailProtection = get_nss_trust(epTrust);
  457. *codeSigning = get_nss_trust(csTrust);
  458. *stepUpApproved = stepUp;
  459. return PR_SUCCESS;
  460. }
  461. NSS_IMPLEMENT PRStatus
  462. nssCryptokiCRL_GetAttributes (
  463. nssCryptokiObject *crlObject,
  464. nssSession *sessionOpt,
  465. NSSArena *arenaOpt,
  466. NSSItem *encodingOpt,
  467. NSSItem *subjectOpt,
  468. CK_ULONG* crl_class,
  469. NSSUTF8 **urlOpt,
  470. PRBool *isKRLOpt
  471. )
  472. {
  473. PRStatus status;
  474. NSSSlot *slot;
  475. nssSession *session;
  476. CK_ATTRIBUTE_PTR attr;
  477. CK_ATTRIBUTE crl_template[7];
  478. CK_ULONG crl_size;
  479. PRUint32 i;
  480. NSS_CK_TEMPLATE_START(crl_template, attr, crl_size);
  481. if (crl_class) {
  482. NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CLASS);
  483. }
  484. if (encodingOpt) {
  485. NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
  486. }
  487. if (urlOpt) {
  488. NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NSS_URL);
  489. }
  490. if (isKRLOpt) {
  491. NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NSS_KRL);
  492. }
  493. if (subjectOpt) {
  494. NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT);
  495. }
  496. NSS_CK_TEMPLATE_FINISH(crl_template, attr, crl_size);
  497. status = nssToken_GetCachedObjectAttributes(crlObject->token, NULL,
  498. crlObject,
  499. CKO_NSS_CRL,
  500. crl_template, crl_size);
  501. if (status != PR_SUCCESS) {
  502. session = sessionOpt ?
  503. sessionOpt :
  504. nssToken_GetDefaultSession(crlObject->token);
  505. if (session == NULL) {
  506. nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
  507. return PR_FAILURE;
  508. }
  509. slot = nssToken_GetSlot(crlObject->token);
  510. status = nssCKObject_GetAttributes(crlObject->handle,
  511. crl_template, crl_size,
  512. arenaOpt, session, slot);
  513. nssSlot_Destroy(slot);
  514. if (status != PR_SUCCESS) {
  515. return status;
  516. }
  517. }
  518. i=0;
  519. if (crl_class) {
  520. NSS_CK_ATTRIBUTE_TO_ULONG(&crl_template[i], *crl_class); i++;
  521. }
  522. if (encodingOpt) {
  523. NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], encodingOpt); i++;
  524. }
  525. if (urlOpt) {
  526. NSS_CK_ATTRIBUTE_TO_UTF8(&crl_template[i], *urlOpt); i++;
  527. }
  528. if (isKRLOpt) {
  529. NSS_CK_ATTRIBUTE_TO_BOOL(&crl_template[i], *isKRLOpt); i++;
  530. }
  531. if (subjectOpt) {
  532. NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], subjectOpt); i++;
  533. }
  534. return PR_SUCCESS;
  535. }
  536. NSS_IMPLEMENT PRStatus
  537. nssCryptokiPrivateKey_SetCertificate (
  538. nssCryptokiObject *keyObject,
  539. nssSession *sessionOpt,
  540. const NSSUTF8 *nickname,
  541. NSSItem *id,
  542. NSSDER *subject
  543. )
  544. {
  545. CK_RV ckrv;
  546. CK_ATTRIBUTE_PTR attr;
  547. CK_ATTRIBUTE key_template[3];
  548. CK_ULONG key_size;
  549. void *epv = nssToken_GetCryptokiEPV(keyObject->token);
  550. nssSession *session;
  551. NSSToken *token = keyObject->token;
  552. nssSession *defaultSession = nssToken_GetDefaultSession(token);
  553. PRBool createdSession = PR_FALSE;
  554. NSS_CK_TEMPLATE_START(key_template, attr, key_size);
  555. NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname);
  556. NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
  557. NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
  558. NSS_CK_TEMPLATE_FINISH(key_template, attr, key_size);
  559. if (sessionOpt) {
  560. if (!nssSession_IsReadWrite(sessionOpt)) {
  561. return PR_FAILURE;
  562. }
  563. session = sessionOpt;
  564. } else if (defaultSession && nssSession_IsReadWrite(defaultSession)) {
  565. session = defaultSession;
  566. } else {
  567. NSSSlot *slot = nssToken_GetSlot(token);
  568. session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE);
  569. nssSlot_Destroy(slot);
  570. if (!session) {
  571. return PR_FAILURE;
  572. }
  573. createdSession = PR_TRUE;
  574. }
  575. ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle,
  576. keyObject->handle,
  577. key_template,
  578. key_size);
  579. if (createdSession) {
  580. nssSession_Destroy(session);
  581. }
  582. return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
  583. }