Switch nonce generation to purely random

The old implementation of counting up from a random starting
point had the problem that is allowed an attacker to find out
the write order of the blocks.
This commit is contained in:
Jakob Unterwurzacher 2015-10-04 21:36:16 +02:00
parent df52aab082
commit e6b7353f4e
1 changed files with 15 additions and 35 deletions

View File

@ -1,56 +1,36 @@
package cryptfs package cryptfs
import ( import (
"bytes"
"fmt"
"crypto/rand" "crypto/rand"
"encoding/binary"
"encoding/hex" "encoding/hex"
"sync"
) )
type nonce96 struct {
lock sync.Mutex
high32 uint32
low64 uint64
ready int
}
var gcmNonce nonce96
// Get "n" random bytes from /dev/urandom or panic // Get "n" random bytes from /dev/urandom or panic
func RandBytes(n int) []byte { func RandBytes(n int) []byte {
b := make([]byte, n) b := make([]byte, n)
_, err := rand.Read(b) _, err := rand.Read(b)
if err != nil { if err != nil {
panic("Could not get random bytes for nonce") panic("Failed to read random bytes: " + err.Error())
} }
return b return b
} }
func (n *nonce96) init() { var gcmNonce nonce96
b := RandBytes(8)
n.low64 = binary.BigEndian.Uint64(b) type nonce96 struct {
b = RandBytes(4) lastNonce []byte
n.high32 = binary.BigEndian.Uint32(b)
n.ready = 1
return
} }
// Get a random 96 bit nonce
func (n *nonce96) Get() []byte { func (n *nonce96) Get() []byte {
n.lock.Lock() nonce := RandBytes(12)
if n.ready == 0 { Debug.Printf("nonce96.Get(): %s\n", hex.EncodeToString(nonce))
n.init() if bytes.Equal(nonce, n.lastNonce) {
m := fmt.Sprintf("Got the same nonce twice: %s. This should never happen!", hex.EncodeToString(nonce))
panic(m)
} }
n.low64++ n.lastNonce = nonce
if n.low64 == 0 { return nonce
// Counter has wrapped
n.high32++
}
r := make([]byte, 12)
binary.BigEndian.PutUint32(r[0:4], n.high32)
binary.BigEndian.PutUint64(r[4:12], n.low64)
n.lock.Unlock()
Debug.Printf("nonce96.Get(): %s\n", hex.EncodeToString(r))
return r
} }