PageRenderTime 41ms CodeModel.GetById 25ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/lib/util/secitem.c

http://github.com/zpao/v8monkey
C | 328 lines | 227 code | 33 blank | 68 comment | 91 complexity | 81cfe4e57fac082167bc2774e4d8ac5a 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
 37/*
 38 * Support routines for SECItem data structure.
 39 *
 40 * $Id: secitem.c,v 1.16 2011/07/22 21:22:40 wtc%google.com Exp $
 41 */
 42
 43#include "seccomon.h"
 44#include "secitem.h"
 45#include "base64.h"
 46#include "secerr.h"
 47
 48SECItem *
 49SECITEM_AllocItem(PRArenaPool *arena, SECItem *item, unsigned int len)
 50{
 51    SECItem *result = NULL;
 52    void *mark = NULL;
 53
 54    if (arena != NULL) {
 55	mark = PORT_ArenaMark(arena);
 56    }
 57
 58    if (item == NULL) {
 59	if (arena != NULL) {
 60	    result = PORT_ArenaZAlloc(arena, sizeof(SECItem));
 61	} else {
 62	    result = PORT_ZAlloc(sizeof(SECItem));
 63	}
 64	if (result == NULL) {
 65	    goto loser;
 66	}
 67    } else {
 68	PORT_Assert(item->data == NULL);
 69	result = item;
 70    }
 71
 72    result->len = len;
 73    if (len) {
 74	if (arena != NULL) {
 75	    result->data = PORT_ArenaAlloc(arena, len);
 76	} else {
 77	    result->data = PORT_Alloc(len);
 78	}
 79	if (result->data == NULL) {
 80	    goto loser;
 81	}
 82    } else {
 83	result->data = NULL;
 84    }
 85
 86    if (mark) {
 87	PORT_ArenaUnmark(arena, mark);
 88    }
 89    return(result);
 90
 91loser:
 92    if ( arena != NULL ) {
 93	if (mark) {
 94	    PORT_ArenaRelease(arena, mark);
 95	}
 96	if (item != NULL) {
 97	    item->data = NULL;
 98	    item->len = 0;
 99	}
100    } else {
101	if (result != NULL) {
102	    SECITEM_FreeItem(result, (item == NULL) ? PR_TRUE : PR_FALSE);
103	}
104	/*
105	 * If item is not NULL, the above has set item->data and
106	 * item->len to 0.
107	 */
108    }
109    return(NULL);
110}
111
112SECStatus
113SECITEM_ReallocItem(PRArenaPool *arena, SECItem *item, unsigned int oldlen,
114		    unsigned int newlen)
115{
116    PORT_Assert(item != NULL);
117    if (item == NULL) {
118	/* XXX Set error.  But to what? */
119	return SECFailure;
120    }
121
122    /*
123     * If no old length, degenerate to just plain alloc.
124     */
125    if (oldlen == 0) {
126	PORT_Assert(item->data == NULL || item->len == 0);
127	if (newlen == 0) {
128	    /* Nothing to do.  Weird, but not a failure.  */
129	    return SECSuccess;
130	}
131	item->len = newlen;
132	if (arena != NULL) {
133	    item->data = PORT_ArenaAlloc(arena, newlen);
134	} else {
135	    item->data = PORT_Alloc(newlen);
136	}
137    } else {
138	if (arena != NULL) {
139	    item->data = PORT_ArenaGrow(arena, item->data, oldlen, newlen);
140	} else {
141	    item->data = PORT_Realloc(item->data, newlen);
142	}
143    }
144
145    if (item->data == NULL) {
146	return SECFailure;
147    }
148
149    return SECSuccess;
150}
151
152SECComparison
153SECITEM_CompareItem(const SECItem *a, const SECItem *b)
154{
155    unsigned m;
156    SECComparison rv;
157
158    if (a == b)
159    	return SECEqual;
160    if (!a || !a->len || !a->data) 
161        return (!b || !b->len || !b->data) ? SECEqual : SECLessThan;
162    if (!b || !b->len || !b->data) 
163    	return SECGreaterThan;
164
165    m = ( ( a->len < b->len ) ? a->len : b->len );
166    
167    rv = (SECComparison) PORT_Memcmp(a->data, b->data, m);
168    if (rv) {
169	return rv;
170    }
171    if (a->len < b->len) {
172	return SECLessThan;
173    }
174    if (a->len == b->len) {
175	return SECEqual;
176    }
177    return SECGreaterThan;
178}
179
180PRBool
181SECITEM_ItemsAreEqual(const SECItem *a, const SECItem *b)
182{
183    if (a->len != b->len)
184        return PR_FALSE;
185    if (!a->len)
186    	return PR_TRUE;
187    if (!a->data || !b->data) {
188        /* avoid null pointer crash. */
189	return (PRBool)(a->data == b->data);
190    }
191    return (PRBool)!PORT_Memcmp(a->data, b->data, a->len);
192}
193
194SECItem *
195SECITEM_DupItem(const SECItem *from)
196{
197    return SECITEM_ArenaDupItem(NULL, from);
198}
199
200SECItem *
201SECITEM_ArenaDupItem(PRArenaPool *arena, const SECItem *from)
202{
203    SECItem *to;
204    
205    if ( from == NULL ) {
206	return(NULL);
207    }
208    
209    if ( arena != NULL ) {
210	to = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem));
211    } else {
212	to = (SECItem *)PORT_Alloc(sizeof(SECItem));
213    }
214    if ( to == NULL ) {
215	return(NULL);
216    }
217
218    if ( arena != NULL ) {
219	to->data = (unsigned char *)PORT_ArenaAlloc(arena, from->len);
220    } else {
221	to->data = (unsigned char *)PORT_Alloc(from->len);
222    }
223    if ( to->data == NULL ) {
224	PORT_Free(to);
225	return(NULL);
226    }
227
228    to->len = from->len;
229    to->type = from->type;
230    if ( to->len ) {
231	PORT_Memcpy(to->data, from->data, to->len);
232    }
233    
234    return(to);
235}
236
237SECStatus
238SECITEM_CopyItem(PRArenaPool *arena, SECItem *to, const SECItem *from)
239{
240    to->type = from->type;
241    if (from->data && from->len) {
242	if ( arena ) {
243	    to->data = (unsigned char*) PORT_ArenaAlloc(arena, from->len);
244	} else {
245	    to->data = (unsigned char*) PORT_Alloc(from->len);
246	}
247	
248	if (!to->data) {
249	    return SECFailure;
250	}
251	PORT_Memcpy(to->data, from->data, from->len);
252	to->len = from->len;
253    } else {
254	/*
255	 * If from->data is NULL but from->len is nonzero, this function
256	 * will succeed.  Is this right?
257	 */
258	to->data = 0;
259	to->len = 0;
260    }
261    return SECSuccess;
262}
263
264void
265SECITEM_FreeItem(SECItem *zap, PRBool freeit)
266{
267    if (zap) {
268	PORT_Free(zap->data);
269	zap->data = 0;
270	zap->len = 0;
271	if (freeit) {
272	    PORT_Free(zap);
273	}
274    }
275}
276
277void
278SECITEM_ZfreeItem(SECItem *zap, PRBool freeit)
279{
280    if (zap) {
281	PORT_ZFree(zap->data, zap->len);
282	zap->data = 0;
283	zap->len = 0;
284	if (freeit) {
285	    PORT_ZFree(zap, sizeof(SECItem));
286	}
287    }
288}
289/* these reroutines were taken from pkix oid.c, which is supposed to
290 * replace this file some day */
291/*
292 * This is the hash function.  We simply XOR the encoded form with
293 * itself in sizeof(PLHashNumber)-byte chunks.  Improving this
294 * routine is left as an excercise for the more mathematically
295 * inclined student.
296 */
297PLHashNumber PR_CALLBACK
298SECITEM_Hash ( const void *key)
299{
300    const SECItem *item = (const SECItem *)key;
301    PLHashNumber rv = 0;
302
303    PRUint8 *data = (PRUint8 *)item->data;
304    PRUint32 i;
305    PRUint8 *rvc = (PRUint8 *)&rv;
306
307    for( i = 0; i < item->len; i++ ) {
308        rvc[ i % sizeof(rv) ] ^= *data;
309        data++;
310    }
311
312    return rv;
313}
314
315/*
316 * This is the key-compare function.  It simply does a lexical
317 * comparison on the item data.  This does not result in
318 * quite the same ordering as the "sequence of numbers" order,
319 * but heck it's only used internally by the hash table anyway.
320 */
321PRIntn PR_CALLBACK
322SECITEM_HashCompare ( const void *k1, const void *k2)
323{
324    const SECItem *i1 = (const SECItem *)k1;
325    const SECItem *i2 = (const SECItem *)k2;
326
327    return SECITEM_ItemsAreEqual(i1,i2);
328}