From 344d7e0a6f06cf7829dc5af1732dfbd116597dc1 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Sun, 18 Feb 2018 16:01:46 +0100 Subject: [PATCH] siv_aead: create private key copy and implement wiping Having a private copy relieves the caller from worrying about whether he can zero his copy. The copy can be cleared by calling Wipe(). --- internal/siv_aead/siv_aead.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/internal/siv_aead/siv_aead.go b/internal/siv_aead/siv_aead.go index 3cb42ab..eabb5e2 100644 --- a/internal/siv_aead/siv_aead.go +++ b/internal/siv_aead/siv_aead.go @@ -32,7 +32,9 @@ func New(key []byte) cipher.AEAD { } // Same as "New" without the 64-byte restriction. -func new2(key []byte) cipher.AEAD { +func new2(keyIn []byte) cipher.AEAD { + // Create a private copy so the caller can zero the one he owns + key := append([]byte{}, keyIn...) return &sivAead{ key: key, } @@ -53,6 +55,9 @@ func (s *sivAead) Seal(dst, nonce, plaintext, authData []byte) []byte { // SIV supports any nonce size, but in gocryptfs we exclusively use 16. log.Panic("nonce must be 16 bytes long") } + if len(s.key) == 0 { + log.Panic("Key has been wiped?") + } // https://github.com/jacobsa/crypto/blob/master/siv/encrypt.go#L48: // As per RFC 5297 section 3, you may use this function for nonce-based // authenticated encryption by passing a nonce as the last associated @@ -71,7 +76,22 @@ func (s *sivAead) Open(dst, nonce, ciphertext, authData []byte) ([]byte, error) // SIV supports any nonce size, but in gocryptfs we exclusively use 16. log.Panic("nonce must be 16 bytes long") } + if len(s.key) == 0 { + log.Panic("Key has been wiped?") + } associated := [][]byte{authData, nonce} dec, err := siv.Decrypt(s.key, ciphertext, associated) return append(dst, dec...), err } + +// Wipe tries to wipe the AES key from memory by overwriting it with zeros +// and setting the reference to nil. +// +// This is not bulletproof due to possible GC copies, but +// still raises to bar for extracting the key. +func (s *sivAead) Wipe() { + for i := range s.key { + s.key[i] = 0 + } + s.key = nil +}