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
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)