mirror of
https://github.com/minio/minio.git
synced 2025-11-07 04:42:56 -05:00
remove support for FIPS 140-2 with boringcrypto (#21292)
This commit removes FIPS 140-2 related code for the following reasons: - FIPS 140-2 is a compliance, not a security requirement. Being FIPS 140-2 compliant has no security implication on its own. From a tech. perspetive, a FIPS 140-2 compliant implementation is not necessarily secure and a non-FIPS 140-2 compliant implementation is not necessarily insecure. It depends on the concret design and crypto primitives/constructions used. - The boringcrypto branch used to achieve FIPS 140-2 compliance was never officially supported by the Go team and is now in maintainance mode. It is replaced by a built-in FIPS 140-3 module. It will be removed eventually. Ref: https://github.com/golang/go/issues/69536 - FIPS 140-2 modules are no longer re-certified after Sep. 2026. Ref: https://csrc.nist.gov/projects/cryptographic-module-validation-program Signed-off-by: Andreas Auernhammer <github@aead.dev>
This commit is contained in:
committed by
GitHub
parent
c0a33952c6
commit
1d50cae43d
@@ -27,7 +27,6 @@ import (
|
||||
"io"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/minio/minio/internal/fips"
|
||||
"github.com/minio/minio/internal/kms"
|
||||
"github.com/secure-io/sio-go"
|
||||
"github.com/secure-io/sio-go/sioutil"
|
||||
@@ -64,7 +63,7 @@ func DecryptBytes(k *kms.KMS, ciphertext []byte, context kms.Context) ([]byte, e
|
||||
// ciphertext.
|
||||
func Encrypt(k *kms.KMS, plaintext io.Reader, ctx kms.Context) (io.Reader, error) {
|
||||
algorithm := sio.AES_256_GCM
|
||||
if !fips.Enabled && !sioutil.NativeAES() {
|
||||
if !sioutil.NativeAES() {
|
||||
algorithm = sio.ChaCha20Poly1305
|
||||
}
|
||||
|
||||
@@ -145,9 +144,6 @@ func Decrypt(k *kms.KMS, ciphertext io.Reader, associatedData kms.Context) (io.R
|
||||
if err := json.Unmarshal(metadataBuffer, &metadata); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fips.Enabled && metadata.Algorithm != sio.AES_256_GCM {
|
||||
return nil, fmt.Errorf("config: unsupported encryption algorithm: %q is not supported in FIPS mode", metadata.Algorithm)
|
||||
}
|
||||
|
||||
key, err := k.Decrypt(context.TODO(), &kms.DecryptRequest{
|
||||
Name: metadata.KeyID,
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/internal/config"
|
||||
"github.com/minio/minio/internal/fips"
|
||||
"github.com/minio/minio/internal/crypto"
|
||||
"github.com/minio/pkg/v3/env"
|
||||
xnet "github.com/minio/pkg/v3/net"
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
@@ -165,8 +165,8 @@ func LookupConfig(kvs config.KVS, rootCAs *x509.CertPool) (Config, error) {
|
||||
MinVersion: tls.VersionTLS12,
|
||||
NextProtos: []string{"http/1.1", "h2"},
|
||||
ClientSessionCache: tls.NewLRUClientSessionCache(64),
|
||||
CipherSuites: fips.TLSCiphersBackwardCompatible(),
|
||||
CurvePreferences: fips.TLSCurveIDs(),
|
||||
CipherSuites: crypto.TLSCiphersBackwardCompatible(),
|
||||
CurvePreferences: crypto.TLSCurveIDs(),
|
||||
}
|
||||
// This is only to support client side certificate authentication
|
||||
// https://coreos.com/etcd/docs/latest/op-guide/security.html
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
|
||||
"github.com/minio/madmin-go/v3"
|
||||
"github.com/minio/minio/internal/config"
|
||||
"github.com/minio/minio/internal/fips"
|
||||
"github.com/minio/minio/internal/crypto"
|
||||
"github.com/minio/pkg/v3/ldap"
|
||||
)
|
||||
|
||||
@@ -197,7 +197,7 @@ func Lookup(s config.Config, rootCAs *x509.CertPool) (l Config, err error) {
|
||||
MinVersion: tls.VersionTLS12,
|
||||
NextProtos: []string{"h2", "http/1.1"},
|
||||
ClientSessionCache: tls.NewLRUClientSessionCache(100),
|
||||
CipherSuites: fips.TLSCiphersBackwardCompatible(), // Contains RSA key exchange
|
||||
CipherSuites: crypto.TLSCiphersBackwardCompatible(), // Contains RSA key exchange
|
||||
RootCAs: rootCAs,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !fips
|
||||
// +build !fips
|
||||
|
||||
package openid
|
||||
|
||||
import (
|
||||
@@ -22,7 +19,7 @@ import (
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
|
||||
// Needed for SHA3 to work - See: https://golang.org/src/crypto/crypto.go?s=1034:1288
|
||||
_ "golang.org/x/crypto/sha3" // There is no SHA-3 FIPS-140 2 compliant implementation
|
||||
_ "golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
// Specific instances for EC256 and company
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !fips
|
||||
// +build !fips
|
||||
|
||||
package openid
|
||||
|
||||
import (
|
||||
@@ -23,7 +20,7 @@ import (
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
|
||||
// Needed for SHA3 to work - See: https://golang.org/src/crypto/crypto.go?s=1034:1288
|
||||
_ "golang.org/x/crypto/sha3" // There is no SHA-3 FIPS-140 2 compliant implementation
|
||||
_ "golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
// Specific instances for RS256 and company
|
||||
|
||||
@@ -15,22 +15,7 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Package fips provides functionality to configure cryptographic
|
||||
// implementations compliant with FIPS 140.
|
||||
//
|
||||
// FIPS 140 [1] is a US standard for data processing that specifies
|
||||
// requirements for cryptographic modules. Software that is "FIPS 140
|
||||
// compliant" must use approved cryptographic primitives only and that
|
||||
// are implemented by a FIPS 140 certified cryptographic module.
|
||||
//
|
||||
// So, FIPS 140 requires that a certified implementation of e.g. AES
|
||||
// is used to implement more high-level cryptographic protocols.
|
||||
// It does not require any specific security criteria for those
|
||||
// high-level protocols. FIPS 140 focuses only on the implementation
|
||||
// and usage of the most low-level cryptographic building blocks.
|
||||
//
|
||||
// [1]: https://en.wikipedia.org/wiki/FIPS_140
|
||||
package fips
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
@@ -38,40 +23,13 @@ import (
|
||||
"github.com/minio/sio"
|
||||
)
|
||||
|
||||
// Enabled indicates whether cryptographic primitives,
|
||||
// like AES or SHA-256, are implemented using a FIPS 140
|
||||
// certified module.
|
||||
//
|
||||
// If FIPS-140 is enabled no non-NIST/FIPS approved
|
||||
// primitives must be used.
|
||||
const Enabled = enabled
|
||||
|
||||
// DARECiphers returns a list of supported cipher suites
|
||||
// for the DARE object encryption.
|
||||
func DARECiphers() []byte {
|
||||
if Enabled {
|
||||
return []byte{sio.AES_256_GCM}
|
||||
}
|
||||
return []byte{sio.AES_256_GCM, sio.CHACHA20_POLY1305}
|
||||
}
|
||||
func DARECiphers() []byte { return []byte{sio.AES_256_GCM, sio.CHACHA20_POLY1305} }
|
||||
|
||||
// TLSCiphers returns a list of supported TLS transport
|
||||
// cipher suite IDs.
|
||||
//
|
||||
// The list contains only ciphers that use AES-GCM or
|
||||
// (non-FIPS) CHACHA20-POLY1305 and ellitpic curve key
|
||||
// exchange.
|
||||
func TLSCiphers() []uint16 {
|
||||
if Enabled {
|
||||
return []uint16{
|
||||
tls.TLS_AES_128_GCM_SHA256, // TLS 1.3
|
||||
tls.TLS_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, // TLS 1.2
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
}
|
||||
}
|
||||
return []uint16{
|
||||
tls.TLS_CHACHA20_POLY1305_SHA256, // TLS 1.3
|
||||
tls.TLS_AES_128_GCM_SHA256,
|
||||
@@ -92,24 +50,6 @@ func TLSCiphers() []uint16 {
|
||||
// ciphers for backward compatibility. In particular, AES-CBC
|
||||
// and non-ECDHE ciphers.
|
||||
func TLSCiphersBackwardCompatible() []uint16 {
|
||||
if Enabled {
|
||||
return []uint16{
|
||||
tls.TLS_AES_128_GCM_SHA256, // TLS 1.3
|
||||
tls.TLS_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, // TLS 1.2 ECDHE GCM
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, // TLS 1.2 ECDHE CBC
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
tls.TLS_RSA_WITH_AES_128_GCM_SHA256, // TLS 1.2 non-ECDHE
|
||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
}
|
||||
}
|
||||
return []uint16{
|
||||
tls.TLS_CHACHA20_POLY1305_SHA256, // TLS 1.3
|
||||
tls.TLS_AES_128_GCM_SHA256,
|
||||
@@ -134,10 +74,5 @@ func TLSCiphersBackwardCompatible() []uint16 {
|
||||
// TLSCurveIDs returns a list of supported elliptic curve IDs
|
||||
// in preference order.
|
||||
func TLSCurveIDs() []tls.CurveID {
|
||||
var curves []tls.CurveID
|
||||
if !Enabled {
|
||||
curves = append(curves, tls.X25519) // Only enable X25519 in non-FIPS mode
|
||||
}
|
||||
curves = append(curves, tls.CurveP256, tls.CurveP384, tls.CurveP521)
|
||||
return curves
|
||||
return []tls.CurveID{tls.CurveP256, tls.X25519, tls.CurveP384, tls.CurveP521}
|
||||
}
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"io"
|
||||
"path"
|
||||
|
||||
"github.com/minio/minio/internal/fips"
|
||||
"github.com/minio/minio/internal/hash/sha256"
|
||||
"github.com/minio/minio/internal/logger"
|
||||
"github.com/minio/sio"
|
||||
@@ -98,7 +97,7 @@ func (key ObjectKey) Seal(extKey []byte, iv [32]byte, domain, bucket, object str
|
||||
mac.Write([]byte(SealAlgorithm))
|
||||
mac.Write([]byte(path.Join(bucket, object))) // use path.Join for canonical 'bucket/object'
|
||||
mac.Sum(sealingKey[:0])
|
||||
if n, err := sio.Encrypt(&encryptedKey, bytes.NewReader(key[:]), sio.Config{Key: sealingKey[:], CipherSuites: fips.DARECiphers()}); n != 64 || err != nil {
|
||||
if n, err := sio.Encrypt(&encryptedKey, bytes.NewReader(key[:]), sio.Config{Key: sealingKey[:]}); n != 64 || err != nil {
|
||||
logger.CriticalIf(context.Background(), errors.New("Unable to generate sealed key"))
|
||||
}
|
||||
sealedKey := SealedKey{
|
||||
@@ -123,12 +122,12 @@ func (key *ObjectKey) Unseal(extKey []byte, sealedKey SealedKey, domain, bucket,
|
||||
mac.Write([]byte(domain))
|
||||
mac.Write([]byte(SealAlgorithm))
|
||||
mac.Write([]byte(path.Join(bucket, object))) // use path.Join for canonical 'bucket/object'
|
||||
unsealConfig = sio.Config{MinVersion: sio.Version20, Key: mac.Sum(nil), CipherSuites: fips.DARECiphers()}
|
||||
unsealConfig = sio.Config{MinVersion: sio.Version20, Key: mac.Sum(nil)}
|
||||
case InsecureSealAlgorithm:
|
||||
sha := sha256.New()
|
||||
sha.Write(extKey)
|
||||
sha.Write(sealedKey.IV[:])
|
||||
unsealConfig = sio.Config{MinVersion: sio.Version10, Key: sha.Sum(nil), CipherSuites: fips.DARECiphers()}
|
||||
unsealConfig = sio.Config{MinVersion: sio.Version10, Key: sha.Sum(nil)}
|
||||
}
|
||||
|
||||
if out, err := sio.DecryptBuffer(key[:0], sealedKey.Key[:], unsealConfig); len(out) != 32 || err != nil {
|
||||
@@ -159,7 +158,7 @@ func (key ObjectKey) SealETag(etag []byte) []byte {
|
||||
var buffer bytes.Buffer
|
||||
mac := hmac.New(sha256.New, key[:])
|
||||
mac.Write([]byte("SSE-etag"))
|
||||
if _, err := sio.Encrypt(&buffer, bytes.NewReader(etag), sio.Config{Key: mac.Sum(nil), CipherSuites: fips.DARECiphers()}); err != nil {
|
||||
if _, err := sio.Encrypt(&buffer, bytes.NewReader(etag), sio.Config{Key: mac.Sum(nil)}); err != nil {
|
||||
logger.CriticalIf(context.Background(), errors.New("Unable to encrypt ETag using object key"))
|
||||
}
|
||||
return buffer.Bytes()
|
||||
@@ -175,5 +174,5 @@ func (key ObjectKey) UnsealETag(etag []byte) ([]byte, error) {
|
||||
}
|
||||
mac := hmac.New(sha256.New, key[:])
|
||||
mac.Write([]byte("SSE-etag"))
|
||||
return sio.DecryptBuffer(make([]byte, 0, len(etag)), etag, sio.Config{Key: mac.Sum(nil), CipherSuites: fips.DARECiphers()})
|
||||
return sio.DecryptBuffer(make([]byte, 0, len(etag)), etag, sio.Config{Key: mac.Sum(nil)})
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/minio/minio/internal/fips"
|
||||
"github.com/minio/minio/internal/ioutil"
|
||||
"github.com/minio/minio/internal/logger"
|
||||
"github.com/minio/sio"
|
||||
@@ -101,7 +100,7 @@ func unsealObjectKey(clientKey []byte, metadata map[string]string, bucket, objec
|
||||
// EncryptSinglePart encrypts an io.Reader which must be the
|
||||
// body of a single-part PUT request.
|
||||
func EncryptSinglePart(r io.Reader, key ObjectKey) io.Reader {
|
||||
r, err := sio.EncryptReader(r, sio.Config{MinVersion: sio.Version20, Key: key[:], CipherSuites: fips.DARECiphers()})
|
||||
r, err := sio.EncryptReader(r, sio.Config{MinVersion: sio.Version20, Key: key[:]})
|
||||
if err != nil {
|
||||
logger.CriticalIf(context.Background(), errors.New("Unable to encrypt io.Reader using object key"))
|
||||
}
|
||||
@@ -123,7 +122,7 @@ func DecryptSinglePart(w io.Writer, offset, length int64, key ObjectKey) io.Writ
|
||||
const PayloadSize = 1 << 16 // DARE 2.0
|
||||
w = ioutil.LimitedWriter(w, offset%PayloadSize, length)
|
||||
|
||||
decWriter, err := sio.DecryptWriter(w, sio.Config{Key: key[:], CipherSuites: fips.DARECiphers()})
|
||||
decWriter, err := sio.DecryptWriter(w, sio.Config{Key: key[:]})
|
||||
if err != nil {
|
||||
logger.CriticalIf(context.Background(), errors.New("Unable to decrypt io.Writer using object key"))
|
||||
}
|
||||
|
||||
@@ -117,7 +117,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio/internal/fips"
|
||||
"github.com/minio/minio/internal/hash/sha256"
|
||||
xhttp "github.com/minio/minio/internal/http"
|
||||
"github.com/minio/sio"
|
||||
@@ -346,8 +345,7 @@ func Decrypt(key []byte, etag ETag) (ETag, error) {
|
||||
|
||||
plaintext := make([]byte, 0, 16)
|
||||
etag, err := sio.DecryptBuffer(plaintext, etag, sio.Config{
|
||||
Key: decryptionKey,
|
||||
CipherSuites: fips.DARECiphers(),
|
||||
Key: decryptionKey,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build fips && linux && amd64
|
||||
// +build fips,linux,amd64
|
||||
|
||||
package fips
|
||||
|
||||
import _ "crypto/tls/fipsonly"
|
||||
|
||||
const enabled = true
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !fips
|
||||
// +build !fips
|
||||
|
||||
package fips
|
||||
|
||||
const enabled = false
|
||||
Reference in New Issue
Block a user