]> git.saurik.com Git - apple/security.git/blob - libsecurity_smime/lib/SecAsn1Item.c
Security-59306.101.1.tar.gz
[apple/security.git] / libsecurity_smime / lib / SecAsn1Item.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 SecAsn1Item data structure.
36 */
37
38 #include "SecAsn1Item.h"
39 #include <security_asn1/seccomon.h>
40 #include <security_asn1/secerr.h>
41 #include <security_asn1/secport.h>
42
43 SecAsn1Item *
44 SECITEM_AllocItem(PRArenaPool *arena, SecAsn1Item *item, size_t len)
45 {
46 SecAsn1Item *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(SecAsn1Item));
56 } else {
57 result = PORT_ZAlloc(sizeof(SecAsn1Item));
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 ) {
83 if (mark) {
84 PORT_ArenaRelease(arena, mark);
85 }
86 if (item != NULL) {
87 item->Data = NULL;
88 item->Length = 0;
89 }
90 } else {
91 if (result != NULL) {
92 SECITEM_FreeItem(result, (item == NULL) ? PR_TRUE : PR_FALSE);
93 }
94 }
95 return(NULL);
96 }
97
98 SECStatus
99 SECITEM_ReallocItem(PRArenaPool *arena, SecAsn1Item *item, size_t oldlen,
100 size_t newlen)
101 {
102 PORT_Assert(item != NULL);
103 if (item == NULL) {
104 /* XXX Set error. But to what? */
105 return SECFailure;
106 }
107
108 /*
109 * If no old length, degenerate to just plain alloc.
110 */
111 if (oldlen == 0) {
112 PORT_Assert(item->Data == NULL || item->Length == 0);
113 if (newlen == 0) {
114 /* Nothing to do. Weird, but not a failure. */
115 return SECSuccess;
116 }
117 item->Length = newlen;
118 if (arena != NULL) {
119 item->Data = PORT_ArenaAlloc(arena, newlen);
120 } else {
121 item->Data = PORT_Alloc(newlen);
122 }
123 } else {
124 if (arena != NULL) {
125 item->Data = PORT_ArenaGrow(arena, item->Data, oldlen, newlen);
126 } else {
127 item->Data = PORT_Realloc(item->Data, newlen);
128 }
129 }
130
131 if (item->Data == NULL) {
132 return SECFailure;
133 }
134
135 return SECSuccess;
136 }
137
138 SECComparison
139 SECITEM_CompareItem(const SecAsn1Item *a, const SecAsn1Item *b)
140 {
141 size_t m;
142 SECComparison rv;
143
144 m = ( ( a->Length < b->Length ) ? a->Length : b->Length );
145
146 rv = (SECComparison) PORT_Memcmp(a->Data, b->Data, m);
147 if (rv) {
148 return rv;
149 }
150 if (a->Length < b->Length) {
151 return SECLessThan;
152 }
153 if (a->Length == b->Length) {
154 return SECEqual;
155 }
156 return SECGreaterThan;
157 }
158
159 Boolean
160 SECITEM_ItemsAreEqual(const SecAsn1Item *a, const SecAsn1Item *b)
161 {
162 if (a->Length != b->Length)
163 return PR_FALSE;
164 if (!a->Length)
165 return PR_TRUE;
166 if (!a->Data || !b->Data) {
167 /* avoid null pointer crash. */
168 return (Boolean)(a->Data == b->Data);
169 }
170 return (Boolean)!PORT_Memcmp(a->Data, b->Data, a->Length);
171 }
172
173 SecAsn1Item *
174 SECITEM_DupItem(const SecAsn1Item *from)
175 {
176 return SECITEM_ArenaDupItem(NULL, from);
177 }
178
179 SecAsn1Item *
180 SECITEM_ArenaDupItem(PRArenaPool *arena, const SecAsn1Item *from)
181 {
182 SecAsn1Item *to;
183
184 if ( from == NULL ) {
185 return(NULL);
186 }
187
188 if ( arena != NULL ) {
189 to = (SecAsn1Item *)PORT_ArenaAlloc(arena, sizeof(SecAsn1Item));
190 } else {
191 to = (SecAsn1Item *)PORT_Alloc(sizeof(SecAsn1Item));
192 }
193 if ( to == NULL ) {
194 return(NULL);
195 }
196
197 if ( arena != NULL ) {
198 to->Data = (unsigned char *)PORT_ArenaAlloc(arena, from->Length);
199 } else {
200 to->Data = (unsigned char *)PORT_Alloc(from->Length);
201 }
202 if ( to->Data == NULL ) {
203 PORT_Free(to);
204 return(NULL);
205 }
206
207 to->Length = from->Length;
208 // to->type = from->type;
209 if ( to->Length ) {
210 PORT_Memcpy(to->Data, from->Data, to->Length);
211 }
212
213 return(to);
214 }
215
216 SECStatus
217 SECITEM_CopyItem(PRArenaPool *arena, SecAsn1Item *to, const SecAsn1Item *from)
218 {
219 // to->type = from->type;
220 if (from->Data && from->Length) {
221 if ( arena ) {
222 to->Data = (unsigned char*) PORT_ArenaAlloc(arena, from->Length);
223 } else {
224 to->Data = (unsigned char*) PORT_Alloc(from->Length);
225 }
226
227 if (!to->Data) {
228 return SECFailure;
229 }
230 PORT_Memcpy(to->Data, from->Data, from->Length);
231 to->Length = from->Length;
232 } else {
233 to->Data = 0;
234 to->Length = 0;
235 }
236 return SECSuccess;
237 }
238
239 void
240 SECITEM_FreeItem(SecAsn1Item *zap, Boolean freeit)
241 {
242 if (zap) {
243 PORT_Free(zap->Data);
244 zap->Data = 0;
245 zap->Length = 0;
246 if (freeit) {
247 PORT_Free(zap);
248 }
249 }
250 }
251
252 void
253 SECITEM_ZfreeItem(SecAsn1Item *zap, Boolean freeit)
254 {
255 if (zap) {
256 PORT_ZFree(zap->Data, zap->Length);
257 zap->Data = 0;
258 zap->Length = 0;
259 if (freeit) {
260 PORT_ZFree(zap, sizeof(SecAsn1Item));
261 }
262 }
263 }
264
265
266 /* these reroutines were taken from pkix oid.c, which is supposed to
267 * replace this file some day */
268 /*
269 * This is the hash function. We simply XOR the encoded form with
270 * itself in sizeof(PLHashNumber)-byte chunks. Improving this
271 * routine is left as an excercise for the more mathematically
272 * inclined student.
273 */
274 PLHashNumber PR_CALLBACK
275 SECITEM_Hash ( const void *key)
276 {
277 const SecAsn1Item *item = (const SecAsn1Item *)key;
278 PLHashNumber rv = 0;
279
280 PRUint8 *data = (PRUint8 *)item->Data;
281 PRUint8 *rvc = (PRUint8 *)&rv;
282
283 size_t i;
284
285 for( i = 0; i < item->Length; i++ ) {
286 rvc[ i % sizeof(rv) ] ^= *data;
287 data++;
288 }
289
290 return rv;
291 }
292
293 /*
294 * This is the key-compare function. It simply does a lexical
295 * comparison on the item data. This does not result in
296 * quite the same ordering as the "sequence of numbers" order,
297 * but heck it's only used internally by the hash table anyway.
298 */
299 PRIntn PR_CALLBACK
300 SECITEM_HashCompare ( const void *k1, const void *k2)
301 {
302 const SecAsn1Item *i1 = (const SecAsn1Item *)k1;
303 const SecAsn1Item *i2 = (const SecAsn1Item *)k2;
304
305 return SECITEM_ItemsAreEqual(i1,i2);
306 }