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