Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/softoken/legacydb/lgutil.c @ 3:150b72113545
Add DBM and legacydb support
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Tue, 05 Aug 2014 18:32:02 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:a945361df361 | 3:150b72113545 |
---|---|
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 #include "lgdb.h" | |
5 #include "secerr.h" | |
6 #include "lgglue.h" | |
7 | |
8 /* | |
9 * ******************** Attribute Utilities ******************************* | |
10 */ | |
11 | |
12 /* | |
13 * look up and attribute structure from a type and Object structure. | |
14 * The returned attribute is referenced and needs to be freed when | |
15 * it is no longer needed. | |
16 */ | |
17 const CK_ATTRIBUTE * | |
18 lg_FindAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, | |
19 CK_ULONG count ) | |
20 { | |
21 unsigned int i; | |
22 | |
23 for (i=0; i < count; i++) { | |
24 if (templ[i].type == type) { | |
25 return &templ[i]; | |
26 } | |
27 } | |
28 return NULL; | |
29 } | |
30 | |
31 | |
32 /* | |
33 * return true if object has attribute | |
34 */ | |
35 PRBool | |
36 lg_hasAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, | |
37 CK_ULONG count ) | |
38 { | |
39 if (lg_FindAttribute(type, templ, count) == NULL) { | |
40 return PR_FALSE; | |
41 } | |
42 return PR_TRUE; | |
43 } | |
44 | |
45 /* | |
46 * copy an attribute into a SECItem. Secitem is allocated in the specified | |
47 * arena. | |
48 */ | |
49 CK_RV | |
50 lg_Attribute2SecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type, | |
51 const CK_ATTRIBUTE *templ, CK_ULONG count, | |
52 SECItem *item) | |
53 { | |
54 int len; | |
55 const CK_ATTRIBUTE *attribute; | |
56 | |
57 attribute = lg_FindAttribute(type, templ, count); | |
58 if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; | |
59 len = attribute->ulValueLen; | |
60 | |
61 if (arena) { | |
62 item->data = (unsigned char *) PORT_ArenaAlloc(arena,len); | |
63 } else { | |
64 item->data = (unsigned char *) PORT_Alloc(len); | |
65 } | |
66 if (item->data == NULL) { | |
67 return CKR_HOST_MEMORY; | |
68 } | |
69 item->len = len; | |
70 PORT_Memcpy(item->data, attribute->pValue, len); | |
71 return CKR_OK; | |
72 } | |
73 | |
74 | |
75 /* | |
76 * copy an unsigned attribute into a SECItem. Secitem is allocated in | |
77 * the specified arena. | |
78 */ | |
79 CK_RV | |
80 lg_Attribute2SSecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type, | |
81 const CK_ATTRIBUTE *templ, CK_ULONG count, | |
82 SECItem *item) | |
83 { | |
84 const CK_ATTRIBUTE *attribute; | |
85 item->data = NULL; | |
86 | |
87 attribute = lg_FindAttribute(type, templ, count); | |
88 if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; | |
89 | |
90 (void)SECITEM_AllocItem(arena, item, attribute->ulValueLen); | |
91 if (item->data == NULL) { | |
92 return CKR_HOST_MEMORY; | |
93 } | |
94 PORT_Memcpy(item->data, attribute->pValue, item->len); | |
95 return CKR_OK; | |
96 } | |
97 | |
98 /* | |
99 * copy an unsigned attribute into a SECItem. Secitem is allocated in | |
100 * the specified arena. | |
101 */ | |
102 CK_RV | |
103 lg_PrivAttr2SSecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type, | |
104 const CK_ATTRIBUTE *templ, CK_ULONG count, | |
105 SECItem *item, SDB *sdbpw) | |
106 { | |
107 const CK_ATTRIBUTE *attribute; | |
108 SECItem epki, *dest = NULL; | |
109 SECStatus rv; | |
110 | |
111 item->data = NULL; | |
112 | |
113 attribute = lg_FindAttribute(type, templ, count); | |
114 if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; | |
115 | |
116 epki.data = attribute->pValue; | |
117 epki.len = attribute->ulValueLen; | |
118 | |
119 rv = lg_util_decrypt(sdbpw, &epki, &dest); | |
120 if (rv != SECSuccess) { | |
121 return CKR_USER_NOT_LOGGED_IN; | |
122 } | |
123 (void)SECITEM_AllocItem(arena, item, dest->len); | |
124 if (item->data == NULL) { | |
125 SECITEM_FreeItem(dest, PR_TRUE); | |
126 return CKR_HOST_MEMORY; | |
127 } | |
128 | |
129 PORT_Memcpy(item->data, dest->data, item->len); | |
130 SECITEM_FreeItem(dest, PR_TRUE); | |
131 return CKR_OK; | |
132 } | |
133 | |
134 CK_RV | |
135 lg_PrivAttr2SecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type, | |
136 const CK_ATTRIBUTE *templ, CK_ULONG count, | |
137 SECItem *item, SDB *sdbpw) | |
138 { | |
139 return lg_PrivAttr2SSecItem(arena, type, templ, count, item, sdbpw); | |
140 } | |
141 | |
142 /* | |
143 * this is only valid for CK_BBOOL type attributes. Return the state | |
144 * of that attribute. | |
145 */ | |
146 PRBool | |
147 lg_isTrue(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, CK_ULONG count) | |
148 { | |
149 const CK_ATTRIBUTE *attribute; | |
150 PRBool tok = PR_FALSE; | |
151 | |
152 attribute=lg_FindAttribute(type, templ, count); | |
153 if (attribute == NULL) { return PR_FALSE; } | |
154 tok = (PRBool)(*(CK_BBOOL *)attribute->pValue); | |
155 | |
156 return tok; | |
157 } | |
158 | |
159 /* | |
160 * return a null terminated string from attribute 'type'. This string | |
161 * is allocated and needs to be freed with PORT_Free() When complete. | |
162 */ | |
163 char * | |
164 lg_getString(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, CK_ULONG count) | |
165 { | |
166 const CK_ATTRIBUTE *attribute; | |
167 char *label = NULL; | |
168 | |
169 attribute = lg_FindAttribute(type, templ, count); | |
170 if (attribute == NULL) return NULL; | |
171 | |
172 if (attribute->pValue != NULL) { | |
173 label = (char *) PORT_Alloc(attribute->ulValueLen+1); | |
174 if (label == NULL) { | |
175 return NULL; | |
176 } | |
177 | |
178 PORT_Memcpy(label,attribute->pValue, attribute->ulValueLen); | |
179 label[attribute->ulValueLen] = 0; | |
180 } | |
181 return label; | |
182 } | |
183 | |
184 CK_RV | |
185 lg_GetULongAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, | |
186 CK_ULONG count, CK_ULONG *longData) | |
187 { | |
188 const CK_ATTRIBUTE *attribute; | |
189 CK_ULONG value = 0; | |
190 const unsigned char *data; | |
191 int i; | |
192 | |
193 attribute = lg_FindAttribute(type, templ, count); | |
194 if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; | |
195 | |
196 if (attribute->ulValueLen != 4) { | |
197 return CKR_ATTRIBUTE_VALUE_INVALID; | |
198 } | |
199 data = (const unsigned char *)attribute->pValue; | |
200 for (i=0; i < 4; i++) { | |
201 value |= (CK_ULONG)(data[i]) << ((3-i)*8); | |
202 } | |
203 | |
204 *longData = value; | |
205 return CKR_OK; | |
206 } | |
207 | |
208 /* | |
209 * ******************** Object Utilities ******************************* | |
210 */ | |
211 | |
212 SECStatus | |
213 lg_deleteTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle) | |
214 { | |
215 SECItem *item; | |
216 PRBool rem; | |
217 PLHashTable *hashTable= lg_GetHashTable(sdb); | |
218 | |
219 item = (SECItem *)PL_HashTableLookup(hashTable, (void *)handle); | |
220 rem = PL_HashTableRemove(hashTable,(void *)handle) ; | |
221 if (rem && item) { | |
222 SECITEM_FreeItem(item,PR_TRUE); | |
223 } | |
224 return rem ? SECSuccess : SECFailure; | |
225 } | |
226 | |
227 /* must be called holding lg_DBLock(sdb) */ | |
228 static SECStatus | |
229 lg_addTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle, SECItem *key) | |
230 { | |
231 PLHashEntry *entry; | |
232 SECItem *item; | |
233 PLHashTable *hashTable= lg_GetHashTable(sdb); | |
234 | |
235 item = SECITEM_DupItem(key); | |
236 if (item == NULL) { | |
237 return SECFailure; | |
238 } | |
239 entry = PL_HashTableAdd(hashTable,(void *)handle,item); | |
240 if (entry == NULL) { | |
241 SECITEM_FreeItem(item,PR_TRUE); | |
242 return SECFailure; | |
243 } | |
244 return SECSuccess; | |
245 } | |
246 | |
247 /* must be called holding lg_DBLock(sdb) */ | |
248 const SECItem * | |
249 lg_lookupTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle) | |
250 { | |
251 PLHashTable *hashTable= lg_GetHashTable(sdb); | |
252 return (const SECItem *)PL_HashTableLookup(hashTable, (void *)handle); | |
253 } | |
254 | |
255 | |
256 static PRIntn | |
257 lg_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg) | |
258 { | |
259 SECItem *item = (SECItem *)entry->value; | |
260 | |
261 SECITEM_FreeItem(item, PR_TRUE); | |
262 return HT_ENUMERATE_NEXT; | |
263 } | |
264 | |
265 CK_RV | |
266 lg_ClearTokenKeyHashTable(SDB *sdb) | |
267 { | |
268 PLHashTable *hashTable; | |
269 lg_DBLock(sdb); | |
270 hashTable= lg_GetHashTable(sdb); | |
271 PL_HashTableEnumerateEntries(hashTable, lg_freeHashItem, NULL); | |
272 lg_DBUnlock(sdb); | |
273 return CKR_OK; | |
274 } | |
275 | |
276 /* | |
277 * handle Token Object stuff | |
278 */ | |
279 static void | |
280 lg_XORHash(unsigned char *key, unsigned char *dbkey, int len) | |
281 { | |
282 int i; | |
283 | |
284 PORT_Memset(key, 0, 4); | |
285 | |
286 for (i=0; i < len-4; i += 4) { | |
287 key[0] ^= dbkey[i]; | |
288 key[1] ^= dbkey[i+1]; | |
289 key[2] ^= dbkey[i+2]; | |
290 key[3] ^= dbkey[i+3]; | |
291 } | |
292 } | |
293 | |
294 /* Make a token handle for an object and record it so we can find it again */ | |
295 CK_OBJECT_HANDLE | |
296 lg_mkHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class) | |
297 { | |
298 unsigned char hashBuf[4]; | |
299 CK_OBJECT_HANDLE handle; | |
300 const SECItem *key; | |
301 | |
302 handle = class; | |
303 /* there is only one KRL, use a fixed handle for it */ | |
304 if (handle != LG_TOKEN_KRL_HANDLE) { | |
305 lg_XORHash(hashBuf,dbKey->data,dbKey->len); | |
306 handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) | | |
307 (hashBuf[2] << 8) | hashBuf[3]; | |
308 handle = class | (handle & ~(LG_TOKEN_TYPE_MASK|LG_TOKEN_MASK)); | |
309 /* we have a CRL who's handle has randomly matched the reserved KRL | |
310 * handle, increment it */ | |
311 if (handle == LG_TOKEN_KRL_HANDLE) { | |
312 handle++; | |
313 } | |
314 } | |
315 | |
316 lg_DBLock(sdb); | |
317 while ((key = lg_lookupTokenKeyByHandle(sdb,handle)) != NULL) { | |
318 if (SECITEM_ItemsAreEqual(key,dbKey)) { | |
319 lg_DBUnlock(sdb); | |
320 return handle; | |
321 } | |
322 handle++; | |
323 } | |
324 lg_addTokenKeyByHandle(sdb,handle,dbKey); | |
325 lg_DBUnlock(sdb); | |
326 return handle; | |
327 } | |
328 | |
329 PRBool | |
330 lg_poisonHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class) | |
331 { | |
332 unsigned char hashBuf[4]; | |
333 CK_OBJECT_HANDLE handle; | |
334 const SECItem *key; | |
335 | |
336 handle = class; | |
337 /* there is only one KRL, use a fixed handle for it */ | |
338 if (handle != LG_TOKEN_KRL_HANDLE) { | |
339 lg_XORHash(hashBuf,dbKey->data,dbKey->len); | |
340 handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) | | |
341 (hashBuf[2] << 8) | hashBuf[3]; | |
342 handle = class | (handle & ~(LG_TOKEN_TYPE_MASK|LG_TOKEN_MASK)); | |
343 /* we have a CRL who's handle has randomly matched the reserved KRL | |
344 * handle, increment it */ | |
345 if (handle == LG_TOKEN_KRL_HANDLE) { | |
346 handle++; | |
347 } | |
348 } | |
349 lg_DBLock(sdb); | |
350 while ((key = lg_lookupTokenKeyByHandle(sdb,handle)) != NULL) { | |
351 if (SECITEM_ItemsAreEqual(key,dbKey)) { | |
352 key->data[0] ^= 0x80; | |
353 lg_DBUnlock(sdb); | |
354 return PR_TRUE; | |
355 } | |
356 handle++; | |
357 } | |
358 lg_DBUnlock(sdb); | |
359 return PR_FALSE; | |
360 } | |
361 | |
362 static LGEncryptFunc lg_encrypt_stub = NULL; | |
363 static LGDecryptFunc lg_decrypt_stub = NULL; | |
364 | |
365 void | |
366 legacy_SetCryptFunctions(LGEncryptFunc enc, LGDecryptFunc dec) | |
367 { | |
368 lg_encrypt_stub = enc; | |
369 lg_decrypt_stub = dec; | |
370 } | |
371 | |
372 SECStatus lg_util_encrypt(PLArenaPool *arena, SDB *sdb, | |
373 SECItem *plainText, SECItem **cipherText) | |
374 { | |
375 if (lg_encrypt_stub == NULL) { | |
376 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
377 return SECFailure; | |
378 } | |
379 return (*lg_encrypt_stub)(arena, sdb, plainText, cipherText); | |
380 } | |
381 | |
382 SECStatus lg_util_decrypt(SDB *sdb, SECItem *cipherText, SECItem **plainText) | |
383 { | |
384 if (lg_decrypt_stub == NULL) { | |
385 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
386 return SECFailure; | |
387 } | |
388 return (*lg_decrypt_stub)(sdb, cipherText, plainText); | |
389 } | |
390 | |
391 |