diff options
Diffstat (limited to 'crypto/crypto_test.go')
| -rw-r--r-- | crypto/crypto_test.go | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index 7447e40..6f5c8f0 100644 --- a/crypto/crypto_test.go +++ b/crypto/crypto_test.go @@ -22,6 +22,11 @@ package crypto import ( "bytes" "compress/zlib" + "crypto/aes" + "crypto/sha256" + "fmt" + "fscrypt/metadata" + "fscrypt/util" "os" "testing" ) @@ -46,6 +51,15 @@ var fakeInvalidDescriptor = "123456789abcdef" var fakeValidPolicyKey, _ = makeKey(42, PolicyKeyLen) var fakeInvalidPolicyKey, _ = makeKey(42, PolicyKeyLen-1) +var fakeWrappingKey, _ = makeKey(17, InternalKeyLen) + +// Checks that len(array) == expected +func lengthCheck(name string, array []byte, expected int) error { + if len(array) != expected { + return util.InvalidLengthError(name, expected, len(array)) + } + return nil +} // Tests the two ways of making keys func TestMakeKeys(t *testing.T) { @@ -170,3 +184,198 @@ func didCompress(input []byte) bool { return err == nil && len(input) > output.Len() } + +// Checks that the input arrays are all distinct +func buffersDistinct(buffers ...[]byte) bool { + for i := 0; i < len(buffers); i++ { + for j := i + 1; j < len(buffers); j++ { + if bytes.Equal(buffers[i], buffers[j]) { + // Different entry, but equal arrays + return false + } + } + } + return true +} + +// Checks that our cryptographic operations all produce distinct data +func TestKeysAndOutputsDistinct(t *testing.T) { + data, err := Wrap(fakeWrappingKey, fakeValidPolicyKey) + if err != nil { + t.Fatal(err) + } + + encKey, authKey := stretchKey(fakeWrappingKey) + + if !buffersDistinct(fakeWrappingKey.data, fakeValidPolicyKey.data, + encKey.data, authKey.data, data.IV, data.EncryptedKey, data.Hmac) { + t.Error("Key wrapping produced duplicate data") + } +} + +// Check that Wrap() works with fixed keys +func TestWrapSucceeds(t *testing.T) { + data, err := Wrap(fakeWrappingKey, fakeValidPolicyKey) + if err != nil { + t.Fatal(err) + } + + if err = lengthCheck("IV", data.IV, aes.BlockSize); err != nil { + t.Error(err) + } + if err = lengthCheck("Encrypted Key", data.EncryptedKey, PolicyKeyLen); err != nil { + t.Error(err) + } + if err = lengthCheck("HMAC", data.Hmac, sha256.Size); err != nil { + t.Error(err) + } +} + +// Checks that applying Wrap then Unwrap gives the original data +func testWrapUnwrapEqual(wrappingKey *Key, secretKey *Key) error { + data, err := Wrap(wrappingKey, secretKey) + if err != nil { + return err + } + + secret, err := Unwrap(wrappingKey, data) + if err != nil { + return err + } + defer secret.Wipe() + + if !bytes.Equal(secretKey.data, secret.data) { + return fmt.Errorf("Got %x after wrap/unwrap with w=%x and s=%x", + secret.data, wrappingKey.data, secretKey.data) + } + return nil +} + +// Check that Unwrap(Wrap(x)) == x with fixed keys +func TestWrapUnwrapEqual(t *testing.T) { + if err := testWrapUnwrapEqual(fakeWrappingKey, fakeValidPolicyKey); err != nil { + t.Error(err) + } +} + +// Check that Unwrap(Wrap(x)) == x with random keys +func TestRandomWrapUnwrapEqual(t *testing.T) { + for i := 0; i < 10; i++ { + wk, err := NewRandomKey(InternalKeyLen) + if err != nil { + t.Fatal(err) + } + sk, err := NewRandomKey(InternalKeyLen) + if err != nil { + t.Fatal(err) + } + if err = testWrapUnwrapEqual(wk, sk); err != nil { + t.Error(err) + } + wk.Wipe() + sk.Wipe() + } +} + +// Check that Unwrap(Wrap(x)) == x with differing lengths of secret key +func TestDifferentLengthSecretKey(t *testing.T) { + wk, err := makeKey(1, InternalKeyLen) + if err != nil { + t.Fatal(err) + } + for i := 0; i < 100; i++ { + sk, err := makeKey(2, i) + if err != nil { + t.Fatal(err) + } + if err = testWrapUnwrapEqual(wk, sk); err != nil { + t.Error(err) + } + sk.Wipe() + } +} + +// Wrong length of wrapping key should fail +func TestWrongWrappingKeyLength(t *testing.T) { + _, err := Wrap(fakeValidPolicyKey, fakeWrappingKey) + if err == nil { + t.Fatal("using a policy key for wrapping should fail") + } +} + +// Wraping twice with the same keys should give different components +func TestWrapTwiceDistinct(t *testing.T) { + data1, err := Wrap(fakeWrappingKey, fakeValidPolicyKey) + if err != nil { + t.Fatal(err) + } + data2, err := Wrap(fakeWrappingKey, fakeValidPolicyKey) + if err != nil { + t.Fatal(err) + } + if !buffersDistinct(data1.IV, data1.EncryptedKey, data1.Hmac, + data2.IV, data2.EncryptedKey, data2.Hmac) { + t.Error("Wrapping same keys twice should give distinct results") + } +} + +// Attempts to Unwrap data with key after altering tweek, should fail +func testFailWithTweek(key *Key, data *metadata.WrappedKeyData, tweek []byte) error { + tweek[0]++ + _, err := Unwrap(key, data) + tweek[0]-- + return err +} + +// Wrapping then unwrapping with different components altered +func TestUnwrapWrongKey(t *testing.T) { + data, err := Wrap(fakeWrappingKey, fakeValidPolicyKey) + if err != nil { + t.Fatal(err) + } + if testFailWithTweek(fakeWrappingKey, data, fakeWrappingKey.data) == nil { + t.Error("using a different wrapping key should make unwrap fail") + } +} + +func TestUnwrapWrongData(t *testing.T) { + data, err := Wrap(fakeWrappingKey, fakeValidPolicyKey) + if err != nil { + t.Fatal(err) + } + if testFailWithTweek(fakeWrappingKey, data, data.EncryptedKey) == nil { + t.Error("changing encryption key should make unwrap fail") + } + if testFailWithTweek(fakeWrappingKey, data, data.IV) == nil { + t.Error("changing IV should make unwrap fail") + } + if testFailWithTweek(fakeWrappingKey, data, data.Hmac) == nil { + t.Error("changing HMAC should make unwrap fail") + } +} + +func BenchmarkWrap(b *testing.B) { + for n := 0; n < b.N; n++ { + Wrap(fakeWrappingKey, fakeValidPolicyKey) + } +} + +func BenchmarkUnwrap(b *testing.B) { + data, _ := Wrap(fakeWrappingKey, fakeValidPolicyKey) + + for n := 0; n < b.N; n++ { + Unwrap(fakeWrappingKey, data) + } +} + +func BenchmarkRandomWrapUnwrap(b *testing.B) { + for n := 0; n < b.N; n++ { + wk, _ := NewRandomKey(InternalKeyLen) + sk, _ := NewRandomKey(InternalKeyLen) + + testWrapUnwrapEqual(wk, sk) + // Must manually call wipe here, or test will use too much memory. + wk.Wipe() + sk.Wipe() + } +} |