nss/SOURCES/nss-3.90-fips-safe-memset.p...

507 lines
19 KiB
Diff

diff -up ./lib/freebl/aeskeywrap.c.safe_zero ./lib/freebl/aeskeywrap.c
--- ./lib/freebl/aeskeywrap.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/aeskeywrap.c 2023-11-22 14:42:24.246388369 -0800
@@ -512,7 +512,7 @@ AESKeyWrap_EncryptKWP(AESKeyWrapContext
PORT_Memcpy(iv + AES_KEY_WRAP_BLOCK_SIZE, input, inputLen);
rv = AES_Encrypt(&cx->aescx, output, pOutputLen, maxOutputLen, iv,
outLen);
- PORT_Memset(iv, 0, sizeof(iv));
+ PORT_SafeZero(iv, sizeof(iv));
return rv;
}
@@ -528,7 +528,7 @@ AESKeyWrap_EncryptKWP(AESKeyWrapContext
PORT_ZFree(newBuf, paddedInputLen);
/* a little overkill, we only need to clear out the length, but this
* is easier to verify we got it all */
- PORT_Memset(iv, 0, sizeof(iv));
+ PORT_SafeZero(iv, sizeof(iv));
return rv;
}
@@ -631,12 +631,12 @@ AESKeyWrap_DecryptKWP(AESKeyWrapContext
loser:
/* if we failed, make sure we don't return any data to the user */
if ((rv != SECSuccess) && (output == newBuf)) {
- PORT_Memset(newBuf, 0, paddedLen);
+ PORT_SafeZero(newBuf, paddedLen);
}
/* clear out CSP sensitive data from the heap and stack */
if (allocBuf) {
PORT_ZFree(allocBuf, paddedLen);
}
- PORT_Memset(iv, 0, sizeof(iv));
+ PORT_SafeZero(iv, sizeof(iv));
return rv;
}
diff -up ./lib/freebl/blapii.h.safe_zero ./lib/freebl/blapii.h
--- ./lib/freebl/blapii.h.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/blapii.h 2023-11-22 14:42:24.246388369 -0800
@@ -101,10 +101,10 @@ PRBool ppc_crypto_support();
#ifdef NSS_FIPS_DISABLED
#define BLAPI_CLEAR_STACK(stack_size)
#else
-#define BLAPI_CLEAR_STACK(stack_size) \
- { \
- volatile char _stkclr[stack_size]; \
- PORT_Memset((void *)&_stkclr[0], 0, stack_size); \
+#define BLAPI_CLEAR_STACK(stack_size) \
+ { \
+ volatile char _stkclr[stack_size]; \
+ PORT_SafeZero((void *)&_stkclr[0], stack_size); \
}
#endif
diff -up ./lib/freebl/drbg.c.safe_zero ./lib/freebl/drbg.c
--- ./lib/freebl/drbg.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/drbg.c 2023-11-22 14:42:24.246388369 -0800
@@ -197,7 +197,7 @@ prng_initEntropy(void)
SHA256_Update(&ctx, block, sizeof(block));
SHA256_End(&ctx, globalrng->previousEntropyHash, NULL,
sizeof(globalrng->previousEntropyHash));
- PORT_Memset(block, 0, sizeof(block));
+ PORT_SafeZero(block, sizeof(block));
SHA256_DestroyContext(&ctx, PR_FALSE);
return PR_SUCCESS;
}
@@ -246,8 +246,8 @@ prng_getEntropy(PRUint8 *buffer, size_t
}
out:
- PORT_Memset(hash, 0, sizeof hash);
- PORT_Memset(block, 0, sizeof block);
+ PORT_SafeZero(hash, sizeof hash);
+ PORT_SafeZero(block, sizeof block);
return rv;
}
@@ -393,8 +393,8 @@ prng_Hashgen(RNGContext *rng, PRUint8 *r
PRNG_ADD_CARRY_ONLY(data, (sizeof data) - 1, carry);
SHA256_DestroyContext(&ctx, PR_FALSE);
}
- PORT_Memset(data, 0, sizeof data);
- PORT_Memset(thisHash, 0, sizeof thisHash);
+ PORT_SafeZero(data, sizeof data);
+ PORT_SafeZero(thisHash, sizeof thisHash);
}
/*
@@ -455,7 +455,7 @@ prng_generateNewBytes(RNGContext *rng,
PRNG_ADD_CARRY_ONLY(rng->reseed_counter, (sizeof rng->reseed_counter) - 1, carry);
/* if the prng failed, don't return any output, signal softoken */
- PORT_Memset(H, 0, sizeof H);
+ PORT_SafeZero(H, sizeof H);
if (!rng->isValid) {
PORT_Memset(returned_bytes, 0, no_of_returned_bytes);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
diff -up ./lib/freebl/dsa.c.safe_zero ./lib/freebl/dsa.c
--- ./lib/freebl/dsa.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/dsa.c 2023-11-22 14:42:24.246388369 -0800
@@ -471,7 +471,7 @@ dsa_SignDigest(DSAPrivateKey *key, SECIt
err = MP_OKAY;
signature->len = dsa_signature_len;
cleanup:
- PORT_Memset(localDigestData, 0, DSA_MAX_SUBPRIME_LEN);
+ PORT_SafeZero(localDigestData, DSA_MAX_SUBPRIME_LEN);
mp_clear(&p);
mp_clear(&q);
mp_clear(&g);
@@ -532,7 +532,7 @@ DSA_SignDigest(DSAPrivateKey *key, SECIt
rv = dsa_SignDigest(key, signature, digest, kSeed);
} while (rv != SECSuccess && PORT_GetError() == SEC_ERROR_NEED_RANDOM &&
--retries > 0);
- PORT_Memset(kSeed, 0, sizeof kSeed);
+ PORT_SafeZero(kSeed, sizeof kSeed);
return rv;
}
@@ -673,7 +673,7 @@ DSA_VerifyDigest(DSAPublicKey *key, cons
verified = SECSuccess; /* Signature verified. */
}
cleanup:
- PORT_Memset(localDigestData, 0, sizeof localDigestData);
+ PORT_SafeZero(localDigestData, sizeof localDigestData);
mp_clear(&p);
mp_clear(&q);
mp_clear(&g);
diff -up ./lib/freebl/gcm.c.safe_zero ./lib/freebl/gcm.c
--- ./lib/freebl/gcm.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/gcm.c 2023-11-22 14:42:24.246388369 -0800
@@ -480,7 +480,7 @@ gcmHash_Final(gcmHashContext *ghash, uns
rv = SECSuccess;
cleanup:
- PORT_Memset(T, 0, sizeof(T));
+ PORT_SafeZero(T, sizeof(T));
return rv;
}
@@ -596,15 +596,15 @@ GCM_CreateContext(void *context, freeblC
if (rv != SECSuccess) {
goto loser;
}
- PORT_Memset(H, 0, AES_BLOCK_SIZE);
+ PORT_SafeZero(H, AES_BLOCK_SIZE);
gcm->ctr_context_init = PR_TRUE;
return gcm;
loser:
- PORT_Memset(H, 0, AES_BLOCK_SIZE);
+ PORT_SafeZero(H, AES_BLOCK_SIZE);
if (ghash && ghash->mem) {
void *mem = ghash->mem;
- PORT_Memset(ghash, 0, sizeof(gcmHashContext));
+ PORT_SafeZero(ghash, sizeof(gcmHashContext));
PORT_Free(mem);
}
if (gcm) {
@@ -682,11 +682,11 @@ gcm_InitCounter(GCMContext *gcm, const u
goto loser;
}
- PORT_Memset(&ctrParams, 0, sizeof ctrParams);
+ PORT_SafeZero(&ctrParams, sizeof ctrParams);
return SECSuccess;
loser:
- PORT_Memset(&ctrParams, 0, sizeof ctrParams);
+ PORT_SafeZero(&ctrParams, sizeof ctrParams);
if (freeCtr) {
CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
}
@@ -866,10 +866,10 @@ GCM_DecryptUpdate(GCMContext *gcm, unsig
if (NSS_SecureMemcmp(tag, intag, tagBytes) != 0) {
/* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
PORT_SetError(SEC_ERROR_BAD_DATA);
- PORT_Memset(tag, 0, sizeof(tag));
+ PORT_SafeZero(tag, sizeof(tag));
return SECFailure;
}
- PORT_Memset(tag, 0, sizeof(tag));
+ PORT_SafeZero(tag, sizeof(tag));
/* finish the decryption */
return CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout,
inbuf, inlen, AES_BLOCK_SIZE);
@@ -1159,10 +1159,10 @@ GCM_DecryptAEAD(GCMContext *gcm, unsigne
/* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
PORT_SetError(SEC_ERROR_BAD_DATA);
- PORT_Memset(tag, 0, sizeof(tag));
+ PORT_SafeZero(tag, sizeof(tag));
return SECFailure;
}
- PORT_Memset(tag, 0, sizeof(tag));
+ PORT_SafeZero(tag, sizeof(tag));
/* finish the decryption */
rv = CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout,
inbuf, inlen, AES_BLOCK_SIZE);
diff -up ./lib/freebl/hmacct.c.safe_zero ./lib/freebl/hmacct.c
--- ./lib/freebl/hmacct.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/hmacct.c 2023-11-22 14:42:24.246388369 -0800
@@ -274,10 +274,10 @@ MAC(unsigned char *mdOut,
hashObj->end(mdState, mdOut, mdOutLen, mdOutMax);
hashObj->destroy(mdState, PR_TRUE);
- PORT_Memset(lengthBytes, 0, sizeof lengthBytes);
- PORT_Memset(hmacPad, 0, sizeof hmacPad);
- PORT_Memset(firstBlock, 0, sizeof firstBlock);
- PORT_Memset(macOut, 0, sizeof macOut);
+ PORT_SafeZero(lengthBytes, sizeof lengthBytes);
+ PORT_SafeZero(hmacPad, sizeof hmacPad);
+ PORT_SafeZero(firstBlock, sizeof firstBlock);
+ PORT_SafeZero(macOut, sizeof macOut);
return SECSuccess;
}
diff -up ./lib/freebl/intel-gcm-wrap.c.safe_zero ./lib/freebl/intel-gcm-wrap.c
--- ./lib/freebl/intel-gcm-wrap.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/intel-gcm-wrap.c 2023-11-22 14:42:24.246388369 -0800
@@ -195,7 +195,7 @@ intel_aes_gcmInitCounter(intel_AES_GCMCo
void
intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit)
{
- PORT_Memset(gcm, 0, sizeof(intel_AES_GCMContext));
+ PORT_SafeZero(gcm, sizeof(intel_AES_GCMContext));
if (freeit) {
PORT_Free(gcm);
}
diff -up ./lib/freebl/ppc-gcm-wrap.c.safe_zero ./lib/freebl/ppc-gcm-wrap.c
--- ./lib/freebl/ppc-gcm-wrap.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/ppc-gcm-wrap.c 2023-11-22 14:42:24.246388369 -0800
@@ -169,7 +169,7 @@ ppc_aes_gcmInitCounter(ppc_AES_GCMContex
void
ppc_AES_GCM_DestroyContext(ppc_AES_GCMContext *gcm, PRBool freeit)
{
- PORT_Memset(gcm, 0, sizeof(ppc_AES_GCMContext));
+ PORT_SafeZero(gcm, sizeof(ppc_AES_GCMContext));
if (freeit) {
PORT_Free(gcm);
}
diff -up ./lib/freebl/pqg.c.safe_zero ./lib/freebl/pqg.c
--- ./lib/freebl/pqg.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/pqg.c 2023-11-22 14:42:24.246388369 -0800
@@ -703,7 +703,7 @@ cleanup:
mp_clear(&a);
mp_clear(&z);
mp_clear(&two_length_minus_1);
- PORT_Memset(x, 0, sizeof(x));
+ PORT_SafeZero(x, sizeof(x));
if (err) {
MP_TO_SEC_ERROR(err);
rv = SECFailure;
@@ -859,7 +859,7 @@ cleanup:
mp_clear(&c);
mp_clear(&c0);
mp_clear(&one);
- PORT_Memset(x, 0, sizeof(x));
+ PORT_SafeZero(x, sizeof(x));
if (err) {
MP_TO_SEC_ERROR(err);
rv = SECFailure;
@@ -1072,7 +1072,7 @@ makePfromQandSeed(
CHECK_MPI_OK(mp_sub_d(&c, 1, &c)); /* c -= 1 */
CHECK_MPI_OK(mp_sub(&X, &c, P)); /* P = X - c */
cleanup:
- PORT_Memset(V_j, 0, sizeof V_j);
+ PORT_SafeZero(V_j, sizeof V_j);
mp_clear(&W);
mp_clear(&X);
mp_clear(&c);
@@ -1221,7 +1221,7 @@ makeGfromIndex(HASH_HashType hashtype,
/* step 11.
* return valid G */
cleanup:
- PORT_Memset(data, 0, sizeof(data));
+ PORT_SafeZero(data, sizeof(data));
if (hashcx) {
hashobj->destroy(hashcx, PR_TRUE);
}
diff -up ./lib/freebl/rijndael.c.safe_zero ./lib/freebl/rijndael.c
--- ./lib/freebl/rijndael.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/rijndael.c 2023-11-22 14:42:24.247388378 -0800
@@ -1114,7 +1114,7 @@ AES_DestroyContext(AESContext *cx, PRBoo
cx->worker_cx = NULL;
cx->destroy = NULL;
}
- PORT_Memset(cx, 0, sizeof(AESContext));
+ PORT_SafeZero(cx, sizeof(AESContext));
if (freeit) {
PORT_Free(mem);
} else {
diff -up ./lib/freebl/rsa.c.safe_zero ./lib/freebl/rsa.c
--- ./lib/freebl/rsa.c.safe_zero 2023-11-22 14:41:24.066840894 -0800
+++ ./lib/freebl/rsa.c 2023-11-22 14:42:24.247388378 -0800
@@ -143,8 +143,8 @@ rsa_build_from_primes(const mp_int *p, c
/* 2. Compute phi = (p-1)*(q-1) */
CHECK_MPI_OK(mp_sub_d(p, 1, &psub1));
CHECK_MPI_OK(mp_sub_d(q, 1, &qsub1));
+ CHECK_MPI_OK(mp_lcm(&psub1, &qsub1, &phi));
if (needPublicExponent || needPrivateExponent) {
- CHECK_MPI_OK(mp_lcm(&psub1, &qsub1, &phi));
/* 3. Compute d = e**-1 mod(phi) */
/* or e = d**-1 mod(phi) as necessary */
if (needPublicExponent) {
@@ -165,6 +165,15 @@ rsa_build_from_primes(const mp_int *p, c
goto cleanup;
}
+ /* make sure we weren't passed in a d or e = 1 mod phi */
+ /* just need to check d, because if one is = 1 mod phi, they both are */
+ CHECK_MPI_OK(mp_mod(d, &phi, &tmp));
+ if (mp_cmp_d(&tmp, 2) <= 0) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+ goto cleanup;
+ }
+
/* 4. Compute exponent1 = d mod (p-1) */
CHECK_MPI_OK(mp_mod(d, &psub1, &tmp));
MPINT_TO_SECITEM(&tmp, &key->exponent1, key->arena);
@@ -1152,6 +1161,8 @@ rsa_PrivateKeyOpCRTCheckedPubKey(RSAPriv
/* Perform a public key operation v = m ** e mod n */
CHECK_MPI_OK(mp_exptmod(m, &e, &n, &v));
if (mp_cmp(&v, c) != 0) {
+ /* this error triggers a fips fatal error lock */
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
rv = SECFailure;
}
cleanup:
diff -up ./lib/freebl/rsapkcs.c.safe_zero ./lib/freebl/rsapkcs.c
--- ./lib/freebl/rsapkcs.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/rsapkcs.c 2023-11-22 14:42:24.247388378 -0800
@@ -977,14 +977,14 @@ rsa_GetHMACContext(const SECHashObject *
/* now create the hmac key */
hmac = HMAC_Create(hash, keyHash, keyLen, PR_TRUE);
if (hmac == NULL) {
- PORT_Memset(keyHash, 0, sizeof(keyHash));
+ PORT_SafeZero(keyHash, sizeof(keyHash));
return NULL;
}
HMAC_Begin(hmac);
HMAC_Update(hmac, input, inputLen);
rv = HMAC_Finish(hmac, keyHash, &keyLen, sizeof(keyHash));
if (rv != SECSuccess) {
- PORT_Memset(keyHash, 0, sizeof(keyHash));
+ PORT_SafeZero(keyHash, sizeof(keyHash));
HMAC_Destroy(hmac, PR_TRUE);
return NULL;
}
@@ -992,7 +992,7 @@ rsa_GetHMACContext(const SECHashObject *
* reuse the original context allocated above so we don't
* need to allocate and free another one */
rv = HMAC_ReInit(hmac, hash, keyHash, keyLen, PR_TRUE);
- PORT_Memset(keyHash, 0, sizeof(keyHash));
+ PORT_SafeZero(keyHash, sizeof(keyHash));
if (rv != SECSuccess) {
HMAC_Destroy(hmac, PR_TRUE);
return NULL;
@@ -1042,7 +1042,7 @@ rsa_HMACPrf(HMACContext *hmac, const cha
return rv;
}
PORT_Memcpy(output, hmacLast, left);
- PORT_Memset(hmacLast, 0, sizeof(hmacLast));
+ PORT_SafeZero(hmacLast, sizeof(hmacLast));
}
return rv;
}
@@ -1087,7 +1087,7 @@ rsa_GetErrorLength(HMACContext *hmac, in
outLength = PORT_CT_SEL(PORT_CT_LT(candidate, maxLegalLen),
candidate, outLength);
}
- PORT_Memset(out, 0, sizeof(out));
+ PORT_SafeZero(out, sizeof(out));
return outLength;
}
diff -up ./lib/freebl/shvfy.c.safe_zero ./lib/freebl/shvfy.c
--- ./lib/freebl/shvfy.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/shvfy.c 2023-11-22 14:42:24.247388378 -0800
@@ -365,7 +365,7 @@ blapi_SHVerifyDSACheck(PRFileDesc *shFD,
/* verify the hash against the check file */
rv = DSA_VerifyDigest(key, signature, &hash);
- PORT_Memset(hashBuf, 0, sizeof hashBuf);
+ PORT_SafeZero(hashBuf, sizeof hashBuf);
return (rv == SECSuccess) ? PR_TRUE : PR_FALSE;
}
#endif
@@ -427,7 +427,7 @@ blapi_SHVerifyHMACCheck(PRFileDesc *shFD
if (rv == SECSuccess) {
result = SECITEM_ItemsAreEqual(signature, &hash);
}
- PORT_Memset(hashBuf, 0, sizeof hashBuf);
+ PORT_SafeZero(hashBuf, sizeof hashBuf);
return result;
}
@@ -451,7 +451,7 @@ blapi_SHVerifyFile(const char *shName, P
#ifndef NSS_STRICT_INTEGRITY
DSAPublicKey key;
- PORT_Memset(&key, 0, sizeof(key));
+ PORT_SafeZero(&key, sizeof(key));
#endif
/* If our integrity check was never ran or failed, fail any other
@@ -597,7 +597,7 @@ blapi_SHVerifyFile(const char *shName, P
shFD = NULL;
loser:
- PORT_Memset(&header, 0, sizeof header);
+ PORT_SafeZero(&header, sizeof header);
if (checkName != NULL) {
PORT_Free(checkName);
}
diff -up ./lib/freebl/tlsprfalg.c.safe_zero ./lib/freebl/tlsprfalg.c
--- ./lib/freebl/tlsprfalg.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/tlsprfalg.c 2023-11-22 14:42:24.247388378 -0800
@@ -82,8 +82,8 @@ loser:
/* clear out state so it's not left on the stack */
if (cx)
HMAC_Destroy(cx, PR_TRUE);
- PORT_Memset(state, 0, sizeof(state));
- PORT_Memset(outbuf, 0, sizeof(outbuf));
+ PORT_SafeZero(state, sizeof(state));
+ PORT_SafeZero(outbuf, sizeof(outbuf));
return rv;
}
diff -up ./lib/freebl/unix_urandom.c.safe_zero ./lib/freebl/unix_urandom.c
--- ./lib/freebl/unix_urandom.c.safe_zero 2023-11-22 14:42:24.247388378 -0800
+++ ./lib/freebl/unix_urandom.c 2023-11-22 14:44:15.519400684 -0800
@@ -22,7 +22,7 @@ RNG_SystemInfoForRNG(void)
return;
}
RNG_RandomUpdate(bytes, numBytes);
- PORT_Memset(bytes, 0, sizeof bytes);
+ PORT_SafeZero(bytes, sizeof bytes);
}
#ifdef NSS_FIPS_140_3
diff -up ./lib/softoken/pkcs11c.c.safe_zero ./lib/softoken/pkcs11c.c
--- ./lib/softoken/pkcs11c.c.safe_zero 2023-11-22 14:41:24.069840921 -0800
+++ ./lib/softoken/pkcs11c.c 2023-11-22 14:42:24.248388387 -0800
@@ -5092,7 +5092,7 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
if ((signature_length >= pairwise_digest_length) &&
(PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0)) {
PORT_Free(signature);
- return CKR_DEVICE_ERROR;
+ return CKR_GENERAL_ERROR;
}
/* Verify the known hash using the public key. */
diff -up ./lib/util/secport.h.safe_zero ./lib/util/secport.h
--- ./lib/util/secport.h.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/util/secport.h 2023-11-22 14:42:24.248388387 -0800
@@ -36,6 +36,9 @@
#include <sys/types.h>
#include <ctype.h>
+/* ask for Annex K for memset_s. will set the appropriate #define
+ * if Annex K is supported */
+#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
@@ -182,6 +185,39 @@ SEC_END_PROTOS
#endif /*SUNOS4*/
#define PORT_Memset memset
+/* there are cases where the compiler optimizes away our attempt to clear
+ * out our stack variables. There are multiple solutions for this problem,
+ * but they aren't universally accepted on all platforms. This attempts
+ * to select the best solution available given our os, compilier, and libc */
+#ifdef __STDC_LIB_EXT1__
+/* if the os implements C11 annex K, use memset_s */
+#define PORT_SafeZero(p, n) memset_s(p, n, 0, n)
+#else
+#ifdef XP_WIN
+/* windows has a secure zero funtion */
+#define PORT_SafeZero(p, n) SecureZeroMemory(p, n)
+#else
+/* _DEFAULT_SORUCE == BSD source in GCC based environments
+ * if other environmens support explicit_bzero, their defines
+ * should be added here */
+#if defined(_DEFAULT_SOURCE) || defined(_BSD_SOURCE)
+#define PORT_SafeZero(p, n) explicit_bzero(p, n)
+#else
+/* if the os doesn't support one of the above, but does support
+ * memset_explicit, you can add the definition for memset with the
+ * appropriate define check here */
+/* define an explicitly implementated Safe zero if the OS
+ * doesn't provide one */
+#define PORT_SafeZero(p, n) \
+ if (p != NULL) { \
+ volatile unsigned char *__vl = (unsigned char *)p; \
+ size_t __nl = n; \
+ while (__nl--) *__vl++ = 0; \
+ }
+#endif /* no explicit_bzero */
+#endif /* no windows SecureZeroMemory */
+#endif /* no memset_s */
+
#define PORT_Strcasecmp PL_strcasecmp
#define PORT_Strcat strcat
#define PORT_Strchr strchr