]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_smime/lib/secitem.c
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_smime / lib / secitem.c
1 /*
2 * The contents of this file are subject to the Mozilla Public
3 * License Version 1.1 (the "License"); you may not use this file
4 * except in compliance with the License. You may obtain a copy of
5 * the License at http://www.mozilla.org/MPL/
6 *
7 * Software distributed under the License is distributed on an "AS
8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9 * implied. See the License for the specific language governing
10 * rights and limitations under the License.
11 *
12 * The Original Code is the Netscape security libraries.
13 *
14 * The Initial Developer of the Original Code is Netscape
15 * Communications Corporation. Portions created by Netscape are
16 * Copyright (C) 1994-2000 Netscape Communications Corporation. All
17 * Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * Alternatively, the contents of this file may be used under the
22 * terms of the GNU General Public License Version 2 or later (the
23 * "GPL"), in which case the provisions of the GPL are applicable
24 * instead of those above. If you wish to allow use of your
25 * version of this file only under the terms of the GPL and not to
26 * allow others to use your version of this file under the MPL,
27 * indicate your decision by deleting the provisions above and
28 * replace them with the notice and other provisions required by
29 * the GPL. If you do not delete the provisions above, a recipient
30 * may use your version of this file under either the MPL or the
31 * GPL.
32 */
33
34 /*
35 * Support routines for SECItem data structure.
36 */
37
38 #include "secitem.h"
39 #include <security_asn1/seccomon.h>
40 #include <security_asn1/secerr.h>
41 #include <Security/x509defs.h>
42
43 SECItem *
44 SECITEM_AllocItem(PRArenaPool *arena, SECItem *item, size_t len)
45 {
46 SECItem *result = NULL;
47 void *mark = NULL;
48
49 if (arena != NULL) {
50 mark = PORT_ArenaMark(arena);
51 }
52
53 if (item == NULL) {
54 if (arena != NULL) {
55 result = PORT_ArenaZAlloc(arena, sizeof(SECItem));
56 } else {
57 result = PORT_ZAlloc(sizeof(SECItem));
58 }
59 if (result == NULL) {
60 goto loser;
61 }
62 } else {
63 PORT_Assert(item->Data == NULL);
64 result = item;
65 }
66
67 result->Length = len;
68 if (len) {
69 if (arena != NULL) {
70 result->Data = PORT_ArenaAlloc(arena, len);
71 } else {
72 result->Data = PORT_Alloc(len);
73 }
74 }
75
76 if (mark) {
77 PORT_ArenaUnmark(arena, mark);
78 }
79 return(result);
80
81 loser:
82 if (arena != NULL && mark) {
83 PORT_ArenaRelease(arena, mark);
84 }
85 return(NULL);
86 }
87
88 SECStatus
89 SECITEM_ReallocItem(PRArenaPool *arena, SECItem *item, unsigned int oldlen,
90 unsigned int newlen)
91 {
92 PORT_Assert(item != NULL);
93 if (item == NULL) {
94 /* XXX Set error. But to what? */
95 return SECFailure;
96 }
97
98 /*
99 * If no old length, degenerate to just plain alloc.
100 */
101 if (oldlen == 0) {
102 PORT_Assert(item->Data == NULL || item->Length == 0);
103 if (newlen == 0) {
104 /* Nothing to do. Weird, but not a failure. */
105 return SECSuccess;
106 }
107 item->Length = newlen;
108 if (arena != NULL) {
109 item->Data = PORT_ArenaAlloc(arena, newlen);
110 } else {
111 item->Data = PORT_Alloc(newlen);
112 }
113 } else {
114 if (arena != NULL) {
115 item->Data = PORT_ArenaGrow(arena, item->Data, oldlen, newlen);
116 } else {
117 item->Data = PORT_Realloc(item->Data, newlen);
118 }
119 }
120
121 if (item->Data == NULL) {
122 return SECFailure;
123 }
124
125 return SECSuccess;
126 }
127
128 SECComparison
129 SECITEM_CompareItem(const SECItem *a, const SECItem *b)
130 {
131 CSSM_SIZE m;
132 SECComparison rv;
133
134 m = ( ( a->Length < b->Length ) ? a->Length : b->Length );
135
136 rv = (SECComparison) PORT_Memcmp(a->Data, b->Data, m);
137 if (rv) {
138 return rv;
139 }
140 if (a->Length < b->Length) {
141 return SECLessThan;
142 }
143 if (a->Length == b->Length) {
144 return SECEqual;
145 }
146 return SECGreaterThan;
147 }
148
149 Boolean
150 SECITEM_ItemsAreEqual(const SECItem *a, const SECItem *b)
151 {
152 if (a->Length != b->Length)
153 return PR_FALSE;
154 if (!a->Length)
155 return PR_TRUE;
156 if (!a->Data || !b->Data) {
157 /* avoid null pointer crash. */
158 return (Boolean)(a->Data == b->Data);
159 }
160 return (Boolean)!PORT_Memcmp(a->Data, b->Data, a->Length);
161 }
162
163 SECItem *
164 SECITEM_DupItem(const SECItem *from)
165 {
166 return SECITEM_ArenaDupItem(NULL, from);
167 }
168
169 SECItem *
170 SECITEM_ArenaDupItem(PRArenaPool *arena, const SECItem *from)
171 {
172 SECItem *to;
173
174 if ( from == NULL ) {
175 return(NULL);
176 }
177
178 if ( arena != NULL ) {
179 to = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem));
180 } else {
181 to = (SECItem *)PORT_Alloc(sizeof(SECItem));
182 }
183 if ( to == NULL ) {
184 return(NULL);
185 }
186
187 if ( arena != NULL ) {
188 to->Data = (unsigned char *)PORT_ArenaAlloc(arena, from->Length);
189 } else {
190 to->Data = (unsigned char *)PORT_Alloc(from->Length);
191 }
192 if ( to->Data == NULL ) {
193 PORT_Free(to);
194 return(NULL);
195 }
196
197 to->Length = from->Length;
198 // to->type = from->type;
199 if ( to->Length ) {
200 PORT_Memcpy(to->Data, from->Data, to->Length);
201 }
202
203 return(to);
204 }
205
206 SECStatus
207 SECITEM_CopyItem(PRArenaPool *arena, SECItem *to, const SECItem *from)
208 {
209 // to->type = from->type;
210 if (from->Data && from->Length) {
211 if ( arena ) {
212 to->Data = (unsigned char*) PORT_ArenaAlloc(arena, from->Length);
213 } else {
214 to->Data = (unsigned char*) PORT_Alloc(from->Length);
215 }
216
217 if (!to->Data) {
218 return SECFailure;
219 }
220 PORT_Memcpy(to->Data, from->Data, from->Length);
221 to->Length = from->Length;
222 } else {
223 to->Data = 0;
224 to->Length = 0;
225 }
226 return SECSuccess;
227 }
228
229 void
230 SECITEM_FreeItem(SECItem *zap, Boolean freeit)
231 {
232 if (zap) {
233 PORT_Free(zap->Data);
234 zap->Data = 0;
235 zap->Length = 0;
236 if (freeit) {
237 PORT_Free(zap);
238 }
239 }
240 }
241
242 void
243 SECITEM_ZfreeItem(SECItem *zap, Boolean freeit)
244 {
245 if (zap) {
246 PORT_ZFree(zap->Data, zap->Length);
247 zap->Data = 0;
248 zap->Length = 0;
249 if (freeit) {
250 PORT_ZFree(zap, sizeof(SECItem));
251 }
252 }
253 }
254
255
256 /* these reroutines were taken from pkix oid.c, which is supposed to
257 * replace this file some day */
258 /*
259 * This is the hash function. We simply XOR the encoded form with
260 * itself in sizeof(PLHashNumber)-byte chunks. Improving this
261 * routine is left as an excercise for the more mathematically
262 * inclined student.
263 */
264 PLHashNumber PR_CALLBACK
265 SECITEM_Hash ( const void *key)
266 {
267 const SECItem *item = (const SECItem *)key;
268 PLHashNumber rv = 0;
269
270 PRUint8 *data = (PRUint8 *)item->Data;
271 PRUint32 i;
272 PRUint8 *rvc = (PRUint8 *)&rv;
273
274 for( i = 0; i < item->Length; i++ ) {
275 rvc[ i % sizeof(rv) ] ^= *data;
276 data++;
277 }
278
279 return rv;
280 }
281
282 /*
283 * This is the key-compare function. It simply does a lexical
284 * comparison on the item data. This does not result in
285 * quite the same ordering as the "sequence of numbers" order,
286 * but heck it's only used internally by the hash table anyway.
287 */
288 PRIntn PR_CALLBACK
289 SECITEM_HashCompare ( const void *k1, const void *k2)
290 {
291 const SECItem *i1 = (const SECItem *)k1;
292 const SECItem *i2 = (const SECItem *)k2;
293
294 return SECITEM_ItemsAreEqual(i1,i2);
295 }