| 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 | /* |
| 6 | * secport.h - portability interfaces for security libraries |
| 7 | */ |
| 8 | |
| 9 | #ifndef _SECPORT_H_ |
| 10 | #define _SECPORT_H_ |
| 11 | |
| 12 | #include "utilrename.h" |
| 13 | #include "prlink.h" |
| 14 | |
| 15 | /* |
| 16 | * define XP_WIN, or XP_UNIX, in case they are not defined |
| 17 | * by anyone else |
| 18 | */ |
| 19 | #ifdef _WINDOWS |
| 20 | #ifndef XP_WIN |
| 21 | #define XP_WIN |
| 22 | #endif |
| 23 | #if defined(_WIN32) || defined(WIN32) |
| 24 | #ifndef XP_WIN32 |
| 25 | #define XP_WIN32 |
| 26 | #endif |
| 27 | #endif |
| 28 | #endif |
| 29 | |
| 30 | #ifdef unix |
| 31 | #ifndef XP_UNIX |
| 32 | #define XP_UNIX |
| 33 | #endif |
| 34 | #endif |
| 35 | |
| 36 | #include <sys/types.h> |
| 37 | |
| 38 | #include <ctype.h> |
| 39 | #include <string.h> |
| 40 | #include <stddef.h> |
| 41 | #include <stdlib.h> |
| 42 | #include <stdint.h> |
| 43 | #include "prtypes.h" |
| 44 | #include "prlog.h" /* for PR_ASSERT */ |
| 45 | #include "plarena.h" |
| 46 | #include "plstr.h" |
| 47 | |
| 48 | /* |
| 49 | * HACK for NSS 2.8 to allow Admin to compile without source changes. |
| 50 | */ |
| 51 | #ifndef SEC_BEGIN_PROTOS |
| 52 | #include "seccomon.h" |
| 53 | #endif |
| 54 | |
| 55 | /* |
| 56 | * The PORT_*Arena* function signatures mostly involve PLArenaPool* arguments. |
| 57 | * But this is misleading! It's not actually safe to use vanilla PLArenaPools |
| 58 | * with them. There are two "subclasses" of PLArenaPool that should be used |
| 59 | * instead. |
| 60 | * |
| 61 | * - PORTArenaPool (defined in secport.c): this "subclass" is always |
| 62 | * heap-allocated and uses a (heap-allocated) lock to protect all accesses. |
| 63 | * Use PORT_NewArena() and PORT_FreeArena() to create and destroy |
| 64 | * PORTArenaPools. |
| 65 | * |
| 66 | * - PORTCheapArenaPool (defined here): this "subclass" can be stack-allocated |
| 67 | * and does not use a lock to protect accesses. This makes it cheaper but |
| 68 | * less general. It is best used for arena pools that (a) are hot, (b) have |
| 69 | * lifetimes bounded within a single function, and (c) don't need locking. |
| 70 | * Use PORT_InitCheapArena() and PORT_DestroyCheapArena() to initialize and |
| 71 | * finalize PORTCheapArenaPools. |
| 72 | * |
| 73 | * All the other PORT_Arena* functions will operate safely with either |
| 74 | * subclass. |
| 75 | */ |
| 76 | typedef struct PORTCheapArenaPool_str { |
| 77 | PLArenaPool arena; |
| 78 | PRUint32 magic; /* This is used to distinguish the two subclasses. */ |
| 79 | } PORTCheapArenaPool; |
| 80 | |
| 81 | SEC_BEGIN_PROTOS |
| 82 | |
| 83 | extern void *PORT_Alloc(size_t len); |
| 84 | extern void *PORT_Realloc(void *old, size_t len); |
| 85 | extern void *PORT_ZAlloc(size_t len); |
| 86 | extern void *PORT_ZAllocAligned(size_t bytes, size_t alignment, void **mem); |
| 87 | extern void *PORT_ZAllocAlignedOffset(size_t bytes, size_t alignment, |
| 88 | size_t offset); |
| 89 | extern void PORT_Free(void *ptr); |
| 90 | extern void PORT_ZFree(void *ptr, size_t len); |
| 91 | extern char *PORT_Strdup(const char *s); |
| 92 | extern void PORT_SetError(int value); |
| 93 | extern int PORT_GetError(void); |
| 94 | |
| 95 | /* These functions are for use with PORTArenaPools. */ |
| 96 | extern PLArenaPool *PORT_NewArena(unsigned long chunksize); |
| 97 | extern void PORT_FreeArena(PLArenaPool *arena, PRBool zero); |
| 98 | |
| 99 | /* These functions are for use with PORTCheapArenaPools. */ |
| 100 | extern void PORT_InitCheapArena(PORTCheapArenaPool *arena, |
| 101 | unsigned long chunksize); |
| 102 | extern void PORT_DestroyCheapArena(PORTCheapArenaPool *arena); |
| 103 | |
| 104 | /* These functions work with both kinds of arena pool. */ |
| 105 | extern void *PORT_ArenaAlloc(PLArenaPool *arena, size_t size); |
| 106 | extern void *PORT_ArenaZAlloc(PLArenaPool *arena, size_t size); |
| 107 | extern void *PORT_ArenaGrow(PLArenaPool *arena, void *ptr, |
| 108 | size_t oldsize, size_t newsize); |
| 109 | extern void *PORT_ArenaMark(PLArenaPool *arena); |
| 110 | extern void PORT_ArenaRelease(PLArenaPool *arena, void *mark); |
| 111 | extern void PORT_ArenaZRelease(PLArenaPool *arena, void *mark); |
| 112 | extern void PORT_ArenaUnmark(PLArenaPool *arena, void *mark); |
| 113 | extern char *PORT_ArenaStrdup(PLArenaPool *arena, const char *str); |
| 114 | |
| 115 | SEC_END_PROTOS |
| 116 | |
| 117 | #define PORT_Assert PR_ASSERT |
| 118 | /* This is a variation of PORT_Assert where the arguments will be always |
| 119 | * used either in Debug or not. But, in optimized mode the result will be |
| 120 | * ignored. See more details in Bug 1588015. */ |
| 121 | #define PORT_AssertArg PR_ASSERT_ARG |
| 122 | |
| 123 | /* Assert the current location can't be reached, passing a reason-string. */ |
| 124 | #define PORT_AssertNotReached(reasonStr) PR_NOT_REACHED(reasonStr) |
| 125 | |
| 126 | /* macros to handle endian based byte conversion */ |
| 127 | #define PORT_GET_BYTE_BE(value, offset, len) \ |
| 128 | ((unsigned char)(((len) - (offset)-1) >= sizeof(value) ? 0 : (((value) >> (((len) - (offset)-1) * PR_BITS_PER_BYTE)) & 0xff))) |
| 129 | #define PORT_GET_BYTE_LE(value, offset, len) \ |
| 130 | ((unsigned char)((offset) > sizeof(value) ? 0 : (((value) >> ((offset)*PR_BITS_PER_BYTE)) & 0xff))) |
| 131 | |
| 132 | /* This runs a function that should return SECSuccess. |
| 133 | * Intended for NSS internal use only. |
| 134 | * The return value is asserted in a debug build, otherwise it is ignored. |
| 135 | * This is no substitute for proper error handling. It is OK only if you |
| 136 | * have ensured that the function cannot fail by other means such as checking |
| 137 | * prerequisites. In that case this can be used as a safeguard against |
| 138 | * unexpected changes in a function. |
| 139 | */ |
| 140 | #ifdef DEBUG |
| 141 | #define PORT_CheckSuccess(f) PR_ASSERT((f) == SECSuccess) |
| 142 | #else |
| 143 | #define PORT_CheckSuccess(f) (f) |
| 144 | #endif |
| 145 | #define PORT_ZNew(type) (type *)PORT_ZAlloc(sizeof(type)) |
| 146 | #define PORT_ZNewAligned(type, alignment, mem) \ |
| 147 | (type *)PORT_ZAllocAlignedOffset(sizeof(type), alignment, offsetof(type, mem)) |
| 148 | #define PORT_New(type) (type *)PORT_Alloc(sizeof(type)) |
| 149 | #define PORT_ArenaNew(poolp, type) \ |
| 150 | (type *)PORT_ArenaAlloc(poolp, sizeof(type)) |
| 151 | #define PORT_ArenaZNew(poolp, type) \ |
| 152 | (type *)PORT_ArenaZAlloc(poolp, sizeof(type)) |
| 153 | #define PORT_NewArray(type, num) \ |
| 154 | (type *)PORT_Alloc(sizeof(type) * (num)) |
| 155 | #define PORT_ZNewArray(type, num) \ |
| 156 | (type *)PORT_ZAlloc(sizeof(type) * (num)) |
| 157 | #define PORT_ArenaNewArray(poolp, type, num) \ |
| 158 | (type *)PORT_ArenaAlloc(poolp, sizeof(type) * (num)) |
| 159 | #define PORT_ArenaZNewArray(poolp, type, num) \ |
| 160 | (type *)PORT_ArenaZAlloc(poolp, sizeof(type) * (num)) |
| 161 | |
| 162 | /* Please, keep these defines sorted alphabetically. Thanks! */ |
| 163 | |
| 164 | #define PORT_Atoi(buff) (int)strtol(buff, NULL, 10) |
| 165 | |
| 166 | /* Returns a UTF-8 encoded constant error string for err. |
| 167 | * Returns NULL if initialization of the error tables fails |
| 168 | * due to insufficient memory. |
| 169 | * |
| 170 | * This string must not be modified by the application. |
| 171 | */ |
| 172 | #define PORT_ErrorToString(err) PR_ErrorToString((err), PR_LANGUAGE_I_DEFAULT) |
| 173 | |
| 174 | #define PORT_ErrorToName PR_ErrorToName |
| 175 | |
| 176 | #define PORT_Memcmp memcmp |
| 177 | #define PORT_Memcpy memcpy |
| 178 | #ifndef SUNOS4 |
| 179 | #define PORT_Memmove memmove |
| 180 | #else /*SUNOS4*/ |
| 181 | #define PORT_Memmove(s, ct, n) bcopy((ct), (s), (n)) |
| 182 | #endif /*SUNOS4*/ |
| 183 | #define PORT_Memset memset |
| 184 | |
| 185 | #define PORT_Strcasecmp PL_strcasecmp |
| 186 | #define PORT_Strcat strcat |
| 187 | #define PORT_Strchr strchr |
| 188 | #define PORT_Strrchr strrchr |
| 189 | #define PORT_Strcmp strcmp |
| 190 | #define PORT_Strcpy strcpy |
| 191 | #define PORT_Strlen(s) strlen(s) |
| 192 | #define PORT_Strncasecmp PL_strncasecmp |
| 193 | #define PORT_Strncat strncat |
| 194 | #define PORT_Strncmp strncmp |
| 195 | #define PORT_Strncpy strncpy |
| 196 | #define PORT_Strpbrk strpbrk |
| 197 | #define PORT_Strstr strstr |
| 198 | #define PORT_Strtok strtok |
| 199 | |
| 200 | #define PORT_Tolower tolower |
| 201 | |
| 202 | typedef PRBool(PR_CALLBACK *PORTCharConversionWSwapFunc)(PRBool toUnicode, |
| 203 | unsigned char *inBuf, unsigned int inBufLen, |
| 204 | unsigned char *outBuf, unsigned int maxOutBufLen, |
| 205 | unsigned int *outBufLen, PRBool swapBytes); |
| 206 | |
| 207 | typedef PRBool(PR_CALLBACK *PORTCharConversionFunc)(PRBool toUnicode, |
| 208 | unsigned char *inBuf, unsigned int inBufLen, |
| 209 | unsigned char *outBuf, unsigned int maxOutBufLen, |
| 210 | unsigned int *outBufLen); |
| 211 | |
| 212 | SEC_BEGIN_PROTOS |
| 213 | |
| 214 | void PORT_SetUCS4_UTF8ConversionFunction(PORTCharConversionFunc convFunc); |
| 215 | void PORT_SetUCS2_ASCIIConversionFunction(PORTCharConversionWSwapFunc convFunc); |
| 216 | PRBool PORT_UCS4_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf, |
| 217 | unsigned int inBufLen, unsigned char *outBuf, |
| 218 | unsigned int maxOutBufLen, unsigned int *outBufLen); |
| 219 | PRBool PORT_UCS2_ASCIIConversion(PRBool toUnicode, unsigned char *inBuf, |
| 220 | unsigned int inBufLen, unsigned char *outBuf, |
| 221 | unsigned int maxOutBufLen, unsigned int *outBufLen, |
| 222 | PRBool swapBytes); |
| 223 | void PORT_SetUCS2_UTF8ConversionFunction(PORTCharConversionFunc convFunc); |
| 224 | PRBool PORT_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf, |
| 225 | unsigned int inBufLen, unsigned char *outBuf, |
| 226 | unsigned int maxOutBufLen, unsigned int *outBufLen); |
| 227 | |
| 228 | /* One-way conversion from ISO-8859-1 to UTF-8 */ |
| 229 | PRBool PORT_ISO88591_UTF8Conversion(const unsigned char *inBuf, |
| 230 | unsigned int inBufLen, unsigned char *outBuf, |
| 231 | unsigned int maxOutBufLen, unsigned int *outBufLen); |
| 232 | |
| 233 | extern PRBool |
| 234 | sec_port_ucs4_utf8_conversion_function( |
| 235 | PRBool toUnicode, |
| 236 | unsigned char *inBuf, |
| 237 | unsigned int inBufLen, |
| 238 | unsigned char *outBuf, |
| 239 | unsigned int maxOutBufLen, |
| 240 | unsigned int *outBufLen); |
| 241 | |
| 242 | extern PRBool |
| 243 | sec_port_ucs2_utf8_conversion_function( |
| 244 | PRBool toUnicode, |
| 245 | unsigned char *inBuf, |
| 246 | unsigned int inBufLen, |
| 247 | unsigned char *outBuf, |
| 248 | unsigned int maxOutBufLen, |
| 249 | unsigned int *outBufLen); |
| 250 | |
| 251 | /* One-way conversion from ISO-8859-1 to UTF-8 */ |
| 252 | extern PRBool |
| 253 | sec_port_iso88591_utf8_conversion_function( |
| 254 | const unsigned char *inBuf, |
| 255 | unsigned int inBufLen, |
| 256 | unsigned char *outBuf, |
| 257 | unsigned int maxOutBufLen, |
| 258 | unsigned int *outBufLen); |
| 259 | |
| 260 | extern int NSS_PutEnv(const char *envVarName, const char *envValue); |
| 261 | |
| 262 | extern int NSS_SecureMemcmp(const void *a, const void *b, size_t n); |
| 263 | extern unsigned int NSS_SecureMemcmpZero(const void *mem, size_t n); |
| 264 | extern void NSS_SecureSelect(void *dest, const void *src0, const void *src1, size_t n, unsigned char b); |
| 265 | extern PRBool NSS_GetSystemFIPSEnabled(void); |
| 266 | |
| 267 | /* |
| 268 | * Load a shared library called "newShLibName" in the same directory as |
| 269 | * a shared library that is already loaded, called existingShLibName. |
| 270 | * A pointer to a static function in that shared library, |
| 271 | * staticShLibFunc, is required. |
| 272 | * |
| 273 | * existingShLibName: |
| 274 | * The file name of the shared library that shall be used as the |
| 275 | * "reference library". The loader will attempt to load the requested |
| 276 | * library from the same directory as the reference library. |
| 277 | * |
| 278 | * staticShLibFunc: |
| 279 | * Pointer to a static function in the "reference library". |
| 280 | * |
| 281 | * newShLibName: |
| 282 | * The simple file name of the new shared library to be loaded. |
| 283 | * |
| 284 | * We use PR_GetLibraryFilePathname to get the pathname of the loaded |
| 285 | * shared lib that contains this function, and then do a |
| 286 | * PR_LoadLibraryWithFlags with an absolute pathname for the shared |
| 287 | * library to be loaded. |
| 288 | * |
| 289 | * On Windows, the "alternate search path" strategy is employed, if available. |
| 290 | * On Unix, if existingShLibName is a symbolic link, and no link exists for the |
| 291 | * new library, the original link will be resolved, and the new library loaded |
| 292 | * from the resolved location. |
| 293 | * |
| 294 | * If the new shared library is not found in the same location as the reference |
| 295 | * library, it will then be loaded from the normal system library path. |
| 296 | */ |
| 297 | PRLibrary * |
| 298 | PORT_LoadLibraryFromOrigin(const char *existingShLibName, |
| 299 | PRFuncPtr staticShLibFunc, |
| 300 | const char *newShLibName); |
| 301 | |
| 302 | SEC_END_PROTOS |
| 303 | |
| 304 | /* |
| 305 | * Constant time macros |
| 306 | */ |
| 307 | /* These macros use the fact that arithmetic shift shifts-in the sign bit. |
| 308 | * However, this is not ensured by the C standard so you may need to replace |
| 309 | * them with something else for odd compilers. These macros work for object |
| 310 | * sizes up to 32 bits. The inequalities will produce incorrect results if |
| 311 | * abs(a-b) >= PR_UINT32_MAX/2. This can be a voided if unsigned values stay |
| 312 | * within the range 0-PRUINT32_MAX/2 and signed values stay within the range |
| 313 | * -PRINT32_MAX/2-PRINT32_MAX/2. If these are insufficient, we can fix |
| 314 | * this by either expanding the PORT_CT_DUPLICATE_MSB_TO_ALL to PRUint64 |
| 315 | * or by creating the following new macros for inequality: |
| 316 | * |
| 317 | * PORT_CT_OVERFLOW prevents the overflow condition by handling the case |
| 318 | * where the high bits in a and b are different specially. Basically if |
| 319 | * the high bit in a and b differs we can just |
| 320 | * copy the high bit of one of the parameters to determine the result as |
| 321 | * follows: |
| 322 | * GxU if a has the high bit on, a>b, so d=a |
| 323 | * LxU if b has the high bit on, a<b, so d=b |
| 324 | * GxS if b has the high bit on, it's negative a>b so d=b |
| 325 | * LxS if a has the high bit on, it's negative a<b so d=a |
| 326 | * where PORT_CT_xxU() macros do unsigned compares and PORT_CT_xxS() do signed |
| 327 | * compares. |
| 328 | * |
| 329 | * #define PORT_CT_OVERFLOW(a,b,c,d) \ |
| 330 | * PORT_CT_SEL(PORT_CT_DUPLICATE_MSB_TO_ALL((a)^(b)), \ |
| 331 | * (PORT_CT_DUPLICATE_MSB_TO_ALL(d)),c) |
| 332 | * #define PORT_CT_GTU(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_GT(a,b),a) |
| 333 | * #define PORT_CT_LTU(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_LT(a,b),b) |
| 334 | * #define PORT_CT_GEU(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_GE(a,b),a) |
| 335 | * #define PORT_CT_LEU(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_LE(a,b),b) |
| 336 | * #define PORT_CT_GTS(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_GT(a,b),b) |
| 337 | * #define PORT_CT_LTS(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_LT(a,b),a) |
| 338 | * #define PORT_CT_GES(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_GE(a,b),b) |
| 339 | * #define PORT_CT_LES(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_LE(a,b),a) |
| 340 | * |
| 341 | * |
| 342 | * */ |
| 343 | /* Constant-time helper macro that copies the MSB of x to all other bits. */ |
| 344 | #define PORT_CT_DUPLICATE_MSB_TO_ALL(x) ((PRUint32)((PRInt32)(x) >> (sizeof(PRInt32) * 8 - 1))) |
| 345 | |
| 346 | /* Constant-time helper macro that selects l or r depending on all-1 or all-0 |
| 347 | * mask m */ |
| 348 | #define PORT_CT_SEL(m, l, r) (((m) & (l)) | (~(m) & (r))) |
| 349 | |
| 350 | /* Constant-time helper macro that returns all-1s if x is not 0; and all-0s |
| 351 | * otherwise. */ |
| 352 | #define PORT_CT_NOT_ZERO(x) (PORT_CT_DUPLICATE_MSB_TO_ALL(((x) | (0 - (x))))) |
| 353 | |
| 354 | /* Constant-time helper macro that returns all-1s if x is 0; and all-0s |
| 355 | * otherwise. */ |
| 356 | #define PORT_CT_ZERO(x) (~PORT_CT_DUPLICATE_MSB_TO_ALL(((x) | (0 - (x))))) |
| 357 | |
| 358 | /* Constant-time helper macro for equalities and inequalities. |
| 359 | * returns all-1's for true and all-0's for false */ |
| 360 | #define PORT_CT_EQ(a, b) PORT_CT_ZERO(((a) - (b))) |
| 361 | #define PORT_CT_NE(a, b) PORT_CT_NOT_ZERO(((a) - (b))) |
| 362 | #define PORT_CT_GT(a, b) PORT_CT_DUPLICATE_MSB_TO_ALL((b) - (a)) |
| 363 | #define PORT_CT_LT(a, b) PORT_CT_DUPLICATE_MSB_TO_ALL((a) - (b)) |
| 364 | #define PORT_CT_GE(a, b) (~PORT_CT_LT(a, b)) |
| 365 | #define PORT_CT_LE(a, b) (~PORT_CT_GT(a, b)) |
| 366 | #define PORT_CT_TRUE (~0) |
| 367 | #define PORT_CT_FALSE 0 |
| 368 | |
| 369 | #ifdef CT_VERIF |
| 370 | #include <valgrind/memcheck.h> |
| 371 | #define NSS_CLASSIFY(buf, length) VALGRIND_MAKE_MEM_UNDEFINED(buf, length); |
| 372 | #define NSS_DECLASSIFY(buf, length) VALGRIND_MAKE_MEM_DEFINED(buf, length); |
| 373 | #else |
| 374 | #define NSS_CLASSIFY(buf, length) |
| 375 | #define NSS_DECLASSIFY(buf, length) |
| 376 | #endif |
| 377 | |
| 378 | #endif /* _SECPORT_H_ */ |
| 379 | |