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) } |