Back to index

lightning-sunbird  0.9+nobinonly
secitem.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /*
00038  * Support routines for SECItem data structure.
00039  *
00040  * $Id: secitem.c,v 1.11.28.2 2006/04/25 04:37:13 nelson%bolyard.com Exp $
00041  */
00042 
00043 #include "seccomon.h"
00044 #include "secitem.h"
00045 #include "base64.h"
00046 #include "secerr.h"
00047 
00048 SECItem *
00049 SECITEM_AllocItem(PRArenaPool *arena, SECItem *item, unsigned int len)
00050 {
00051     SECItem *result = NULL;
00052     void *mark = NULL;
00053 
00054     if (arena != NULL) {
00055        mark = PORT_ArenaMark(arena);
00056     }
00057 
00058     if (item == NULL) {
00059        if (arena != NULL) {
00060            result = PORT_ArenaZAlloc(arena, sizeof(SECItem));
00061        } else {
00062            result = PORT_ZAlloc(sizeof(SECItem));
00063        }
00064        if (result == NULL) {
00065            goto loser;
00066        }
00067     } else {
00068        PORT_Assert(item->data == NULL);
00069        result = item;
00070     }
00071 
00072     result->len = len;
00073     if (len) {
00074        if (arena != NULL) {
00075            result->data = PORT_ArenaAlloc(arena, len);
00076        } else {
00077            result->data = PORT_Alloc(len);
00078        }
00079     }
00080 
00081     if (mark) {
00082        PORT_ArenaUnmark(arena, mark);
00083     }
00084     return(result);
00085 
00086 loser:
00087     if ( arena != NULL ) {
00088        if (mark) {
00089            PORT_ArenaRelease(arena, mark);
00090        }
00091        if (item != NULL) {
00092            item->data = NULL;
00093            item->len = 0;
00094        }
00095     } else {
00096        if (result != NULL) {
00097            SECITEM_FreeItem(result, (item == NULL) ? PR_TRUE : PR_FALSE);
00098        }
00099     }
00100     return(NULL);
00101 }
00102 
00103 SECStatus
00104 SECITEM_ReallocItem(PRArenaPool *arena, SECItem *item, unsigned int oldlen,
00105                   unsigned int newlen)
00106 {
00107     PORT_Assert(item != NULL);
00108     if (item == NULL) {
00109        /* XXX Set error.  But to what? */
00110        return SECFailure;
00111     }
00112 
00113     /*
00114      * If no old length, degenerate to just plain alloc.
00115      */
00116     if (oldlen == 0) {
00117        PORT_Assert(item->data == NULL || item->len == 0);
00118        if (newlen == 0) {
00119            /* Nothing to do.  Weird, but not a failure.  */
00120            return SECSuccess;
00121        }
00122        item->len = newlen;
00123        if (arena != NULL) {
00124            item->data = PORT_ArenaAlloc(arena, newlen);
00125        } else {
00126            item->data = PORT_Alloc(newlen);
00127        }
00128     } else {
00129        if (arena != NULL) {
00130            item->data = PORT_ArenaGrow(arena, item->data, oldlen, newlen);
00131        } else {
00132            item->data = PORT_Realloc(item->data, newlen);
00133        }
00134     }
00135 
00136     if (item->data == NULL) {
00137        return SECFailure;
00138     }
00139 
00140     return SECSuccess;
00141 }
00142 
00143 SECComparison
00144 SECITEM_CompareItem(const SECItem *a, const SECItem *b)
00145 {
00146     unsigned m;
00147     SECComparison rv;
00148 
00149     if (!a || !a->len || !a->data) 
00150         return (!b || !b->len || !b->data) ? SECEqual : SECLessThan;
00151     if (!b || !b->len || !b->data) 
00152        return SECGreaterThan;
00153 
00154     m = ( ( a->len < b->len ) ? a->len : b->len );
00155     
00156     rv = (SECComparison) PORT_Memcmp(a->data, b->data, m);
00157     if (rv) {
00158        return rv;
00159     }
00160     if (a->len < b->len) {
00161        return SECLessThan;
00162     }
00163     if (a->len == b->len) {
00164        return SECEqual;
00165     }
00166     return SECGreaterThan;
00167 }
00168 
00169 PRBool
00170 SECITEM_ItemsAreEqual(const SECItem *a, const SECItem *b)
00171 {
00172     if (a->len != b->len)
00173         return PR_FALSE;
00174     if (!a->len)
00175        return PR_TRUE;
00176     if (!a->data || !b->data) {
00177         /* avoid null pointer crash. */
00178        return (PRBool)(a->data == b->data);
00179     }
00180     return (PRBool)!PORT_Memcmp(a->data, b->data, a->len);
00181 }
00182 
00183 SECItem *
00184 SECITEM_DupItem(const SECItem *from)
00185 {
00186     return SECITEM_ArenaDupItem(NULL, from);
00187 }
00188 
00189 SECItem *
00190 SECITEM_ArenaDupItem(PRArenaPool *arena, const SECItem *from)
00191 {
00192     SECItem *to;
00193     
00194     if ( from == NULL ) {
00195        return(NULL);
00196     }
00197     
00198     if ( arena != NULL ) {
00199        to = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem));
00200     } else {
00201        to = (SECItem *)PORT_Alloc(sizeof(SECItem));
00202     }
00203     if ( to == NULL ) {
00204        return(NULL);
00205     }
00206 
00207     if ( arena != NULL ) {
00208        to->data = (unsigned char *)PORT_ArenaAlloc(arena, from->len);
00209     } else {
00210        to->data = (unsigned char *)PORT_Alloc(from->len);
00211     }
00212     if ( to->data == NULL ) {
00213        PORT_Free(to);
00214        return(NULL);
00215     }
00216 
00217     to->len = from->len;
00218     to->type = from->type;
00219     if ( to->len ) {
00220        PORT_Memcpy(to->data, from->data, to->len);
00221     }
00222     
00223     return(to);
00224 }
00225 
00226 SECStatus
00227 SECITEM_CopyItem(PRArenaPool *arena, SECItem *to, const SECItem *from)
00228 {
00229     to->type = from->type;
00230     if (from->data && from->len) {
00231        if ( arena ) {
00232            to->data = (unsigned char*) PORT_ArenaAlloc(arena, from->len);
00233        } else {
00234            to->data = (unsigned char*) PORT_Alloc(from->len);
00235        }
00236        
00237        if (!to->data) {
00238            return SECFailure;
00239        }
00240        PORT_Memcpy(to->data, from->data, from->len);
00241        to->len = from->len;
00242     } else {
00243        to->data = 0;
00244        to->len = 0;
00245     }
00246     return SECSuccess;
00247 }
00248 
00249 void
00250 SECITEM_FreeItem(SECItem *zap, PRBool freeit)
00251 {
00252     if (zap) {
00253        PORT_Free(zap->data);
00254        zap->data = 0;
00255        zap->len = 0;
00256        if (freeit) {
00257            PORT_Free(zap);
00258        }
00259     }
00260 }
00261 
00262 void
00263 SECITEM_ZfreeItem(SECItem *zap, PRBool freeit)
00264 {
00265     if (zap) {
00266        PORT_ZFree(zap->data, zap->len);
00267        zap->data = 0;
00268        zap->len = 0;
00269        if (freeit) {
00270            PORT_ZFree(zap, sizeof(SECItem));
00271        }
00272     }
00273 }
00274 /* these reroutines were taken from pkix oid.c, which is supposed to
00275  * replace this file some day */
00276 /*
00277  * This is the hash function.  We simply XOR the encoded form with
00278  * itself in sizeof(PLHashNumber)-byte chunks.  Improving this
00279  * routine is left as an excercise for the more mathematically
00280  * inclined student.
00281  */
00282 PLHashNumber PR_CALLBACK
00283 SECITEM_Hash ( const void *key)
00284 {
00285     const SECItem *item = (const SECItem *)key;
00286     PLHashNumber rv = 0;
00287 
00288     PRUint8 *data = (PRUint8 *)item->data;
00289     PRUint32 i;
00290     PRUint8 *rvc = (PRUint8 *)&rv;
00291 
00292     for( i = 0; i < item->len; i++ ) {
00293         rvc[ i % sizeof(rv) ] ^= *data;
00294         data++;
00295     }
00296 
00297     return rv;
00298 }
00299 
00300 /*
00301  * This is the key-compare function.  It simply does a lexical
00302  * comparison on the item data.  This does not result in
00303  * quite the same ordering as the "sequence of numbers" order,
00304  * but heck it's only used internally by the hash table anyway.
00305  */
00306 PRIntn PR_CALLBACK
00307 SECITEM_HashCompare ( const void *k1, const void *k2)
00308 {
00309     const SECItem *i1 = (const SECItem *)k1;
00310     const SECItem *i2 = (const SECItem *)k2;
00311 
00312     return SECITEM_ItemsAreEqual(i1,i2);
00313 }