Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/util/secitem.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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 /* | |
6 * Support routines for SECItem data structure. | |
7 */ | |
8 | |
9 #include "seccomon.h" | |
10 #include "secitem.h" | |
11 #include "secerr.h" | |
12 #include "secport.h" | |
13 | |
14 SECItem * | |
15 SECITEM_AllocItem(PLArenaPool *arena, SECItem *item, unsigned int len) | |
16 { | |
17 SECItem *result = NULL; | |
18 void *mark = NULL; | |
19 | |
20 if (arena != NULL) { | |
21 mark = PORT_ArenaMark(arena); | |
22 } | |
23 | |
24 if (item == NULL) { | |
25 if (arena != NULL) { | |
26 result = PORT_ArenaZAlloc(arena, sizeof(SECItem)); | |
27 } else { | |
28 result = PORT_ZAlloc(sizeof(SECItem)); | |
29 } | |
30 if (result == NULL) { | |
31 goto loser; | |
32 } | |
33 } else { | |
34 PORT_Assert(item->data == NULL); | |
35 result = item; | |
36 } | |
37 | |
38 result->len = len; | |
39 if (len) { | |
40 if (arena != NULL) { | |
41 result->data = PORT_ArenaAlloc(arena, len); | |
42 } else { | |
43 result->data = PORT_Alloc(len); | |
44 } | |
45 if (result->data == NULL) { | |
46 goto loser; | |
47 } | |
48 } else { | |
49 result->data = NULL; | |
50 } | |
51 | |
52 if (mark) { | |
53 PORT_ArenaUnmark(arena, mark); | |
54 } | |
55 return(result); | |
56 | |
57 loser: | |
58 if ( arena != NULL ) { | |
59 if (mark) { | |
60 PORT_ArenaRelease(arena, mark); | |
61 } | |
62 if (item != NULL) { | |
63 item->data = NULL; | |
64 item->len = 0; | |
65 } | |
66 } else { | |
67 if (result != NULL) { | |
68 SECITEM_FreeItem(result, (item == NULL) ? PR_TRUE : PR_FALSE); | |
69 } | |
70 /* | |
71 * If item is not NULL, the above has set item->data and | |
72 * item->len to 0. | |
73 */ | |
74 } | |
75 return(NULL); | |
76 } | |
77 | |
78 SECStatus | |
79 SECITEM_ReallocItem(PLArenaPool *arena, SECItem *item, unsigned int oldlen, | |
80 unsigned int newlen) | |
81 { | |
82 PORT_Assert(item != NULL); | |
83 if (item == NULL) { | |
84 /* XXX Set error. But to what? */ | |
85 return SECFailure; | |
86 } | |
87 | |
88 /* | |
89 * If no old length, degenerate to just plain alloc. | |
90 */ | |
91 if (oldlen == 0) { | |
92 PORT_Assert(item->data == NULL || item->len == 0); | |
93 if (newlen == 0) { | |
94 /* Nothing to do. Weird, but not a failure. */ | |
95 return SECSuccess; | |
96 } | |
97 item->len = newlen; | |
98 if (arena != NULL) { | |
99 item->data = PORT_ArenaAlloc(arena, newlen); | |
100 } else { | |
101 item->data = PORT_Alloc(newlen); | |
102 } | |
103 } else { | |
104 if (arena != NULL) { | |
105 item->data = PORT_ArenaGrow(arena, item->data, oldlen, newlen); | |
106 } else { | |
107 item->data = PORT_Realloc(item->data, newlen); | |
108 } | |
109 } | |
110 | |
111 if (item->data == NULL) { | |
112 return SECFailure; | |
113 } | |
114 | |
115 return SECSuccess; | |
116 } | |
117 | |
118 SECStatus | |
119 SECITEM_ReallocItemV2(PLArenaPool *arena, SECItem *item, unsigned int newlen) | |
120 { | |
121 unsigned char *newdata = NULL; | |
122 | |
123 PORT_Assert(item); | |
124 if (!item) { | |
125 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
126 return SECFailure; | |
127 } | |
128 | |
129 if (item->len == newlen) { | |
130 return SECSuccess; | |
131 } | |
132 | |
133 if (!newlen) { | |
134 if (!arena) { | |
135 PORT_Free(item->data); | |
136 } | |
137 item->data = NULL; | |
138 item->len = 0; | |
139 return SECSuccess; | |
140 } | |
141 | |
142 if (!item->data) { | |
143 /* allocate fresh block of memory */ | |
144 PORT_Assert(!item->len); | |
145 if (arena) { | |
146 newdata = PORT_ArenaAlloc(arena, newlen); | |
147 } else { | |
148 newdata = PORT_Alloc(newlen); | |
149 } | |
150 } else { | |
151 /* reallocate or adjust existing block of memory */ | |
152 if (arena) { | |
153 if (item->len > newlen) { | |
154 /* There's no need to realloc a shorter block from the arena, | |
155 * because it would result in using even more memory! | |
156 * Therefore we'll continue to use the old block and | |
157 * set the item to the shorter size. | |
158 */ | |
159 item->len = newlen; | |
160 return SECSuccess; | |
161 } | |
162 newdata = PORT_ArenaGrow(arena, item->data, item->len, newlen); | |
163 } else { | |
164 newdata = PORT_Realloc(item->data, newlen); | |
165 } | |
166 } | |
167 | |
168 if (!newdata) { | |
169 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
170 return SECFailure; | |
171 } | |
172 | |
173 item->len = newlen; | |
174 item->data = newdata; | |
175 return SECSuccess; | |
176 } | |
177 | |
178 SECComparison | |
179 SECITEM_CompareItem(const SECItem *a, const SECItem *b) | |
180 { | |
181 unsigned m; | |
182 int rv; | |
183 | |
184 if (a == b) | |
185 return SECEqual; | |
186 if (!a || !a->len || !a->data) | |
187 return (!b || !b->len || !b->data) ? SECEqual : SECLessThan; | |
188 if (!b || !b->len || !b->data) | |
189 return SECGreaterThan; | |
190 | |
191 m = ( ( a->len < b->len ) ? a->len : b->len ); | |
192 | |
193 rv = PORT_Memcmp(a->data, b->data, m); | |
194 if (rv) { | |
195 return rv < 0 ? SECLessThan : SECGreaterThan; | |
196 } | |
197 if (a->len < b->len) { | |
198 return SECLessThan; | |
199 } | |
200 if (a->len == b->len) { | |
201 return SECEqual; | |
202 } | |
203 return SECGreaterThan; | |
204 } | |
205 | |
206 PRBool | |
207 SECITEM_ItemsAreEqual(const SECItem *a, const SECItem *b) | |
208 { | |
209 if (a->len != b->len) | |
210 return PR_FALSE; | |
211 if (!a->len) | |
212 return PR_TRUE; | |
213 if (!a->data || !b->data) { | |
214 /* avoid null pointer crash. */ | |
215 return (PRBool)(a->data == b->data); | |
216 } | |
217 return (PRBool)!PORT_Memcmp(a->data, b->data, a->len); | |
218 } | |
219 | |
220 SECItem * | |
221 SECITEM_DupItem(const SECItem *from) | |
222 { | |
223 return SECITEM_ArenaDupItem(NULL, from); | |
224 } | |
225 | |
226 SECItem * | |
227 SECITEM_ArenaDupItem(PLArenaPool *arena, const SECItem *from) | |
228 { | |
229 SECItem *to; | |
230 | |
231 if ( from == NULL ) { | |
232 return(NULL); | |
233 } | |
234 | |
235 if ( arena != NULL ) { | |
236 to = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem)); | |
237 } else { | |
238 to = (SECItem *)PORT_Alloc(sizeof(SECItem)); | |
239 } | |
240 if ( to == NULL ) { | |
241 return(NULL); | |
242 } | |
243 | |
244 if ( arena != NULL ) { | |
245 to->data = (unsigned char *)PORT_ArenaAlloc(arena, from->len); | |
246 } else { | |
247 to->data = (unsigned char *)PORT_Alloc(from->len); | |
248 } | |
249 if ( to->data == NULL ) { | |
250 PORT_Free(to); | |
251 return(NULL); | |
252 } | |
253 | |
254 to->len = from->len; | |
255 to->type = from->type; | |
256 if ( to->len ) { | |
257 PORT_Memcpy(to->data, from->data, to->len); | |
258 } | |
259 | |
260 return(to); | |
261 } | |
262 | |
263 SECStatus | |
264 SECITEM_CopyItem(PLArenaPool *arena, SECItem *to, const SECItem *from) | |
265 { | |
266 to->type = from->type; | |
267 if (from->data && from->len) { | |
268 if ( arena ) { | |
269 to->data = (unsigned char*) PORT_ArenaAlloc(arena, from->len); | |
270 } else { | |
271 to->data = (unsigned char*) PORT_Alloc(from->len); | |
272 } | |
273 | |
274 if (!to->data) { | |
275 return SECFailure; | |
276 } | |
277 PORT_Memcpy(to->data, from->data, from->len); | |
278 to->len = from->len; | |
279 } else { | |
280 /* | |
281 * If from->data is NULL but from->len is nonzero, this function | |
282 * will succeed. Is this right? | |
283 */ | |
284 to->data = 0; | |
285 to->len = 0; | |
286 } | |
287 return SECSuccess; | |
288 } | |
289 | |
290 void | |
291 SECITEM_FreeItem(SECItem *zap, PRBool freeit) | |
292 { | |
293 if (zap) { | |
294 PORT_Free(zap->data); | |
295 zap->data = 0; | |
296 zap->len = 0; | |
297 if (freeit) { | |
298 PORT_Free(zap); | |
299 } | |
300 } | |
301 } | |
302 | |
303 void | |
304 SECITEM_ZfreeItem(SECItem *zap, PRBool freeit) | |
305 { | |
306 if (zap) { | |
307 PORT_ZFree(zap->data, zap->len); | |
308 zap->data = 0; | |
309 zap->len = 0; | |
310 if (freeit) { | |
311 PORT_ZFree(zap, sizeof(SECItem)); | |
312 } | |
313 } | |
314 } | |
315 /* these reroutines were taken from pkix oid.c, which is supposed to | |
316 * replace this file some day */ | |
317 /* | |
318 * This is the hash function. We simply XOR the encoded form with | |
319 * itself in sizeof(PLHashNumber)-byte chunks. Improving this | |
320 * routine is left as an excercise for the more mathematically | |
321 * inclined student. | |
322 */ | |
323 PLHashNumber PR_CALLBACK | |
324 SECITEM_Hash ( const void *key) | |
325 { | |
326 const SECItem *item = (const SECItem *)key; | |
327 PLHashNumber rv = 0; | |
328 | |
329 PRUint8 *data = (PRUint8 *)item->data; | |
330 PRUint32 i; | |
331 PRUint8 *rvc = (PRUint8 *)&rv; | |
332 | |
333 for( i = 0; i < item->len; i++ ) { | |
334 rvc[ i % sizeof(rv) ] ^= *data; | |
335 data++; | |
336 } | |
337 | |
338 return rv; | |
339 } | |
340 | |
341 /* | |
342 * This is the key-compare function. It simply does a lexical | |
343 * comparison on the item data. This does not result in | |
344 * quite the same ordering as the "sequence of numbers" order, | |
345 * but heck it's only used internally by the hash table anyway. | |
346 */ | |
347 PRIntn PR_CALLBACK | |
348 SECITEM_HashCompare ( const void *k1, const void *k2) | |
349 { | |
350 const SECItem *i1 = (const SECItem *)k1; | |
351 const SECItem *i2 = (const SECItem *)k2; | |
352 | |
353 return SECITEM_ItemsAreEqual(i1,i2); | |
354 } | |
355 | |
356 SECItemArray * | |
357 SECITEM_AllocArray(PLArenaPool *arena, SECItemArray *array, unsigned int len) | |
358 { | |
359 SECItemArray *result = NULL; | |
360 void *mark = NULL; | |
361 | |
362 if (array != NULL && array->items != NULL) { | |
363 PORT_Assert(0); | |
364 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
365 return NULL; | |
366 } | |
367 | |
368 if (arena != NULL) { | |
369 mark = PORT_ArenaMark(arena); | |
370 } | |
371 | |
372 if (array == NULL) { | |
373 if (arena != NULL) { | |
374 result = PORT_ArenaZAlloc(arena, sizeof(SECItemArray)); | |
375 } else { | |
376 result = PORT_ZAlloc(sizeof(SECItemArray)); | |
377 } | |
378 if (result == NULL) { | |
379 goto loser; | |
380 } | |
381 } else { | |
382 result = array; | |
383 } | |
384 | |
385 result->len = len; | |
386 if (len) { | |
387 if (arena != NULL) { | |
388 result->items = PORT_ArenaZNewArray(arena, SECItem, len); | |
389 } else { | |
390 result->items = PORT_ZNewArray(SECItem, len); | |
391 } | |
392 if (result->items == NULL) { | |
393 goto loser; | |
394 } | |
395 } else { | |
396 result->items = NULL; | |
397 } | |
398 | |
399 if (mark) { | |
400 PORT_ArenaUnmark(arena, mark); | |
401 } | |
402 return result; | |
403 | |
404 loser: | |
405 if ( arena != NULL ) { | |
406 if (mark) { | |
407 PORT_ArenaRelease(arena, mark); | |
408 } | |
409 } else { | |
410 if (result != NULL && array == NULL) { | |
411 PORT_Free(result); | |
412 } | |
413 } | |
414 if (array != NULL) { | |
415 array->items = NULL; | |
416 array->len = 0; | |
417 } | |
418 return NULL; | |
419 } | |
420 | |
421 static void | |
422 secitem_FreeArray(SECItemArray *array, PRBool zero_items, PRBool freeit) | |
423 { | |
424 unsigned int i; | |
425 | |
426 if (!array || !array->len || !array->items) | |
427 return; | |
428 | |
429 for (i = 0; i < array->len; ++i) { | |
430 SECItem *item = &array->items[i]; | |
431 | |
432 if (item->data) { | |
433 if (zero_items) { | |
434 SECITEM_ZfreeItem(item, PR_FALSE); | |
435 } else { | |
436 SECITEM_FreeItem(item, PR_FALSE); | |
437 } | |
438 } | |
439 } | |
440 PORT_Free(array->items); | |
441 array->items = NULL; | |
442 array->len = 0; | |
443 | |
444 if (freeit) | |
445 PORT_Free(array); | |
446 } | |
447 | |
448 void SECITEM_FreeArray(SECItemArray *array, PRBool freeit) | |
449 { | |
450 secitem_FreeArray(array, PR_FALSE, freeit); | |
451 } | |
452 | |
453 void SECITEM_ZfreeArray(SECItemArray *array, PRBool freeit) | |
454 { | |
455 secitem_FreeArray(array, PR_TRUE, freeit); | |
456 } | |
457 | |
458 SECItemArray * | |
459 SECITEM_DupArray(PLArenaPool *arena, const SECItemArray *from) | |
460 { | |
461 SECItemArray *result; | |
462 unsigned int i; | |
463 | |
464 /* Require a "from" array. | |
465 * Reject an inconsistent "from" array with NULL data and nonzero length. | |
466 * However, allow a "from" array of zero length. | |
467 */ | |
468 if (!from || (!from->items && from->len)) | |
469 return NULL; | |
470 | |
471 result = SECITEM_AllocArray(arena, NULL, from->len); | |
472 if (!result) | |
473 return NULL; | |
474 | |
475 for (i = 0; i < from->len; ++i) { | |
476 SECStatus rv = SECITEM_CopyItem(arena, | |
477 &result->items[i], &from->items[i]); | |
478 if (rv != SECSuccess) { | |
479 SECITEM_ZfreeArray(result, PR_TRUE); | |
480 return NULL; | |
481 } | |
482 } | |
483 | |
484 return result; | |
485 } |