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