Coverage Report

Created: 2025-08-18 06:34

/src/nss/lib/util/secport.h
Line
Count
Source (jump to first uncovered line)
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
/* ask for Annex K for memset_s. will set the appropriate #define
40
 * if Annex K is supported */
41
#define __STDC_WANT_LIB_EXT1__ 1
42
#include <string.h>
43
#include <stddef.h>
44
#include <stdlib.h>
45
#include <stdint.h>
46
#include "prtypes.h"
47
#include "prlog.h" /* for PR_ASSERT */
48
#include "plarena.h"
49
#include "plstr.h"
50
51
/*
52
 * HACK for NSS 2.8 to allow Admin to compile without source changes.
53
 */
54
#ifndef SEC_BEGIN_PROTOS
55
#include "seccomon.h"
56
#endif
57
58
/*
59
 * The PORT_*Arena* function signatures mostly involve PLArenaPool* arguments.
60
 * But this is misleading! It's not actually safe to use vanilla PLArenaPools
61
 * with them. There are two "subclasses" of PLArenaPool that should be used
62
 * instead.
63
 *
64
 * - PORTArenaPool (defined in secport.c): this "subclass" is always
65
 *   heap-allocated and uses a (heap-allocated) lock to protect all accesses.
66
 *   Use PORT_NewArena() and PORT_FreeArena() to create and destroy
67
 *   PORTArenaPools.
68
 *
69
 * - PORTCheapArenaPool (defined here): this "subclass" can be stack-allocated
70
 *   and does not use a lock to protect accesses. This makes it cheaper but
71
 *   less general. It is best used for arena pools that (a) are hot, (b) have
72
 *   lifetimes bounded within a single function, and (c) don't need locking.
73
 *   Use PORT_InitCheapArena() and PORT_DestroyCheapArena() to initialize and
74
 *   finalize PORTCheapArenaPools.
75
 *
76
 * All the other PORT_Arena* functions will operate safely with either
77
 * subclass.
78
 */
79
typedef struct PORTCheapArenaPool_str {
80
    PLArenaPool arena;
81
    PRUint32 magic; /* This is used to distinguish the two subclasses. */
82
} PORTCheapArenaPool;
83
84
SEC_BEGIN_PROTOS
85
86
extern void *PORT_Alloc(size_t len);
87
extern void *PORT_Realloc(void *old, size_t len);
88
extern void *PORT_ZAlloc(size_t len);
89
extern void *PORT_ZAllocAligned(size_t bytes, size_t alignment, void **mem);
90
extern void *PORT_ZAllocAlignedOffset(size_t bytes, size_t alignment,
91
                                      size_t offset);
92
extern void PORT_Free(void *ptr);
93
extern void PORT_ZFree(void *ptr, size_t len);
94
extern char *PORT_Strdup(const char *s);
95
extern void PORT_SetError(int value);
96
extern int PORT_GetError(void);
97
98
/* These functions are for use with PORTArenaPools. */
99
extern PLArenaPool *PORT_NewArena(unsigned long chunksize);
100
extern void PORT_FreeArena(PLArenaPool *arena, PRBool zero);
101
102
/* These functions are for use with PORTCheapArenaPools. */
103
extern void PORT_InitCheapArena(PORTCheapArenaPool *arena,
104
                                unsigned long chunksize);
105
extern void PORT_DestroyCheapArena(PORTCheapArenaPool *arena);
106
107
/* These functions work with both kinds of arena pool. */
108
extern void *PORT_ArenaAlloc(PLArenaPool *arena, size_t size);
109
extern void *PORT_ArenaZAlloc(PLArenaPool *arena, size_t size);
110
extern void *PORT_ArenaGrow(PLArenaPool *arena, void *ptr,
111
                            size_t oldsize, size_t newsize);
112
extern void *PORT_ArenaMark(PLArenaPool *arena);
113
extern void PORT_ArenaRelease(PLArenaPool *arena, void *mark);
114
extern void PORT_ArenaZRelease(PLArenaPool *arena, void *mark);
115
extern void PORT_ArenaUnmark(PLArenaPool *arena, void *mark);
116
extern char *PORT_ArenaStrdup(PLArenaPool *arena, const char *str);
117
118
SEC_END_PROTOS
119
120
205M
#define PORT_Assert PR_ASSERT
121
/* This is a variation of PORT_Assert where the arguments will be always
122
 * used either in Debug or not. But, in optimized mode the result will be
123
 * ignored. See more details in Bug 1588015. */
124
#define PORT_AssertArg PR_ASSERT_ARG
125
126
/* Assert the current location can't be reached, passing a reason-string. */
127
#define PORT_AssertNotReached(reasonStr) PR_NOT_REACHED(reasonStr)
128
129
/* macros to handle endian based byte conversion */
130
#define PORT_GET_BYTE_BE(value, offset, len) \
131
    ((unsigned char)(((len) - (offset)-1) >= sizeof(value) ? 0 : (((value) >> (((len) - (offset)-1) * PR_BITS_PER_BYTE)) & 0xff)))
132
#define PORT_GET_BYTE_LE(value, offset, len) \
133
    ((unsigned char)((offset) > sizeof(value) ? 0 : (((value) >> ((offset)*PR_BITS_PER_BYTE)) & 0xff)))
134
135
/* This runs a function that should return SECSuccess.
136
 * Intended for NSS internal use only.
137
 * The return value is asserted in a debug build, otherwise it is ignored.
138
 * This is no substitute for proper error handling.  It is OK only if you
139
 * have ensured that the function cannot fail by other means such as checking
140
 * prerequisites.  In that case this can be used as a safeguard against
141
 * unexpected changes in a function.
142
 */
143
#ifdef DEBUG
144
#define PORT_CheckSuccess(f) PR_ASSERT((f) == SECSuccess)
145
#else
146
#define PORT_CheckSuccess(f) (f)
147
#endif
148
17.3k
#define PORT_ZNew(type) (type *)PORT_ZAlloc(sizeof(type))
149
#define PORT_ZNewAligned(type, alignment, mem) \
150
    (type *)PORT_ZAllocAlignedOffset(sizeof(type), alignment, offsetof(type, mem))
151
#define PORT_New(type) (type *)PORT_Alloc(sizeof(type))
152
#define PORT_ArenaNew(poolp, type) \
153
    (type *)PORT_ArenaAlloc(poolp, sizeof(type))
154
#define PORT_ArenaZNew(poolp, type) \
155
0
    (type *)PORT_ArenaZAlloc(poolp, sizeof(type))
156
#define PORT_NewArray(type, num) \
157
    (type *)PORT_Alloc(sizeof(type) * (num))
158
#define PORT_ZNewArray(type, num) \
159
0
    (type *)PORT_ZAlloc(sizeof(type) * (num))
160
#define PORT_ArenaNewArray(poolp, type, num) \
161
0
    (type *)PORT_ArenaAlloc(poolp, sizeof(type) * (num))
162
#define PORT_ArenaZNewArray(poolp, type, num) \
163
1
    (type *)PORT_ArenaZAlloc(poolp, sizeof(type) * (num))
164
165
/* Please, keep these defines sorted alphabetically.  Thanks! */
166
167
#define PORT_Atoi(buff) (int)strtol(buff, NULL, 10)
168
169
/* Returns a UTF-8 encoded constant error string for err.
170
 * Returns NULL if initialization of the error tables fails
171
 * due to insufficient memory.
172
 *
173
 * This string must not be modified by the application.
174
 */
175
#define PORT_ErrorToString(err) PR_ErrorToString((err), PR_LANGUAGE_I_DEFAULT)
176
177
#define PORT_ErrorToName PR_ErrorToName
178
179
971k
#define PORT_Memcmp memcmp
180
24.4M
#define PORT_Memcpy memcpy
181
#define PORT_Memmove memmove
182
28.2M
#define PORT_Memset memset
183
184
3
#define PORT_Strcasecmp PL_strcasecmp
185
52
#define PORT_Strcat strcat
186
0
#define PORT_Strchr strchr
187
#define PORT_Strrchr strrchr
188
#define PORT_Strcmp strcmp
189
52
#define PORT_Strcpy strcpy
190
15
#define PORT_Strlen(s) strlen(s)
191
705
#define PORT_Strncasecmp PL_strncasecmp
192
0
#define PORT_Strncat strncat
193
8
#define PORT_Strncmp strncmp
194
1
#define PORT_Strncpy strncpy
195
#define PORT_Strpbrk strpbrk
196
0
#define PORT_Strstr strstr
197
#define PORT_Strtok strtok
198
199
#define PORT_Tolower tolower
200
201
typedef PRBool(PR_CALLBACK *PORTCharConversionWSwapFunc)(PRBool toUnicode,
202
                                                         unsigned char *inBuf, unsigned int inBufLen,
203
                                                         unsigned char *outBuf, unsigned int maxOutBufLen,
204
                                                         unsigned int *outBufLen, PRBool swapBytes);
205
206
typedef PRBool(PR_CALLBACK *PORTCharConversionFunc)(PRBool toUnicode,
207
                                                    unsigned char *inBuf, unsigned int inBufLen,
208
                                                    unsigned char *outBuf, unsigned int maxOutBufLen,
209
                                                    unsigned int *outBufLen);
210
211
SEC_BEGIN_PROTOS
212
213
void PORT_SetUCS4_UTF8ConversionFunction(PORTCharConversionFunc convFunc);
214
void PORT_SetUCS2_ASCIIConversionFunction(PORTCharConversionWSwapFunc convFunc);
215
PRBool PORT_UCS4_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf,
216
                                unsigned int inBufLen, unsigned char *outBuf,
217
                                unsigned int maxOutBufLen, unsigned int *outBufLen);
218
PRBool PORT_UCS2_ASCIIConversion(PRBool toUnicode, unsigned char *inBuf,
219
                                 unsigned int inBufLen, unsigned char *outBuf,
220
                                 unsigned int maxOutBufLen, unsigned int *outBufLen,
221
                                 PRBool swapBytes);
222
void PORT_SetUCS2_UTF8ConversionFunction(PORTCharConversionFunc convFunc);
223
PRBool PORT_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf,
224
                                unsigned int inBufLen, unsigned char *outBuf,
225
                                unsigned int maxOutBufLen, unsigned int *outBufLen);
226
227
/* One-way conversion from ISO-8859-1 to UTF-8 */
228
PRBool PORT_ISO88591_UTF8Conversion(const unsigned char *inBuf,
229
                                    unsigned int inBufLen, unsigned char *outBuf,
230
                                    unsigned int maxOutBufLen, unsigned int *outBufLen);
231
232
extern PRBool
233
sec_port_ucs4_utf8_conversion_function(
234
    PRBool toUnicode,
235
    unsigned char *inBuf,
236
    unsigned int inBufLen,
237
    unsigned char *outBuf,
238
    unsigned int maxOutBufLen,
239
    unsigned int *outBufLen);
240
241
extern PRBool
242
sec_port_ucs2_utf8_conversion_function(
243
    PRBool toUnicode,
244
    unsigned char *inBuf,
245
    unsigned int inBufLen,
246
    unsigned char *outBuf,
247
    unsigned int maxOutBufLen,
248
    unsigned int *outBufLen);
249
250
/* One-way conversion from ISO-8859-1 to UTF-8 */
251
extern PRBool
252
sec_port_iso88591_utf8_conversion_function(
253
    const unsigned char *inBuf,
254
    unsigned int inBufLen,
255
    unsigned char *outBuf,
256
    unsigned int maxOutBufLen,
257
    unsigned int *outBufLen);
258
259
extern int NSS_PutEnv(const char *envVarName, const char *envValue);
260
261
extern void PORT_SafeZero(void *p, size_t n);
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_ */