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