Adds support for SHA-3 to transit (#13367)

* Adding support for SHA3 in the transit backend.

* Adds SHA-3 tests for transit sign/verify path. Adds SHA-3 tests for logical system tools path hash functionality. Updates documentation to include SHA-3 algorithms in system tools path hashing.

* Adds changelog entry.

Co-authored-by: robison jacka <robison@packetized.io>
This commit is contained in:
Matt Schultz 2021-12-08 12:29:33 -06:00 committed by GitHub
parent be07a202d9
commit 85f5cfc356
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 160 additions and 1 deletions

View File

@ -9,6 +9,8 @@ import (
"fmt"
"hash"
"golang.org/x/crypto/sha3"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
@ -31,6 +33,10 @@ func (b *backend) pathHash() *framework.Path {
* sha2-256
* sha2-384
* sha2-512
* sha3-224
* sha3-256
* sha3-384
* sha3-512
Defaults to "sha2-256".`,
},
@ -86,6 +92,14 @@ func (b *backend) pathHashWrite(ctx context.Context, req *logical.Request, d *fr
hf = sha512.New384()
case "sha2-512":
hf = sha512.New()
case "sha3-224":
hf = sha3.New224()
case "sha3-256":
hf = sha3.New256()
case "sha3-384":
hf = sha3.New384()
case "sha3-512":
hf = sha3.New512()
default:
return logical.ErrorResponse(fmt.Sprintf("unsupported algorithm %s", algorithm)), nil
}

View File

@ -67,6 +67,24 @@ func TestTransit_Hash(t *testing.T) {
req.Data["format"] = "base64"
doRequest(req, false, "2dOA8puXrWodkumH2D+loCZTMB4QBt0rzVGvpZqRR+nK7a+JUhq8DwtoKtzUf7USuDQ8g0oy8yb+m+8AVCzohw==")
// Test SHA3
req.Data["format"] = "hex"
req.Data["algorithm"] = "sha3-224"
doRequest(req, false, "ced91e69d89c837e87cff960bd64fd9b9f92325fb9add8988d33d007")
req.Data["algorithm"] = "sha3-256"
doRequest(req, false, "e4bd866ec3fa52df3b7842aa97b448bc859a7606cefcdad1715847f4b82a6c93")
req.Data["algorithm"] = "sha3-384"
doRequest(req, false, "715cd38cbf8d0bab426b6a084d649760be555dd64b34de6db148a3fbf2cd2aa5d8b03eb6eda73a3e9a8769c00b4c2113")
req.Data["algorithm"] = "sha3-512"
doRequest(req, false, "f7cac5ad830422a5408b36a60a60620687be180765a3e2895bc3bdbd857c9e08246c83064d4e3612f0cb927f3ead208413ab98624bf7b0617af0f03f62080976")
// Test returning SHA3 as base64
req.Data["format"] = "base64"
doRequest(req, false, "98rFrYMEIqVAizamCmBiBoe+GAdlo+KJW8O9vYV8nggkbIMGTU42EvDLkn8+rSCEE6uYYkv3sGF68PA/YggJdg==")
// Test bad input/format/algorithm
req.Data["format"] = "base92"
doRequest(req, true, "")

View File

@ -60,6 +60,10 @@ func (b *backend) pathHMAC() *framework.Path {
* sha2-256
* sha2-384
* sha2-512
* sha3-224
* sha3-256
* sha3-384
* sha3-512
Defaults to "sha2-256".`,
},

View File

@ -114,6 +114,24 @@ func TestTransit_HMAC(t *testing.T) {
req.Data["format"] = "base64"
doRequest(req, false, "vault:v1:PSXLXvkvKF4CpU65e2bK1tGBZQpcpCEM32fq2iUoiTyQQCfBcGJJItQ+60tMwWXAPQrC290AzTrNJucGrr4GFA==")
// Test SHA3
req.Path = "hmac/foo"
req.Data["algorithm"] = "sha3-224"
doRequest(req, false, "vault:v1:TGipmKH8LR/BkMolYpDYy0BJCIhTtGPDhV2VkQ==")
req.Data["algorithm"] = "sha3-256"
doRequest(req, false, "vault:v1:+px9V/7QYLfdK808zPESC2T/L33uFf4Blzsn9Jy838o=")
req.Data["algorithm"] = "sha3-384"
doRequest(req, false, "vault:v1:YGoRwN4UdTRYZeOER86jsQOB8piWenzLDzJ2wJQK/Jq59rAsY8lh7SCdqqCyFg70")
req.Data["algorithm"] = "sha3-512"
doRequest(req, false, "vault:v1:GrNA8sU88naMPEQ7UZGj9EJl7YJhl03AFHfxcEURFrtvnobdea9ZlZHePpxAx/oCaC7R2HkrAO+Tu3uXPIl3lg==")
// Test returning SHA3 as base64
req.Data["format"] = "base64"
doRequest(req, false, "vault:v1:GrNA8sU88naMPEQ7UZGj9EJl7YJhl03AFHfxcEURFrtvnobdea9ZlZHePpxAx/oCaC7R2HkrAO+Tu3uXPIl3lg==")
req.Data["algorithm"] = "foobar"
doRequest(req, true, "")

View File

@ -88,6 +88,10 @@ derivation is enabled; currently only available with ed25519 keys.`,
* sha2-256
* sha2-384
* sha2-512
* sha3-224
* sha3-256
* sha3-384
* sha3-512
Defaults to "sha2-256". Not valid for all key types,
including ed25519.`,
@ -183,6 +187,10 @@ derivation is enabled; currently only available with ed25519 keys.`,
* sha2-256
* sha2-384
* sha2-512
* sha3-224
* sha3-256
* sha3-384
* sha3-512
Defaults to "sha2-256". Not valid for all key types.`,
},

View File

@ -237,6 +237,26 @@ func testTransit_SignVerify_ECDSA(t *testing.T, bits int) {
sig = signRequest(req, false, "")
verifyRequest(req, false, "", sig)
req.Data["hash_algorithm"] = "sha2-512"
sig = signRequest(req, false, "")
verifyRequest(req, false, "", sig)
req.Data["hash_algorithm"] = "sha3-224"
sig = signRequest(req, false, "")
verifyRequest(req, false, "", sig)
req.Data["hash_algorithm"] = "sha3-256"
sig = signRequest(req, false, "")
verifyRequest(req, false, "", sig)
req.Data["hash_algorithm"] = "sha3-384"
sig = signRequest(req, false, "")
verifyRequest(req, false, "", sig)
req.Data["hash_algorithm"] = "sha3-512"
sig = signRequest(req, false, "")
verifyRequest(req, false, "", sig)
req.Data["prehashed"] = true
sig = signRequest(req, false, "")
verifyRequest(req, false, "", sig)

3
changelog/13367.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:feature
secrets/transit: Add support for SHA-3 in the Transit backend.
```

View File

@ -5,6 +5,8 @@ import (
"crypto/sha256"
"crypto/sha512"
"hash"
"golang.org/x/crypto/sha3"
)
type HashType uint32
@ -16,6 +18,10 @@ const (
HashTypeSHA2256
HashTypeSHA2384
HashTypeSHA2512
HashTypeSHA3224
HashTypeSHA3256
HashTypeSHA3384
HashTypeSHA3512
)
type MarshalingType uint32
@ -33,6 +39,10 @@ var (
"sha2-256": HashTypeSHA2256,
"sha2-384": HashTypeSHA2384,
"sha2-512": HashTypeSHA2512,
"sha3-224": HashTypeSHA3224,
"sha3-256": HashTypeSHA3256,
"sha3-384": HashTypeSHA3384,
"sha3-512": HashTypeSHA3512,
}
HashFuncMap = map[HashType]func() hash.Hash{
@ -41,6 +51,10 @@ var (
HashTypeSHA2256: sha256.New,
HashTypeSHA2384: sha512.New384,
HashTypeSHA2512: sha512.New,
HashTypeSHA3224: sha3.New224,
HashTypeSHA3256: sha3.New256,
HashTypeSHA3384: sha3.New384,
HashTypeSHA3512: sha3.New512,
}
MarshalingTypeMap = map[string]MarshalingType{

View File

@ -1140,6 +1140,14 @@ func (p *Policy) Sign(ver int, context, input []byte, hashAlgorithm HashType, si
algo = crypto.SHA384
case HashTypeSHA2512:
algo = crypto.SHA512
case HashTypeSHA3224:
algo = crypto.SHA3_224
case HashTypeSHA3256:
algo = crypto.SHA3_256
case HashTypeSHA3384:
algo = crypto.SHA3_384
case HashTypeSHA3512:
algo = crypto.SHA3_512
default:
return nil, errutil.InternalError{Err: "unsupported hash algorithm"}
}
@ -1311,6 +1319,14 @@ func (p *Policy) VerifySignature(context, input []byte, hashAlgorithm HashType,
algo = crypto.SHA384
case HashTypeSHA2512:
algo = crypto.SHA512
case HashTypeSHA3224:
algo = crypto.SHA3_224
case HashTypeSHA3256:
algo = crypto.SHA3_256
case HashTypeSHA3384:
algo = crypto.SHA3_384
case HashTypeSHA3512:
algo = crypto.SHA3_512
default:
return false, errutil.InternalError{Err: "unsupported hash algorithm"}
}

View File

@ -20,6 +20,8 @@ import (
"time"
"unicode"
"golang.org/x/crypto/sha3"
"github.com/hashicorp/errwrap"
log "github.com/hashicorp/go-hclog"
memdb "github.com/hashicorp/go-memdb"
@ -3363,6 +3365,14 @@ func (b *SystemBackend) pathHashWrite(ctx context.Context, req *logical.Request,
hf = sha512.New384()
case "sha2-512":
hf = sha512.New()
case "sha3-224":
hf = sha3.New224()
case "sha3-256":
hf = sha3.New256()
case "sha3-384":
hf = sha3.New384()
case "sha3-512":
hf = sha3.New512()
default:
return logical.ErrorResponse(fmt.Sprintf("unsupported algorithm %s", algorithm)), nil
}

View File

@ -2283,7 +2283,7 @@ func TestSystemBackend_ToolsHash(t *testing.T) {
t.Fatal("no sum key found in returned data")
}
if sum.(string) != expected {
t.Fatal("mismatched hashes")
t.Fatalf("mismatched hashes: got: %s, expect: %s", sum.(string), expected)
}
}
@ -2309,6 +2309,20 @@ func TestSystemBackend_ToolsHash(t *testing.T) {
req.Data["format"] = "base64"
doRequest(req, false, "2dOA8puXrWodkumH2D+loCZTMB4QBt0rzVGvpZqRR+nK7a+JUhq8DwtoKtzUf7USuDQ8g0oy8yb+m+8AVCzohw==")
// Test SHA-3
req.Data["format"] = "hex"
req.Data["algorithm"] = "sha3-224"
doRequest(req, false, "ced91e69d89c837e87cff960bd64fd9b9f92325fb9add8988d33d007")
req.Data["algorithm"] = "sha3-256"
doRequest(req, false, "e4bd866ec3fa52df3b7842aa97b448bc859a7606cefcdad1715847f4b82a6c93")
req.Data["algorithm"] = "sha3-384"
doRequest(req, false, "715cd38cbf8d0bab426b6a084d649760be555dd64b34de6db148a3fbf2cd2aa5d8b03eb6eda73a3e9a8769c00b4c2113")
req.Data["algorithm"] = "sha3-512"
doRequest(req, false, "f7cac5ad830422a5408b36a60a60620687be180765a3e2895bc3bdbd857c9e08246c83064d4e3612f0cb927f3ead208413ab98624bf7b0617af0f03f62080976")
// Test bad input/format/algorithm
req.Data["format"] = "base92"
doRequest(req, true, "")

View File

@ -700,6 +700,10 @@ algorithm.
- `sha2-256`
- `sha2-384`
- `sha2-512`
- `sha3-224`
- `sha3-256`
- `sha3-384`
- `sha3-512`
- `input` `(string: <required>)`  Specifies the **base64 encoded** input data.
@ -762,6 +766,10 @@ be used.
- `sha2-256`
- `sha2-384`
- `sha2-512`
- `sha3-224`
- `sha3-256`
- `sha3-384`
- `sha3-512`
- `input` `(string: "")`  Specifies the **base64 encoded** input data. One of
`input` or `batch_input` must be supplied.
@ -885,6 +893,10 @@ supports signing.
- `sha2-256`
- `sha2-384`
- `sha2-512`
- `sha3-224`
- `sha3-256`
- `sha3-384`
- `sha3-512`
~> ** Warning:** `sha1` should be considered a compromised algorithm and used
only for legacy applications. Signing using SHA-1 can be blocked by operators by
@ -1039,6 +1051,10 @@ data.
- `sha2-256`
- `sha2-384`
- `sha2-512`
- `sha3-224`
- `sha3-256`
- `sha3-384`
- `sha3-512`
~> ** Warning:** `sha1` should be considered a compromised algorithm. Signatures
verified using the algorithm could be forgeries. Verification using SHA-1 can

View File

@ -70,6 +70,10 @@ algorithm.
- `sha2-256`
- `sha2-384`
- `sha2-512`
- `sha3-224`
- `sha3-256`
- `sha3-384`
- `sha3-512`
- `input` `(string: <required>)`  Specifies the **base64 encoded** input data.