tor-browser

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

pkix_pl_bigint.c (11276B)


      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_bigint.c
      6 *
      7 * BigInt Object Functions
      8 *
      9 */
     10 
     11 #include "pkix_pl_bigint.h"
     12 
     13 /* --Private-Big-Int-Functions------------------------------------ */
     14 
     15 /*
     16 * FUNCTION: pkix_pl_BigInt_Comparator
     17 * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
     18 */
     19 static PKIX_Error *
     20 pkix_pl_BigInt_Comparator(
     21        PKIX_PL_Object *firstObject,
     22        PKIX_PL_Object *secondObject,
     23        PKIX_Int32 *pResult,
     24        void *plContext)
     25 {
     26        PKIX_PL_BigInt *firstBigInt = NULL;
     27        PKIX_PL_BigInt *secondBigInt = NULL;
     28        char *firstPtr = NULL;
     29        char *secondPtr = NULL;
     30        PKIX_UInt32 firstLen, secondLen;
     31 
     32        PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Comparator");
     33        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
     34 
     35        PKIX_CHECK(pkix_CheckTypes
     36                    (firstObject, secondObject, PKIX_BIGINT_TYPE, plContext),
     37                    PKIX_ARGUMENTSNOTBIGINTS);
     38 
     39        /* It's safe to cast */
     40        firstBigInt = (PKIX_PL_BigInt*)firstObject;
     41        secondBigInt = (PKIX_PL_BigInt*)secondObject;
     42 
     43        *pResult = 0;
     44        firstPtr = firstBigInt->dataRep;
     45        secondPtr = secondBigInt->dataRep;
     46        firstLen = firstBigInt->length;
     47        secondLen = secondBigInt->length;
     48 
     49        if (firstLen < secondLen) {
     50                *pResult = -1;
     51        } else if (firstLen > secondLen) {
     52                *pResult = 1;
     53        } else if (firstLen == secondLen) {
     54                PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcmp).\n");
     55                *pResult = PORT_Memcmp(firstPtr, secondPtr, firstLen);
     56        }
     57 
     58 cleanup:
     59 
     60        PKIX_RETURN(BIGINT);
     61 }
     62 
     63 /*
     64 * FUNCTION: pkix_pl_BigInt_Destroy
     65 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
     66 */
     67 static PKIX_Error *
     68 pkix_pl_BigInt_Destroy(
     69        PKIX_PL_Object *object,
     70        void *plContext)
     71 {
     72        PKIX_PL_BigInt *bigInt = NULL;
     73 
     74        PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Destroy");
     75        PKIX_NULLCHECK_ONE(object);
     76 
     77        PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
     78                    PKIX_OBJECTNOTBIGINT);
     79 
     80        bigInt = (PKIX_PL_BigInt*)object;
     81 
     82        PKIX_FREE(bigInt->dataRep);
     83        bigInt->dataRep = NULL;
     84        bigInt->length = 0;
     85 
     86 cleanup:
     87 
     88        PKIX_RETURN(BIGINT);
     89 }
     90 
     91 
     92 /*
     93 * FUNCTION: pkix_pl_BigInt_ToString
     94 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
     95 */
     96 static PKIX_Error *
     97 pkix_pl_BigInt_ToString(
     98        PKIX_PL_Object *object,
     99        PKIX_PL_String **pString,
    100        void *plContext)
    101 {
    102        PKIX_PL_BigInt *bigInt = NULL;
    103        char *outputText = NULL;
    104        PKIX_UInt32 i, j, lengthChars;
    105 
    106        PKIX_ENTER(BIGINT, "pkix_pl_BigInt_ToString");
    107        PKIX_NULLCHECK_TWO(object, pString);
    108 
    109        PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
    110                    PKIX_OBJECTNOTBIGINT);
    111 
    112        bigInt = (PKIX_PL_BigInt*)object;
    113 
    114        /* number of chars = 2 * (number of bytes) + null terminator */
    115        lengthChars = (bigInt->length * 2) + 1;
    116 
    117        PKIX_CHECK(PKIX_PL_Malloc
    118                    (lengthChars, (void **)&outputText, plContext),
    119                    PKIX_MALLOCFAILED);
    120 
    121        for (i = 0, j = 0; i < bigInt->length; i += 1, j += 2){
    122                outputText[j] = pkix_i2hex
    123                        ((char) ((*(bigInt->dataRep+i) & 0xf0) >> 4));
    124                outputText[j+1] = pkix_i2hex
    125                        ((char) (*(bigInt->dataRep+i) & 0x0f));
    126        }
    127 
    128        outputText[lengthChars-1] = '\0';
    129 
    130        PKIX_CHECK(PKIX_PL_String_Create
    131                    (PKIX_ESCASCII,
    132                    outputText,
    133                    0,
    134                    pString,
    135                    plContext),
    136                    PKIX_STRINGCREATEFAILED);
    137 
    138 cleanup:
    139 
    140        PKIX_FREE(outputText);
    141 
    142        PKIX_RETURN(BIGINT);
    143 }
    144 
    145 
    146 /*
    147 * FUNCTION: pkix_pl_BigInt_Hashcode
    148 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
    149 */
    150 static PKIX_Error *
    151 pkix_pl_BigInt_Hashcode(
    152        PKIX_PL_Object *object,
    153        PKIX_UInt32 *pHashcode,
    154        void *plContext)
    155 {
    156        PKIX_PL_BigInt *bigInt = NULL;
    157 
    158        PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Hashcode");
    159        PKIX_NULLCHECK_TWO(object, pHashcode);
    160 
    161        PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
    162                    PKIX_OBJECTNOTBIGINT);
    163 
    164        bigInt = (PKIX_PL_BigInt*)object;
    165 
    166        PKIX_CHECK(pkix_hash
    167                    ((void *)bigInt->dataRep,
    168                    bigInt->length,
    169                    pHashcode,
    170                    plContext),
    171                    PKIX_HASHFAILED);
    172 
    173 cleanup:
    174 
    175        PKIX_RETURN(BIGINT);
    176 }
    177 
    178 /*
    179 * FUNCTION: pkix_pl_BigInt_Equals
    180 * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
    181 */
    182 static PKIX_Error *
    183 pkix_pl_BigInt_Equals(
    184        PKIX_PL_Object *first,
    185        PKIX_PL_Object *second,
    186        PKIX_Boolean *pResult,
    187        void *plContext)
    188 {
    189        PKIX_UInt32 secondType;
    190        PKIX_Int32 cmpResult = 0;
    191 
    192        PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Equals");
    193        PKIX_NULLCHECK_THREE(first, second, pResult);
    194 
    195        PKIX_CHECK(pkix_CheckType(first, PKIX_BIGINT_TYPE, plContext),
    196                PKIX_FIRSTOBJECTNOTBIGINT);
    197 
    198        PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
    199                PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
    200 
    201        *pResult = PKIX_FALSE;
    202 
    203        if (secondType != PKIX_BIGINT_TYPE) goto cleanup;
    204 
    205        PKIX_CHECK(pkix_pl_BigInt_Comparator
    206                (first, second, &cmpResult, plContext),
    207                PKIX_BIGINTCOMPARATORFAILED);
    208 
    209        *pResult = (cmpResult == 0);
    210 
    211 cleanup:
    212 
    213        PKIX_RETURN(BIGINT);
    214 }
    215 
    216 /*
    217 * FUNCTION: pkix_pl_BigInt_RegisterSelf
    218 * DESCRIPTION:
    219 *  Registers PKIX_BIGINT_TYPE and its related functions with systemClasses[]
    220 * THREAD SAFETY:
    221 *  Not Thread Safe - for performance and complexity reasons
    222 *
    223 *  Since this function is only called by PKIX_PL_Initialize, which should
    224 *  only be called once, it is acceptable that this function is not
    225 *  thread-safe.
    226 */
    227 PKIX_Error *
    228 pkix_pl_BigInt_RegisterSelf(void *plContext)
    229 {
    230 
    231        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
    232        pkix_ClassTable_Entry entry;
    233 
    234        PKIX_ENTER(BIGINT, "pkix_pl_BigInt_RegisterSelf");
    235 
    236        entry.description = "BigInt";
    237        entry.objCounter = 0;
    238        entry.typeObjectSize = sizeof(PKIX_PL_BigInt);
    239        entry.destructor = pkix_pl_BigInt_Destroy;
    240        entry.equalsFunction = pkix_pl_BigInt_Equals;
    241        entry.hashcodeFunction = pkix_pl_BigInt_Hashcode;
    242        entry.toStringFunction = pkix_pl_BigInt_ToString;
    243        entry.comparator = pkix_pl_BigInt_Comparator;
    244        entry.duplicateFunction = pkix_duplicateImmutable;
    245 
    246        systemClasses[PKIX_BIGINT_TYPE] = entry;
    247 
    248        PKIX_RETURN(BIGINT);
    249 }
    250 
    251 /*
    252 * FUNCTION: pkix_pl_BigInt_CreateWithBytes
    253 * DESCRIPTION:
    254 *
    255 *  Creates a new BigInt of size "length" representing the array of bytes
    256 *  pointed to by "bytes" and stores it at "pBigInt". The caller should make
    257 *  sure that the first byte is not 0x00 (unless it is the the only byte).
    258 *  This function does not do that checking.
    259 *
    260 *  Once created, a PKIX_PL_BigInt object is immutable.
    261 *
    262 * PARAMETERS:
    263 *  "bytes"
    264 *      Address of array of bytes. Must be non-NULL.
    265 *  "length"
    266 *      Length of the array. Must be non-zero.
    267 *  "pBigInt"
    268 *      Address where object pointer will be stored. Must be non-NULL.
    269 *  "plContext" - Platform-specific context pointer.
    270 * THREAD SAFETY:
    271 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    272 * RETURNS:
    273 *  Returns NULL if the function succeeds.
    274 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    275 */
    276 PKIX_Error *
    277 pkix_pl_BigInt_CreateWithBytes(
    278        char *bytes,
    279        PKIX_UInt32 length,
    280        PKIX_PL_BigInt **pBigInt,
    281        void *plContext)
    282 {
    283        PKIX_PL_BigInt *bigInt = NULL;
    284 
    285        PKIX_ENTER(BIGINT, "pkix_pl_BigInt_CreateWithBytes");
    286        PKIX_NULLCHECK_TWO(pBigInt, bytes);
    287 
    288        if (length == 0) {
    289                PKIX_ERROR(PKIX_BIGINTLENGTH0INVALID)
    290        }
    291 
    292        PKIX_CHECK(PKIX_PL_Object_Alloc
    293                (PKIX_BIGINT_TYPE,
    294                sizeof (PKIX_PL_BigInt),
    295                (PKIX_PL_Object **)&bigInt,
    296                plContext),
    297                PKIX_COULDNOTCREATEOBJECT);
    298 
    299        PKIX_CHECK(PKIX_PL_Malloc
    300                    (length, (void **)&(bigInt->dataRep), plContext),
    301                    PKIX_MALLOCFAILED);
    302 
    303        PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcpy).\n");
    304        (void) PORT_Memcpy(bigInt->dataRep, bytes, length);
    305 
    306        bigInt->length = length;
    307 
    308        *pBigInt = bigInt;
    309 
    310 cleanup:
    311 
    312        if (PKIX_ERROR_RECEIVED){
    313                PKIX_DECREF(bigInt);
    314        }
    315 
    316        PKIX_RETURN(BIGINT);
    317 }
    318 
    319 /* --Public-Functions------------------------------------------------------- */
    320 
    321 /*
    322 * FUNCTION: PKIX_PL_BigInt_Create (see comments in pkix_pl_system.h)
    323 */
    324 PKIX_Error *
    325 PKIX_PL_BigInt_Create(
    326        PKIX_PL_String *stringRep,
    327        PKIX_PL_BigInt **pBigInt,
    328        void *plContext)
    329 {
    330        PKIX_PL_BigInt *bigInt = NULL;
    331        char *asciiString = NULL;
    332        PKIX_UInt32 lengthBytes;
    333        PKIX_UInt32 lengthString;
    334        PKIX_UInt32 i;
    335        char currChar;
    336 
    337        PKIX_ENTER(BIGINT, "PKIX_PL_BigInt_Create");
    338        PKIX_NULLCHECK_TWO(pBigInt, stringRep);
    339 
    340        PKIX_CHECK(PKIX_PL_String_GetEncoded
    341                (stringRep,
    342                PKIX_ESCASCII,
    343                (void **)&asciiString,
    344                &lengthString,
    345                plContext),
    346                PKIX_STRINGGETENCODEDFAILED);
    347 
    348        if ((lengthString == 0) || ((lengthString % 2) != 0)){
    349                PKIX_ERROR(PKIX_SOURCESTRINGHASINVALIDLENGTH);
    350        }
    351 
    352        if (lengthString != 2){
    353                if ((asciiString[0] == '0') && (asciiString[1] == '0')){
    354                        PKIX_ERROR(PKIX_FIRSTDOUBLEHEXMUSTNOTBE00);
    355                }
    356        }
    357 
    358        for (i = 0; i < lengthString; i++) {
    359                currChar = asciiString[i];
    360                if (!PKIX_ISXDIGIT(currChar)){
    361                        PKIX_ERROR(PKIX_INVALIDCHARACTERINBIGINT);
    362                }
    363        }
    364 
    365        PKIX_CHECK(PKIX_PL_Object_Alloc
    366                (PKIX_BIGINT_TYPE,
    367                sizeof (PKIX_PL_BigInt),
    368                (PKIX_PL_Object **)&bigInt,
    369                plContext),
    370                PKIX_COULDNOTCREATEOBJECT);
    371 
    372        /* number of bytes = 0.5 * (number of chars) */
    373        lengthBytes = lengthString/2;
    374 
    375        PKIX_CHECK(PKIX_PL_Malloc
    376                    (lengthBytes, (void **)&(bigInt->dataRep), plContext),
    377                    PKIX_MALLOCFAILED);
    378 
    379        for (i = 0; i < lengthString; i += 2){
    380                (bigInt->dataRep)[i/2] =
    381                        (pkix_hex2i(asciiString[i])<<4) |
    382                        pkix_hex2i(asciiString[i+1]);
    383        }
    384 
    385        bigInt->length = lengthBytes;
    386 
    387        *pBigInt = bigInt;
    388 
    389 cleanup:
    390 
    391        PKIX_FREE(asciiString);
    392 
    393        if (PKIX_ERROR_RECEIVED){
    394                PKIX_DECREF(bigInt);
    395        }
    396 
    397        PKIX_RETURN(BIGINT);
    398 }