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 | |