tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkix_pl_bytearray.c (16129B)


      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 * pkix_pl_bytearray.c
      6 *
      7 * ByteArray Object Functions
      8 *
      9 */
     10 
     11 #include "pkix_pl_bytearray.h"
     12 
     13 /* --Private-ByteArray-Functions------------------------------------- */
     14 
     15 /*
     16 * FUNCTION: pkix_pl_ByteArray_ToHexString
     17 * DESCRIPTION:
     18 *
     19 *  Creates a hex-String representation of the ByteArray pointed to by "array"
     20 *  and stores the result at "pString". The hex-String consists of hex-digit
     21 *  pairs separated by spaces, and the entire string enclosed within square
     22 *  brackets, e.g. [43 61 6E 20 79 6F 75 20 72 65 61 64 20 74 68 69 73 3F].
     23 *  A zero-length ByteArray is represented as [].
     24 * PARAMETERS
     25 *  "array"
     26 *      ByteArray to be represented by the hex-String; must be non-NULL
     27 *  "pString"
     28 *      Address where String will be stored. Must be non-NULL.
     29 *  "plContext"
     30 *      Platform-specific context pointer.
     31 * THREAD SAFETY:
     32 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
     33 * RETURNS:
     34 *  Returns NULL if the function succeeds.
     35 *  Returns a Cert Error if the function fails in a non-fatal way.
     36 *  Returns a Fatal Error if the function fails in an unrecoverable way.
     37 */
     38 PKIX_Error *
     39 pkix_pl_ByteArray_ToHexString(
     40        PKIX_PL_ByteArray *array,
     41        PKIX_PL_String **pString,
     42        void *plContext)
     43 {
     44        char *tempText = NULL;
     45        char *stringText = NULL; /* "[XX XX XX ...]" */
     46        PKIX_UInt32 i, outputLen, bufferSize;
     47 
     48        PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_ToHexString");
     49        PKIX_NULLCHECK_TWO(array, pString);
     50 
     51        if ((array->length) == 0) {
     52                PKIX_CHECK(PKIX_PL_String_Create
     53                        (PKIX_ESCASCII, "[]", 0, pString, plContext),
     54                        PKIX_COULDNOTCREATESTRING);
     55        } else {
     56                /*
     57                 * Allocate space for format string
     58                 * '[' + "XX" + (n-1)*" XX" + ']' + '\0'
     59                 */
     60                bufferSize = 2 + (3*(array->length));
     61 
     62                PKIX_CHECK(PKIX_PL_Malloc
     63                        (bufferSize, (void **)&stringText, plContext),
     64                        PKIX_COULDNOTALLOCATEMEMORY);
     65 
     66                stringText[0] = 0;
     67                outputLen = 0;
     68 
     69                PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
     70                tempText = PR_smprintf
     71                        ("[%02X", (0x0FF&((char *)(array->array))[0]));
     72                PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
     73                outputLen += PL_strlen(tempText);
     74 
     75                PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
     76                stringText = PL_strcat(stringText, tempText);
     77 
     78                PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
     79                PR_smprintf_free(tempText);
     80 
     81                for (i = 1; i < array->length; i++) {
     82                        PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
     83                        tempText = PR_smprintf
     84                                (" %02X", (0x0FF&((char *)(array->array))[i]));
     85 
     86                        if (tempText == NULL){
     87                                PKIX_ERROR(PKIX_PRSMPRINTFFAILED);
     88                        }
     89 
     90                        PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
     91                        outputLen += PL_strlen(tempText);
     92 
     93                        PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
     94                        stringText = PL_strcat(stringText, tempText);
     95 
     96                        PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
     97                        PR_smprintf_free(tempText);
     98                        tempText = NULL;
     99                }
    100 
    101                stringText[outputLen++] = ']';
    102                stringText[outputLen] = 0;
    103 
    104                PKIX_CHECK(PKIX_PL_String_Create
    105                        (PKIX_ESCASCII,
    106                        stringText,
    107                        0,
    108                        pString,
    109                        plContext),
    110                        PKIX_COULDNOTCREATESTRING);
    111        }
    112 
    113 cleanup:
    114 
    115        PKIX_FREE(stringText);
    116        PKIX_RETURN(BYTEARRAY);
    117 }
    118 
    119 /*
    120 * FUNCTION: pkix_pl_ByteArray_Comparator
    121 * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
    122 *
    123 *  NOTE:
    124 *  It is not clear that this definition of comparing byte arrays makes
    125 *  sense. It does allow you to tell whether two blocks of memory are
    126 *  identical, so we only use it for the Equals function (i.e. we don't
    127 *  register it as a Compare function for ByteArray).
    128 */
    129 static PKIX_Error *
    130 pkix_pl_ByteArray_Comparator(
    131        PKIX_PL_Object *firstObject,
    132        PKIX_PL_Object *secondObject,
    133        PKIX_Int32 *pResult,
    134        void *plContext)
    135 {
    136        PKIX_PL_ByteArray *firstByteArray = NULL;
    137        PKIX_PL_ByteArray *secondByteArray = NULL;
    138        unsigned char *firstData = NULL;
    139        unsigned char *secondData = NULL;
    140        PKIX_UInt32 i;
    141 
    142        PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Comparator");
    143        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
    144 
    145        PKIX_CHECK(pkix_CheckTypes
    146                (firstObject, secondObject, PKIX_BYTEARRAY_TYPE, plContext),
    147                PKIX_ARGUMENTSNOTBYTEARRAYS);
    148 
    149        /* It's safe to cast */
    150        firstByteArray = (PKIX_PL_ByteArray *)firstObject;
    151        secondByteArray = (PKIX_PL_ByteArray *)secondObject;
    152 
    153        *pResult = 0;
    154        firstData = (unsigned char *)firstByteArray->array;
    155        secondData = (unsigned char *)secondByteArray->array;
    156 
    157        if (firstByteArray->length < secondByteArray->length) {
    158                *pResult = -1;
    159        } else if (firstByteArray->length > secondByteArray->length) {
    160                *pResult = 1;
    161        } else if (firstByteArray->length == secondByteArray->length) {
    162                /* Check if both array contents are identical */
    163                for (i = 0;
    164                    (i < firstByteArray->length) && (*pResult == 0);
    165                    i++) {
    166                        if (firstData[i] < secondData[i]) {
    167                                *pResult = -1;
    168                        } else if (firstData[i] > secondData[i]) {
    169                                *pResult = 1;
    170                        }
    171                }
    172        }
    173 
    174 cleanup:
    175 
    176        PKIX_RETURN(BYTEARRAY);
    177 }
    178 
    179 /*
    180 * FUNCTION: pkix_pl_ByteArray_ToString
    181 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
    182 */
    183 static PKIX_Error *
    184 pkix_pl_ByteArray_ToString(
    185        PKIX_PL_Object *object,
    186        PKIX_PL_String **pString,
    187        void *plContext)
    188 {
    189        PKIX_PL_ByteArray *array = NULL;
    190        char *tempText = NULL;
    191        char *stringText = NULL; /* "[OOO, OOO, ... OOO]" */
    192        PKIX_UInt32 i, outputLen, bufferSize;
    193 
    194        PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_ToString");
    195        PKIX_NULLCHECK_TWO(object, pString);
    196 
    197        PKIX_CHECK(pkix_CheckType(object, PKIX_BYTEARRAY_TYPE, plContext),
    198                    PKIX_OBJECTNOTBYTEARRAY);
    199 
    200        array = (PKIX_PL_ByteArray *)object;
    201 
    202        if ((array->length) == 0) {
    203                PKIX_CHECK(PKIX_PL_String_Create
    204                        (PKIX_ESCASCII, "[]", 0, pString, plContext),
    205                        PKIX_COULDNOTCREATESTRING);
    206        } else {
    207                /* Allocate space for "XXX, ". */
    208                bufferSize = 2+5*array->length;
    209 
    210                /* Allocate space for format string */
    211                PKIX_CHECK(PKIX_PL_Malloc
    212                        (bufferSize, (void **)&stringText, plContext),
    213                        PKIX_MALLOCFAILED);
    214 
    215                stringText[0] = 0;
    216                outputLen = 0;
    217 
    218                PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
    219                tempText =
    220                        PR_smprintf
    221                            ("[%03u", (0x0FF&((char *)(array->array))[0]));
    222                PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
    223                outputLen += PL_strlen(tempText);
    224 
    225                PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
    226                stringText = PL_strcat(stringText, tempText);
    227 
    228                PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
    229                PR_smprintf_free(tempText);
    230 
    231                for (i = 1; i < array->length; i++) {
    232                        PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
    233                        tempText = PR_smprintf
    234                                (", %03u",
    235                                (0x0FF&((char *)(array->array))[i]));
    236 
    237                        if (tempText == NULL){
    238                                PKIX_ERROR(PKIX_PRSMPRINTFFAILED);
    239                        }
    240 
    241                        PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
    242                        outputLen += PL_strlen(tempText);
    243 
    244                        PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
    245                        stringText = PL_strcat(stringText, tempText);
    246 
    247                        PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
    248                        PR_smprintf_free(tempText);
    249                        tempText = NULL;
    250                }
    251 
    252                stringText[outputLen++] = ']';
    253                stringText[outputLen] = 0;
    254 
    255                PKIX_CHECK(PKIX_PL_String_Create
    256                        (PKIX_ESCASCII, stringText, 0, pString, plContext),
    257                        PKIX_STRINGCREATEFAILED);
    258 
    259        }
    260 
    261 cleanup:
    262 
    263        PKIX_FREE(stringText);
    264        PKIX_RETURN(BYTEARRAY);
    265 }
    266 
    267 /*
    268 * FUNCTION: pkix_pl_ByteArray_Equals
    269 * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
    270 */
    271 static PKIX_Error *
    272 pkix_pl_ByteArray_Equals(
    273        PKIX_PL_Object *first,
    274        PKIX_PL_Object *second,
    275        PKIX_Boolean *pResult,
    276        void *plContext)
    277 {
    278        PKIX_UInt32 secondType;
    279        PKIX_Int32 cmpResult = 0;
    280 
    281        PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Equals");
    282        PKIX_NULLCHECK_THREE(first, second, pResult);
    283 
    284        /* Sanity check: Test that "first" is a ByteArray */
    285        PKIX_CHECK(pkix_CheckType(first, PKIX_BYTEARRAY_TYPE, plContext),
    286                    PKIX_FIRSTARGUMENTNOTBYTEARRAY);
    287 
    288        PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
    289                    PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
    290 
    291        /* If types differ, then we will return false */
    292        *pResult = PKIX_FALSE;
    293 
    294        /* Second type may not be a BA */
    295        if (secondType != PKIX_BYTEARRAY_TYPE) goto cleanup;
    296 
    297        /* It's safe to cast here */
    298        PKIX_CHECK(pkix_pl_ByteArray_Comparator
    299                (first, second, &cmpResult, plContext),
    300                PKIX_BYTEARRAYCOMPARATORFAILED);
    301 
    302        /* ByteArrays are equal iff Comparator Result is 0 */
    303        *pResult = (cmpResult == 0);
    304 
    305 cleanup:
    306 
    307        PKIX_RETURN(BYTEARRAY);
    308 }
    309 
    310 /*
    311 * FUNCTION: pkix_pl_ByteArray_Destroy
    312 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
    313 */
    314 static PKIX_Error *
    315 pkix_pl_ByteArray_Destroy(
    316        PKIX_PL_Object *object,
    317        void *plContext)
    318 {
    319        PKIX_PL_ByteArray *array = NULL;
    320 
    321        PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Destroy");
    322        PKIX_NULLCHECK_ONE(object);
    323 
    324        PKIX_CHECK(pkix_CheckType(object, PKIX_BYTEARRAY_TYPE, plContext),
    325                    PKIX_OBJECTNOTBYTEARRAY);
    326 
    327        array = (PKIX_PL_ByteArray*)object;
    328 
    329        PKIX_FREE(array->array);
    330        array->array = NULL;
    331        array->length = 0;
    332 
    333 cleanup:
    334 
    335        PKIX_RETURN(BYTEARRAY);
    336 }
    337 
    338 /*
    339 * FUNCTION: pkix_pl_ByteArray_Hashcode
    340 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
    341 */
    342 static PKIX_Error *
    343 pkix_pl_ByteArray_Hashcode(
    344        PKIX_PL_Object *object,
    345        PKIX_UInt32 *pHashcode,
    346        void *plContext)
    347 {
    348        PKIX_PL_ByteArray *array = NULL;
    349 
    350        PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Hashcode");
    351        PKIX_NULLCHECK_TWO(object, pHashcode);
    352 
    353        PKIX_CHECK(pkix_CheckType(object, PKIX_BYTEARRAY_TYPE, plContext),
    354                    PKIX_OBJECTNOTBYTEARRAY);
    355 
    356        array = (PKIX_PL_ByteArray*)object;
    357 
    358        PKIX_CHECK(pkix_hash
    359                ((const unsigned char *)array->array,
    360                array->length,
    361                pHashcode,
    362                plContext),
    363                PKIX_HASHFAILED);
    364 
    365 cleanup:
    366 
    367        PKIX_RETURN(BYTEARRAY);
    368 }
    369 
    370 /*
    371 * FUNCTION: pkix_pl_ByteArray_RegisterSelf
    372 * DESCRIPTION:
    373 * Registers PKIX_BYTEARRAY_TYPE and its related functions with systemClasses[]
    374 * THREAD SAFETY:
    375 *  Not Thread Safe - for performance and complexity reasons
    376 *
    377 *  Since this function is only called by PKIX_PL_Initialize, which should
    378 *  only be called once, it is acceptable that this function is not
    379 *  thread-safe.
    380 */
    381 PKIX_Error *
    382 pkix_pl_ByteArray_RegisterSelf(void *plContext)
    383 {
    384 
    385        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
    386        pkix_ClassTable_Entry entry;
    387 
    388        PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_RegisterSelf");
    389 
    390        entry.description = "ByteArray";
    391        entry.objCounter = 0;
    392        entry.typeObjectSize = sizeof(PKIX_PL_ByteArray);
    393        entry.destructor = pkix_pl_ByteArray_Destroy;
    394        entry.equalsFunction = pkix_pl_ByteArray_Equals;
    395        entry.hashcodeFunction = pkix_pl_ByteArray_Hashcode;
    396        entry.toStringFunction = pkix_pl_ByteArray_ToString;
    397        entry.comparator = NULL;
    398        entry.duplicateFunction = pkix_duplicateImmutable;
    399 
    400        systemClasses[PKIX_BYTEARRAY_TYPE] = entry;
    401 
    402        PKIX_RETURN(BYTEARRAY);
    403 }
    404 
    405 /* --Public-Functions------------------------------------------------------- */
    406 
    407 /*
    408 * FUNCTION: PKIX_PL_ByteArray_Create (see comments in pkix_pl_system.h)
    409 */
    410 PKIX_Error *
    411 PKIX_PL_ByteArray_Create(
    412        void *array,
    413        PKIX_UInt32 length,
    414        PKIX_PL_ByteArray **pByteArray,
    415        void *plContext)
    416 {
    417        PKIX_PL_ByteArray *byteArray = NULL;
    418 
    419        PKIX_ENTER(BYTEARRAY, "PKIX_PL_ByteArray_Create");
    420        PKIX_NULLCHECK_ONE(pByteArray);
    421 
    422        PKIX_CHECK(PKIX_PL_Object_Alloc
    423                (PKIX_BYTEARRAY_TYPE,
    424                sizeof (PKIX_PL_ByteArray),
    425                (PKIX_PL_Object **)&byteArray,
    426                plContext),
    427                PKIX_COULDNOTCREATEOBJECTSTORAGE);
    428 
    429        byteArray->length = length;
    430        byteArray->array = NULL;
    431 
    432        if (length != 0){
    433                /* Alloc space for array */
    434                PKIX_NULLCHECK_ONE(array);
    435 
    436                PKIX_CHECK(PKIX_PL_Malloc
    437                            (length, (void**)&(byteArray->array), plContext),
    438                            PKIX_MALLOCFAILED);
    439 
    440                PKIX_BYTEARRAY_DEBUG("\tCalling PORT_Memcpy).\n");
    441                (void) PORT_Memcpy(byteArray->array, array, length);
    442        }
    443 
    444        *pByteArray = byteArray;
    445 
    446 cleanup:
    447 
    448        if (PKIX_ERROR_RECEIVED){
    449                PKIX_DECREF(byteArray);
    450        }
    451 
    452        PKIX_RETURN(BYTEARRAY);
    453 }
    454 
    455 /*
    456 * FUNCTION: PKIX_PL_ByteArray_GetPointer (see comments in pkix_pl_system.h)
    457 */
    458 PKIX_Error *
    459 PKIX_PL_ByteArray_GetPointer(
    460        PKIX_PL_ByteArray *byteArray,
    461        void **pArray,
    462        void *plContext)
    463 {
    464        void *bytes = NULL;
    465        PKIX_ENTER(BYTEARRAY, "PKIX_PL_ByteArray_GetPointer");
    466        PKIX_NULLCHECK_TWO(byteArray, pArray);
    467 
    468        if (byteArray->length != 0){
    469                PKIX_CHECK(PKIX_PL_Malloc
    470                            (byteArray->length, &bytes, plContext),
    471                            PKIX_MALLOCFAILED);
    472 
    473                PKIX_BYTEARRAY_DEBUG("\tCalling PORT_Memcpy).\n");
    474                (void) PORT_Memcpy
    475                        (bytes, byteArray->array, byteArray->length);
    476        }
    477 
    478        *pArray = bytes;
    479 
    480 cleanup:
    481 
    482        if (PKIX_ERROR_RECEIVED){
    483                PKIX_FREE(bytes);
    484        }
    485 
    486        PKIX_RETURN(BYTEARRAY);
    487 }
    488 
    489 /*
    490 * FUNCTION: PKIX_PL_ByteArray_GetLength (see comments in pkix_pl_system.h)
    491 */
    492 PKIX_Error *
    493 PKIX_PL_ByteArray_GetLength(
    494        PKIX_PL_ByteArray *byteArray,
    495        PKIX_UInt32 *pLength,
    496        void *plContext)
    497 {
    498        PKIX_ENTER(BYTEARRAY, "PKIX_PL_ByteArray_GetLength");
    499        PKIX_NULLCHECK_TWO(byteArray, pLength);
    500 
    501        *pLength = byteArray->length;
    502 
    503        PKIX_RETURN(BYTEARRAY);
    504 }