func mockPolicyStoreNoCache(t *testing.T) *PolicyStore { sysView := logical.TestSystemView() sysView.CachingDisabledVal = true _, barrier, _ := mockBarrier(t) view := NewBarrierView(barrier, "foo/") p := NewPolicyStore(view, sysView) return p }
func TestPolicyFuzzing(t *testing.T) { var be *backend sysView := logical.TestSystemView() be = Backend(&logical.BackendConfig{ System: sysView, }) testPolicyFuzzingCommon(t, be) sysView.CachingDisabledVal = true be = Backend(&logical.BackendConfig{ System: sysView, }) testPolicyFuzzingCommon(t, be) }
func TestPolicyFuzzing(t *testing.T) { // Don't run if not during acceptance tests if os.Getenv(logicaltest.TestEnvVar) == "" { t.Skip(fmt.Sprintf("Acceptance tests skipped unless env '%s' set", logicaltest.TestEnvVar)) return } var be *backend sysView := logical.TestSystemView() be = Backend(&logical.BackendConfig{ System: sysView, }) testPolicyFuzzingCommon(t, be) sysView.CachingDisabledVal = true be = Backend(&logical.BackendConfig{ System: sysView, }) testPolicyFuzzingCommon(t, be) }
func TestConvergentEncryption(t *testing.T) { var b *backend sysView := logical.TestSystemView() storage := &logical.InmemStorage{} b = Backend(&logical.BackendConfig{ StorageView: storage, System: sysView, }) req := &logical.Request{ Storage: storage, Operation: logical.UpdateOperation, Path: "keys/testkeynonderived", Data: map[string]interface{}{ "derived": false, "convergent_encryption": true, }, } resp, err := b.HandleRequest(req) if err != nil { t.Fatal(err) } if resp == nil { t.Fatal("expected non-nil response") } if !resp.IsError() { t.Fatalf("bad: expected error response, got %#v", *resp) } req.Path = "keys/testkey" req.Data = map[string]interface{}{ "derived": true, "convergent_encryption": true, } resp, err = b.HandleRequest(req) if err != nil { t.Fatal(err) } if resp != nil { t.Fatalf("bad: got resp %#v", *resp) } // First, test using an invalid length of nonce req.Path = "encrypt/testkey" req.Data = map[string]interface{}{ "plaintext": "emlwIHphcA==", // "zip zap" "nonce": "Zm9vIGJhcg==", // "foo bar" "context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S", } resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if !resp.IsError() { t.Fatalf("expected error response, got %#v", *resp) } // Ensure we fail if we do not provide a nonce req.Data = map[string]interface{}{ "plaintext": "emlwIHphcA==", // "zip zap" "context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S", } resp, err = b.HandleRequest(req) if err == nil && (resp == nil || !resp.IsError()) { t.Fatal("expected error response") } // Now test encrypting the same value twice req.Data = map[string]interface{}{ "plaintext": "emlwIHphcA==", // "zip zap" "nonce": "b25ldHdvdGhyZWVl", // "onetwothreee" "context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S", } resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext1 := resp.Data["ciphertext"].(string) resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext2 := resp.Data["ciphertext"].(string) if ciphertext1 != ciphertext2 { t.Fatalf("expected the same ciphertext but got %s and %s", ciphertext1, ciphertext2) } // For sanity, also check a different nonce value... req.Data = map[string]interface{}{ "plaintext": "emlwIHphcA==", // "zip zap" "nonce": "dHdvdGhyZWVmb3Vy", // "twothreefour" "context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S", } resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext3 := resp.Data["ciphertext"].(string) resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext4 := resp.Data["ciphertext"].(string) if ciphertext3 != ciphertext4 { t.Fatalf("expected the same ciphertext but got %s and %s", ciphertext3, ciphertext4) } if ciphertext1 == ciphertext3 { t.Fatalf("expected different ciphertexts") } // ...and a different context value req.Data = map[string]interface{}{ "plaintext": "emlwIHphcA==", // "zip zap" "nonce": "dHdvdGhyZWVmb3Vy", // "twothreefour" "context": "qV4h9iQyvn+raODOer4JNAsOhkXBwdT4HZ677Ql4KLqXSU+Jk4C/fXBWbv6xkSYT", } resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext5 := resp.Data["ciphertext"].(string) resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext6 := resp.Data["ciphertext"].(string) if ciphertext5 != ciphertext6 { t.Fatalf("expected the same ciphertext but got %s and %s", ciphertext5, ciphertext6) } if ciphertext1 == ciphertext5 { t.Fatalf("expected different ciphertexts") } if ciphertext3 == ciphertext5 { t.Fatalf("expected different ciphertexts") } }
func TestConvergentEncryption(t *testing.T) { var b *backend sysView := logical.TestSystemView() storage := &logical.InmemStorage{} b = Backend(&logical.BackendConfig{ StorageView: storage, System: sysView, }) req := &logical.Request{ Storage: storage, Operation: logical.UpdateOperation, Path: "keys/testkeynonderived", Data: map[string]interface{}{ "derived": false, "convergent_encryption": true, }, } resp, err := b.HandleRequest(req) if err != nil { t.Fatal(err) } if resp == nil { t.Fatal("expected non-nil response") } if !resp.IsError() { t.Fatalf("bad: expected error response, got %#v", *resp) } req.Path = "keys/testkey" req.Data = map[string]interface{}{ "derived": true, "convergent_encryption": true, } resp, err = b.HandleRequest(req) if err != nil { t.Fatal(err) } if resp != nil { t.Fatalf("bad: got resp %#v", *resp) } // First, test using an invalid length of nonce req.Path = "encrypt/testkey" req.Data = map[string]interface{}{ "plaintext": "emlwIHphcA==", // "zip zap" "context": "Zm9vIGJhcg==", // "foo bar" } resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if !resp.IsError() { t.Fatalf("expected error response, got %#v", *resp) } // Now test encrypting the same value twice req.Data = map[string]interface{}{ "plaintext": "emlwIHphcA==", // "zip zap" "context": "b25ldHdvdGhyZWVl", // "onetwothreee" } resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext1 := resp.Data["ciphertext"].(string) resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext2 := resp.Data["ciphertext"].(string) if ciphertext1 != ciphertext2 { t.Fatalf("expected the same ciphertext but got %s and %s", ciphertext1, ciphertext2) } // For sanity, also check a different value req.Data = map[string]interface{}{ "plaintext": "emlwIHphcA==", // "zip zap" "context": "dHdvdGhyZWVmb3Vy", // "twothreefour" } resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext3 := resp.Data["ciphertext"].(string) resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext4 := resp.Data["ciphertext"].(string) if ciphertext3 != ciphertext4 { t.Fatalf("expected the same ciphertext but got %s and %s", ciphertext1, ciphertext2) } if ciphertext1 == ciphertext3 { t.Fatalf("expected different ciphertexts") } }
func mockPolicyStore(t *testing.T) *PolicyStore { _, barrier, _ := mockBarrier(t) view := NewBarrierView(barrier, "foo/") p := NewPolicyStore(view, logical.TestSystemView()) return p }
func TestTransit_SignVerify(t *testing.T) { var b *backend sysView := logical.TestSystemView() storage := &logical.InmemStorage{} b = Backend(&logical.BackendConfig{ StorageView: storage, System: sysView, }) // First create a key req := &logical.Request{ Storage: storage, Operation: logical.UpdateOperation, Path: "keys/foo", Data: map[string]interface{}{ "type": "ecdsa-p256", }, } _, err := b.HandleRequest(req) if err != nil { t.Fatal(err) } // Now, change the key value to something we control p, lock, err := b.lm.GetPolicyShared(storage, "foo") if err != nil { t.Fatal(err) } // We don't care as we're the only one using this lock.RUnlock() // Useful code to output a key for openssl verification /* { key := p.Keys[p.LatestVersion] keyBytes, _ := x509.MarshalECPrivateKey(&ecdsa.PrivateKey{ PublicKey: ecdsa.PublicKey{ Curve: elliptic.P256(), X: key.X, Y: key.Y, }, D: key.D, }) pemBlock := &pem.Block{ Type: "EC PRIVATE KEY", Bytes: keyBytes, } pemBytes := pem.EncodeToMemory(pemBlock) t.Fatalf("X: %s, Y: %s, D: %s, marshaled: %s", key.X.Text(16), key.Y.Text(16), key.D.Text(16), string(pemBytes)) } */ keyEntry := p.Keys[p.LatestVersion] _, ok := keyEntry.EC_X.SetString("7336010a6da5935113d26d9ea4bb61b3b8d102c9a8083ed432f9b58fd7e80686", 16) if !ok { t.Fatal("could not set X") } _, ok = keyEntry.EC_Y.SetString("4040aa31864691a8a9e7e3ec9250e85425b797ad7be34ba8df62bfbad45ebb0e", 16) if !ok { t.Fatal("could not set Y") } _, ok = keyEntry.EC_D.SetString("99e5569be8683a2691dfc560ca9dfa71e887867a3af60635a08a3e3655aba3ef", 16) if !ok { t.Fatal("could not set D") } p.Keys[p.LatestVersion] = keyEntry if err = p.Persist(storage); err != nil { t.Fatal(err) } req.Data = map[string]interface{}{ "input": "dGhlIHF1aWNrIGJyb3duIGZveA==", } signRequest := func(req *logical.Request, errExpected bool, postpath string) string { req.Path = "sign/foo" + postpath resp, err := b.HandleRequest(req) if err != nil && !errExpected { t.Fatal(err) } if resp == nil { t.Fatal("expected non-nil response") } if errExpected { if !resp.IsError() { t.Fatalf("bad: got error response: %#v", *resp) } return "" } if resp.IsError() { t.Fatalf("bad: got error response: %#v", *resp) } value, ok := resp.Data["signature"] if !ok { t.Fatalf("no signature key found in returned data, got resp data %#v", resp.Data) } return value.(string) } verifyRequest := func(req *logical.Request, errExpected bool, postpath, sig string) { req.Path = "verify/foo" + postpath req.Data["signature"] = sig resp, err := b.HandleRequest(req) if err != nil && !errExpected { t.Fatalf("got error: %v, sig was %v", err, sig) } if errExpected { if resp != nil && !resp.IsError() { t.Fatalf("bad: got error response: %#v", *resp) } return } if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("bad: got error response: %#v", *resp) } value, ok := resp.Data["valid"] if !ok { t.Fatalf("no valid key found in returned data, got resp data %#v", resp.Data) } if !value.(bool) && !errExpected { t.Fatalf("verification failed; req was %#v, resp is %#v", *req, *resp) } } // Comparisons are against values generated via openssl // Test defaults -- sha2-256 sig := signRequest(req, false, "") verifyRequest(req, false, "", sig) // Test a bad signature verifyRequest(req, true, "", sig[0:len(sig)-2]) // Test a signature generated with the same key by openssl sig = `vault:v1:MEUCIAgnEl9V8P305EBAlz68Nq4jZng5fE8k6MactcnlUw9dAiEAvJVePg3dazW6MaW7lRAVtEz82QJDVmR98tXCl8Pc7DA=` verifyRequest(req, false, "", sig) // Test algorithm selection in the path sig = signRequest(req, false, "/sha2-224") verifyRequest(req, false, "/sha2-224", sig) // Reset and test algorithm selection in the data req.Data["algorithm"] = "sha2-224" sig = signRequest(req, false, "") verifyRequest(req, false, "", sig) req.Data["algorithm"] = "sha2-384" sig = signRequest(req, false, "") verifyRequest(req, false, "", sig) // Test 512 and save sig for later to ensure we can't validate once min // decryption version is set req.Data["algorithm"] = "sha2-512" sig = signRequest(req, false, "") verifyRequest(req, false, "", sig) v1sig := sig // Test bad algorithm req.Data["algorithm"] = "foobar" signRequest(req, true, "") // Test bad input req.Data["algorithm"] = "sha2-256" req.Data["input"] = "foobar" signRequest(req, true, "") // Rotate and set min decryption version err = p.Rotate(storage) if err != nil { t.Fatal(err) } err = p.Rotate(storage) if err != nil { t.Fatal(err) } p.MinDecryptionVersion = 2 if err = p.Persist(storage); err != nil { t.Fatal(err) } req.Data["input"] = "dGhlIHF1aWNrIGJyb3duIGZveA==" req.Data["algorithm"] = "sha2-256" // Make sure signing still works fine sig = signRequest(req, false, "") verifyRequest(req, false, "", sig) // Now try the v1 verifyRequest(req, true, "", v1sig) }
func testConvergentEncryptionCommon(t *testing.T, ver int) { var b *backend sysView := logical.TestSystemView() storage := &logical.InmemStorage{} b = Backend(&logical.BackendConfig{ StorageView: storage, System: sysView, }) req := &logical.Request{ Storage: storage, Operation: logical.UpdateOperation, Path: "keys/testkeynonderived", Data: map[string]interface{}{ "derived": false, "convergent_encryption": true, }, } resp, err := b.HandleRequest(req) if err != nil { t.Fatal(err) } if resp == nil { t.Fatal("expected non-nil response") } if !resp.IsError() { t.Fatalf("bad: expected error response, got %#v", *resp) } p := &policy{ Name: "testkey", Type: keyType_AES256_GCM96, Derived: true, ConvergentEncryption: true, ConvergentVersion: ver, } err = p.rotate(storage) if err != nil { t.Fatal(err) } // First, test using an invalid length of nonce -- this is only used for v1 convergent req.Path = "encrypt/testkey" if ver < 2 { req.Data = map[string]interface{}{ "plaintext": "emlwIHphcA==", // "zip zap" "nonce": "Zm9vIGJhcg==", // "foo bar" "context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S", } resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if !resp.IsError() { t.Fatalf("expected error response, got %#v", *resp) } // Ensure we fail if we do not provide a nonce req.Data = map[string]interface{}{ "plaintext": "emlwIHphcA==", // "zip zap" "context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S", } resp, err = b.HandleRequest(req) if err == nil && (resp == nil || !resp.IsError()) { t.Fatal("expected error response") } } // Now test encrypting the same value twice req.Data = map[string]interface{}{ "plaintext": "emlwIHphcA==", // "zip zap" "nonce": "b25ldHdvdGhyZWVl", // "onetwothreee" "context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S", } resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext1 := resp.Data["ciphertext"].(string) resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext2 := resp.Data["ciphertext"].(string) if ciphertext1 != ciphertext2 { t.Fatalf("expected the same ciphertext but got %s and %s", ciphertext1, ciphertext2) } // For sanity, also check a different nonce value... req.Data = map[string]interface{}{ "plaintext": "emlwIHphcA==", // "zip zap" "nonce": "dHdvdGhyZWVmb3Vy", // "twothreefour" "context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S", } if ver < 2 { req.Data["nonce"] = "dHdvdGhyZWVmb3Vy" // "twothreefour" } else { req.Data["context"] = "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOldandSdd7S" } resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext3 := resp.Data["ciphertext"].(string) resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext4 := resp.Data["ciphertext"].(string) if ciphertext3 != ciphertext4 { t.Fatalf("expected the same ciphertext but got %s and %s", ciphertext3, ciphertext4) } if ciphertext1 == ciphertext3 { t.Fatalf("expected different ciphertexts") } // ...and a different context value req.Data = map[string]interface{}{ "plaintext": "emlwIHphcA==", // "zip zap" "nonce": "dHdvdGhyZWVmb3Vy", // "twothreefour" "context": "qV4h9iQyvn+raODOer4JNAsOhkXBwdT4HZ677Ql4KLqXSU+Jk4C/fXBWbv6xkSYT", } resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext5 := resp.Data["ciphertext"].(string) resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext6 := resp.Data["ciphertext"].(string) if ciphertext5 != ciphertext6 { t.Fatalf("expected the same ciphertext but got %s and %s", ciphertext5, ciphertext6) } if ciphertext1 == ciphertext5 { t.Fatalf("expected different ciphertexts") } if ciphertext3 == ciphertext5 { t.Fatalf("expected different ciphertexts") } // Finally, check operations on empty values // First, check without setting a plaintext at all req.Data = map[string]interface{}{ "nonce": "b25ldHdvdGhyZWVl", // "onetwothreee" "context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S", } resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if !resp.IsError() { t.Fatalf("expected error response, got: %#v", *resp) } // Now set plaintext to empty req.Data = map[string]interface{}{ "plaintext": "", "nonce": "b25ldHdvdGhyZWVl", // "onetwothreee" "context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S", } resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext7 := resp.Data["ciphertext"].(string) resp, err = b.HandleRequest(req) if resp == nil { t.Fatal("expected non-nil response") } if resp.IsError() { t.Fatalf("got error response: %#v", *resp) } ciphertext8 := resp.Data["ciphertext"].(string) if ciphertext7 != ciphertext8 { t.Fatalf("expected the same ciphertext but got %s and %s", ciphertext7, ciphertext8) } }
func TestTransit_Hash(t *testing.T) { var b *backend sysView := logical.TestSystemView() storage := &logical.InmemStorage{} b = Backend(&logical.BackendConfig{ StorageView: storage, System: sysView, }) req := &logical.Request{ Storage: storage, Operation: logical.UpdateOperation, Path: "hash", Data: map[string]interface{}{ "input": "dGhlIHF1aWNrIGJyb3duIGZveA==", }, } doRequest := func(req *logical.Request, errExpected bool, expected string) { resp, err := b.HandleRequest(req) if err != nil && !errExpected { t.Fatal(err) } if resp == nil { t.Fatal("expected non-nil response") } if errExpected { if !resp.IsError() { t.Fatalf("bad: got error response: %#v", *resp) } return } if resp.IsError() { t.Fatalf("bad: got error response: %#v", *resp) } sum, ok := resp.Data["sum"] if !ok { t.Fatal("no sum key found in returned data") } if sum.(string) != expected { t.Fatal("mismatched hashes") } } // Test defaults -- sha2-256 doRequest(req, false, "9ecb36561341d18eb65484e833efea61edc74b84cf5e6ae1b81c63533e25fc8f") // Test algorithm selection in the path req.Path = "hash/sha2-224" doRequest(req, false, "ea074a96cabc5a61f8298a2c470f019074642631a49e1c5e2f560865") // Reset and test algorithm selection in the data req.Path = "hash" req.Data["algorithm"] = "sha2-224" doRequest(req, false, "ea074a96cabc5a61f8298a2c470f019074642631a49e1c5e2f560865") req.Data["algorithm"] = "sha2-384" doRequest(req, false, "15af9ec8be783f25c583626e9491dbf129dd6dd620466fdf05b3a1d0bb8381d30f4d3ec29f923ff1e09a0f6b337365a6") req.Data["algorithm"] = "sha2-512" doRequest(req, false, "d9d380f29b97ad6a1d92e987d83fa5a02653301e1006dd2bcd51afa59a9147e9caedaf89521abc0f0b682adcd47fb512b8343c834a32f326fe9bef00542ce887") // Test returning as base64 req.Data["format"] = "base64" doRequest(req, false, "2dOA8puXrWodkumH2D+loCZTMB4QBt0rzVGvpZqRR+nK7a+JUhq8DwtoKtzUf7USuDQ8g0oy8yb+m+8AVCzohw==") // Test bad input/format/algorithm req.Data["format"] = "base92" doRequest(req, true, "") req.Data["format"] = "hex" req.Data["algorithm"] = "foobar" doRequest(req, true, "") req.Data["algorithm"] = "sha2-256" req.Data["input"] = "foobar" doRequest(req, true, "") }
func TestTransit_Random(t *testing.T) { var b *backend sysView := logical.TestSystemView() storage := &logical.InmemStorage{} b = Backend(&logical.BackendConfig{ StorageView: storage, System: sysView, }) req := &logical.Request{ Storage: storage, Operation: logical.UpdateOperation, Path: "random", Data: map[string]interface{}{}, } doRequest := func(req *logical.Request, errExpected bool, format string, numBytes int) { getResponse := func() []byte { resp, err := b.HandleRequest(req) if err != nil && !errExpected { t.Fatal(err) } if resp == nil { t.Fatal("expected non-nil response") } if errExpected { if !resp.IsError() { t.Fatalf("bad: got error response: %#v", *resp) } return nil } if resp.IsError() { t.Fatalf("bad: got error response: %#v", *resp) } if _, ok := resp.Data["random_bytes"]; !ok { t.Fatal("no random_bytes found in response") } outputStr := resp.Data["random_bytes"].(string) var outputBytes []byte switch format { case "base64": outputBytes, err = base64.StdEncoding.DecodeString(outputStr) case "hex": outputBytes, err = hex.DecodeString(outputStr) default: t.Fatal("unknown format") } if err != nil { t.Fatal(err) } return outputBytes } rand1 := getResponse() // Expected error if rand1 == nil { return } rand2 := getResponse() if len(rand1) != numBytes || len(rand2) != numBytes { t.Fatal("length of output random bytes not what is exepcted") } if reflect.DeepEqual(rand1, rand2) { t.Fatal("found identical ouputs") } } // Test defaults doRequest(req, false, "base64", 32) // Test size selection in the path req.Path = "random/24" req.Data["format"] = "hex" doRequest(req, false, "hex", 24) // Test bad input/format req.Path = "random" req.Data["format"] = "base92" doRequest(req, true, "", 0) req.Data["format"] = "hex" req.Data["bytes"] = -1 doRequest(req, true, "", 0) }
func TestTransit_HMAC(t *testing.T) { var b *backend sysView := logical.TestSystemView() storage := &logical.InmemStorage{} b = Backend(&logical.BackendConfig{ StorageView: storage, System: sysView, }) // First create a key req := &logical.Request{ Storage: storage, Operation: logical.UpdateOperation, Path: "keys/foo", } _, err := b.HandleRequest(req) if err != nil { t.Fatal(err) } // Now, change the key value to something we control p, lock, err := b.lm.GetPolicyShared(storage, "foo") if err != nil { t.Fatal(err) } // We don't care as we're the only one using this lock.RUnlock() keyEntry := p.Keys[p.LatestVersion] keyEntry.HMACKey = []byte("01234567890123456789012345678901") p.Keys[p.LatestVersion] = keyEntry if err = p.Persist(storage); err != nil { t.Fatal(err) } req.Path = "hmac/foo" req.Data = map[string]interface{}{ "input": "dGhlIHF1aWNrIGJyb3duIGZveA==", } doRequest := func(req *logical.Request, errExpected bool, expected string) { path := req.Path defer func() { req.Path = path }() resp, err := b.HandleRequest(req) if err != nil && !errExpected { panic(fmt.Sprintf("%v", err)) } if resp == nil { t.Fatal("expected non-nil response") } if errExpected { if !resp.IsError() { t.Fatalf("bad: got error response: %#v", *resp) } return } if resp.IsError() { t.Fatalf("bad: got error response: %#v", *resp) } value, ok := resp.Data["hmac"] if !ok { t.Fatalf("no hmac key found in returned data, got resp data %#v", resp.Data) } if value.(string) != expected { panic(fmt.Sprintf("mismatched hashes; expected %s, got resp data %#v", expected, resp.Data)) } // Now verify req.Path = strings.Replace(req.Path, "hmac", "verify", -1) req.Data["hmac"] = value.(string) resp, err = b.HandleRequest(req) if err != nil { t.Fatalf("%v: %v", err, resp) } if resp == nil { t.Fatal("expected non-nil response") } if resp.Data["valid"].(bool) == false { panic(fmt.Sprintf("error validating hmac;\nreq:\n%#v\nresp:\n%#v", *req, *resp)) } } // Comparisons are against values generated via openssl // Test defaults -- sha2-256 doRequest(req, false, "vault:v1:UcBvm5VskkukzZHlPgm3p5P/Yr/PV6xpuOGZISya3A4=") // Test algorithm selection in the path req.Path = "hmac/foo/sha2-224" doRequest(req, false, "vault:v1:3p+ZWVquYDvu2dSTCa65Y3fgoMfIAc6fNaBbtg==") // Reset and test algorithm selection in the data req.Path = "hmac/foo" req.Data["algorithm"] = "sha2-224" doRequest(req, false, "vault:v1:3p+ZWVquYDvu2dSTCa65Y3fgoMfIAc6fNaBbtg==") req.Data["algorithm"] = "sha2-384" doRequest(req, false, "vault:v1:jDB9YXdPjpmr29b1JCIEJO93IydlKVfD9mA2EO9OmJtJQg3QAV5tcRRRb7IQGW9p") req.Data["algorithm"] = "sha2-512" doRequest(req, false, "vault:v1:PSXLXvkvKF4CpU65e2bK1tGBZQpcpCEM32fq2iUoiTyQQCfBcGJJItQ+60tMwWXAPQrC290AzTrNJucGrr4GFA==") // Test returning as base64 req.Data["format"] = "base64" doRequest(req, false, "vault:v1:PSXLXvkvKF4CpU65e2bK1tGBZQpcpCEM32fq2iUoiTyQQCfBcGJJItQ+60tMwWXAPQrC290AzTrNJucGrr4GFA==") req.Data["algorithm"] = "foobar" doRequest(req, true, "") req.Data["algorithm"] = "sha2-256" req.Data["input"] = "foobar" doRequest(req, true, "") req.Data["input"] = "dGhlIHF1aWNrIGJyb3duIGZveA==" // Rotate err = p.rotate(storage) if err != nil { t.Fatal(err) } keyEntry = p.Keys[2] // Set to another value we control keyEntry.HMACKey = []byte("12345678901234567890123456789012") p.Keys[2] = keyEntry if err = p.Persist(storage); err != nil { t.Fatal(err) } doRequest(req, false, "vault:v2:Dt+mO/B93kuWUbGMMobwUNX5Wodr6dL3JH4DMfpQ0kw=") // Verify a previous version req.Path = "verify/foo" req.Data["hmac"] = "vault:v1:UcBvm5VskkukzZHlPgm3p5P/Yr/PV6xpuOGZISya3A4=" resp, err := b.HandleRequest(req) if err != nil { t.Fatalf("%v: %v", err, resp) } if resp == nil { t.Fatal("expected non-nil response") } if resp.Data["valid"].(bool) == false { t.Fatalf("error validating hmac\nreq\n%#v\nresp\n%#v", *req, *resp) } // Try a bad value req.Data["hmac"] = "vault:v1:UcBvm4VskkukzZHlPgm3p5P/Yr/PV6xpuOGZISya3A4=" resp, err = b.HandleRequest(req) if err != nil { t.Fatalf("%v: %v", err, resp) } if resp == nil { t.Fatal("expected non-nil response") } if resp.Data["valid"].(bool) { t.Fatalf("expected error validating hmac") } // Set min decryption version, attempt to verify p.MinDecryptionVersion = 2 if err = p.Persist(storage); err != nil { t.Fatal(err) } req.Data["hmac"] = "vault:v1:UcBvm5VskkukzZHlPgm3p5P/Yr/PV6xpuOGZISya3A4=" resp, err = b.HandleRequest(req) if err == nil { t.Fatalf("expected an error, got response %#v", resp) } if err != logical.ErrInvalidRequest { t.Fatalf("expected invalid request error, got %v", err) } }