/security/nss/lib/ckfw/capi/cobject.c

http://github.com/zpao/v8monkey · C · 2343 lines · 1963 code · 200 blank · 180 comment · 336 complexity · 7efbd9cfff44089c2b6669fa99323158 MD5 · raw file

Large files are truncated click here to view the full file

  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. * Portions created by Red Hat, Inc, are Copyright (C) 2005
  21. *
  22. * Contributor(s):
  23. * Bob Relyea <rrelyea@redhat.com>
  24. * Muzaffar Mahkamov <mmahkamov@eisst.com>
  25. *
  26. * Alternatively, the contents of this file may be used under the terms of
  27. * either the GNU General Public License Version 2 or later (the "GPL"), or
  28. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  29. * in which case the provisions of the GPL or the LGPL are applicable instead
  30. * of those above. If you wish to allow use of your version of this file only
  31. * under the terms of either the GPL or the LGPL, and not to allow others to
  32. * use your version of this file under the terms of the MPL, indicate your
  33. * decision by deleting the provisions above and replace them with the notice
  34. * and other provisions required by the GPL or the LGPL. If you do not delete
  35. * the provisions above, a recipient may use your version of this file under
  36. * the terms of any one of the MPL, the GPL or the LGPL.
  37. *
  38. * ***** END LICENSE BLOCK ***** */
  39. #ifdef DEBUG
  40. static const char CVS_ID[] = "@(#) $RCSfile: cobject.c,v $ $Revision: 1.9 $ $Date: 2011/02/02 17:13:40 $";
  41. #endif /* DEBUG */
  42. #include "ckcapi.h"
  43. #include "nssbase.h"
  44. /*
  45. * ckcapi/cobject.c
  46. *
  47. * This file implements the NSSCKMDObject object for the
  48. * "nss to capi objects" cryptoki module.
  49. */
  50. const CK_ATTRIBUTE_TYPE certAttrs[] = {
  51. CKA_CLASS,
  52. CKA_TOKEN,
  53. CKA_PRIVATE,
  54. CKA_MODIFIABLE,
  55. CKA_LABEL,
  56. CKA_CERTIFICATE_TYPE,
  57. CKA_SUBJECT,
  58. CKA_ISSUER,
  59. CKA_SERIAL_NUMBER,
  60. CKA_VALUE
  61. };
  62. const PRUint32 certAttrsCount = NSS_CKCAPI_ARRAY_SIZE(certAttrs);
  63. /* private keys, for now only support RSA */
  64. const CK_ATTRIBUTE_TYPE privKeyAttrs[] = {
  65. CKA_CLASS,
  66. CKA_TOKEN,
  67. CKA_PRIVATE,
  68. CKA_MODIFIABLE,
  69. CKA_LABEL,
  70. CKA_KEY_TYPE,
  71. CKA_DERIVE,
  72. CKA_LOCAL,
  73. CKA_SUBJECT,
  74. CKA_SENSITIVE,
  75. CKA_DECRYPT,
  76. CKA_SIGN,
  77. CKA_SIGN_RECOVER,
  78. CKA_UNWRAP,
  79. CKA_EXTRACTABLE,
  80. CKA_ALWAYS_SENSITIVE,
  81. CKA_NEVER_EXTRACTABLE,
  82. CKA_MODULUS,
  83. CKA_PUBLIC_EXPONENT,
  84. };
  85. const PRUint32 privKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(privKeyAttrs);
  86. /* public keys, for now only support RSA */
  87. const CK_ATTRIBUTE_TYPE pubKeyAttrs[] = {
  88. CKA_CLASS,
  89. CKA_TOKEN,
  90. CKA_PRIVATE,
  91. CKA_MODIFIABLE,
  92. CKA_LABEL,
  93. CKA_KEY_TYPE,
  94. CKA_DERIVE,
  95. CKA_LOCAL,
  96. CKA_SUBJECT,
  97. CKA_ENCRYPT,
  98. CKA_VERIFY,
  99. CKA_VERIFY_RECOVER,
  100. CKA_WRAP,
  101. CKA_MODULUS,
  102. CKA_PUBLIC_EXPONENT,
  103. };
  104. const PRUint32 pubKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(pubKeyAttrs);
  105. static const CK_BBOOL ck_true = CK_TRUE;
  106. static const CK_BBOOL ck_false = CK_FALSE;
  107. static const CK_CERTIFICATE_TYPE ckc_x509 = CKC_X_509;
  108. static const CK_KEY_TYPE ckk_rsa = CKK_RSA;
  109. static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE;
  110. static const CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY;
  111. static const CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY;
  112. static const NSSItem ckcapi_trueItem = {
  113. (void *)&ck_true, (PRUint32)sizeof(CK_BBOOL) };
  114. static const NSSItem ckcapi_falseItem = {
  115. (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) };
  116. static const NSSItem ckcapi_x509Item = {
  117. (void *)&ckc_x509, (PRUint32)sizeof(CK_CERTIFICATE_TYPE) };
  118. static const NSSItem ckcapi_rsaItem = {
  119. (void *)&ckk_rsa, (PRUint32)sizeof(CK_KEY_TYPE) };
  120. static const NSSItem ckcapi_certClassItem = {
  121. (void *)&cko_certificate, (PRUint32)sizeof(CK_OBJECT_CLASS) };
  122. static const NSSItem ckcapi_privKeyClassItem = {
  123. (void *)&cko_private_key, (PRUint32)sizeof(CK_OBJECT_CLASS) };
  124. static const NSSItem ckcapi_pubKeyClassItem = {
  125. (void *)&cko_public_key, (PRUint32)sizeof(CK_OBJECT_CLASS) };
  126. static const NSSItem ckcapi_emptyItem = {
  127. (void *)&ck_true, 0};
  128. /*
  129. * these are utilities. The chould be moved to a new utilities file.
  130. */
  131. /*
  132. * unwrap a single DER value
  133. */
  134. unsigned char *
  135. nss_ckcapi_DERUnwrap
  136. (
  137. unsigned char *src,
  138. unsigned int size,
  139. unsigned int *outSize,
  140. unsigned char **next
  141. )
  142. {
  143. unsigned char *start = src;
  144. unsigned char *end = src+size;
  145. unsigned int len = 0;
  146. /* initialize error condition return values */
  147. *outSize = 0;
  148. if (next) {
  149. *next = src;
  150. }
  151. if (size < 2) {
  152. return start;
  153. }
  154. src++; /* skip the tag -- should check it against an expected value! */
  155. len = (unsigned) *src++;
  156. if (len & 0x80) {
  157. unsigned int count = len & 0x7f;
  158. len = 0;
  159. if (count+2 > size) {
  160. return start;
  161. }
  162. while (count-- > 0) {
  163. len = (len << 8) | (unsigned) *src++;
  164. }
  165. }
  166. if (len + (src-start) > size) {
  167. return start;
  168. }
  169. if (next) {
  170. *next = src+len;
  171. }
  172. *outSize = len;
  173. return src;
  174. }
  175. /*
  176. * convert a PKCS #11 bytestrin into a CK_ULONG, the byte stream must be
  177. * less than sizeof (CK_ULONG).
  178. */
  179. CK_ULONG
  180. nss_ckcapi_DataToInt
  181. (
  182. NSSItem *data,
  183. CK_RV *pError
  184. )
  185. {
  186. CK_ULONG value = 0;
  187. unsigned long count = data->size;
  188. unsigned char *dataPtr = data->data;
  189. unsigned long size = 0;
  190. *pError = CKR_OK;
  191. while (count--) {
  192. value = value << 8;
  193. value = value + *dataPtr++;
  194. if (size || value) {
  195. size++;
  196. }
  197. }
  198. if (size > sizeof(CK_ULONG)) {
  199. *pError = CKR_ATTRIBUTE_VALUE_INVALID;
  200. }
  201. return value;
  202. }
  203. /*
  204. * convert a CK_ULONG to a bytestream. Data is stored in the buffer 'buf'
  205. * and must be at least CK_ULONG. Caller must provide buf.
  206. */
  207. CK_ULONG
  208. nss_ckcapi_IntToData
  209. (
  210. CK_ULONG value,
  211. NSSItem *data,
  212. unsigned char *dataPtr,
  213. CK_RV *pError
  214. )
  215. {
  216. unsigned long count = 0;
  217. unsigned long i;
  218. #define SHIFT ((sizeof(CK_ULONG)-1)*8)
  219. PRBool first = 0;
  220. *pError = CKR_OK;
  221. data->data = dataPtr;
  222. for (i=0; i < sizeof(CK_ULONG); i++) {
  223. unsigned char digit = (unsigned char)((value >> SHIFT) & 0xff);
  224. value = value << 8;
  225. /* drop leading zero bytes */
  226. if (first && (0 == digit)) {
  227. continue;
  228. }
  229. *dataPtr++ = digit;
  230. count++;
  231. }
  232. data->size = count;
  233. return count;
  234. }
  235. /*
  236. * get an attribute from a template. Value is returned in NSS item.
  237. * data for the item is owned by the template.
  238. */
  239. CK_RV
  240. nss_ckcapi_GetAttribute
  241. (
  242. CK_ATTRIBUTE_TYPE type,
  243. CK_ATTRIBUTE *template,
  244. CK_ULONG templateSize,
  245. NSSItem *item
  246. )
  247. {
  248. CK_ULONG i;
  249. for (i=0; i < templateSize; i++) {
  250. if (template[i].type == type) {
  251. item->data = template[i].pValue;
  252. item->size = template[i].ulValueLen;
  253. return CKR_OK;
  254. }
  255. }
  256. return CKR_TEMPLATE_INCOMPLETE;
  257. }
  258. /*
  259. * get an attribute which is type CK_ULONG.
  260. */
  261. CK_ULONG
  262. nss_ckcapi_GetULongAttribute
  263. (
  264. CK_ATTRIBUTE_TYPE type,
  265. CK_ATTRIBUTE *template,
  266. CK_ULONG templateSize,
  267. CK_RV *pError
  268. )
  269. {
  270. NSSItem item;
  271. *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
  272. if (CKR_OK != *pError) {
  273. return (CK_ULONG) 0;
  274. }
  275. if (item.size != sizeof(CK_ULONG)) {
  276. *pError = CKR_ATTRIBUTE_VALUE_INVALID;
  277. return (CK_ULONG) 0;
  278. }
  279. return *(CK_ULONG *)item.data;
  280. }
  281. /*
  282. * get an attribute which is type CK_BBOOL.
  283. */
  284. CK_BBOOL
  285. nss_ckcapi_GetBoolAttribute
  286. (
  287. CK_ATTRIBUTE_TYPE type,
  288. CK_ATTRIBUTE *template,
  289. CK_ULONG templateSize,
  290. CK_RV *pError
  291. )
  292. {
  293. NSSItem item;
  294. *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
  295. if (CKR_OK != *pError) {
  296. return (CK_BBOOL) 0;
  297. }
  298. if (item.size != sizeof(CK_BBOOL)) {
  299. *pError = CKR_ATTRIBUTE_VALUE_INVALID;
  300. return (CK_BBOOL) 0;
  301. }
  302. return *(CK_BBOOL *)item.data;
  303. }
  304. /*
  305. * get an attribute which is type CK_BBOOL.
  306. */
  307. char *
  308. nss_ckcapi_GetStringAttribute
  309. (
  310. CK_ATTRIBUTE_TYPE type,
  311. CK_ATTRIBUTE *template,
  312. CK_ULONG templateSize,
  313. CK_RV *pError
  314. )
  315. {
  316. NSSItem item;
  317. char *str;
  318. /* get the attribute */
  319. *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
  320. if (CKR_OK != *pError) {
  321. return (char *)NULL;
  322. }
  323. /* make sure it is null terminated */
  324. str = nss_ZNEWARRAY(NULL, char, item.size+1);
  325. if ((char *)NULL == str) {
  326. *pError = CKR_HOST_MEMORY;
  327. return (char *)NULL;
  328. }
  329. nsslibc_memcpy(str, item.data, item.size);
  330. str[item.size] = 0;
  331. return str;
  332. }
  333. /*
  334. * Return the size in bytes of a wide string, including the terminating null
  335. * character
  336. */
  337. int
  338. nss_ckcapi_WideSize
  339. (
  340. LPCWSTR wide
  341. )
  342. {
  343. DWORD size;
  344. if ((LPWSTR)NULL == wide) {
  345. return 0;
  346. }
  347. size = wcslen(wide)+1;
  348. return size*sizeof(WCHAR);
  349. }
  350. /*
  351. * Covert a Unicode wide character string to a UTF8 string
  352. */
  353. char *
  354. nss_ckcapi_WideToUTF8
  355. (
  356. LPCWSTR wide
  357. )
  358. {
  359. DWORD size;
  360. char *buf;
  361. if ((LPWSTR)NULL == wide) {
  362. return (char *)NULL;
  363. }
  364. size = WideCharToMultiByte(CP_UTF8, 0, wide, -1, NULL, 0, NULL, 0);
  365. if (size == 0) {
  366. return (char *)NULL;
  367. }
  368. buf = nss_ZNEWARRAY(NULL, char, size);
  369. size = WideCharToMultiByte(CP_UTF8, 0, wide, -1, buf, size, NULL, 0);
  370. if (size == 0) {
  371. nss_ZFreeIf(buf);
  372. return (char *)NULL;
  373. }
  374. return buf;
  375. }
  376. /*
  377. * Return a Wide String duplicated with nss allocated memory.
  378. */
  379. LPWSTR
  380. nss_ckcapi_WideDup
  381. (
  382. LPCWSTR wide
  383. )
  384. {
  385. DWORD len;
  386. LPWSTR buf;
  387. if ((LPWSTR)NULL == wide) {
  388. return (LPWSTR)NULL;
  389. }
  390. len = wcslen(wide)+1;
  391. buf = nss_ZNEWARRAY(NULL, WCHAR, len);
  392. if ((LPWSTR) NULL == buf) {
  393. return buf;
  394. }
  395. nsslibc_memcpy(buf, wide, len*sizeof(WCHAR));
  396. return buf;
  397. }
  398. /*
  399. * Covert a UTF8 string to Unicode wide character
  400. */
  401. LPWSTR
  402. nss_ckcapi_UTF8ToWide
  403. (
  404. char *buf
  405. )
  406. {
  407. DWORD size;
  408. LPWSTR wide;
  409. if ((char *)NULL == buf) {
  410. return (LPWSTR) NULL;
  411. }
  412. size = MultiByteToWideChar(CP_UTF8, 0, buf, -1, NULL, 0);
  413. if (size == 0) {
  414. return (LPWSTR) NULL;
  415. }
  416. wide = nss_ZNEWARRAY(NULL, WCHAR, size);
  417. size = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wide, size);
  418. if (size == 0) {
  419. nss_ZFreeIf(wide);
  420. return (LPWSTR) NULL;
  421. }
  422. return wide;
  423. }
  424. /*
  425. * keep all the knowlege of how the internalObject is laid out in this function
  426. *
  427. * nss_ckcapi_FetchKeyContainer
  428. *
  429. * fetches the Provider container and info as well as a key handle for a
  430. * private key. If something other than a private key is passed in,
  431. * this function fails with CKR_KEY_TYPE_INCONSISTENT
  432. */
  433. NSS_EXTERN CK_RV
  434. nss_ckcapi_FetchKeyContainer
  435. (
  436. ckcapiInternalObject *iKey,
  437. HCRYPTPROV *hProv,
  438. DWORD *keySpec,
  439. HCRYPTKEY *hKey
  440. )
  441. {
  442. ckcapiCertObject *co;
  443. ckcapiKeyObject *ko;
  444. BOOL rc, dummy;
  445. DWORD msError;
  446. switch (iKey->type) {
  447. default:
  448. case ckcapiRaw:
  449. /* can't have raw private keys */
  450. return CKR_KEY_TYPE_INCONSISTENT;
  451. case ckcapiCert:
  452. if (iKey->objClass != CKO_PRIVATE_KEY) {
  453. /* Only private keys have private key provider handles */
  454. return CKR_KEY_TYPE_INCONSISTENT;
  455. }
  456. co = &iKey->u.cert;
  457. /* OK, get the Provider */
  458. rc = CryptAcquireCertificatePrivateKey(co->certContext,
  459. CRYPT_ACQUIRE_CACHE_FLAG|CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, hProv,
  460. keySpec, &dummy);
  461. if (!rc) {
  462. goto loser;
  463. }
  464. break;
  465. case ckcapiBareKey:
  466. if (iKey->objClass != CKO_PRIVATE_KEY) {
  467. /* Only private keys have private key provider handles */
  468. return CKR_KEY_TYPE_INCONSISTENT;
  469. }
  470. ko = &iKey->u.key;
  471. /* OK, get the Provider */
  472. if (0 == ko->hProv) {
  473. rc = CryptAcquireContext(hProv,
  474. ko->containerName,
  475. ko->provName,
  476. ko->provInfo.dwProvType , 0);
  477. if (!rc) {
  478. goto loser;
  479. }
  480. } else {
  481. *hProv = ko->hProv;
  482. }
  483. *keySpec = ko->provInfo.dwKeySpec;
  484. break;
  485. }
  486. /* and get the crypto handle */
  487. rc = CryptGetUserKey(*hProv, *keySpec, hKey);
  488. if (!rc) {
  489. goto loser;
  490. }
  491. return CKR_OK;
  492. loser:
  493. /* map the microsoft error before leaving */
  494. msError = GetLastError();
  495. switch (msError) {
  496. case ERROR_INVALID_HANDLE:
  497. case ERROR_INVALID_PARAMETER:
  498. case NTE_BAD_KEY:
  499. case NTE_NO_KEY:
  500. case NTE_BAD_PUBLIC_KEY:
  501. case NTE_BAD_KEYSET:
  502. case NTE_KEYSET_NOT_DEF:
  503. return CKR_KEY_TYPE_INCONSISTENT;
  504. case NTE_BAD_UID:
  505. case NTE_KEYSET_ENTRY_BAD:
  506. return CKR_DEVICE_ERROR;
  507. }
  508. return CKR_GENERAL_ERROR;
  509. }
  510. /*
  511. * take a DER PUBLIC Key block and return the modulus and exponent
  512. */
  513. static void
  514. ckcapi_CertPopulateModulusExponent
  515. (
  516. ckcapiInternalObject *io
  517. )
  518. {
  519. ckcapiKeyParams *kp = &io->u.cert.key;
  520. PCCERT_CONTEXT certContext = io->u.cert.certContext;
  521. unsigned char *pkData =
  522. certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData;
  523. unsigned int size=
  524. certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData;
  525. unsigned int newSize;
  526. unsigned char *ptr, *newptr;
  527. /* find the start of the modulus -- this will not give good results if
  528. * the key isn't an rsa key! */
  529. ptr = nss_ckcapi_DERUnwrap(pkData, size, &newSize, NULL);
  530. kp->modulus.data = nss_ckcapi_DERUnwrap(ptr, newSize,
  531. &kp->modulus.size, &newptr);
  532. /* changed from signed to unsigned int */
  533. if (0 == *(char *)kp->modulus.data) {
  534. kp->modulus.data = ((char *)kp->modulus.data)+1;
  535. kp->modulus.size = kp->modulus.size - 1;
  536. }
  537. /* changed from signed to unsigned int */
  538. kp->exponent.data = nss_ckcapi_DERUnwrap(newptr, (newptr-ptr)+newSize,
  539. &kp->exponent.size, NULL);
  540. if (0 == *(char *)kp->exponent.data) {
  541. kp->exponent.data = ((char *)kp->exponent.data)+1;
  542. kp->exponent.size = kp->exponent.size - 1;
  543. }
  544. return;
  545. }
  546. typedef struct _CAPI_RSA_KEY_BLOB {
  547. PUBLICKEYSTRUC header;
  548. RSAPUBKEY rsa;
  549. char data[1];
  550. } CAPI_RSA_KEY_BLOB;
  551. #define CAPI_MODULUS_OFFSET(modSize) 0
  552. #define CAPI_PRIME_1_OFFSET(modSize) (modSize)
  553. #define CAPI_PRIME_2_OFFSET(modSize) ((modSize)+(modSize)/2)
  554. #define CAPI_EXPONENT_1_OFFSET(modSize) ((modSize)*2)
  555. #define CAPI_EXPONENT_2_OFFSET(modSize) ((modSize)*2+(modSize)/2)
  556. #define CAPI_COEFFICIENT_OFFSET(modSize) ((modSize)*3)
  557. #define CAPI_PRIVATE_EXP_OFFSET(modSize) ((modSize)*3+(modSize)/2)
  558. void
  559. ckcapi_FetchPublicKey
  560. (
  561. ckcapiInternalObject *io
  562. )
  563. {
  564. ckcapiKeyParams *kp;
  565. HCRYPTPROV hProv;
  566. DWORD keySpec;
  567. HCRYPTKEY hKey = 0;
  568. CK_RV error;
  569. DWORD bufLen;
  570. BOOL rc;
  571. unsigned long modulus;
  572. char *buf = NULL;
  573. CAPI_RSA_KEY_BLOB *blob;
  574. error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey);
  575. if (CKR_OK != error) {
  576. goto loser;
  577. }
  578. kp = (ckcapiCert == io->type) ? &io->u.cert.key : &io->u.key.key;
  579. rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen);
  580. if (!rc) {
  581. goto loser;
  582. }
  583. buf = nss_ZNEWARRAY(NULL, char, bufLen);
  584. rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen);
  585. if (!rc) {
  586. goto loser;
  587. }
  588. /* validate the blob */
  589. blob = (CAPI_RSA_KEY_BLOB *)buf;
  590. if ((PUBLICKEYBLOB != blob->header.bType) ||
  591. (0x02 != blob->header.bVersion) ||
  592. (0x31415352 != blob->rsa.magic)) {
  593. goto loser;
  594. }
  595. modulus = blob->rsa.bitlen/8;
  596. kp->pubKey = buf;
  597. buf = NULL;
  598. kp->modulus.data = &blob->data[CAPI_MODULUS_OFFSET(modulus)];
  599. kp->modulus.size = modulus;
  600. ckcapi_ReverseData(&kp->modulus);
  601. nss_ckcapi_IntToData(blob->rsa.pubexp, &kp->exponent,
  602. kp->publicExponentData, &error);
  603. loser:
  604. nss_ZFreeIf(buf);
  605. if (0 != hKey) {
  606. CryptDestroyKey(hKey);
  607. }
  608. return;
  609. }
  610. void
  611. ckcapi_FetchPrivateKey
  612. (
  613. ckcapiInternalObject *io
  614. )
  615. {
  616. ckcapiKeyParams *kp;
  617. HCRYPTPROV hProv;
  618. DWORD keySpec;
  619. HCRYPTKEY hKey = 0;
  620. CK_RV error;
  621. DWORD bufLen;
  622. BOOL rc;
  623. unsigned long modulus;
  624. char *buf = NULL;
  625. CAPI_RSA_KEY_BLOB *blob;
  626. error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey);
  627. if (CKR_OK != error) {
  628. goto loser;
  629. }
  630. kp = (ckcapiCert == io->type) ? &io->u.cert.key : &io->u.key.key;
  631. rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen);
  632. if (!rc) {
  633. goto loser;
  634. }
  635. buf = nss_ZNEWARRAY(NULL, char, bufLen);
  636. rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen);
  637. if (!rc) {
  638. goto loser;
  639. }
  640. /* validate the blob */
  641. blob = (CAPI_RSA_KEY_BLOB *)buf;
  642. if ((PRIVATEKEYBLOB != blob->header.bType) ||
  643. (0x02 != blob->header.bVersion) ||
  644. (0x32415352 != blob->rsa.magic)) {
  645. goto loser;
  646. }
  647. modulus = blob->rsa.bitlen/8;
  648. kp->privateKey = buf;
  649. buf = NULL;
  650. kp->privateExponent.data = &blob->data[CAPI_PRIVATE_EXP_OFFSET(modulus)];
  651. kp->privateExponent.size = modulus;
  652. ckcapi_ReverseData(&kp->privateExponent);
  653. kp->prime1.data = &blob->data[CAPI_PRIME_1_OFFSET(modulus)];
  654. kp->prime1.size = modulus/2;
  655. ckcapi_ReverseData(&kp->prime1);
  656. kp->prime2.data = &blob->data[CAPI_PRIME_2_OFFSET(modulus)];
  657. kp->prime2.size = modulus/2;
  658. ckcapi_ReverseData(&kp->prime2);
  659. kp->exponent1.data = &blob->data[CAPI_EXPONENT_1_OFFSET(modulus)];
  660. kp->exponent1.size = modulus/2;
  661. ckcapi_ReverseData(&kp->exponent1);
  662. kp->exponent2.data = &blob->data[CAPI_EXPONENT_2_OFFSET(modulus)];
  663. kp->exponent2.size = modulus/2;
  664. ckcapi_ReverseData(&kp->exponent2);
  665. kp->coefficient.data = &blob->data[CAPI_COEFFICIENT_OFFSET(modulus)];
  666. kp->coefficient.size = modulus/2;
  667. ckcapi_ReverseData(&kp->coefficient);
  668. loser:
  669. nss_ZFreeIf(buf);
  670. if (0 != hKey) {
  671. CryptDestroyKey(hKey);
  672. }
  673. return;
  674. }
  675. void
  676. ckcapi_PopulateModulusExponent
  677. (
  678. ckcapiInternalObject *io
  679. )
  680. {
  681. if (ckcapiCert == io->type) {
  682. ckcapi_CertPopulateModulusExponent(io);
  683. } else {
  684. ckcapi_FetchPublicKey(io);
  685. }
  686. return;
  687. }
  688. /*
  689. * fetch the friendly name attribute.
  690. * can only be called with ckcapiCert type objects!
  691. */
  692. void
  693. ckcapi_FetchLabel
  694. (
  695. ckcapiInternalObject *io
  696. )
  697. {
  698. ckcapiCertObject *co = &io->u.cert;
  699. char *label;
  700. PCCERT_CONTEXT certContext = io->u.cert.certContext;
  701. char labelDataUTF16[128];
  702. DWORD size = sizeof(labelDataUTF16);
  703. DWORD size8 = sizeof(co->labelData);
  704. BOOL rv;
  705. rv = CertGetCertificateContextProperty(certContext,
  706. CERT_FRIENDLY_NAME_PROP_ID, labelDataUTF16, &size);
  707. if (rv) {
  708. co->labelData = nss_ckcapi_WideToUTF8((LPCWSTR)labelDataUTF16);
  709. if ((CHAR *)NULL == co->labelData) {
  710. rv = 0;
  711. } else {
  712. size = strlen(co->labelData);
  713. }
  714. }
  715. label = co->labelData;
  716. /* we are presuming a user cert, make sure it has a nickname, even if
  717. * Microsoft never gave it one */
  718. if (!rv && co->hasID) {
  719. DWORD mserror = GetLastError();
  720. #define DEFAULT_NICKNAME "no Microsoft nickname"
  721. label = DEFAULT_NICKNAME;
  722. size = sizeof(DEFAULT_NICKNAME);
  723. rv = 1;
  724. }
  725. if (rv) {
  726. co->label.data = label;
  727. co->label.size = size;
  728. }
  729. return;
  730. }
  731. void
  732. ckcapi_FetchSerial
  733. (
  734. ckcapiInternalObject *io
  735. )
  736. {
  737. ckcapiCertObject *co = &io->u.cert;
  738. PCCERT_CONTEXT certContext = io->u.cert.certContext;
  739. DWORD size = sizeof(co->derSerial);
  740. BOOL rc = CryptEncodeObject(X509_ASN_ENCODING,
  741. X509_MULTI_BYTE_INTEGER,
  742. &certContext->pCertInfo->SerialNumber,
  743. co->derSerial,
  744. &size);
  745. if (rc) {
  746. co->serial.data = co->derSerial;
  747. co->serial.size = size;
  748. }
  749. return;
  750. }
  751. /*
  752. * fetch the key ID.
  753. */
  754. void
  755. ckcapi_FetchID
  756. (
  757. ckcapiInternalObject *io
  758. )
  759. {
  760. PCCERT_CONTEXT certContext = io->u.cert.certContext;
  761. DWORD size = 0;
  762. BOOL rc;
  763. rc = CertGetCertificateContextProperty(certContext,
  764. CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
  765. if (!rc) {
  766. return;
  767. }
  768. io->idData = nss_ZNEWARRAY(NULL, char, size);
  769. if (io->idData == NULL) {
  770. return;
  771. }
  772. rc = CertGetCertificateContextProperty(certContext,
  773. CERT_KEY_IDENTIFIER_PROP_ID, io->idData, &size);
  774. if (!rc) {
  775. nss_ZFreeIf(io->idData);
  776. io->idData = NULL;
  777. return;
  778. }
  779. io->id.data = io->idData;
  780. io->id.size = size;
  781. return;
  782. }
  783. /*
  784. * fetch the hash key.
  785. */
  786. void
  787. ckcapi_CertFetchHashKey
  788. (
  789. ckcapiInternalObject *io
  790. )
  791. {
  792. ckcapiCertObject *co = &io->u.cert;
  793. PCCERT_CONTEXT certContext = io->u.cert.certContext;
  794. DWORD size = certContext->cbCertEncoded;
  795. DWORD max = sizeof(io->hashKeyData)-1;
  796. DWORD offset = 0;
  797. /* make sure we don't over flow. NOTE: cutting the top of a cert is
  798. * not a big issue because the signature for will be unique for the cert */
  799. if (size > max) {
  800. offset = size - max;
  801. size = max;
  802. }
  803. nsslibc_memcpy(io->hashKeyData,certContext->pbCertEncoded+offset, size);
  804. io->hashKeyData[size] = (char)(io->objClass & 0xff);
  805. io->hashKey.data = io->hashKeyData;
  806. io->hashKey.size = size+1;
  807. return;
  808. }
  809. /*
  810. * fetch the hash key.
  811. */
  812. void
  813. ckcapi_KeyFetchHashKey
  814. (
  815. ckcapiInternalObject *io
  816. )
  817. {
  818. ckcapiKeyObject *ko = &io->u.key;
  819. DWORD size;
  820. DWORD max = sizeof(io->hashKeyData)-2;
  821. DWORD offset = 0;
  822. DWORD provLen = strlen(ko->provName);
  823. DWORD containerLen = strlen(ko->containerName);
  824. size = provLen + containerLen;
  825. /* make sure we don't overflow, try to keep things unique */
  826. if (size > max) {
  827. DWORD diff = ((size - max)+1)/2;
  828. provLen -= diff;
  829. containerLen -= diff;
  830. size = provLen+containerLen;
  831. }
  832. nsslibc_memcpy(io->hashKeyData, ko->provName, provLen);
  833. nsslibc_memcpy(&io->hashKeyData[provLen],
  834. ko->containerName,
  835. containerLen);
  836. io->hashKeyData[size] = (char)(io->objClass & 0xff);
  837. io->hashKeyData[size+1] = (char)(ko->provInfo.dwKeySpec & 0xff);
  838. io->hashKey.data = io->hashKeyData;
  839. io->hashKey.size = size+2;
  840. return;
  841. }
  842. /*
  843. * fetch the hash key.
  844. */
  845. void
  846. ckcapi_FetchHashKey
  847. (
  848. ckcapiInternalObject *io
  849. )
  850. {
  851. if (ckcapiCert == io->type) {
  852. ckcapi_CertFetchHashKey(io);
  853. } else {
  854. ckcapi_KeyFetchHashKey(io);
  855. }
  856. return;
  857. }
  858. const NSSItem *
  859. ckcapi_FetchCertAttribute
  860. (
  861. ckcapiInternalObject *io,
  862. CK_ATTRIBUTE_TYPE type
  863. )
  864. {
  865. PCCERT_CONTEXT certContext = io->u.cert.certContext;
  866. switch(type) {
  867. case CKA_CLASS:
  868. return &ckcapi_certClassItem;
  869. case CKA_TOKEN:
  870. return &ckcapi_trueItem;
  871. case CKA_MODIFIABLE:
  872. case CKA_PRIVATE:
  873. return &ckcapi_falseItem;
  874. case CKA_CERTIFICATE_TYPE:
  875. return &ckcapi_x509Item;
  876. case CKA_LABEL:
  877. if (0 == io->u.cert.label.size) {
  878. ckcapi_FetchLabel(io);
  879. }
  880. return &io->u.cert.label;
  881. case CKA_SUBJECT:
  882. if (0 == io->u.cert.subject.size) {
  883. io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData;
  884. io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData;
  885. }
  886. return &io->u.cert.subject;
  887. case CKA_ISSUER:
  888. if (0 == io->u.cert.issuer.size) {
  889. io->u.cert.issuer.data = certContext->pCertInfo->Issuer.pbData;
  890. io->u.cert.issuer.size = certContext->pCertInfo->Issuer.cbData;
  891. }
  892. return &io->u.cert.issuer;
  893. case CKA_SERIAL_NUMBER:
  894. if (0 == io->u.cert.serial.size) {
  895. /* not exactly right. This should be the encoded serial number, but
  896. * it's the decoded serial number! */
  897. ckcapi_FetchSerial(io);
  898. }
  899. return &io->u.cert.serial;
  900. case CKA_VALUE:
  901. if (0 == io->u.cert.derCert.size) {
  902. io->u.cert.derCert.data = io->u.cert.certContext->pbCertEncoded;
  903. io->u.cert.derCert.size = io->u.cert.certContext->cbCertEncoded;
  904. }
  905. return &io->u.cert.derCert;
  906. case CKA_ID:
  907. if (!io->u.cert.hasID) {
  908. return NULL;
  909. }
  910. if (0 == io->id.size) {
  911. ckcapi_FetchID(io);
  912. }
  913. return &io->id;
  914. default:
  915. break;
  916. }
  917. return NULL;
  918. }
  919. const NSSItem *
  920. ckcapi_FetchPubKeyAttribute
  921. (
  922. ckcapiInternalObject *io,
  923. CK_ATTRIBUTE_TYPE type
  924. )
  925. {
  926. PRBool isCertType = (ckcapiCert == io->type);
  927. ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key;
  928. switch(type) {
  929. case CKA_CLASS:
  930. return &ckcapi_pubKeyClassItem;
  931. case CKA_TOKEN:
  932. case CKA_LOCAL:
  933. case CKA_ENCRYPT:
  934. case CKA_VERIFY:
  935. case CKA_VERIFY_RECOVER:
  936. return &ckcapi_trueItem;
  937. case CKA_PRIVATE:
  938. case CKA_MODIFIABLE:
  939. case CKA_DERIVE:
  940. case CKA_WRAP:
  941. return &ckcapi_falseItem;
  942. case CKA_KEY_TYPE:
  943. return &ckcapi_rsaItem;
  944. case CKA_LABEL:
  945. if (!isCertType) {
  946. return &ckcapi_emptyItem;
  947. }
  948. if (0 == io->u.cert.label.size) {
  949. ckcapi_FetchLabel(io);
  950. }
  951. return &io->u.cert.label;
  952. case CKA_SUBJECT:
  953. if (!isCertType) {
  954. return &ckcapi_emptyItem;
  955. }
  956. if (0 == io->u.cert.subject.size) {
  957. PCCERT_CONTEXT certContext= io->u.cert.certContext;
  958. io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData;
  959. io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData;
  960. }
  961. return &io->u.cert.subject;
  962. case CKA_MODULUS:
  963. if (0 == kp->modulus.size) {
  964. ckcapi_PopulateModulusExponent(io);
  965. }
  966. return &kp->modulus;
  967. case CKA_PUBLIC_EXPONENT:
  968. if (0 == kp->modulus.size) {
  969. ckcapi_PopulateModulusExponent(io);
  970. }
  971. return &kp->exponent;
  972. case CKA_ID:
  973. if (0 == io->id.size) {
  974. ckcapi_FetchID(io);
  975. }
  976. return &io->id;
  977. default:
  978. break;
  979. }
  980. return NULL;
  981. }
  982. const NSSItem *
  983. ckcapi_FetchPrivKeyAttribute
  984. (
  985. ckcapiInternalObject *io,
  986. CK_ATTRIBUTE_TYPE type
  987. )
  988. {
  989. PRBool isCertType = (ckcapiCert == io->type);
  990. ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key;
  991. switch(type) {
  992. case CKA_CLASS:
  993. return &ckcapi_privKeyClassItem;
  994. case CKA_TOKEN:
  995. case CKA_LOCAL:
  996. case CKA_SIGN:
  997. case CKA_DECRYPT:
  998. case CKA_SIGN_RECOVER:
  999. return &ckcapi_trueItem;
  1000. case CKA_SENSITIVE:
  1001. case CKA_PRIVATE: /* should move in the future */
  1002. case CKA_MODIFIABLE:
  1003. case CKA_DERIVE:
  1004. case CKA_UNWRAP:
  1005. case CKA_EXTRACTABLE: /* will probably move in the future */
  1006. case CKA_ALWAYS_SENSITIVE:
  1007. case CKA_NEVER_EXTRACTABLE:
  1008. return &ckcapi_falseItem;
  1009. case CKA_KEY_TYPE:
  1010. return &ckcapi_rsaItem;
  1011. case CKA_LABEL:
  1012. if (!isCertType) {
  1013. return &ckcapi_emptyItem;
  1014. }
  1015. if (0 == io->u.cert.label.size) {
  1016. ckcapi_FetchLabel(io);
  1017. }
  1018. return &io->u.cert.label;
  1019. case CKA_SUBJECT:
  1020. if (!isCertType) {
  1021. return &ckcapi_emptyItem;
  1022. }
  1023. if (0 == io->u.cert.subject.size) {
  1024. PCCERT_CONTEXT certContext= io->u.cert.certContext;
  1025. io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData;
  1026. io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData;
  1027. }
  1028. return &io->u.cert.subject;
  1029. case CKA_MODULUS:
  1030. if (0 == kp->modulus.size) {
  1031. ckcapi_PopulateModulusExponent(io);
  1032. }
  1033. return &kp->modulus;
  1034. case CKA_PUBLIC_EXPONENT:
  1035. if (0 == kp->modulus.size) {
  1036. ckcapi_PopulateModulusExponent(io);
  1037. }
  1038. return &kp->exponent;
  1039. case CKA_PRIVATE_EXPONENT:
  1040. if (0 == kp->privateExponent.size) {
  1041. ckcapi_FetchPrivateKey(io);
  1042. }
  1043. return &kp->privateExponent;
  1044. case CKA_PRIME_1:
  1045. if (0 == kp->privateExponent.size) {
  1046. ckcapi_FetchPrivateKey(io);
  1047. }
  1048. return &kp->prime1;
  1049. case CKA_PRIME_2:
  1050. if (0 == kp->privateExponent.size) {
  1051. ckcapi_FetchPrivateKey(io);
  1052. }
  1053. return &kp->prime2;
  1054. case CKA_EXPONENT_1:
  1055. if (0 == kp->privateExponent.size) {
  1056. ckcapi_FetchPrivateKey(io);
  1057. }
  1058. return &kp->exponent1;
  1059. case CKA_EXPONENT_2:
  1060. if (0 == kp->privateExponent.size) {
  1061. ckcapi_FetchPrivateKey(io);
  1062. }
  1063. return &kp->exponent2;
  1064. case CKA_COEFFICIENT:
  1065. if (0 == kp->privateExponent.size) {
  1066. ckcapi_FetchPrivateKey(io);
  1067. }
  1068. return &kp->coefficient;
  1069. case CKA_ID:
  1070. if (0 == io->id.size) {
  1071. ckcapi_FetchID(io);
  1072. }
  1073. return &io->id;
  1074. default:
  1075. return NULL;
  1076. }
  1077. }
  1078. const NSSItem *
  1079. nss_ckcapi_FetchAttribute
  1080. (
  1081. ckcapiInternalObject *io,
  1082. CK_ATTRIBUTE_TYPE type
  1083. )
  1084. {
  1085. CK_ULONG i;
  1086. if (io->type == ckcapiRaw) {
  1087. for( i = 0; i < io->u.raw.n; i++ ) {
  1088. if( type == io->u.raw.types[i] ) {
  1089. return &io->u.raw.items[i];
  1090. }
  1091. }
  1092. return NULL;
  1093. }
  1094. /* deal with the common attributes */
  1095. switch (io->objClass) {
  1096. case CKO_CERTIFICATE:
  1097. return ckcapi_FetchCertAttribute(io, type);
  1098. case CKO_PRIVATE_KEY:
  1099. return ckcapi_FetchPrivKeyAttribute(io, type);
  1100. case CKO_PUBLIC_KEY:
  1101. return ckcapi_FetchPubKeyAttribute(io, type);
  1102. }
  1103. return NULL;
  1104. }
  1105. /*
  1106. * check to see if the certificate already exists
  1107. */
  1108. static PRBool
  1109. ckcapi_cert_exists(
  1110. NSSItem *value,
  1111. ckcapiInternalObject **io
  1112. )
  1113. {
  1114. int count,i;
  1115. PRUint32 size = 0;
  1116. ckcapiInternalObject **listp = NULL;
  1117. CK_ATTRIBUTE myTemplate[2];
  1118. CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
  1119. CK_ULONG templateCount = 2;
  1120. CK_RV error;
  1121. PRBool found = PR_FALSE;
  1122. myTemplate[0].type = CKA_CLASS;
  1123. myTemplate[0].pValue = &cert_class;
  1124. myTemplate[0].ulValueLen = sizeof(cert_class);
  1125. myTemplate[1].type = CKA_VALUE;
  1126. myTemplate[1].pValue = value->data;
  1127. myTemplate[1].ulValueLen = value->size;
  1128. count = nss_ckcapi_collect_all_certs(myTemplate, templateCount, &listp,
  1129. &size, 0, &error);
  1130. /* free them */
  1131. if (count > 1) {
  1132. *io = listp[0];
  1133. found = PR_TRUE;
  1134. }
  1135. for (i=1; i < count; i++) {
  1136. nss_ckcapi_DestroyInternalObject(listp[i]);
  1137. }
  1138. nss_ZFreeIf(listp);
  1139. return found;
  1140. }
  1141. static PRBool
  1142. ckcapi_cert_hasEmail
  1143. (
  1144. PCCERT_CONTEXT certContext
  1145. )
  1146. {
  1147. int count;
  1148. count = CertGetNameString(certContext, CERT_NAME_EMAIL_TYPE,
  1149. 0, NULL, NULL, 0);
  1150. return count > 1 ? PR_TRUE : PR_FALSE;
  1151. }
  1152. static PRBool
  1153. ckcapi_cert_isRoot
  1154. (
  1155. PCCERT_CONTEXT certContext
  1156. )
  1157. {
  1158. return CertCompareCertificateName(certContext->dwCertEncodingType,
  1159. &certContext->pCertInfo->Issuer, &certContext->pCertInfo->Subject);
  1160. }
  1161. static PRBool
  1162. ckcapi_cert_isCA
  1163. (
  1164. PCCERT_CONTEXT certContext
  1165. )
  1166. {
  1167. PCERT_EXTENSION extension;
  1168. CERT_BASIC_CONSTRAINTS2_INFO basicInfo;
  1169. DWORD size = sizeof(basicInfo);
  1170. BOOL rc;
  1171. extension = CertFindExtension (szOID_BASIC_CONSTRAINTS,
  1172. certContext->pCertInfo->cExtension,
  1173. certContext->pCertInfo->rgExtension);
  1174. if ((PCERT_EXTENSION) NULL == extension ) {
  1175. return PR_FALSE;
  1176. }
  1177. rc = CryptDecodeObject(X509_ASN_ENCODING, szOID_BASIC_CONSTRAINTS2,
  1178. extension->Value.pbData, extension->Value.cbData,
  1179. 0, &basicInfo, &size);
  1180. if (!rc) {
  1181. return PR_FALSE;
  1182. }
  1183. return (PRBool) basicInfo.fCA;
  1184. }
  1185. static CRYPT_KEY_PROV_INFO *
  1186. ckcapi_cert_getPrivateKeyInfo
  1187. (
  1188. PCCERT_CONTEXT certContext,
  1189. NSSItem *keyID
  1190. )
  1191. {
  1192. BOOL rc;
  1193. CRYPT_HASH_BLOB msKeyID;
  1194. DWORD size = 0;
  1195. CRYPT_KEY_PROV_INFO *prov = NULL;
  1196. msKeyID.cbData = keyID->size;
  1197. msKeyID.pbData = keyID->data;
  1198. rc = CryptGetKeyIdentifierProperty(
  1199. &msKeyID,
  1200. CERT_KEY_PROV_INFO_PROP_ID,
  1201. 0, NULL, NULL, NULL, &size);
  1202. if (!rc) {
  1203. return (CRYPT_KEY_PROV_INFO *)NULL;
  1204. }
  1205. prov = (CRYPT_KEY_PROV_INFO *)nss_ZAlloc(NULL, size);
  1206. if ((CRYPT_KEY_PROV_INFO *)prov == NULL) {
  1207. return (CRYPT_KEY_PROV_INFO *) NULL;
  1208. }
  1209. rc = CryptGetKeyIdentifierProperty(
  1210. &msKeyID,
  1211. CERT_KEY_PROV_INFO_PROP_ID,
  1212. 0, NULL, NULL, prov, &size);
  1213. if (!rc) {
  1214. nss_ZFreeIf(prov);
  1215. return (CRYPT_KEY_PROV_INFO *)NULL;
  1216. }
  1217. return prov;
  1218. }
  1219. static CRYPT_KEY_PROV_INFO *
  1220. ckcapi_cert_getProvInfo
  1221. (
  1222. ckcapiInternalObject *io
  1223. )
  1224. {
  1225. BOOL rc;
  1226. DWORD size = 0;
  1227. CRYPT_KEY_PROV_INFO *prov = NULL;
  1228. rc = CertGetCertificateContextProperty(
  1229. io->u.cert.certContext,
  1230. CERT_KEY_PROV_INFO_PROP_ID,
  1231. NULL, &size);
  1232. if (!rc) {
  1233. return (CRYPT_KEY_PROV_INFO *)NULL;
  1234. }
  1235. prov = (CRYPT_KEY_PROV_INFO *)nss_ZAlloc(NULL, size);
  1236. if ((CRYPT_KEY_PROV_INFO *)prov == NULL) {
  1237. return (CRYPT_KEY_PROV_INFO *) NULL;
  1238. }
  1239. rc = CertGetCertificateContextProperty(
  1240. io->u.cert.certContext,
  1241. CERT_KEY_PROV_INFO_PROP_ID,
  1242. prov, &size);
  1243. if (!rc) {
  1244. nss_ZFreeIf(prov);
  1245. return (CRYPT_KEY_PROV_INFO *)NULL;
  1246. }
  1247. return prov;
  1248. }
  1249. /* forward declaration */
  1250. static void
  1251. ckcapi_removeObjectFromHash
  1252. (
  1253. ckcapiInternalObject *io
  1254. );
  1255. /*
  1256. * Finalize - unneeded
  1257. * Destroy
  1258. * IsTokenObject - CK_TRUE
  1259. * GetAttributeCount
  1260. * GetAttributeTypes
  1261. * GetAttributeSize
  1262. * GetAttribute
  1263. * SetAttribute
  1264. * GetObjectSize
  1265. */
  1266. static CK_RV
  1267. ckcapi_mdObject_Destroy
  1268. (
  1269. NSSCKMDObject *mdObject,
  1270. NSSCKFWObject *fwObject,
  1271. NSSCKMDSession *mdSession,
  1272. NSSCKFWSession *fwSession,
  1273. NSSCKMDToken *mdToken,
  1274. NSSCKFWToken *fwToken,
  1275. NSSCKMDInstance *mdInstance,
  1276. NSSCKFWInstance *fwInstance
  1277. )
  1278. {
  1279. ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
  1280. CK_OBJECT_CLASS objClass;
  1281. BOOL rc;
  1282. DWORD provType;
  1283. DWORD msError;
  1284. PRBool isCertType = (PRBool)(ckcapiCert == io->type);
  1285. HCERTSTORE hStore = 0;
  1286. if (ckcapiRaw == io->type) {
  1287. /* there is not 'object write protected' error, use the next best thing */
  1288. return CKR_TOKEN_WRITE_PROTECTED;
  1289. }
  1290. objClass = io->objClass;
  1291. if (CKO_CERTIFICATE == objClass) {
  1292. PCCERT_CONTEXT certContext;
  1293. /* get the store */
  1294. hStore = CertOpenSystemStore(0, io->u.cert.certStore);
  1295. if (0 == hStore) {
  1296. rc = 0;
  1297. goto loser;
  1298. }
  1299. certContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING, 0,
  1300. CERT_FIND_EXISTING, io->u.cert.certContext, NULL);
  1301. if ((PCCERT_CONTEXT)NULL == certContext) {
  1302. rc = 0;
  1303. goto loser;
  1304. }
  1305. rc = CertDeleteCertificateFromStore(certContext);
  1306. } else {
  1307. char *provName = NULL;
  1308. char *containerName = NULL;
  1309. HCRYPTPROV hProv;
  1310. CRYPT_HASH_BLOB msKeyID;
  1311. if (0 == io->id.size) {
  1312. ckcapi_FetchID(io);
  1313. }
  1314. if (isCertType) {
  1315. CRYPT_KEY_PROV_INFO * provInfo = ckcapi_cert_getProvInfo(io);
  1316. provName = nss_ckcapi_WideToUTF8(provInfo->pwszProvName);
  1317. containerName = nss_ckcapi_WideToUTF8(provInfo->pwszContainerName);
  1318. provType = provInfo->dwProvType;
  1319. nss_ZFreeIf(provInfo);
  1320. } else {
  1321. provName = io->u.key.provName;
  1322. containerName = io->u.key.containerName;
  1323. provType = io->u.key.provInfo.dwProvType;
  1324. io->u.key.provName = NULL;
  1325. io->u.key.containerName = NULL;
  1326. }
  1327. /* first remove the key id pointer */
  1328. msKeyID.cbData = io->id.size;
  1329. msKeyID.pbData = io->id.data;
  1330. rc = CryptSetKeyIdentifierProperty(&msKeyID,
  1331. CERT_KEY_PROV_INFO_PROP_ID, CRYPT_KEYID_DELETE_FLAG, NULL, NULL, NULL);
  1332. if (rc) {
  1333. rc = CryptAcquireContext(&hProv, containerName, provName, provType,
  1334. CRYPT_DELETEKEYSET);
  1335. }
  1336. nss_ZFreeIf(provName);
  1337. nss_ZFreeIf(containerName);
  1338. }
  1339. loser:
  1340. if (hStore) {
  1341. CertCloseStore(hStore, 0);
  1342. }
  1343. if (!rc) {
  1344. msError = GetLastError();
  1345. return CKR_GENERAL_ERROR;
  1346. }
  1347. /* remove it from the hash */
  1348. ckcapi_removeObjectFromHash(io);
  1349. /* free the puppy.. */
  1350. nss_ckcapi_DestroyInternalObject(io);
  1351. return CKR_OK;
  1352. }
  1353. static CK_BBOOL
  1354. ckcapi_mdObject_IsTokenObject
  1355. (
  1356. NSSCKMDObject *mdObject,
  1357. NSSCKFWObject *fwObject,
  1358. NSSCKMDSession *mdSession,
  1359. NSSCKFWSession *fwSession,
  1360. NSSCKMDToken *mdToken,
  1361. NSSCKFWToken *fwToken,
  1362. NSSCKMDInstance *mdInstance,
  1363. NSSCKFWInstance *fwInstance
  1364. )
  1365. {
  1366. return CK_TRUE;
  1367. }
  1368. static CK_ULONG
  1369. ckcapi_mdObject_GetAttributeCount
  1370. (
  1371. NSSCKMDObject *mdObject,
  1372. NSSCKFWObject *fwObject,
  1373. NSSCKMDSession *mdSession,
  1374. NSSCKFWSession *fwSession,
  1375. NSSCKMDToken *mdToken,
  1376. NSSCKFWToken *fwToken,
  1377. NSSCKMDInstance *mdInstance,
  1378. NSSCKFWInstance *fwInstance,
  1379. CK_RV *pError
  1380. )
  1381. {
  1382. ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
  1383. if (ckcapiRaw == io->type) {
  1384. return io->u.raw.n;
  1385. }
  1386. switch (io->objClass) {
  1387. case CKO_CERTIFICATE:
  1388. return certAttrsCount;
  1389. case CKO_PUBLIC_KEY:
  1390. return pubKeyAttrsCount;
  1391. case CKO_PRIVATE_KEY:
  1392. return privKeyAttrsCount;
  1393. default:
  1394. break;
  1395. }
  1396. return 0;
  1397. }
  1398. static CK_RV
  1399. ckcapi_mdObject_GetAttributeTypes
  1400. (
  1401. NSSCKMDObject *mdObject,
  1402. NSSCKFWObject *fwObject,
  1403. NSSCKMDSession *mdSession,
  1404. NSSCKFWSession *fwSession,
  1405. NSSCKMDToken *mdToken,
  1406. NSSCKFWToken *fwToken,
  1407. NSSCKMDInstance *mdInstance,
  1408. NSSCKFWInstance *fwInstance,
  1409. CK_ATTRIBUTE_TYPE_PTR typeArray,
  1410. CK_ULONG ulCount
  1411. )
  1412. {
  1413. ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
  1414. CK_ULONG i;
  1415. CK_RV error = CKR_OK;
  1416. const CK_ATTRIBUTE_TYPE *attrs = NULL;
  1417. CK_ULONG size = ckcapi_mdObject_GetAttributeCount(
  1418. mdObject, fwObject, mdSession, fwSession,
  1419. mdToken, fwToken, mdInstance, fwInstance, &error);
  1420. if( size != ulCount ) {
  1421. return CKR_BUFFER_TOO_SMALL;
  1422. }
  1423. if (io->type == ckcapiRaw) {
  1424. attrs = io->u.raw.types;
  1425. } else switch(io->objClass) {
  1426. case CKO_CERTIFICATE:
  1427. attrs = certAttrs;
  1428. break;
  1429. case CKO_PUBLIC_KEY:
  1430. attrs = pubKeyAttrs;
  1431. break;
  1432. case CKO_PRIVATE_KEY:
  1433. attrs = privKeyAttrs;
  1434. break;
  1435. default:
  1436. return CKR_OK;
  1437. }
  1438. for( i = 0; i < size; i++) {
  1439. typeArray[i] = attrs[i];
  1440. }
  1441. return CKR_OK;
  1442. }
  1443. static CK_ULONG
  1444. ckcapi_mdObject_GetAttributeSize
  1445. (
  1446. NSSCKMDObject *mdObject,
  1447. NSSCKFWObject *fwObject,
  1448. NSSCKMDSession *mdSession,
  1449. NSSCKFWSession *fwSession,
  1450. NSSCKMDToken *mdToken,
  1451. NSSCKFWToken *fwToken,
  1452. NSSCKMDInstance *mdInstance,
  1453. NSSCKFWInstance *fwInstance,
  1454. CK_ATTRIBUTE_TYPE attribute,
  1455. CK_RV *pError
  1456. )
  1457. {
  1458. ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
  1459. const NSSItem *b;
  1460. b = nss_ckcapi_FetchAttribute(io, attribute);
  1461. if ((const NSSItem *)NULL == b) {
  1462. *pError = CKR_ATTRIBUTE_TYPE_INVALID;
  1463. return 0;
  1464. }
  1465. return b->size;
  1466. }
  1467. static CK_RV
  1468. ckcapi_mdObject_SetAttribute
  1469. (
  1470. NSSCKMDObject *mdObject,
  1471. NSSCKFWObject *fwObject,
  1472. NSSCKMDSession *mdSession,
  1473. NSSCKFWSession *fwSession,
  1474. NSSCKMDToken *mdToken,
  1475. NSSCKFWToken *fwToken,
  1476. NSSCKMDInstance *mdInstance,
  1477. NSSCKFWInstance *fwInstance,
  1478. CK_ATTRIBUTE_TYPE attribute,
  1479. NSSItem *value
  1480. )
  1481. {
  1482. return CKR_OK;
  1483. }
  1484. static NSSCKFWItem
  1485. ckcapi_mdObject_GetAttribute
  1486. (
  1487. NSSCKMDObject *mdObject,
  1488. NSSCKFWObject *fwObject,
  1489. NSSCKMDSession *mdSession,
  1490. NSSCKFWSession *fwSession,
  1491. NSSCKMDToken *mdToken,
  1492. NSSCKFWToken *fwToken,
  1493. NSSCKMDInstance *mdInstance,
  1494. NSSCKFWInstance *fwInstance,
  1495. CK_ATTRIBUTE_TYPE attribute,
  1496. CK_RV *pError
  1497. )
  1498. {
  1499. NSSCKFWItem mdItem;
  1500. ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
  1501. mdItem.needsFreeing = PR_FALSE;
  1502. mdItem.item = (NSSItem*)nss_ckcapi_FetchAttribute(io, attribute);
  1503. if ((NSSItem *)NULL == mdItem.item) {
  1504. *pError = CKR_ATTRIBUTE_TYPE_INVALID;
  1505. }
  1506. return mdItem;
  1507. }
  1508. static CK_ULONG
  1509. ckcapi_mdObject_GetObjectSize
  1510. (
  1511. NSSCKMDObject *mdObject,
  1512. NSSCKFWObject *fwObject,
  1513. NSSCKMDSession *mdSession,
  1514. NSSCKFWSession *fwSession,
  1515. NSSCKMDToken *mdToken,
  1516. NSSCKFWToken *fwToken,
  1517. NSSCKMDInstance *mdInstance,
  1518. NSSCKFWInstance *fwInstance,
  1519. CK_RV *pError
  1520. )
  1521. {
  1522. ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
  1523. CK_ULONG rv = 1;
  1524. /* size is irrelevant to this token */
  1525. return rv;
  1526. }
  1527. static const NSSCKMDObject
  1528. ckcapi_prototype_mdObject = {
  1529. (void *)NULL, /* etc */
  1530. NULL, /* Finalize */
  1531. ckcapi_mdObject_Destroy,
  1532. ckcapi_mdObject_IsTokenObject,
  1533. ckcapi_mdObject_GetAttributeCount,
  1534. ckcapi_mdObject_GetAttributeTypes,
  1535. ckcapi_mdObject_GetAttributeSize,
  1536. ckcapi_mdObject_GetAttribute,
  1537. NULL, /* FreeAttribute */
  1538. ckcapi_mdObject_SetAttribute,
  1539. ckcapi_mdObject_GetObjectSize,
  1540. (void *)NULL /* null terminator */
  1541. };
  1542. static nssHash *ckcapiInternalObjectHash = NULL;
  1543. NSS_IMPLEMENT NSSCKMDObject *
  1544. nss_ckcapi_CreateMDObject
  1545. (
  1546. NSSArena *arena,
  1547. ckcapiInternalObject *io,
  1548. CK_RV *pError
  1549. )
  1550. {
  1551. if ((nssHash *)NULL == ckcapiInternalObjectHash) {
  1552. ckcapiInternalObjectHash = nssHash_CreateItem(NULL, 10);
  1553. }
  1554. if (ckcapiCert == io->type) {
  1555. /* the hash key, not a cryptographic key */
  1556. NSSItem *key = &io->hashKey;
  1557. ckcapiInternalObject *old_o = NULL;
  1558. if (key->size == 0) {
  1559. ckcapi_FetchHashKey(io);
  1560. }
  1561. old_o = (ckcapiInternalObject *)
  1562. nssHash_Lookup(ckcapiInternalObjectHash, key);
  1563. if (!old_o) {
  1564. nssHash_Add(ckcapiInternalObjectHash, key, io);
  1565. } else if (old_o != io) {
  1566. nss_ckcapi_DestroyInternalObject(io);
  1567. io = old_o;
  1568. }
  1569. }
  1570. if ( (void*)NULL == io->mdObject.etc) {
  1571. (void) nsslibc_memcpy(&io->mdObject,&ckcapi_prototype_mdObject,
  1572. sizeof(ckcapi_prototype_mdObject));
  1573. io->mdObject.etc = (void *)io;
  1574. }
  1575. return &io->mdObject;
  1576. }
  1577. static void
  1578. ckcapi_removeObjectFromHash
  1579. (
  1580. ckcapiInternalObject *io
  1581. )
  1582. {
  1583. NSSItem *key = &io->hashKey;
  1584. if ((nssHash *)NULL == ckcapiInternalObjectHash) {
  1585. return;
  1586. }
  1587. if (key->size == 0) {
  1588. ckcapi_FetchHashKey(io);
  1589. }
  1590. nssHash_Remove(ckcapiInternalObjectHash, key);
  1591. return;
  1592. }
  1593. void
  1594. nss_ckcapi_DestroyInternalObject
  1595. (
  1596. ckcapiInternalObject *io
  1597. )
  1598. {
  1599. switch (io->type) {
  1600. case ckcapiRaw:
  1601. return;
  1602. case ckcapiCert:
  1603. CertFreeCertificateContext(io->u.cert.certContext);
  1604. nss_ZFreeIf(io->u.cert.labelData);
  1605. nss_ZFreeIf(io->u.cert.key.privateKey);
  1606. nss_ZFreeIf(io->u.cert.key.pubKey);
  1607. nss_ZFreeIf(io->idData);
  1608. break;
  1609. case ckcapiBareKey:
  1610. nss_ZFreeIf(io->u.key.provInfo.pwszContainerName);
  1611. nss_ZFreeIf(io->u.key.provInfo.pwszProvName);
  1612. nss_ZFreeIf(io->u.key.provName);
  1613. nss_ZFreeIf(io->u.key.containerName);
  1614. nss_ZFreeIf(io->u.key.key.privateKey);
  1615. nss_ZFreeIf(io->u.key.key.pubKey);
  1616. if (0 != io->u.key.hProv) {
  1617. CryptReleaseContext(io->u.key.hProv, 0);
  1618. }
  1619. nss_ZFreeIf(io->idData);
  1620. break;
  1621. }
  1622. nss_ZFreeIf(io);
  1623. return;
  1624. }
  1625. static ckcapiInternalObject *
  1626. nss_ckcapi_CreateCertificate
  1627. (
  1628. NSSCKFWSession *fwSession,
  1629. CK_ATTRIBUTE_PTR pTemplate,
  1630. CK_ULONG ulAttributeCount,
  1631. CK_RV *pError
  1632. )
  1633. {
  1634. NSSItem value;
  1635. NSSItem keyID;
  1636. char *storeStr;
  1637. ckcapiInternalObject *io = NULL;
  1638. PCCERT_CONTEXT certContext = NULL;
  1639. PCCERT_CONTEXT storedCertContext = NULL;
  1640. CRYPT_KEY_PROV_INFO *prov_info = NULL;
  1641. char *nickname = NULL;
  1642. HCERTSTORE hStore = 0;
  1643. DWORD msError = 0;
  1644. PRBool hasID;
  1645. CK_RV dummy;
  1646. BOOL rc;
  1647. *pError = nss_ckcapi_GetAttribute(CKA_VALUE, pTemplate,
  1648. ulAttributeCount, &value);
  1649. if (CKR_OK != *pError) {
  1650. return (ckcapiInternalObject *)NULL;
  1651. }
  1652. *pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate,
  1653. ulAttributeCount, &keyID);
  1654. if (CKR_OK != *pError) {
  1655. return (ckcapiInternalObject *)NULL;
  1656. }
  1657. if (ckcapi_cert_exists(&value, &io)) {
  1658. return io;
  1659. }
  1660. /* OK, we are creating a new one, figure out what store it belongs to..
  1661. * first get a certContext handle.. */
  1662. certContext = CertCreateCertificateContext(X509_ASN_ENCODING,
  1663. value.data, value.size);
  1664. if ((PCCERT_CONTEXT) NULL == certContext) {
  1665. msError = GetLastError();
  1666. *pError = CKR_ATTRIBUTE_VALUE_INVALID;
  1667. goto loser;
  1668. }
  1669. /* do we have a private key laying around... */
  1670. prov_info = ckcapi_cert_getPrivateKeyInfo(certContext, &keyID);
  1671. if (prov_info) {
  1672. CRYPT_DATA_BLOB msKeyID;
  1673. storeStr = "My";
  1674. hasID = PR_TRUE;
  1675. rc = CertSetCertificateContextProperty(certContext,
  1676. CERT_KEY_PROV_INFO_PROP_ID,
  1677. 0, prov_info);
  1678. nss_ZFreeIf(prov_info);
  1679. if (!rc) {
  1680. msError = GetLastError();
  1681. *pError = CKR_DEVICE_ERROR;
  1682. goto loser;
  1683. }
  1684. msKeyID.cbData = keyID.size;
  1685. msKeyID.pbData = keyID.data;
  1686. rc = CertSetCertificateContextProperty(certContext,
  1687. CERT_KEY_IDENTIFIER_PROP_ID,
  1688. 0, &msKeyID);
  1689. if (!rc) {
  1690. msError = GetLastError();
  1691. *pError = CKR_DEVICE_ERROR;
  1692. goto loser;
  1693. }
  1694. /* does it look like a CA */
  1695. } else if (ckcapi_cert_isCA(certContext)) {
  1696. storeStr = ckcapi_cert_isRoot(certContext) ? "CA" : "Root";
  1697. /* does it look like an S/MIME cert */
  1698. } else if (ckcapi_cert_hasEmail(certContext)) {
  1699. storeStr = "AddressBook";
  1700. } else {
  1701. /* just pick a store */
  1702. storeStr = "CA";
  1703. }
  1704. /* get the nickname, not an error if we can't find it */
  1705. nickname = nss_ckcapi_GetStringAttribute(CKA_LABEL, pTemplate,
  1706. ulAttributeCount, &dummy);
  1707. if (nickname) {
  1708. LPWSTR nicknameUTF16 = NULL;
  1709. CRYPT_DATA_BLOB nicknameBlob;
  1710. nicknameUTF16 = nss_ckcapi_UTF8ToWide(nickname);
  1711. nss_ZFreeIf(nickname);
  1712. nickname = NULL;
  1713. if ((LPWSTR)NULL == nicknameUTF16) {
  1714. *pError = CKR_HOST_MEMORY;
  1715. goto loser;
  1716. }
  1717. nicknameBlob.cbData = nss_ckcapi_WideSize(nicknameUTF16);
  1718. nicknameBlob.pbData = (BYTE *)nicknameUTF16;
  1719. rc = CertSetCertificateContextProperty(certContext,
  1720. CERT_FRIENDLY_NAME_PROP_ID, 0, &nicknameBlob);
  1721. nss_ZFreeIf(nicknameUTF16);
  1722. if (!rc) {
  1723. msError = GetLastError();
  1724. *pError = CKR_DEVICE_ERROR;
  1725. goto loser;
  1726. }
  1727. }
  1728. hStore = CertOpenSystemStore((HCRYPTPROV) NULL, storeStr);
  1729. if (0 == hStore) {
  1730. msError = GetLastError();
  1731. *pError = CKR_DEVICE_ERROR;
  1732. goto loser;
  1733. }
  1734. rc = CertAddCertificateContextToStore(hStore, certContext,
  1735. CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES, &storedCertContext);
  1736. CertFreeCertificateContext(certContext);
  1737. certContext = NULL;
  1738. CertCloseStore(hStore, 0);
  1739. hStore = 0;
  1740. if (!rc) {
  1741. msError = GetLastError();
  1742. *pError = CKR_DEVICE_ERROR;
  1743. goto loser;
  1744. }
  1745. io = nss_ZNEW(NULL, ckcapiInternalObject);
  1746. if ((ckcapiInternalObject *)NULL == io) {
  1747. *pError = CKR_HOST_MEMORY;
  1748. goto loser;
  1749. }
  1750. io->type = ckcapiCert;
  1751. io->objClass = CKO_CERTIFICATE;
  1752. io->u.cert.certContext = storedCertContext;
  1753. io->u.cert.hasID = hasID;
  1754. return io;
  1755. loser:
  1756. if (certContext) {
  1757. CertFreeCertificateContext(certContext);
  1758. certContext = NULL;
  1759. }
  1760. if (storedCertContext) {
  1761. CertFreeCertificateContext(storedCertContext);
  1762. storedCertContext = NULL;
  1763. }
  1764. if (0 != hStore) {
  1765. CertCloseStore(hStore, 0);
  1766. }
  1767. return (ckcapiInternalObject *)NULL;
  1768. }
  1769. static char *
  1770. ckcapi_getDefaultProvider
  1771. (
  1772. CK_RV *pError
  1773. )
  1774. {
  1775. char *name = NULL;
  1776. BOOL rc;
  1777. DWORD nameLength = 0;
  1778. rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, NULL,
  1779. &nameLength);
  1780. if (!rc) {
  1781. return (char *)NULL;
  1782. }
  1783. name = nss_ZNEWARRAY(NULL, char, nameLength);
  1784. if ((char *)NULL == name ) {
  1785. return (char *)NULL;
  1786. }
  1787. rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, name,
  1788. &nameLength);
  1789. if (!rc) {
  1790. nss_ZFreeIf(name);
  1791. return (char *)NULL;
  1792. }
  1793. return name;
  1794. }
  1795. static char *
  1796. ckcapi_getContainer
  1797. (
  1798. CK_RV *pError,
  1799. NSSItem *id
  1800. )
  1801. {
  1802. RPC_STATUS rstat;
  1803. UUID uuid;
  1804. char *uuidStr;
  1805. char *container;
  1806. rstat = UuidCreate(&uuid);
  1807. rstat = UuidToString(&uuid, &uuidStr);
  1808. /* convert it from rcp memory to our own */
  1809. container = nssUTF8_Duplicate(uuidStr, NULL);
  1810. RpcStringFree(&uuidStr);
  1811. return container;
  1812. }
  1813. static CK_RV
  1814. ckcapi_buildPrivateKeyBlob
  1815. (
  1816. NSSItem *keyBlob,
  1817. NSSItem *modulus,
  1818. NSSItem *publicExponent,
  1819. NSSItem *privateExponent,
  1820. NSSItem *prime1,
  1821. NSSItem *prime2,
  1822. NSSItem *exponent1,
  1823. NSSItem *exponent2,
  1824. NSSItem *coefficient,
  1825. PRBool isKeyExchange
  1826. )
  1827. {
  1828. CAPI_RSA_KEY_BLOB *keyBlobData = NULL;
  1829. unsigned char *target;
  1830. unsigned long modSize = modulus->size;
  1831. unsigned long dataSize;
  1832. CK_RV error = CKR_OK;
  1833. /* validate extras */
  1834. if (privateExponent->size != modSize) {
  1835. error = CKR_ATTRIBUTE_VALUE_INVALID;
  1836. goto loser;
  1837. }
  1838. if (prime1->size != modSize/2) {
  1839. error = CKR_ATTRIBUTE_VALUE_INVALID;
  1840. goto loser;
  1841. }
  1842. if (prime2->size != modSize/2) {
  1843. error = CKR_ATTRIBUTE_VALUE_INVALID;
  1844. goto loser;
  1845. }
  1846. if (exponent1->size != modSize/2) {
  1847. error = CKR_ATTRIBUTE_VALUE_INVALID;
  1848. goto loser;
  1849. }
  1850. if (exponent2->size != modSize/2) {
  1851. error = CKR_ATTRIBUTE_VALUE_INVALID;
  1852. goto loser;
  1853. }
  1854. if (coefficient->size != modSize/2) {
  1855. error = CKR_ATTRIBUTE_VALUE_INVALID;
  1856. goto loser;
  1857. }
  1858. dataSize = (modSize*4)+(modSize/2) + sizeof(CAPI_RSA_KEY_BLOB);
  1859. keyBlobData = (CAPI_RSA_KEY_BLOB *)nss_ZAlloc(NULL, dataSize);
  1860. if ((CAPI_RSA_KEY_BLOB *)NULL == keyBlobData) {
  1861. error = CKR_HOST_MEMORY;
  1862. goto loser;
  1863. }
  1864. keyBlobData->header.bType = PRIVATEKEYBLOB;
  1865. keyBlobData->header.bVersion = 0x02;
  1866. keyBlobData->header.reserved = 0x00;
  1867. keyBlobData->header.aiKeyAlg = isKeyExchange ? CALG_RSA_KEYX:CALG_RSA_SIGN;
  1868. keyBlobData->rsa.magic = 0x32415352;
  1869. keyBlobData->rsa.bitlen = modSize * 8;
  1870. keyBlobData->rsa.pubexp = nss_ckcapi_DataToInt(publicExponent,&error);
  1871. if (CKR_OK != error) {
  1872. goto loser;
  1873. }
  1874. target = &keyBlobData->data[CAPI_MODULUS_OFFSET(modSize)];
  1875. nsslibc_memcpy(target, modulus->data, modulus->size);
  1876. modulus->data = target;
  1877. ckcapi_ReverseData(modulus);
  1878. target = &keyBlobData->data[CAPI_PRIVATE_EXP_OFFSET(modSize)];
  1879. nsslibc_memcpy(target, privateExponent->data, privateExponent->size);
  1880. privateExponent->data = target;
  1881. ckcapi_ReverseData(privateExponent);
  1882. target = &keyBlobData->data[CAPI_PRIME_1_OFFSET(modSize)];
  1883. nsslibc_memcpy(target, prime1->data, prime1->size);
  1884. prime1->data = target;
  1885. ckcapi_ReverseData(prime1);
  1886. target = &keyBlobData->data[CAPI_PRIME_2_OFFSET(modSize)];
  1887. nsslibc_memcpy(target, prime2->data, prime2->size);
  1888. prime2->data = target;
  1889. ckcapi_ReverseData(prime2);
  1890. target = &keyBlobData->data[CAPI_EXPONENT_1_OFFSET(modSize)];
  1891. nsslibc_memcpy(target, exponent1->data, exponent1->size);
  1892. exponent1->data = target;
  1893. ckcapi_ReverseData(exponent1);
  1894. target = &keyBlobData->data[CAPI_EXPONENT_2_OFFSET(modSize)];
  1895. nsslibc_memcpy(target, exponent2->data, exponent2->size);
  1896. exponent2->data = target;
  1897. ckcapi_ReverseData(exponent2);
  1898. target = &keyBlobData->data[CAPI_COEFFICIENT_OFFSET(modSize)];
  1899. nsslibc_memcpy(target, coefficient->data, coefficient->size);
  1900. coefficient->data = target;
  1901. ckcapi_ReverseData(coefficient);
  1902. keyBlob->data = keyBlobData;
  1903. keyBlob->size = dataSize;
  1904. return CKR_OK;
  1905. loser:
  1906. nss_ZFreeIf(keyBlobData);
  1907. return error;
  1908. }
  1909. static ckcapiInternalObject *
  1910. nss_ckcapi_CreatePrivateKey
  1911. (
  1912. NSSCKFWSession *fwSession,
  1913. CK_ATTRIBUTE_PTR pTemplate,
  1914. CK_ULONG ulAttributeCount,
  1915. CK_RV *pError
  1916. )
  1917. {
  1918. NSSItem modulus;
  1919. NSSItem publicExponent;
  1920. NSSItem privateExponent;
  1921. NSSItem exponent1;
  1922. NSSItem exponent2;
  1923. NSSItem prime1;
  1924. NSSItem prime2;
  1925. NSSItem coefficient;
  1926. NSSItem keyID;
  1927. NSSItem keyBlob;
  1928. ckcapiInternalObject *io = NULL;
  1929. char *providerName = NULL;
  1930. char *contai