diff options
| author | Jakob Unterwurzacher | 2016-09-20 21:58:04 +0200 | 
|---|---|---|
| committer | Jakob Unterwurzacher | 2016-09-25 16:43:17 +0200 | 
| commit | 7f87ed78f2f27831f2fa9409106846e3288c6f6e (patch) | |
| tree | b756236a7a9fcfce9f20eeee5ce4ba7aa51b00d9 /internal/cryptocore | |
| parent | d1762c5b95c3279b0a2dfa3df5c99fe59922b666 (diff) | |
cryptocore: add support for GCM-SIV
Diffstat (limited to 'internal/cryptocore')
| -rw-r--r-- | internal/cryptocore/cryptocore.go | 48 | ||||
| -rw-r--r-- | internal/cryptocore/cryptocore_go1.4_test.go | 5 | ||||
| -rw-r--r-- | internal/cryptocore/cryptocore_go1.5_test.go | 2 | ||||
| -rw-r--r-- | internal/cryptocore/cryptocore_test.go | 14 | 
4 files changed, 40 insertions, 29 deletions
| diff --git a/internal/cryptocore/cryptocore.go b/internal/cryptocore/cryptocore.go index 1839aa2..a6708bd 100644 --- a/internal/cryptocore/cryptocore.go +++ b/internal/cryptocore/cryptocore.go @@ -8,17 +8,29 @@ import (  	"fmt"  	"github.com/rfjakob/gocryptfs/internal/stupidgcm" + +	"github.com/rfjakob/gcmsiv"  ) +type BackendTypeEnum int +  const (  	KeyLen     = 32 // AES-256  	AuthTagLen = 16 + +	_                              = iota // Skip zero +	BackendOpenSSL BackendTypeEnum = iota +	BackendGoGCM   BackendTypeEnum = iota +	BackendGCMSIV  BackendTypeEnum = iota  )  type CryptoCore struct { +	// AES-256 block cipher. This is used for EME filename encryption.  	BlockCipher cipher.Block -	Gcm         cipher.AEAD -	GcmIVGen    *nonceGenerator +	// GCM or GCM-SIV. This is used for content encryption. +	AEADCipher cipher.AEAD +	// GCM needs unique IVs (nonces) +	IVGenerator *nonceGenerator  	IVLen       int  } @@ -27,17 +39,12 @@ type CryptoCore struct {  // Even though the "GCMIV128" feature flag is now mandatory, we must still  // support 96-bit IVs here because they are used for encrypting the master  // key in gocryptfs.conf. -func New(key []byte, useOpenssl bool, GCMIV128 bool) *CryptoCore { - +func New(key []byte, backend BackendTypeEnum, IVBitLen int) *CryptoCore {  	if len(key) != KeyLen {  		panic(fmt.Sprintf("Unsupported key length %d", len(key)))  	} -  	// We want the IV size in bytes -	IVLen := 96 / 8 -	if GCMIV128 { -		IVLen = 128 / 8 -	} +	IVLen := IVBitLen / 8  	// Name encryption always uses built-in Go AES through BlockCipher.  	// Content encryption uses BlockCipher only if useOpenssl=false. @@ -47,20 +54,27 @@ func New(key []byte, useOpenssl bool, GCMIV128 bool) *CryptoCore {  	}  	var gcm cipher.AEAD -	if useOpenssl && GCMIV128 { -		// stupidgcm only supports 128-bit IVs +	switch backend { +	case BackendOpenSSL: +		if IVLen != 16 { +			panic("stupidgcm only supports 128-bit IVs") +		}  		gcm = stupidgcm.New(key) -	} else { +	case BackendGoGCM:  		gcm, err = goGCMWrapper(blockCipher, IVLen) -		if err != nil { -			panic(err) -		} +	case BackendGCMSIV: +		gcm, err = gcmsiv.NewGCMSIV(key) +	default: +		panic("unknown backend cipher") +	} +	if err != nil { +		panic(err)  	}  	return &CryptoCore{  		BlockCipher: blockCipher, -		Gcm:         gcm, -		GcmIVGen:    &nonceGenerator{nonceLen: IVLen}, +		AEADCipher:  gcm, +		IVGenerator: &nonceGenerator{nonceLen: IVLen},  		IVLen:       IVLen,  	}  } diff --git a/internal/cryptocore/cryptocore_go1.4_test.go b/internal/cryptocore/cryptocore_go1.4_test.go index 3460d02..14e1e03 100644 --- a/internal/cryptocore/cryptocore_go1.4_test.go +++ b/internal/cryptocore/cryptocore_go1.4_test.go @@ -7,7 +7,8 @@ import (  	"testing"  ) -// Native Go crypto with 128-bit IVs is only supported on Go 1.5 and up +// Native Go crypto with 128-bit IVs is only supported on Go 1.5 and up, +// this should panic.  func TestCryptoCoreNewGo14(t *testing.T) {  	defer func() {  		if r := recover(); r == nil { @@ -15,5 +16,5 @@ func TestCryptoCoreNewGo14(t *testing.T) {  		}  	}()  	key := make([]byte, 32) -	New(key, false, true) +	New(key, BackendGoGCM, 128)  } diff --git a/internal/cryptocore/cryptocore_go1.5_test.go b/internal/cryptocore/cryptocore_go1.5_test.go index 1c93254..f9d38e9 100644 --- a/internal/cryptocore/cryptocore_go1.5_test.go +++ b/internal/cryptocore/cryptocore_go1.5_test.go @@ -9,7 +9,7 @@ import (  func TestCryptoCoreNewGo15(t *testing.T) {  	key := make([]byte, 32) -	c := New(key, false, true) +	c := New(key, BackendGoGCM, 128)  	if c.IVLen != 16 {  		t.Fail()  	} diff --git a/internal/cryptocore/cryptocore_test.go b/internal/cryptocore/cryptocore_test.go index 1151591..9da6059 100644 --- a/internal/cryptocore/cryptocore_test.go +++ b/internal/cryptocore/cryptocore_test.go @@ -4,23 +4,19 @@ import (  	"testing"  ) -// "New" should accept all param combinations +// "New" should accept at least these param combinations  func TestCryptoCoreNew(t *testing.T) {  	key := make([]byte, 32) -	c := New(key, true, true) +	c := New(key, BackendOpenSSL, 128)  	if c.IVLen != 16 {  		t.Fail()  	} -	c = New(key, true, false) +	c = New(key, BackendGoGCM, 96)  	if c.IVLen != 12 {  		t.Fail()  	} -	c = New(key, false, false) -	if c.IVLen != 12 { -		t.Fail() -	} -	// "New(key, false, true)" is tested for Go 1.4 and 1.5+ seperately +	// "New(key, BackendGoGCM, 128)" is tested for Go 1.4 and 1.5+ seperately  }  // "New" should panic on any key not 32 bytes long @@ -32,5 +28,5 @@ func TestNewPanic(t *testing.T) {  	}()  	key := make([]byte, 16) -	New(key, true, true) +	New(key, BackendOpenSSL, 128)  } | 
