diff options
| author | Jakob Unterwurzacher | 2018-02-18 16:07:09 +0100 | 
|---|---|---|
| committer | Jakob Unterwurzacher | 2018-02-18 16:07:09 +0100 | 
| commit | 6c6947126d38f8988bcbf59db088c9cddc55b9ab (patch) | |
| tree | a1cbae590ad2e762b602ccb3489b7625e1e8874e /internal/cryptocore | |
| parent | 344d7e0a6f06cf7829dc5af1732dfbd116597dc1 (diff) | |
cryptocore: zero derived keys
Zero the HKDF-derived keys when we don't need them
anymore, and let the variable run of of scope.
https://github.com/rfjakob/gocryptfs/issues/211
Diffstat (limited to 'internal/cryptocore')
| -rw-r--r-- | internal/cryptocore/cryptocore.go | 46 | 
1 files changed, 33 insertions, 13 deletions
| diff --git a/internal/cryptocore/cryptocore.go b/internal/cryptocore/cryptocore.go index e427350..09bab53 100644 --- a/internal/cryptocore/cryptocore.go +++ b/internal/cryptocore/cryptocore.go @@ -65,12 +65,18 @@ func New(key []byte, aeadType AEADTypeEnum, IVBitLen int, useHKDF bool, forceDec  	// Initialize EME for filename encryption.  	var emeCipher *eme.EMECipher +	var err error  	{ -		emeKey := key +		var emeBlockCipher cipher.Block  		if useHKDF { -			emeKey = hkdfDerive(key, hkdfInfoEMENames, KeyLen) +			emeKey := hkdfDerive(key, hkdfInfoEMENames, KeyLen) +			emeBlockCipher, err = aes.NewCipher(emeKey) +			for i := range emeKey { +				emeKey[i] = 0 +			} +		} else { +			emeBlockCipher, err = aes.NewCipher(key)  		} -		emeBlockCipher, err := aes.NewCipher(emeKey)  		if err != nil {  			log.Panic(err)  		} @@ -80,9 +86,11 @@ func New(key []byte, aeadType AEADTypeEnum, IVBitLen int, useHKDF bool, forceDec  	// Initialize an AEAD cipher for file content encryption.  	var aeadCipher cipher.AEAD  	if aeadType == BackendOpenSSL || aeadType == BackendGoGCM { -		gcmKey := key +		var gcmKey []byte  		if useHKDF {  			gcmKey = hkdfDerive(key, hkdfInfoGCMContent, KeyLen) +		} else { +			gcmKey = append([]byte{}, key...)  		}  		switch aeadType {  		case BackendOpenSSL: @@ -100,22 +108,29 @@ func New(key []byte, aeadType AEADTypeEnum, IVBitLen int, useHKDF bool, forceDec  				log.Panic(err)  			}  		} +		for i := range gcmKey { +			gcmKey[i] = 0 +		}  	} else if aeadType == BackendAESSIV {  		if IVLen != 16 {  			// SIV supports any nonce size, but we only use 16.  			log.Panic("AES-SIV must use 16-byte nonces")  		} +		// AES-SIV uses 1/2 of the key for authentication, 1/2 for +		// encryption, so we need a 64-bytes key for AES-256. Derive it from +		// the 32-byte master key using HKDF, or, for older filesystems, with +		// SHA256.  		var key64 []byte  		if useHKDF {  			key64 = hkdfDerive(key, hkdfInfoSIVContent, siv_aead.KeyLen)  		} else { -			// AES-SIV uses 1/2 of the key for authentication, 1/2 for -			// encryption, so we need a 64-bytes key for AES-256. Derive it from -			// the master key by hashing it with SHA-512.  			s := sha512.Sum512(key)  			key64 = s[:]  		}  		aeadCipher = siv_aead.New(key64) +		for i := range key64 { +			key64[i] = 0 +		}  	} else {  		log.Panic("unknown backend cipher")  	} @@ -129,20 +144,25 @@ func New(key []byte, aeadType AEADTypeEnum, IVBitLen int, useHKDF bool, forceDec  	}  } +type wiper interface { +	Wipe() +} +  // Wipe tries to wipe secret keys from memory by overwriting them with zeros  // and/or setting references to nil.  //  // This is not bulletproof due to possible GC copies, but  // still raises to bar for extracting the key.  func (c *CryptoCore) Wipe() { -	if c.AEADBackend == BackendOpenSSL { -		tlog.Debug.Print("CryptoCore.Wipe: Wiping stupidgcm key") +	be := c.AEADBackend +	if be == BackendOpenSSL || be == BackendAESSIV { +		tlog.Debug.Printf("CryptoCore.Wipe: Wiping AEADBackend %d key", be)  		// We don't use "x, ok :=" because we *want* to crash loudly if the -		// type assertion fails (it should never fail). -		sgcm := c.AEADCipher.(*stupidgcm.StupidGCM) -		sgcm.Wipe() +		// type assertion fails. +		w := c.AEADCipher.(wiper) +		w.Wipe()  	} else { -		tlog.Debug.Print("CryptoCore.Wipe: niling stdlib refs") +		tlog.Debug.Print("CryptoCore.Wipe: Only nil'ing stdlib refs")  	}  	// We have no access to the keys (or key-equivalents) stored inside the  	// Go stdlib. Best we can is to nil the references and force a GC. | 
