/security/nss/lib/ckfw/dbm/db.c

http://github.com/zpao/v8monkey · C · 1068 lines · 857 code · 154 blank · 57 comment · 188 complexity · 4fc1062af43b8f97ff3471b02120fb9c MD5 · raw 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. *
  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: db.c,v $ $Revision: 1.6 $ $Date: 2006/03/02 22:48:54 $";
  38. #endif /* DEBUG */
  39. #include "ckdbm.h"
  40. #define PREFIX_METADATA "0000"
  41. #define PREFIX_OBJECT "0001"
  42. #define PREFIX_INDEX "0002"
  43. static CK_VERSION nss_dbm_db_format_version = { 1, 0 };
  44. struct handle {
  45. char prefix[4];
  46. CK_ULONG id;
  47. };
  48. NSS_IMPLEMENT nss_dbm_db_t *
  49. nss_dbm_db_open
  50. (
  51. NSSArena *arena,
  52. NSSCKFWInstance *fwInstance,
  53. char *filename,
  54. int flags,
  55. CK_RV *pError
  56. )
  57. {
  58. nss_dbm_db_t *rv;
  59. CK_VERSION db_version;
  60. rv = nss_ZNEW(arena, nss_dbm_db_t);
  61. if( (nss_dbm_db_t *)NULL == rv ) {
  62. *pError = CKR_HOST_MEMORY;
  63. return (nss_dbm_db_t *)NULL;
  64. }
  65. rv->db = dbopen(filename, flags, 0600, DB_HASH, (const void *)NULL);
  66. if( (DB *)NULL == rv->db ) {
  67. *pError = CKR_TOKEN_NOT_PRESENT;
  68. return (nss_dbm_db_t *)NULL;
  69. }
  70. rv->crustylock = NSSCKFWInstance_CreateMutex(fwInstance, arena, pError);
  71. if( (NSSCKFWMutex *)NULL == rv->crustylock ) {
  72. return (nss_dbm_db_t *)NULL;
  73. }
  74. db_version = nss_dbm_db_get_format_version(rv);
  75. if( db_version.major != nss_dbm_db_format_version.major ) {
  76. nss_dbm_db_close(rv);
  77. *pError = CKR_TOKEN_NOT_RECOGNIZED;
  78. return (nss_dbm_db_t *)NULL;
  79. }
  80. return rv;
  81. }
  82. NSS_IMPLEMENT void
  83. nss_dbm_db_close
  84. (
  85. nss_dbm_db_t *db
  86. )
  87. {
  88. if( (NSSCKFWMutex *)NULL != db->crustylock ) {
  89. (void)NSSCKFWMutex_Destroy(db->crustylock);
  90. }
  91. if( (DB *)NULL != db->db ) {
  92. (void)db->db->close(db->db);
  93. }
  94. nss_ZFreeIf(db);
  95. }
  96. NSS_IMPLEMENT CK_VERSION
  97. nss_dbm_db_get_format_version
  98. (
  99. nss_dbm_db_t *db
  100. )
  101. {
  102. CK_VERSION rv;
  103. DBT k, v;
  104. int dbrv;
  105. char buffer[64];
  106. rv.major = rv.minor = 0;
  107. k.data = PREFIX_METADATA "FormatVersion";
  108. k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL);
  109. (void)memset(&v, 0, sizeof(v));
  110. /* Locked region */
  111. {
  112. if( CKR_OK != NSSCKFWMutex_Lock(db->crustylock) ) {
  113. return rv;
  114. }
  115. dbrv = db->db->get(db->db, &k, &v, 0);
  116. if( dbrv == 0 ) {
  117. CK_ULONG major = 0, minor = 0;
  118. (void)PR_sscanf(v.data, "%ld.%ld", &major, &minor);
  119. rv.major = major;
  120. rv.minor = minor;
  121. } else if( dbrv > 0 ) {
  122. (void)PR_snprintf(buffer, sizeof(buffer), "%ld.%ld", nss_dbm_db_format_version.major,
  123. nss_dbm_db_format_version.minor);
  124. v.data = buffer;
  125. v.size = nssUTF8_Size((NSSUTF8 *)v.data, (PRStatus *)NULL);
  126. dbrv = db->db->put(db->db, &k, &v, 0);
  127. (void)db->db->sync(db->db, 0);
  128. rv = nss_dbm_db_format_version;
  129. } else {
  130. /* No error return.. */
  131. ;
  132. }
  133. (void)NSSCKFWMutex_Unlock(db->crustylock);
  134. }
  135. return rv;
  136. }
  137. NSS_IMPLEMENT CK_RV
  138. nss_dbm_db_set_label
  139. (
  140. nss_dbm_db_t *db,
  141. NSSUTF8 *label
  142. )
  143. {
  144. CK_RV rv;
  145. DBT k, v;
  146. int dbrv;
  147. k.data = PREFIX_METADATA "Label";
  148. k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL);
  149. v.data = label;
  150. v.size = nssUTF8_Size((NSSUTF8 *)v.data, (PRStatus *)NULL);
  151. /* Locked region */
  152. {
  153. if( CKR_OK != NSSCKFWMutex_Lock(db->crustylock) ) {
  154. return rv;
  155. }
  156. dbrv = db->db->put(db->db, &k, &v, 0);
  157. if( 0 != dbrv ) {
  158. rv = CKR_DEVICE_ERROR;
  159. }
  160. dbrv = db->db->sync(db->db, 0);
  161. if( 0 != dbrv ) {
  162. rv = CKR_DEVICE_ERROR;
  163. }
  164. (void)NSSCKFWMutex_Unlock(db->crustylock);
  165. }
  166. return rv;
  167. }
  168. NSS_IMPLEMENT NSSUTF8 *
  169. nss_dbm_db_get_label
  170. (
  171. nss_dbm_db_t *db,
  172. NSSArena *arena,
  173. CK_RV *pError
  174. )
  175. {
  176. NSSUTF8 *rv = (NSSUTF8 *)NULL;
  177. DBT k, v;
  178. int dbrv;
  179. k.data = PREFIX_METADATA "Label";
  180. k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL);
  181. /* Locked region */
  182. {
  183. if( CKR_OK != NSSCKFWMutex_Lock(db->crustylock) ) {
  184. return rv;
  185. }
  186. dbrv = db->db->get(db->db, &k, &v, 0);
  187. if( 0 == dbrv ) {
  188. rv = nssUTF8_Duplicate((NSSUTF8 *)v.data, arena);
  189. if( (NSSUTF8 *)NULL == rv ) {
  190. *pError = CKR_HOST_MEMORY;
  191. }
  192. } else if( dbrv > 0 ) {
  193. /* Just return null */
  194. ;
  195. } else {
  196. *pError = CKR_DEVICE_ERROR;
  197. ;
  198. }
  199. (void)NSSCKFWMutex_Unlock(db->crustylock);
  200. }
  201. return rv;
  202. }
  203. NSS_IMPLEMENT CK_RV
  204. nss_dbm_db_delete_object
  205. (
  206. nss_dbm_dbt_t *dbt
  207. )
  208. {
  209. CK_RV rv;
  210. int dbrv;
  211. /* Locked region */
  212. {
  213. rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
  214. if( CKR_OK != rv ) {
  215. return rv;
  216. }
  217. dbrv = dbt->my_db->db->del(dbt->my_db->db, &dbt->dbt, 0);
  218. if( 0 != dbrv ) {
  219. rv = CKR_DEVICE_ERROR;
  220. goto done;
  221. }
  222. dbrv = dbt->my_db->db->sync(dbt->my_db->db, 0);
  223. if( 0 != dbrv ) {
  224. rv = CKR_DEVICE_ERROR;
  225. goto done;
  226. }
  227. done:
  228. (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
  229. }
  230. return rv;
  231. }
  232. static CK_ULONG
  233. nss_dbm_db_new_handle
  234. (
  235. nss_dbm_db_t *db,
  236. DBT *dbt, /* pre-allocated */
  237. CK_RV *pError
  238. )
  239. {
  240. CK_ULONG rv;
  241. DBT k, v;
  242. CK_ULONG align = 0, id, myid;
  243. struct handle *hp;
  244. if( sizeof(struct handle) != dbt->size ) {
  245. return EINVAL;
  246. }
  247. /* Locked region */
  248. {
  249. *pError = NSSCKFWMutex_Lock(db->crustylock);
  250. if( CKR_OK != *pError ) {
  251. return EINVAL;
  252. }
  253. k.data = PREFIX_METADATA "LastID";
  254. k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL);
  255. (void)memset(&v, 0, sizeof(v));
  256. rv = db->db->get(db->db, &k, &v, 0);
  257. if( 0 == rv ) {
  258. (void)memcpy(&align, v.data, sizeof(CK_ULONG));
  259. id = ntohl(align);
  260. } else if( rv > 0 ) {
  261. id = 0;
  262. } else {
  263. goto done;
  264. }
  265. myid = id;
  266. id++;
  267. align = htonl(id);
  268. v.data = &align;
  269. v.size = sizeof(CK_ULONG);
  270. rv = db->db->put(db->db, &k, &v, 0);
  271. if( 0 != rv ) {
  272. goto done;
  273. }
  274. rv = db->db->sync(db->db, 0);
  275. if( 0 != rv ) {
  276. goto done;
  277. }
  278. done:
  279. (void)NSSCKFWMutex_Unlock(db->crustylock);
  280. }
  281. if( 0 != rv ) {
  282. return rv;
  283. }
  284. hp = (struct handle *)dbt->data;
  285. (void)memcpy(&hp->prefix[0], PREFIX_OBJECT, 4);
  286. hp->id = myid;
  287. return 0;
  288. }
  289. /*
  290. * This attribute-type-dependent swapping should probably
  291. * be in the Framework, because it'll be a concern of just
  292. * about every Module. Of course any Framework implementation
  293. * will have to be augmentable or overridable by a Module.
  294. */
  295. enum swap_type { type_byte, type_short, type_long, type_opaque };
  296. static enum swap_type
  297. nss_dbm_db_swap_type
  298. (
  299. CK_ATTRIBUTE_TYPE type
  300. )
  301. {
  302. switch( type ) {
  303. case CKA_CLASS: return type_long;
  304. case CKA_TOKEN: return type_byte;
  305. case CKA_PRIVATE: return type_byte;
  306. case CKA_LABEL: return type_opaque;
  307. case CKA_APPLICATION: return type_opaque;
  308. case CKA_VALUE: return type_opaque;
  309. case CKA_CERTIFICATE_TYPE: return type_long;
  310. case CKA_ISSUER: return type_opaque;
  311. case CKA_SERIAL_NUMBER: return type_opaque;
  312. case CKA_KEY_TYPE: return type_long;
  313. case CKA_SUBJECT: return type_opaque;
  314. case CKA_ID: return type_opaque;
  315. case CKA_SENSITIVE: return type_byte;
  316. case CKA_ENCRYPT: return type_byte;
  317. case CKA_DECRYPT: return type_byte;
  318. case CKA_WRAP: return type_byte;
  319. case CKA_UNWRAP: return type_byte;
  320. case CKA_SIGN: return type_byte;
  321. case CKA_SIGN_RECOVER: return type_byte;
  322. case CKA_VERIFY: return type_byte;
  323. case CKA_VERIFY_RECOVER: return type_byte;
  324. case CKA_DERIVE: return type_byte;
  325. case CKA_START_DATE: return type_opaque;
  326. case CKA_END_DATE: return type_opaque;
  327. case CKA_MODULUS: return type_opaque;
  328. case CKA_MODULUS_BITS: return type_long;
  329. case CKA_PUBLIC_EXPONENT: return type_opaque;
  330. case CKA_PRIVATE_EXPONENT: return type_opaque;
  331. case CKA_PRIME_1: return type_opaque;
  332. case CKA_PRIME_2: return type_opaque;
  333. case CKA_EXPONENT_1: return type_opaque;
  334. case CKA_EXPONENT_2: return type_opaque;
  335. case CKA_COEFFICIENT: return type_opaque;
  336. case CKA_PRIME: return type_opaque;
  337. case CKA_SUBPRIME: return type_opaque;
  338. case CKA_BASE: return type_opaque;
  339. case CKA_VALUE_BITS: return type_long;
  340. case CKA_VALUE_LEN: return type_long;
  341. case CKA_EXTRACTABLE: return type_byte;
  342. case CKA_LOCAL: return type_byte;
  343. case CKA_NEVER_EXTRACTABLE: return type_byte;
  344. case CKA_ALWAYS_SENSITIVE: return type_byte;
  345. case CKA_MODIFIABLE: return type_byte;
  346. case CKA_NETSCAPE_URL: return type_opaque;
  347. case CKA_NETSCAPE_EMAIL: return type_opaque;
  348. case CKA_NETSCAPE_SMIME_INFO: return type_opaque;
  349. case CKA_NETSCAPE_SMIME_TIMESTAMP: return type_opaque;
  350. case CKA_NETSCAPE_PKCS8_SALT: return type_opaque;
  351. case CKA_NETSCAPE_PASSWORD_CHECK: return type_opaque;
  352. case CKA_NETSCAPE_EXPIRES: return type_opaque;
  353. case CKA_TRUST_DIGITAL_SIGNATURE: return type_long;
  354. case CKA_TRUST_NON_REPUDIATION: return type_long;
  355. case CKA_TRUST_KEY_ENCIPHERMENT: return type_long;
  356. case CKA_TRUST_DATA_ENCIPHERMENT: return type_long;
  357. case CKA_TRUST_KEY_AGREEMENT: return type_long;
  358. case CKA_TRUST_KEY_CERT_SIGN: return type_long;
  359. case CKA_TRUST_CRL_SIGN: return type_long;
  360. case CKA_TRUST_SERVER_AUTH: return type_long;
  361. case CKA_TRUST_CLIENT_AUTH: return type_long;
  362. case CKA_TRUST_CODE_SIGNING: return type_long;
  363. case CKA_TRUST_EMAIL_PROTECTION: return type_long;
  364. case CKA_TRUST_IPSEC_END_SYSTEM: return type_long;
  365. case CKA_TRUST_IPSEC_TUNNEL: return type_long;
  366. case CKA_TRUST_IPSEC_USER: return type_long;
  367. case CKA_TRUST_TIME_STAMPING: return type_long;
  368. case CKA_NETSCAPE_DB: return type_opaque;
  369. case CKA_NETSCAPE_TRUST: return type_opaque;
  370. default: return type_opaque;
  371. }
  372. }
  373. static void
  374. nss_dbm_db_swap_copy
  375. (
  376. CK_ATTRIBUTE_TYPE type,
  377. void *dest,
  378. void *src,
  379. CK_ULONG len
  380. )
  381. {
  382. switch( nss_dbm_db_swap_type(type) ) {
  383. case type_byte:
  384. case type_opaque:
  385. (void)memcpy(dest, src, len);
  386. break;
  387. case type_short:
  388. {
  389. CK_USHORT s, d;
  390. (void)memcpy(&s, src, sizeof(CK_USHORT));
  391. d = htons(s);
  392. (void)memcpy(dest, &d, sizeof(CK_USHORT));
  393. break;
  394. }
  395. case type_long:
  396. {
  397. CK_ULONG s, d;
  398. (void)memcpy(&s, src, sizeof(CK_ULONG));
  399. d = htonl(s);
  400. (void)memcpy(dest, &d, sizeof(CK_ULONG));
  401. break;
  402. }
  403. }
  404. }
  405. static CK_RV
  406. nss_dbm_db_wrap_object
  407. (
  408. NSSArena *arena,
  409. CK_ATTRIBUTE_PTR pTemplate,
  410. CK_ULONG ulAttributeCount,
  411. DBT *object
  412. )
  413. {
  414. CK_ULONG object_size;
  415. CK_ULONG i;
  416. CK_ULONG *pulData;
  417. char *pcData;
  418. CK_ULONG offset;
  419. object_size = (1 + ulAttributeCount*3) * sizeof(CK_ULONG);
  420. offset = object_size;
  421. for( i = 0; i < ulAttributeCount; i++ ) {
  422. object_size += pTemplate[i].ulValueLen;
  423. }
  424. object->size = object_size;
  425. object->data = nss_ZAlloc(arena, object_size);
  426. if( (void *)NULL == object->data ) {
  427. return CKR_HOST_MEMORY;
  428. }
  429. pulData = (CK_ULONG *)object->data;
  430. pcData = (char *)object->data;
  431. pulData[0] = htonl(ulAttributeCount);
  432. for( i = 0; i < ulAttributeCount; i++ ) {
  433. CK_ULONG len = pTemplate[i].ulValueLen;
  434. pulData[1 + i*3] = htonl(pTemplate[i].type);
  435. pulData[2 + i*3] = htonl(len);
  436. pulData[3 + i*3] = htonl(offset);
  437. nss_dbm_db_swap_copy(pTemplate[i].type, &pcData[offset], pTemplate[i].pValue, len);
  438. offset += len;
  439. }
  440. return CKR_OK;
  441. }
  442. static CK_RV
  443. nss_dbm_db_unwrap_object
  444. (
  445. NSSArena *arena,
  446. DBT *object,
  447. CK_ATTRIBUTE_PTR *ppTemplate,
  448. CK_ULONG *pulAttributeCount
  449. )
  450. {
  451. CK_ULONG *pulData;
  452. char *pcData;
  453. CK_ULONG n, i;
  454. CK_ATTRIBUTE_PTR pTemplate;
  455. pulData = (CK_ULONG *)object->data;
  456. pcData = (char *)object->data;
  457. n = ntohl(pulData[0]);
  458. *pulAttributeCount = n;
  459. pTemplate = nss_ZNEWARRAY(arena, CK_ATTRIBUTE, n);
  460. if( (CK_ATTRIBUTE_PTR)NULL == pTemplate ) {
  461. return CKR_HOST_MEMORY;
  462. }
  463. for( i = 0; i < n; i++ ) {
  464. CK_ULONG len;
  465. CK_ULONG offset;
  466. void *p;
  467. pTemplate[i].type = ntohl(pulData[1 + i*3]);
  468. len = ntohl(pulData[2 + i*3]);
  469. offset = ntohl(pulData[3 + i*3]);
  470. p = nss_ZAlloc(arena, len);
  471. if( (void *)NULL == p ) {
  472. return CKR_HOST_MEMORY;
  473. }
  474. nss_dbm_db_swap_copy(pTemplate[i].type, p, &pcData[offset], len);
  475. pTemplate[i].ulValueLen = len;
  476. pTemplate[i].pValue = p;
  477. }
  478. *ppTemplate = pTemplate;
  479. return CKR_OK;
  480. }
  481. NSS_IMPLEMENT nss_dbm_dbt_t *
  482. nss_dbm_db_create_object
  483. (
  484. NSSArena *arena,
  485. nss_dbm_db_t *db,
  486. CK_ATTRIBUTE_PTR pTemplate,
  487. CK_ULONG ulAttributeCount,
  488. CK_RV *pError,
  489. CK_ULONG *pdbrv
  490. )
  491. {
  492. NSSArena *tmparena = (NSSArena *)NULL;
  493. nss_dbm_dbt_t *rv = (nss_dbm_dbt_t *)NULL;
  494. DBT object;
  495. rv = nss_ZNEW(arena, nss_dbm_dbt_t);
  496. if( (nss_dbm_dbt_t *)NULL == rv ) {
  497. *pError = CKR_HOST_MEMORY;
  498. return (nss_dbm_dbt_t *)NULL;
  499. }
  500. rv->my_db = db;
  501. rv->dbt.size = sizeof(struct handle);
  502. rv->dbt.data = nss_ZAlloc(arena, rv->dbt.size);
  503. if( (void *)NULL == rv->dbt.data ) {
  504. *pError = CKR_HOST_MEMORY;
  505. return (nss_dbm_dbt_t *)NULL;
  506. }
  507. *pdbrv = nss_dbm_db_new_handle(db, &rv->dbt, pError);
  508. if( 0 != *pdbrv ) {
  509. return (nss_dbm_dbt_t *)NULL;
  510. }
  511. tmparena = NSSArena_Create();
  512. if( (NSSArena *)NULL == tmparena ) {
  513. *pError = CKR_HOST_MEMORY;
  514. return (nss_dbm_dbt_t *)NULL;
  515. }
  516. *pError = nss_dbm_db_wrap_object(tmparena, pTemplate, ulAttributeCount, &object);
  517. if( CKR_OK != *pError ) {
  518. return (nss_dbm_dbt_t *)NULL;
  519. }
  520. /* Locked region */
  521. {
  522. *pError = NSSCKFWMutex_Lock(db->crustylock);
  523. if( CKR_OK != *pError ) {
  524. goto loser;
  525. }
  526. *pdbrv = db->db->put(db->db, &rv->dbt, &object, 0);
  527. if( 0 != *pdbrv ) {
  528. *pError = CKR_DEVICE_ERROR;
  529. }
  530. (void)db->db->sync(db->db, 0);
  531. (void)NSSCKFWMutex_Unlock(db->crustylock);
  532. }
  533. loser:
  534. if( (NSSArena *)NULL != tmparena ) {
  535. (void)NSSArena_Destroy(tmparena);
  536. }
  537. return rv;
  538. }
  539. NSS_IMPLEMENT CK_RV
  540. nss_dbm_db_find_objects
  541. (
  542. nss_dbm_find_t *find,
  543. nss_dbm_db_t *db,
  544. CK_ATTRIBUTE_PTR pTemplate,
  545. CK_ULONG ulAttributeCount,
  546. CK_ULONG *pdbrv
  547. )
  548. {
  549. CK_RV rv = CKR_OK;
  550. if( (nss_dbm_db_t *)NULL != db ) {
  551. DBT k, v;
  552. rv = NSSCKFWMutex_Lock(db->crustylock);
  553. if( CKR_OK != rv ) {
  554. return rv;
  555. }
  556. *pdbrv = db->db->seq(db->db, &k, &v, R_FIRST);
  557. while( 0 == *pdbrv ) {
  558. CK_ULONG i, j;
  559. NSSArena *tmparena = (NSSArena *)NULL;
  560. CK_ULONG ulac;
  561. CK_ATTRIBUTE_PTR pt;
  562. if( (k.size < 4) || (0 != memcmp(k.data, PREFIX_OBJECT, 4)) ) {
  563. goto nomatch;
  564. }
  565. tmparena = NSSArena_Create();
  566. rv = nss_dbm_db_unwrap_object(tmparena, &v, &pt, &ulac);
  567. if( CKR_OK != rv ) {
  568. goto loser;
  569. }
  570. for( i = 0; i < ulAttributeCount; i++ ) {
  571. for( j = 0; j < ulac; j++ ) {
  572. if( pTemplate[i].type == pt[j].type ) {
  573. if( pTemplate[i].ulValueLen != pt[j].ulValueLen ) {
  574. goto nomatch;
  575. }
  576. if( 0 != memcmp(pTemplate[i].pValue, pt[j].pValue, pt[j].ulValueLen) ) {
  577. goto nomatch;
  578. }
  579. break;
  580. }
  581. }
  582. if( j == ulac ) {
  583. goto nomatch;
  584. }
  585. }
  586. /* entire template matches */
  587. {
  588. struct nss_dbm_dbt_node *node;
  589. node = nss_ZNEW(find->arena, struct nss_dbm_dbt_node);
  590. if( (struct nss_dbm_dbt_node *)NULL == node ) {
  591. rv = CKR_HOST_MEMORY;
  592. goto loser;
  593. }
  594. node->dbt = nss_ZNEW(find->arena, nss_dbm_dbt_t);
  595. if( (nss_dbm_dbt_t *)NULL == node->dbt ) {
  596. rv = CKR_HOST_MEMORY;
  597. goto loser;
  598. }
  599. node->dbt->dbt.size = k.size;
  600. node->dbt->dbt.data = nss_ZAlloc(find->arena, k.size);
  601. if( (void *)NULL == node->dbt->dbt.data ) {
  602. rv = CKR_HOST_MEMORY;
  603. goto loser;
  604. }
  605. (void)memcpy(node->dbt->dbt.data, k.data, k.size);
  606. node->dbt->my_db = db;
  607. node->next = find->found;
  608. find->found = node;
  609. }
  610. nomatch:
  611. if( (NSSArena *)NULL != tmparena ) {
  612. (void)NSSArena_Destroy(tmparena);
  613. }
  614. *pdbrv = db->db->seq(db->db, &k, &v, R_NEXT);
  615. }
  616. if( *pdbrv < 0 ) {
  617. rv = CKR_DEVICE_ERROR;
  618. goto loser;
  619. }
  620. rv = CKR_OK;
  621. loser:
  622. (void)NSSCKFWMutex_Unlock(db->crustylock);
  623. }
  624. return rv;
  625. }
  626. NSS_IMPLEMENT CK_BBOOL
  627. nss_dbm_db_object_still_exists
  628. (
  629. nss_dbm_dbt_t *dbt
  630. )
  631. {
  632. CK_BBOOL rv;
  633. CK_RV ckrv;
  634. int dbrv;
  635. DBT object;
  636. ckrv = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
  637. if( CKR_OK != ckrv ) {
  638. return CK_FALSE;
  639. }
  640. dbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
  641. if( 0 == dbrv ) {
  642. rv = CK_TRUE;
  643. } else {
  644. rv = CK_FALSE;
  645. }
  646. (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
  647. return rv;
  648. }
  649. NSS_IMPLEMENT CK_ULONG
  650. nss_dbm_db_get_object_attribute_count
  651. (
  652. nss_dbm_dbt_t *dbt,
  653. CK_RV *pError,
  654. CK_ULONG *pdbrv
  655. )
  656. {
  657. CK_ULONG rv = 0;
  658. DBT object;
  659. CK_ULONG *pulData;
  660. /* Locked region */
  661. {
  662. *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
  663. if( CKR_OK != *pError ) {
  664. return rv;
  665. }
  666. *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
  667. if( 0 == *pdbrv ) {
  668. ;
  669. } else if( *pdbrv > 0 ) {
  670. *pError = CKR_OBJECT_HANDLE_INVALID;
  671. goto done;
  672. } else {
  673. *pError = CKR_DEVICE_ERROR;
  674. goto done;
  675. }
  676. pulData = (CK_ULONG *)object.data;
  677. rv = ntohl(pulData[0]);
  678. done:
  679. (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
  680. }
  681. return rv;
  682. }
  683. NSS_IMPLEMENT CK_RV
  684. nss_dbm_db_get_object_attribute_types
  685. (
  686. nss_dbm_dbt_t *dbt,
  687. CK_ATTRIBUTE_TYPE_PTR typeArray,
  688. CK_ULONG ulCount,
  689. CK_ULONG *pdbrv
  690. )
  691. {
  692. CK_RV rv = CKR_OK;
  693. DBT object;
  694. CK_ULONG *pulData;
  695. CK_ULONG n, i;
  696. /* Locked region */
  697. {
  698. rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
  699. if( CKR_OK != rv ) {
  700. return rv;
  701. }
  702. *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
  703. if( 0 == *pdbrv ) {
  704. ;
  705. } else if( *pdbrv > 0 ) {
  706. rv = CKR_OBJECT_HANDLE_INVALID;
  707. goto done;
  708. } else {
  709. rv = CKR_DEVICE_ERROR;
  710. goto done;
  711. }
  712. pulData = (CK_ULONG *)object.data;
  713. n = ntohl(pulData[0]);
  714. if( ulCount < n ) {
  715. rv = CKR_BUFFER_TOO_SMALL;
  716. goto done;
  717. }
  718. for( i = 0; i < n; i++ ) {
  719. typeArray[i] = ntohl(pulData[1 + i*3]);
  720. }
  721. done:
  722. (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
  723. }
  724. return rv;
  725. }
  726. NSS_IMPLEMENT CK_ULONG
  727. nss_dbm_db_get_object_attribute_size
  728. (
  729. nss_dbm_dbt_t *dbt,
  730. CK_ATTRIBUTE_TYPE type,
  731. CK_RV *pError,
  732. CK_ULONG *pdbrv
  733. )
  734. {
  735. CK_ULONG rv = 0;
  736. DBT object;
  737. CK_ULONG *pulData;
  738. CK_ULONG n, i;
  739. /* Locked region */
  740. {
  741. *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
  742. if( CKR_OK != *pError ) {
  743. return rv;
  744. }
  745. *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
  746. if( 0 == *pdbrv ) {
  747. ;
  748. } else if( *pdbrv > 0 ) {
  749. *pError = CKR_OBJECT_HANDLE_INVALID;
  750. goto done;
  751. } else {
  752. *pError = CKR_DEVICE_ERROR;
  753. goto done;
  754. }
  755. pulData = (CK_ULONG *)object.data;
  756. n = ntohl(pulData[0]);
  757. for( i = 0; i < n; i++ ) {
  758. if( type == ntohl(pulData[1 + i*3]) ) {
  759. rv = ntohl(pulData[2 + i*3]);
  760. }
  761. }
  762. if( i == n ) {
  763. *pError = CKR_ATTRIBUTE_TYPE_INVALID;
  764. goto done;
  765. }
  766. done:
  767. (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
  768. }
  769. return rv;
  770. }
  771. NSS_IMPLEMENT NSSItem *
  772. nss_dbm_db_get_object_attribute
  773. (
  774. nss_dbm_dbt_t *dbt,
  775. NSSArena *arena,
  776. CK_ATTRIBUTE_TYPE type,
  777. CK_RV *pError,
  778. CK_ULONG *pdbrv
  779. )
  780. {
  781. NSSItem *rv = (NSSItem *)NULL;
  782. DBT object;
  783. CK_ULONG i;
  784. NSSArena *tmp = NSSArena_Create();
  785. CK_ATTRIBUTE_PTR pTemplate;
  786. CK_ULONG ulAttributeCount;
  787. /* Locked region */
  788. {
  789. *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
  790. if( CKR_OK != *pError ) {
  791. goto loser;
  792. }
  793. *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
  794. if( 0 == *pdbrv ) {
  795. ;
  796. } else if( *pdbrv > 0 ) {
  797. *pError = CKR_OBJECT_HANDLE_INVALID;
  798. goto done;
  799. } else {
  800. *pError = CKR_DEVICE_ERROR;
  801. goto done;
  802. }
  803. *pError = nss_dbm_db_unwrap_object(tmp, &object, &pTemplate, &ulAttributeCount);
  804. if( CKR_OK != *pError ) {
  805. goto done;
  806. }
  807. for( i = 0; i < ulAttributeCount; i++ ) {
  808. if( type == pTemplate[i].type ) {
  809. rv = nss_ZNEW(arena, NSSItem);
  810. if( (NSSItem *)NULL == rv ) {
  811. *pError = CKR_HOST_MEMORY;
  812. goto done;
  813. }
  814. rv->size = pTemplate[i].ulValueLen;
  815. rv->data = nss_ZAlloc(arena, rv->size);
  816. if( (void *)NULL == rv->data ) {
  817. *pError = CKR_HOST_MEMORY;
  818. goto done;
  819. }
  820. (void)memcpy(rv->data, pTemplate[i].pValue, rv->size);
  821. break;
  822. }
  823. }
  824. if( ulAttributeCount == i ) {
  825. *pError = CKR_ATTRIBUTE_TYPE_INVALID;
  826. goto done;
  827. }
  828. done:
  829. (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
  830. }
  831. loser:
  832. if( (NSSArena *)NULL != tmp ) {
  833. NSSArena_Destroy(tmp);
  834. }
  835. return rv;
  836. }
  837. NSS_IMPLEMENT CK_RV
  838. nss_dbm_db_set_object_attribute
  839. (
  840. nss_dbm_dbt_t *dbt,
  841. CK_ATTRIBUTE_TYPE type,
  842. NSSItem *value,
  843. CK_ULONG *pdbrv
  844. )
  845. {
  846. CK_RV rv = CKR_OK;
  847. DBT object;
  848. CK_ULONG i;
  849. NSSArena *tmp = NSSArena_Create();
  850. CK_ATTRIBUTE_PTR pTemplate;
  851. CK_ULONG ulAttributeCount;
  852. /* Locked region */
  853. {
  854. rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
  855. if( CKR_OK != rv ) {
  856. goto loser;
  857. }
  858. *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
  859. if( 0 == *pdbrv ) {
  860. ;
  861. } else if( *pdbrv > 0 ) {
  862. rv = CKR_OBJECT_HANDLE_INVALID;
  863. goto done;
  864. } else {
  865. rv = CKR_DEVICE_ERROR;
  866. goto done;
  867. }
  868. rv = nss_dbm_db_unwrap_object(tmp, &object, &pTemplate, &ulAttributeCount);
  869. if( CKR_OK != rv ) {
  870. goto done;
  871. }
  872. for( i = 0; i < ulAttributeCount; i++ ) {
  873. if( type == pTemplate[i].type ) {
  874. /* Replacing an existing attribute */
  875. pTemplate[i].ulValueLen = value->size;
  876. pTemplate[i].pValue = value->data;
  877. break;
  878. }
  879. }
  880. if( i == ulAttributeCount ) {
  881. /* Adding a new attribute */
  882. CK_ATTRIBUTE_PTR npt = nss_ZNEWARRAY(tmp, CK_ATTRIBUTE, ulAttributeCount+1);
  883. if( (CK_ATTRIBUTE_PTR)NULL == npt ) {
  884. rv = CKR_DEVICE_ERROR;
  885. goto done;
  886. }
  887. for( i = 0; i < ulAttributeCount; i++ ) {
  888. npt[i] = pTemplate[i];
  889. }
  890. npt[ulAttributeCount].type = type;
  891. npt[ulAttributeCount].ulValueLen = value->size;
  892. npt[ulAttributeCount].pValue = value->data;
  893. pTemplate = npt;
  894. ulAttributeCount++;
  895. }
  896. rv = nss_dbm_db_wrap_object(tmp, pTemplate, ulAttributeCount, &object);
  897. if( CKR_OK != rv ) {
  898. goto done;
  899. }
  900. *pdbrv = dbt->my_db->db->put(dbt->my_db->db, &dbt->dbt, &object, 0);
  901. if( 0 != *pdbrv ) {
  902. rv = CKR_DEVICE_ERROR;
  903. goto done;
  904. }
  905. (void)dbt->my_db->db->sync(dbt->my_db->db, 0);
  906. done:
  907. (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
  908. }
  909. loser:
  910. if( (NSSArena *)NULL != tmp ) {
  911. NSSArena_Destroy(tmp);
  912. }
  913. return rv;
  914. }