| 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 * 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 } | |
| OLD | NEW |