use crypto/sha256 for FIPS 140-2 compliance (#11623)

This commit replaces the usage of
github.com/minio/sha256-simd with crypto/sha256
of the standard library in all non-performance
critical paths.

This is necessary for FIPS 140-2 compliance which
requires that all crypto. primitives are implemented
by a FIPS-validated module.

Go can use the Google FIPS module. The boringcrypto
branch of the Go standard library uses the BoringSSL
FIPS module to implement crypto. primitives like AES
or SHA256.

We only keep github.com/minio/sha256-simd when computing
the content-SHA256 of an object. Therefore, this commit
relies on a build tag `fips`.

When MinIO is compiled without the `fips` flag it will
use github.com/minio/sha256-simd. When MinIO is compiled
with the fips flag (go build --tags "fips") then MinIO
uses crypto/sha256 to compute the content-SHA256.
This commit is contained in:
Andreas Auernhammer 2021-02-24 18:00:15 +01:00 committed by GitHub
parent 03172b89e2
commit c1a49be639
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 76 additions and 33 deletions

View File

@ -17,13 +17,13 @@
package cmd package cmd
import ( import (
"crypto/sha256"
"errors" "errors"
"hash" "hash"
"io" "io"
"github.com/minio/highwayhash" "github.com/minio/highwayhash"
"github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger"
sha256 "github.com/minio/sha256-simd"
"golang.org/x/crypto/blake2b" "golang.org/x/crypto/blake2b"
) )

View File

@ -18,6 +18,7 @@ package cmd
import ( import (
"context" "context"
"crypto/sha256"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"net/http" "net/http"
@ -32,7 +33,6 @@ import (
"github.com/minio/minio/cmd/crypto" "github.com/minio/minio/cmd/crypto"
"github.com/minio/minio/pkg/bucket/versioning" "github.com/minio/minio/pkg/bucket/versioning"
"github.com/minio/minio/pkg/madmin" "github.com/minio/minio/pkg/madmin"
sha256 "github.com/minio/sha256-simd"
) )
const ( const (

View File

@ -19,13 +19,13 @@ import (
"context" "context"
"crypto/hmac" "crypto/hmac"
"crypto/rand" "crypto/rand"
"crypto/sha256"
"encoding/binary" "encoding/binary"
"errors" "errors"
"io" "io"
"path" "path"
"github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger"
sha256 "github.com/minio/sha256-simd"
"github.com/minio/sio" "github.com/minio/sio"
) )

View File

@ -19,13 +19,13 @@ import (
"context" "context"
"crypto/hmac" "crypto/hmac"
"crypto/rand" "crypto/rand"
"crypto/sha256"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"sort" "sort"
"github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger"
sha256 "github.com/minio/sha256-simd"
"github.com/minio/sio" "github.com/minio/sio"
) )

View File

@ -20,6 +20,7 @@ import (
"bufio" "bufio"
"crypto/hmac" "crypto/hmac"
"crypto/rand" "crypto/rand"
"crypto/sha256"
"crypto/subtle" "crypto/subtle"
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
@ -33,7 +34,6 @@ import (
"github.com/minio/minio/cmd/crypto" "github.com/minio/minio/cmd/crypto"
xhttp "github.com/minio/minio/cmd/http" xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger"
sha256 "github.com/minio/sha256-simd"
"github.com/minio/sio" "github.com/minio/sio"
) )

View File

@ -18,6 +18,7 @@ package cmd
import ( import (
"context" "context"
"crypto/sha256"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"net/http" "net/http"
@ -28,7 +29,6 @@ import (
"github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/bucket/replication" "github.com/minio/minio/pkg/bucket/replication"
"github.com/minio/minio/pkg/sync/errgroup" "github.com/minio/minio/pkg/sync/errgroup"
"github.com/minio/sha256-simd"
) )
const erasureAlgorithm = "rs-vandermonde" const erasureAlgorithm = "rs-vandermonde"

View File

@ -18,6 +18,7 @@ package cmd
import ( import (
"context" "context"
"crypto/sha256"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"errors" "errors"
@ -33,7 +34,6 @@ import (
"github.com/minio/minio/pkg/color" "github.com/minio/minio/pkg/color"
xioutil "github.com/minio/minio/pkg/ioutil" xioutil "github.com/minio/minio/pkg/ioutil"
"github.com/minio/minio/pkg/sync/errgroup" "github.com/minio/minio/pkg/sync/errgroup"
sha256 "github.com/minio/sha256-simd"
) )
const ( const (

View File

@ -20,6 +20,7 @@ import (
"bytes" "bytes"
"context" "context"
"crypto/rand" "crypto/rand"
"crypto/sha256"
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
@ -46,7 +47,6 @@ import (
"github.com/minio/minio/pkg/auth" "github.com/minio/minio/pkg/auth"
"github.com/minio/minio/pkg/bucket/policy" "github.com/minio/minio/pkg/bucket/policy"
"github.com/minio/minio/pkg/bucket/policy/condition" "github.com/minio/minio/pkg/bucket/policy/condition"
sha256 "github.com/minio/sha256-simd"
minio "github.com/minio/minio/cmd" minio "github.com/minio/minio/cmd"
) )

View File

@ -18,9 +18,8 @@ package cmd
import ( import (
"crypto/md5" "crypto/md5"
"crypto/sha256"
"encoding/hex" "encoding/hex"
"github.com/minio/sha256-simd"
) )
// getSHA256Hash returns SHA-256 hash in hex encoding of given data. // getSHA256Hash returns SHA-256 hash in hex encoding of given data.

View File

@ -19,6 +19,7 @@ package cmd
import ( import (
"bytes" "bytes"
"crypto/hmac" "crypto/hmac"
"crypto/sha256"
"encoding/hex" "encoding/hex"
"io" "io"
"io/ioutil" "io/ioutil"
@ -29,7 +30,6 @@ import (
xhttp "github.com/minio/minio/cmd/http" xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth" "github.com/minio/minio/pkg/auth"
"github.com/minio/sha256-simd"
) )
// http Header "x-amz-content-sha256" == "UNSIGNED-PAYLOAD" indicates that the // http Header "x-amz-content-sha256" == "UNSIGNED-PAYLOAD" indicates that the
@ -65,10 +65,9 @@ func getContentSha256Cksum(r *http.Request, stype serviceType) string {
if err != nil { if err != nil {
logger.CriticalIf(GlobalContext, err) logger.CriticalIf(GlobalContext, err)
} }
sum256 := sha256.New() sum256 := sha256.Sum256(payload)
sum256.Write(payload)
r.Body = ioutil.NopCloser(bytes.NewReader(payload)) r.Body = ioutil.NopCloser(bytes.NewReader(payload))
return hex.EncodeToString(sum256.Sum(nil)) return hex.EncodeToString(sum256[:])
} }
var ( var (

View File

@ -26,6 +26,7 @@ package cmd
import ( import (
"bytes" "bytes"
"crypto/sha256"
"crypto/subtle" "crypto/subtle"
"encoding/hex" "encoding/hex"
"net/http" "net/http"
@ -38,7 +39,6 @@ import (
"github.com/minio/minio-go/v7/pkg/s3utils" "github.com/minio/minio-go/v7/pkg/s3utils"
"github.com/minio/minio-go/v7/pkg/set" "github.com/minio/minio-go/v7/pkg/set"
xhttp "github.com/minio/minio/cmd/http" xhttp "github.com/minio/minio/cmd/http"
sha256 "github.com/minio/sha256-simd"
) )
// AWS Signature Version '4' constants. // AWS Signature Version '4' constants.

View File

@ -21,6 +21,7 @@ package cmd
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"crypto/sha256"
"encoding/hex" "encoding/hex"
"errors" "errors"
"hash" "hash"
@ -31,7 +32,6 @@ import (
humanize "github.com/dustin/go-humanize" humanize "github.com/dustin/go-humanize"
xhttp "github.com/minio/minio/cmd/http" xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/pkg/auth" "github.com/minio/minio/pkg/auth"
sha256 "github.com/minio/sha256-simd"
) )
// Streaming AWS Signature Version '4' constants. // Streaming AWS Signature Version '4' constants.

View File

@ -39,7 +39,6 @@ import (
"github.com/minio/minio/pkg/env" "github.com/minio/minio/pkg/env"
xnet "github.com/minio/minio/pkg/net" xnet "github.com/minio/minio/pkg/net"
"github.com/minio/selfupdate" "github.com/minio/selfupdate"
_ "github.com/minio/sha256-simd" // Needed for sha256 hash verifier.
) )
const ( const (

View File

@ -17,20 +17,19 @@
package target package target
import ( import (
"crypto/sha256"
"crypto/sha512" "crypto/sha512"
"hash"
"github.com/minio/sha256-simd"
"github.com/xdg/scram" "github.com/xdg/scram"
) )
// KafkaSHA256 is a function that returns a crypto/sha256 hasher and should be used // KafkaSHA256 is a function that returns a crypto/sha256 hasher and should be used
// to create Client objects configured for SHA-256 hashing. // to create Client objects configured for SHA-256 hashing.
var KafkaSHA256 scram.HashGeneratorFcn = func() hash.Hash { return sha256.New() } var KafkaSHA256 scram.HashGeneratorFcn = sha256.New
// KafkaSHA512 is a function that returns a crypto/sha512 hasher and should be used // KafkaSHA512 is a function that returns a crypto/sha512 hasher and should be used
// to create Client objects configured for SHA-512 hashing. // to create Client objects configured for SHA-512 hashing.
var KafkaSHA512 scram.HashGeneratorFcn = func() hash.Hash { return sha512.New() } var KafkaSHA512 scram.HashGeneratorFcn = sha512.New
// XDGSCRAMClient implements the client-side of an authentication // XDGSCRAMClient implements the client-side of an authentication
// conversation with a server. A new conversation must be created for // conversation with a server. A new conversation must be created for

View File

@ -25,7 +25,6 @@ import (
"io" "io"
"github.com/minio/minio/pkg/etag" "github.com/minio/minio/pkg/etag"
sha256 "github.com/minio/sha256-simd"
) )
// A Reader wraps an io.Reader and computes the MD5 checksum // A Reader wraps an io.Reader and computes the MD5 checksum
@ -115,7 +114,7 @@ func NewReader(src io.Reader, size int64, md5Hex, sha256Hex string, actualSize i
src = io.LimitReader(src, size) src = io.LimitReader(src, size)
} }
if len(SHA256) != 0 { if len(SHA256) != 0 {
hash = sha256.New() hash = newSHA256()
} }
return &Reader{ return &Reader{
src: etag.NewReader(src, etag.ETag(MD5)), src: etag.NewReader(src, etag.ETag(MD5)),

28
pkg/hash/sha256_fips.go Normal file
View File

@ -0,0 +1,28 @@
// MinIO Cloud Storage, (C) 2021 MinIO, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build fips
package hash
import (
"crypto/sha256"
"hash"
)
// newSHA256 returns a new hash.Hash computing the SHA256 checksum.
// The SHA256 implementation is FIPS 140-2 compliant when the
// boringcrypto branch of Go is used.
// Ref: https://github.com/golang/go/tree/dev.boringcrypto
func newSHA256() hash.Hash { return sha256.New() }

27
pkg/hash/sha256_nofips.go Normal file
View File

@ -0,0 +1,27 @@
// MinIO Cloud Storage, (C) 2021 MinIO, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !fips
package hash
import (
"hash"
sha256 "github.com/minio/sha256-simd"
)
// newSHA256 returns a new hash.Hash computing the SHA256 checksum.
// The SHA256 implementation is not FIPS 140-2 compliant.
func newSHA256() hash.Hash { return sha256.New() }

View File

@ -19,6 +19,7 @@ package madmin
import ( import (
"bytes" "bytes"
"context" "context"
"crypto/sha256"
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
@ -476,7 +477,8 @@ func (adm AdminClient) newRequest(ctx context.Context, method string, reqData re
if length := len(reqData.content); length > 0 { if length := len(reqData.content); length > 0 {
req.ContentLength = int64(length) req.ContentLength = int64(length)
} }
req.Header.Set("X-Amz-Content-Sha256", hex.EncodeToString(sum256(reqData.content))) sum := sha256.Sum256(reqData.content)
req.Header.Set("X-Amz-Content-Sha256", hex.EncodeToString(sum[:]))
req.Body = ioutil.NopCloser(bytes.NewReader(reqData.content)) req.Body = ioutil.NopCloser(bytes.NewReader(reqData.content))
req = signer.SignV4(*req, accessKeyID, secretAccessKey, sessionToken, location) req = signer.SignV4(*req, accessKeyID, secretAccessKey, sessionToken, location)

View File

@ -25,8 +25,6 @@ import (
"net/url" "net/url"
"strings" "strings"
sha256 "github.com/minio/sha256-simd"
"github.com/minio/minio-go/v7/pkg/s3utils" "github.com/minio/minio-go/v7/pkg/s3utils"
) )
@ -37,13 +35,6 @@ const (
adminAPIPrefix = "/" + AdminAPIVersion adminAPIPrefix = "/" + AdminAPIVersion
) )
// sum256 calculate sha256 sum for an input byte array.
func sum256(data []byte) []byte {
hash := sha256.New()
hash.Write(data)
return hash.Sum(nil)
}
// jsonDecoder decode json to go type. // jsonDecoder decode json to go type.
func jsonDecoder(body io.Reader, v interface{}) error { func jsonDecoder(body io.Reader, v interface{}) error {
d := json.NewDecoder(body) d := json.NewDecoder(body)