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