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 }