Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP2:GA
mozilla-nss.1743
nss-CC-zeroize.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File nss-CC-zeroize.patch of Package mozilla-nss.1743
# HG changeset patch # Parent b09c13388473637047ba5363ec2d77cdddb10c5f # Parent 12c829db838f9b243f9ca4a398c93291e5dcbe61 Zeroizations of internal states that could leak outside via heap or stack. diff --git a/lib/freebl/aeskeywrap.c b/lib/freebl/aeskeywrap.c --- a/lib/freebl/aeskeywrap.c +++ b/lib/freebl/aeskeywrap.c @@ -88,16 +88,17 @@ AESKeyWrap_CreateContext(const unsigned ** "cx" the context ** "freeit" if PR_TRUE then free the object as well as its sub-objects */ extern void AESKeyWrap_DestroyContext(AESKeyWrapContext *cx, PRBool freeit) { if (cx) { AES_DestroyContext(&cx->aescx, PR_FALSE); + memset(cx->iv, 0, sizeof (cx->iv)); /* memset(cx, 0, sizeof *cx); */ if (freeit) PORT_Free(cx); } } #if !BIG_ENDIAN_WITH_64_BIT_REGISTERS diff --git a/lib/freebl/cts.c b/lib/freebl/cts.c --- a/lib/freebl/cts.c +++ b/lib/freebl/cts.c @@ -36,16 +36,17 @@ CTS_CreateContext(void *context, freeblC cts->cipher = cipher; cts->context = context; return cts; } void CTS_DestroyContext(CTSContext *cts, PRBool freeit) { + PORT_Memset(cts, 0, sizeof(CTSContext)); if (freeit) { PORT_Free(cts); } } /* * See addemdum to NIST SP 800-38A * Generically handle cipher text stealing. Basically this is doing CBC @@ -133,17 +134,17 @@ CTS_EncryptUpdate(CTSContext *cts, unsig * (Cn-1**) in our buffer. This allows us to have input data == output * data since Cn contains enough information to reconver Cn-1** when * we decrypt (at the cost of some complexity as you can see in decrypt * below */ PORT_Memcpy(lastBlock, inbuf, inlen); PORT_Memset(lastBlock + inlen, 0, blocksize - inlen); rv = (*cts->cipher)(cts->context, outbuf, &tmp, maxout, lastBlock, blocksize, blocksize); - PORT_Memset(lastBlock, 0, blocksize); + PORT_Memset(lastBlock, 0, MAX_BLOCK_SIZE); if (rv == SECSuccess) { *outlen = written + blocksize; } return rv; } #define XOR_BLOCK(x,y,count) for(i=0; i < count; i++) x[i] = x[i] ^ y[i] @@ -225,23 +226,25 @@ CTS_DecryptUpdate(CTSContext *cts, unsig * chaining */ tmp = (fullblocks < blocksize*2) ? cts->iv : inbuf+fullblocks-blocksize*2; PORT_Memcpy(Cn_2, tmp, blocksize); PORT_Memcpy(Cn, inbuf+fullblocks-blocksize, blocksize); rv = (*cts->cipher)(cts->context, outbuf, outlen, maxout, inbuf, fullblocks, blocksize); if (rv != SECSuccess) { - return SECFailure; + rv = SECFailure; + goto cleanup; } *outlen = fullblocks; /* AES low level doesn't set outlen */ inbuf += fullblocks; inlen -= fullblocks; if (inlen == 0) { - return SECSuccess; + rv = SECSuccess; + goto cleanup; } outbuf += fullblocks; /* recover the stolen text */ PORT_Memset(lastBlock, 0, blocksize); PORT_Memcpy(lastBlock, inbuf, inlen); PORT_Memcpy(Cn_1, inbuf, inlen); Pn = outbuf-blocksize; @@ -275,27 +278,26 @@ CTS_DecryptUpdate(CTSContext *cts, unsig /* copy Cn-1* into last buf to recover Cn-1 */ PORT_Memcpy(lastBlock, Cn_1, inlen); /* note: because Cn and Cn-1 were out of order, our pointer to Pn also * points to where Pn-1 needs to reside. From here on out read Pn in * the code as really Pn-1. */ rv = (*cts->cipher)(cts->context, Pn, &tmpLen, blocksize, lastBlock, blocksize, blocksize); if (rv != SECSuccess) { - return SECFailure; + rv = SECFailure; + goto cleanup; } /* make up for the out of order CBC decryption */ XOR_BLOCK(Pn, Cn_2, blocksize); XOR_BLOCK(Pn, Cn, blocksize); /* reset iv to Cn */ PORT_Memcpy(cts->iv, Cn, blocksize); /* This makes Cn the last block for the next decrypt operation, which * matches the encrypt. We don't care about the contexts of last block, * only the side effect of setting the internal IV */ (void) (*cts->cipher)(cts->context, lastBlock, &tmpLen, blocksize, Cn, blocksize, blocksize); - /* clear last block. At this point last block contains Pn xor Cn_1 xor - * Cn_2, both of with an attacker would know, so we need to clear this - * buffer out */ - PORT_Memset(lastBlock, 0, blocksize); +cleanup: + PORT_Memset(lastBlock, 0, MAX_BLOCK_SIZE); /* Cn, Cn_1, and Cn_2 have encrypted data, so no need to clear them */ - return SECSuccess; + return rv; } diff --git a/lib/freebl/dh.c b/lib/freebl/dh.c --- a/lib/freebl/dh.c +++ b/lib/freebl/dh.c @@ -168,36 +168,41 @@ DH_NewKey(DHParams *params, DHPrivateKey CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->prime, ¶ms->prime) ); SECITEM_TO_MPINT(key->prime, &p); /* Set private key's g */ CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->base, ¶ms->base) ); SECITEM_TO_MPINT(key->base, &g); /* Generate private key xa */ SECITEM_AllocItem(arena, &key->privateValue, dh_GetSecretKeyLen(params->prime.len)); - RNG_GenerateGlobalRandomBytes(key->privateValue.data, - key->privateValue.len); + CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(key->privateValue.data, + key->privateValue.len)); SECITEM_TO_MPINT( key->privateValue, &xa ); /* xa < p */ CHECK_MPI_OK( mp_mod(&xa, &p, &xa) ); /* Compute public key Ya = g ** xa mod p */ CHECK_MPI_OK( mp_exptmod(&g, &xa, &p, &Ya) ); MPINT_TO_SECITEM(&Ya, &key->publicValue, key->arena); *privKey = key; cleanup: mp_clear(&g); mp_clear(&xa); mp_clear(&p); mp_clear(&Ya); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } - if (rv) + if (rv) { + SECITEM_ZfreeItem(&key->prime, PR_FALSE); + SECITEM_ZfreeItem(&key->base, PR_FALSE); + SECITEM_ZfreeItem(&key->publicValue, PR_FALSE); + SECITEM_ZfreeItem(&key->privateValue, PR_FALSE); PORT_FreeArena(arena, PR_TRUE); + } return rv; } SECStatus DH_Derive(SECItem *publicValue, SECItem *prime, SECItem *privateValue, SECItem *derivedSecret, diff --git a/lib/freebl/ec.c b/lib/freebl/ec.c --- a/lib/freebl/ec.c +++ b/lib/freebl/ec.c @@ -367,22 +367,22 @@ ec_GenerateRandomPrivateKey(const unsign CHECK_MPI_OK( mp_add(&privKeyVal, &one, &privKeyVal) ); CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len) ); memset(privKeyBytes+len, 0, len); cleanup: mp_clear(&privKeyVal); mp_clear(&order_1); mp_clear(&one); if (err < MP_OKAY) { - MP_TO_SEC_ERROR(err); - rv = SECFailure; - } - if (rv != SECSuccess && privKeyBytes) { - PORT_Free(privKeyBytes); - privKeyBytes = NULL; + MP_TO_SEC_ERROR(err); + if (privKeyBytes) { + memset(privKeyBytes, 0, 2*len); + PORT_Free(privKeyBytes); + privKeyBytes = NULL; + } } return privKeyBytes; } #endif /* NSS_DISABLE_ECC */ /* Generates a new EC key pair. The private key is a random value and * the public key is the result of performing a scalar point multiplication * of that value with the curve's base point. @@ -1061,17 +1061,20 @@ cleanup: mp_clear(&s_); mp_clear(&c); mp_clear(&u1); mp_clear(&u2); mp_clear(&x1); mp_clear(&v); mp_clear(&n); - if (pointC.data) SECITEM_FreeItem(&pointC, PR_FALSE); + if (pointC.data) { + PORT_Memset(pointC.data, 0, 2*flen + 1); + SECITEM_FreeItem(&pointC, PR_FALSE); + } if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } #if EC_DEBUG printf("ECDSA verification %s\n", (rv == SECSuccess) ? "succeeded" : "failed"); diff --git a/lib/freebl/gcm.c b/lib/freebl/gcm.c --- a/lib/freebl/gcm.c +++ b/lib/freebl/gcm.c @@ -196,18 +196,23 @@ static void gcmHash_DestroyContext(gcmHashContext *ghash, PRBool freeit) { mp_clear(&ghash->H); mp_clear(&ghash->X); mp_clear(&ghash->C_i); MP_DIGITS(&ghash->H) = 0; MP_DIGITS(&ghash->X) = 0; MP_DIGITS(&ghash->C_i) = 0; + PORT_Memset(ghash->buffer, 0, sizeof(ghash->buffer)); + ghash->bufLen = 0; + ghash->m = 0; + PORT_Memset(ghash->counterBuf, 0, sizeof(ghash->counterBuf)); + ghash->cLen = 0; if (freeit) { - PORT_Free(ghash); + PORT_Free(ghash); } } static SECStatus gcm_getX(gcmHashContext *ghash, unsigned char *T, unsigned int blocksize) { int len; mp_err err; @@ -268,32 +273,35 @@ gcm_HashMult(gcmHashContext *ghash, cons * the builtin bmulmod from mpi */ CHECK_MPI_OK(mp_bmulmod(&ghash->C_i, &ghash->H, ghash->poly, &ghash->X)); GCM_TRACE_X(ghash, "X%d = ") } rv = SECSuccess; cleanup: + mp_zero(&ghash->C_i); + PORT_Memset(tmp_buf, 0, sizeof(tmp_buf)); if (rv != SECSuccess) { MP_TO_SEC_ERROR(err); } return rv; } static void gcm_zeroX(gcmHashContext *ghash) { mp_zero(&ghash->X); ghash->m = 0; } #endif -#ifdef GCM_USE_ALGORITHM_1 +#if 0 +//#ifdef GCM_USE_ALGORITHM_1 /* use algorithm 1 of McGrew & Viega "The Galois/Counter Mode of Operation" */ #define GCM_ARRAY_SIZE (MAX_BLOCK_SIZE/sizeof(unsigned long)) struct gcmHashContextStr { unsigned long H[GCM_ARRAY_SIZE]; unsigned long X[GCM_ARRAY_SIZE]; unsigned long R; @@ -696,18 +704,20 @@ loser: void GCM_DestroyContext(GCMContext *gcm, PRBool freeit) { /* these two are statically allocated and will be freed when we free * gcm. call their destroy functions to free up any locally * allocated data (like mp_int's) */ CTR_DestroyContext(&gcm->ctr_context, PR_FALSE); gcmHash_DestroyContext(&gcm->ghash_context, PR_FALSE); + gcm->tagBits = 0; + PORT_Memset(gcm->tagKey, 0, sizeof(gcm->tagKey)); if (freeit) { - PORT_Free(gcm); + PORT_Free(gcm); } } static SECStatus gcm_GetTag(GCMContext *gcm, unsigned char *outbuf, unsigned int *outlen, unsigned int maxout, unsigned int blocksize) { @@ -827,26 +837,39 @@ GCM_DecryptUpdate(GCMContext *gcm, unsig } inlen -= tagBytes; intag = inbuf + inlen; /* verify the block */ rv = gcmHash_Update(&gcm->ghash_context, inbuf, inlen, blocksize); if (rv != SECSuccess) { - return SECFailure; + rv = SECFailure; + goto cleanup; } rv = gcm_GetTag(gcm, tag, &len, blocksize, blocksize); if (rv != SECSuccess) { - return SECFailure; + rv = SECFailure; + goto cleanup; } /* Don't decrypt if we can't authenticate the encrypted data! * This assumes that if tagBits is not a multiple of 8, intag will * preserve the masked off missing bits. */ if (NSS_SecureMemcmp(tag, intag, tagBytes) != 0) { - /* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */ - PORT_SetError(SEC_ERROR_BAD_DATA); - return SECFailure; + /* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */ + PORT_SetError(SEC_ERROR_BAD_DATA); + rv = SECFailure; } + +cleanup: + /* stack cleanup */ + tagBytes = 0; + PORT_Memset(tag, 0, sizeof(tag)); + intag = NULL; + len = 0; + /* finish the decryption */ + if (rv != SECSuccess) { + return rv; + } return CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout, inbuf, inlen, blocksize); } diff --git a/lib/freebl/pqg.c b/lib/freebl/pqg.c --- a/lib/freebl/pqg.c +++ b/lib/freebl/pqg.c @@ -707,16 +707,17 @@ cleanup: } if (rv == SECFailure) { mp_zero(prime); if (prime_seed->data) { SECITEM_FreeItem(prime_seed, PR_FALSE); } *prime_gen_counter = 0; } + PORT_Memset(x, 0, sizeof(x)); return rv; } /* ** Perform steps from FIPS 186-3, Appendix C.6 ** ** This generates a provable prime from a seed */ @@ -862,16 +863,17 @@ cleanup: } if (rv == SECFailure) { mp_zero(prime); if (prime_seed->data) { SECITEM_FreeItem(prime_seed, PR_FALSE); } *prime_gen_counter = 0; } + PORT_Memset(x, 0, sizeof(x)); return rv; } /* * Find a Q and algorithm from Seed. */ static SECStatus
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor