mirror of
https://github.com/golang/go.git
synced 2026-04-01 17:07:17 +09:00
crypto: implement fips140=only mode
Running the test suite in this mode is definitely not an option. Testing this will probably look like a very long test that tries all functions. Filed #70514 to track the tests. For #70123 Change-Id: I6f67de83da37dd1e94e620b7f4f4f6aabe040c41 Reviewed-on: https://go-review.googlesource.com/c/go/+/631018 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Auto-Submit: Filippo Valsorda <filippo@golang.org> Reviewed-by: Roland Shoemaker <roland@golang.org> Reviewed-by: Daniel McCarney <daniel@binaryparadox.net> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
committed by
Gopher Robot
parent
07b4266605
commit
b299e9a44f
@@ -8,6 +8,7 @@ package cipher
|
||||
|
||||
import (
|
||||
"crypto/internal/fips140/alias"
|
||||
"crypto/internal/fips140only"
|
||||
"crypto/subtle"
|
||||
)
|
||||
|
||||
@@ -54,6 +55,9 @@ func (x *cfb) XORKeyStream(dst, src []byte) {
|
||||
// using the given [Block]. The iv must be the same length as the [Block]'s block
|
||||
// size.
|
||||
func NewCFBEncrypter(block Block, iv []byte) Stream {
|
||||
if fips140only.Enabled {
|
||||
panic("crypto/cipher: use of CFB is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
return newCFB(block, iv, false)
|
||||
}
|
||||
|
||||
@@ -61,6 +65,9 @@ func NewCFBEncrypter(block Block, iv []byte) Stream {
|
||||
// using the given [Block]. The iv must be the same length as the [Block]'s block
|
||||
// size.
|
||||
func NewCFBDecrypter(block Block, iv []byte) Stream {
|
||||
if fips140only.Enabled {
|
||||
panic("crypto/cipher: use of CFB is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
return newCFB(block, iv, true)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"crypto/internal/fips140/aes"
|
||||
"crypto/internal/fips140/aes/gcm"
|
||||
"crypto/internal/fips140/alias"
|
||||
"crypto/internal/fips140only"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"internal/byteorder"
|
||||
@@ -27,6 +28,9 @@ const (
|
||||
// An exception is when the underlying [Block] was created by aes.NewCipher
|
||||
// on systems with hardware support for AES. See the [crypto/aes] package documentation for details.
|
||||
func NewGCM(cipher Block) (AEAD, error) {
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/cipher: use of GCM with arbitrary IVs is not allowed in FIPS 140-only mode, use NewGCMWithRandomNonce")
|
||||
}
|
||||
return newGCM(cipher, gcmStandardNonceSize, gcmTagSize)
|
||||
}
|
||||
|
||||
@@ -38,6 +42,9 @@ func NewGCM(cipher Block) (AEAD, error) {
|
||||
// cryptosystem that uses non-standard nonce lengths. All other users should use
|
||||
// [NewGCM], which is faster and more resistant to misuse.
|
||||
func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error) {
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/cipher: use of GCM with arbitrary IVs is not allowed in FIPS 140-only mode, use NewGCMWithRandomNonce")
|
||||
}
|
||||
return newGCM(cipher, size, gcmTagSize)
|
||||
}
|
||||
|
||||
@@ -50,12 +57,18 @@ func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error) {
|
||||
// cryptosystem that uses non-standard tag lengths. All other users should use
|
||||
// [NewGCM], which is more resistant to misuse.
|
||||
func NewGCMWithTagSize(cipher Block, tagSize int) (AEAD, error) {
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/cipher: use of GCM with arbitrary IVs is not allowed in FIPS 140-only mode, use NewGCMWithRandomNonce")
|
||||
}
|
||||
return newGCM(cipher, gcmStandardNonceSize, tagSize)
|
||||
}
|
||||
|
||||
func newGCM(cipher Block, nonceSize, tagSize int) (AEAD, error) {
|
||||
c, ok := cipher.(*aes.Block)
|
||||
if !ok {
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/cipher: use of GCM with non-AES ciphers is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
return newGCMFallback(cipher, nonceSize, tagSize)
|
||||
}
|
||||
// We don't return gcm.New directly, because it would always return a non-nil
|
||||
|
||||
@@ -8,6 +8,7 @@ package cipher
|
||||
|
||||
import (
|
||||
"crypto/internal/fips140/alias"
|
||||
"crypto/internal/fips140only"
|
||||
"crypto/subtle"
|
||||
)
|
||||
|
||||
@@ -22,6 +23,10 @@ type ofb struct {
|
||||
// in output feedback mode. The initialization vector iv's length must be equal
|
||||
// to b's block size.
|
||||
func NewOFB(b Block, iv []byte) Stream {
|
||||
if fips140only.Enabled {
|
||||
panic("crypto/cipher: use of OFB is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
blockSize := b.BlockSize()
|
||||
if len(iv) != blockSize {
|
||||
panic("cipher.NewOFB: IV length must equal block size")
|
||||
|
||||
@@ -7,6 +7,8 @@ package des
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"crypto/internal/fips140/alias"
|
||||
"crypto/internal/fips140only"
|
||||
"errors"
|
||||
"internal/byteorder"
|
||||
"strconv"
|
||||
)
|
||||
@@ -27,6 +29,10 @@ type desCipher struct {
|
||||
|
||||
// NewCipher creates and returns a new [cipher.Block].
|
||||
func NewCipher(key []byte) (cipher.Block, error) {
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/des: use of DES is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
if len(key) != 8 {
|
||||
return nil, KeySizeError(len(key))
|
||||
}
|
||||
@@ -71,6 +77,10 @@ type tripleDESCipher struct {
|
||||
|
||||
// NewTripleDESCipher creates and returns a new [cipher.Block].
|
||||
func NewTripleDESCipher(key []byte) (cipher.Block, error) {
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/des: use of TripleDES is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
if len(key) != 24 {
|
||||
return nil, KeySizeError(len(key))
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"crypto/internal/fips140only"
|
||||
"crypto/internal/randutil"
|
||||
)
|
||||
|
||||
@@ -63,6 +64,10 @@ const numMRTests = 64
|
||||
// GenerateParameters puts a random, valid set of DSA parameters into params.
|
||||
// This function can take many seconds, even on fast machines.
|
||||
func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) error {
|
||||
if fips140only.Enabled {
|
||||
return errors.New("crypto/dsa: use of DSA is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
// This function doesn't follow FIPS 186-3 exactly in that it doesn't
|
||||
// use a verification seed to generate the primes. The verification
|
||||
// seed doesn't appear to be exported or used by other code and
|
||||
@@ -157,6 +162,10 @@ GeneratePrimes:
|
||||
// GenerateKey generates a public&private key pair. The Parameters of the
|
||||
// [PrivateKey] must already be valid (see [GenerateParameters]).
|
||||
func GenerateKey(priv *PrivateKey, rand io.Reader) error {
|
||||
if fips140only.Enabled {
|
||||
return errors.New("crypto/dsa: use of DSA is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
if priv.P == nil || priv.Q == nil || priv.G == nil {
|
||||
return errors.New("crypto/dsa: parameters not set up before generating key")
|
||||
}
|
||||
@@ -203,6 +212,10 @@ func fermatInverse(k, P *big.Int) *big.Int {
|
||||
// Be aware that calling Sign with an attacker-controlled [PrivateKey] may
|
||||
// require an arbitrary amount of CPU.
|
||||
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
|
||||
if fips140only.Enabled {
|
||||
return nil, nil, errors.New("crypto/dsa: use of DSA is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
randutil.MaybeReadByte(rand)
|
||||
|
||||
// FIPS 186-3, section 4.6
|
||||
@@ -271,6 +284,10 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
|
||||
// to the byte-length of the subgroup. This function does not perform that
|
||||
// truncation itself.
|
||||
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
|
||||
if fips140only.Enabled {
|
||||
panic("crypto/dsa: use of DSA is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
// FIPS 186-3, section 4.7
|
||||
|
||||
if pub.P.Sign() == 0 {
|
||||
|
||||
@@ -7,6 +7,7 @@ package ecdh
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/internal/fips140/edwards25519/field"
|
||||
"crypto/internal/fips140only"
|
||||
"crypto/internal/randutil"
|
||||
"errors"
|
||||
"io"
|
||||
@@ -34,6 +35,9 @@ func (c *x25519Curve) String() string {
|
||||
}
|
||||
|
||||
func (c *x25519Curve) GenerateKey(rand io.Reader) (*PrivateKey, error) {
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/ecdh: use of X25519 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
key := make([]byte, x25519PrivateKeySize)
|
||||
randutil.MaybeReadByte(rand)
|
||||
if _, err := io.ReadFull(rand, key); err != nil {
|
||||
@@ -43,6 +47,9 @@ func (c *x25519Curve) GenerateKey(rand io.Reader) (*PrivateKey, error) {
|
||||
}
|
||||
|
||||
func (c *x25519Curve) NewPrivateKey(key []byte) (*PrivateKey, error) {
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/ecdh: use of X25519 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
if len(key) != x25519PrivateKeySize {
|
||||
return nil, errors.New("crypto/ecdh: invalid private key size")
|
||||
}
|
||||
@@ -60,6 +67,9 @@ func (c *x25519Curve) NewPrivateKey(key []byte) (*PrivateKey, error) {
|
||||
}
|
||||
|
||||
func (c *x25519Curve) NewPublicKey(key []byte) (*PublicKey, error) {
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/ecdh: use of X25519 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
if len(key) != x25519PublicKeySize {
|
||||
return nil, errors.New("crypto/ecdh: invalid public key")
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ package ecdsa
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"crypto/internal/fips140only"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
@@ -19,6 +20,10 @@ import (
|
||||
// deprecated custom curves.
|
||||
|
||||
func generateLegacy(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) {
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
k, err := randFieldElement(c, rand)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -76,6 +81,10 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
|
||||
}
|
||||
|
||||
func signLegacy(priv *PrivateKey, csprng io.Reader, hash []byte) (sig []byte, err error) {
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
c := priv.Curve
|
||||
|
||||
// A cheap version of hedged signatures, for the deprecated path.
|
||||
@@ -144,6 +153,10 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
|
||||
}
|
||||
|
||||
func verifyLegacy(pub *PublicKey, hash []byte, sig []byte) bool {
|
||||
if fips140only.Enabled {
|
||||
panic("crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
rBytes, sBytes, err := parseSignature(sig)
|
||||
if err != nil {
|
||||
return false
|
||||
|
||||
@@ -18,6 +18,7 @@ package ed25519
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/internal/fips140/ed25519"
|
||||
"crypto/internal/fips140only"
|
||||
cryptorand "crypto/rand"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
@@ -103,6 +104,9 @@ func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOp
|
||||
case hash == crypto.SHA512: // Ed25519ph
|
||||
return ed25519.SignPH(k, message, context)
|
||||
case hash == crypto.Hash(0) && context != "": // Ed25519ctx
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/ed25519: use of Ed25519ctx is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
return ed25519.SignCtx(k, message, context)
|
||||
case hash == crypto.Hash(0): // Ed25519
|
||||
return ed25519.Sign(k, message), nil
|
||||
@@ -219,6 +223,9 @@ func VerifyWithOptions(publicKey PublicKey, message, sig []byte, opts *Options)
|
||||
case opts.Hash == crypto.SHA512: // Ed25519ph
|
||||
return ed25519.VerifyPH(k, message, sig, opts.Context)
|
||||
case opts.Hash == crypto.Hash(0) && opts.Context != "": // Ed25519ctx
|
||||
if fips140only.Enabled {
|
||||
return errors.New("crypto/ed25519: use of Ed25519ctx is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
return ed25519.VerifyCtx(k, message, sig, opts.Context)
|
||||
case opts.Hash == crypto.Hash(0): // Ed25519
|
||||
return ed25519.Verify(k, message, sig)
|
||||
|
||||
@@ -6,6 +6,7 @@ package hkdf
|
||||
|
||||
import (
|
||||
"crypto/internal/fips140/hkdf"
|
||||
"crypto/internal/fips140only"
|
||||
"errors"
|
||||
"hash"
|
||||
)
|
||||
@@ -17,6 +18,9 @@ import (
|
||||
// Expand invocations and different context values. Most common scenarios,
|
||||
// including the generation of multiple keys, should use [Key] instead.
|
||||
func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) {
|
||||
if err := checkFIPS140Only(h, secret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hkdf.Extract(h, secret, salt), nil
|
||||
}
|
||||
|
||||
@@ -28,6 +32,10 @@ func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) {
|
||||
// random or pseudorandom cryptographically strong key. See RFC 5869, Section
|
||||
// 3.3. Most common scenarios will want to use [Key] instead.
|
||||
func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLength int) ([]byte, error) {
|
||||
if err := checkFIPS140Only(h, pseudorandomKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
limit := h().Size() * 255
|
||||
if keyLength > limit {
|
||||
return nil, errors.New("hkdf: requested key length too large")
|
||||
@@ -40,6 +48,10 @@ func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen
|
||||
// returning a []byte of length keyLength that can be used as cryptographic key.
|
||||
// Salt and info can be nil.
|
||||
func Key[Hash hash.Hash](h func() Hash, secret, salt []byte, info string, keyLength int) ([]byte, error) {
|
||||
if err := checkFIPS140Only(h, secret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
limit := h().Size() * 255
|
||||
if keyLength > limit {
|
||||
return nil, errors.New("hkdf: requested key length too large")
|
||||
@@ -47,3 +59,16 @@ func Key[Hash hash.Hash](h func() Hash, secret, salt []byte, info string, keyLen
|
||||
|
||||
return hkdf.Key(h, secret, salt, info, keyLength), nil
|
||||
}
|
||||
|
||||
func checkFIPS140Only[H hash.Hash](h func() H, key []byte) error {
|
||||
if !fips140only.Enabled {
|
||||
return nil
|
||||
}
|
||||
if len(key) < 112/8 {
|
||||
return errors.New("crypto/hkdf: use of keys shorter than 112 bits is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
if !fips140only.ApprovedHash(h()) {
|
||||
return errors.New("crypto/hkdf: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ package hmac
|
||||
import (
|
||||
"crypto/internal/boring"
|
||||
"crypto/internal/fips140/hmac"
|
||||
"crypto/internal/fips140only"
|
||||
"crypto/subtle"
|
||||
"hash"
|
||||
)
|
||||
@@ -42,6 +43,14 @@ func New(h func() hash.Hash, key []byte) hash.Hash {
|
||||
}
|
||||
// BoringCrypto did not recognize h, so fall through to standard Go code.
|
||||
}
|
||||
if fips140only.Enabled {
|
||||
if len(key) < 112/8 {
|
||||
panic("crypto/hmac: use of keys shorter than 112 bits is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
if !fips140only.ApprovedHash(h()) {
|
||||
panic("crypto/hmac: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
}
|
||||
return hmac.New(h, key)
|
||||
}
|
||||
|
||||
|
||||
26
src/crypto/internal/fips140only/fips140only.go
Normal file
26
src/crypto/internal/fips140only/fips140only.go
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fips140only
|
||||
|
||||
import (
|
||||
"crypto/internal/fips140/sha256"
|
||||
"crypto/internal/fips140/sha3"
|
||||
"crypto/internal/fips140/sha512"
|
||||
"hash"
|
||||
"internal/godebug"
|
||||
)
|
||||
|
||||
// Enabled reports whether FIPS 140-only mode is enabled, in which non-approved
|
||||
// cryptography returns an error or panics.
|
||||
var Enabled = godebug.New("#fips140").Value() == "only"
|
||||
|
||||
func ApprovedHash(h hash.Hash) bool {
|
||||
switch h.(type) {
|
||||
case *sha256.Digest, *sha512.Digest, *sha3.Digest:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ package md5
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/internal/fips140only"
|
||||
"errors"
|
||||
"hash"
|
||||
"internal/byteorder"
|
||||
@@ -103,6 +104,9 @@ func consumeUint32(b []byte) ([]byte, uint32) {
|
||||
// [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal
|
||||
// state of the hash.
|
||||
func New() hash.Hash {
|
||||
if fips140only.Enabled {
|
||||
panic("crypto/md5: use of MD5 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
d := new(digest)
|
||||
d.Reset()
|
||||
return d
|
||||
@@ -180,6 +184,9 @@ func (d *digest) checkSum() [Size]byte {
|
||||
|
||||
// Sum returns the MD5 checksum of the data.
|
||||
func Sum(data []byte) [Size]byte {
|
||||
if fips140only.Enabled {
|
||||
panic("crypto/md5: use of MD5 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
var d digest
|
||||
d.Reset()
|
||||
d.Write(data)
|
||||
|
||||
@@ -20,6 +20,8 @@ package pbkdf2
|
||||
|
||||
import (
|
||||
"crypto/internal/fips140/pbkdf2"
|
||||
"crypto/internal/fips140only"
|
||||
"errors"
|
||||
"hash"
|
||||
)
|
||||
|
||||
@@ -40,5 +42,16 @@ import (
|
||||
// Using a higher iteration count will increase the cost of an exhaustive
|
||||
// search but will also make derivation proportionally slower.
|
||||
func Key[Hash hash.Hash](h func() Hash, password string, salt []byte, iter, keyLength int) ([]byte, error) {
|
||||
if fips140only.Enabled {
|
||||
if keyLength < 112/8 {
|
||||
return nil, errors.New("crypto/pbkdf2: use of keys shorter than 112 bits is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
if len(salt) < 128/8 {
|
||||
return nil, errors.New("crypto/pbkdf2: use of salts shorter than 128 bits is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
if !fips140only.ApprovedHash(h()) {
|
||||
return nil, errors.New("crypto/pbkdf2: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
}
|
||||
return pbkdf2.Key(h, password, salt, iter, keyLength)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package rand
|
||||
|
||||
import (
|
||||
"crypto/internal/fips140only"
|
||||
"crypto/internal/randutil"
|
||||
"errors"
|
||||
"io"
|
||||
@@ -14,6 +15,9 @@ import (
|
||||
// Prime returns a number of the given bit length that is prime with high probability.
|
||||
// Prime will return error for any error returned by rand.Read or if bits < 2.
|
||||
func Prime(rand io.Reader, bits int) (*big.Int, error) {
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/rand: use of Prime is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
if bits < 2 {
|
||||
return nil, errors.New("crypto/rand: prime size must be at least 2-bit")
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ package rc4
|
||||
|
||||
import (
|
||||
"crypto/internal/fips140/alias"
|
||||
"crypto/internal/fips140only"
|
||||
"errors"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
@@ -29,6 +31,9 @@ func (k KeySizeError) Error() string {
|
||||
// NewCipher creates and returns a new [Cipher]. The key argument should be the
|
||||
// RC4 key, at least 1 byte and at most 256 bytes.
|
||||
func NewCipher(key []byte) (*Cipher, error) {
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/rc4: use of RC4 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
k := len(key)
|
||||
if k < 1 || k > 256 {
|
||||
return nil, KeySizeError(k)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"crypto"
|
||||
"crypto/internal/boring"
|
||||
"crypto/internal/fips140/rsa"
|
||||
"crypto/internal/fips140only"
|
||||
"errors"
|
||||
"hash"
|
||||
"io"
|
||||
@@ -60,6 +61,12 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
|
||||
if err := checkPublicKeySize(&priv.PublicKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := checkFIPS140OnlyPrivateKey(priv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fips140only.Enabled && !fips140only.ApprovedHash(hash.New()) {
|
||||
return nil, errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
if opts != nil && opts.Hash != 0 {
|
||||
hash = opts.Hash
|
||||
@@ -81,6 +88,9 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
|
||||
h := hash.New()
|
||||
|
||||
saltLength := opts.saltLength()
|
||||
if fips140only.Enabled && saltLength > hash.Size() {
|
||||
return nil, errors.New("crypto/rsa: use of PSS salt longer than the hash is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
switch saltLength {
|
||||
case PSSSaltLengthAuto:
|
||||
saltLength, err = rsa.PSSMaxSaltLength(k.PublicKey(), h)
|
||||
@@ -113,6 +123,12 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts
|
||||
if err := checkPublicKeySize(pub); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := checkFIPS140OnlyPublicKey(pub); err != nil {
|
||||
return err
|
||||
}
|
||||
if fips140only.Enabled && !fips140only.ApprovedHash(hash.New()) {
|
||||
return errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
if boring.Enabled {
|
||||
bkey, err := boringPublicKey(pub)
|
||||
@@ -131,6 +147,9 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts
|
||||
}
|
||||
|
||||
saltLength := opts.saltLength()
|
||||
if fips140only.Enabled && saltLength > hash.Size() {
|
||||
return errors.New("crypto/rsa: use of PSS salt longer than the hash is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
switch saltLength {
|
||||
case PSSSaltLengthAuto:
|
||||
return fipsError(rsa.VerifyPSS(k, hash.New(), digest, sig))
|
||||
@@ -163,6 +182,12 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
|
||||
if err := checkPublicKeySize(pub); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := checkFIPS140OnlyPublicKey(pub); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fips140only.Enabled && !fips140only.ApprovedHash(hash) {
|
||||
return nil, errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
defer hash.Reset()
|
||||
|
||||
@@ -206,6 +231,14 @@ func decryptOAEP(hash, mgfHash hash.Hash, priv *PrivateKey, ciphertext []byte, l
|
||||
if err := checkPublicKeySize(&priv.PublicKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := checkFIPS140OnlyPrivateKey(priv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fips140only.Enabled {
|
||||
if !fips140only.ApprovedHash(hash) || !fips140only.ApprovedHash(mgfHash) {
|
||||
return nil, errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
}
|
||||
|
||||
if boring.Enabled {
|
||||
k := priv.Size()
|
||||
@@ -248,6 +281,12 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [
|
||||
if err := checkPublicKeySize(&priv.PublicKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := checkFIPS140OnlyPrivateKey(priv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fips140only.Enabled && !fips140only.ApprovedHash(hash.New()) {
|
||||
return nil, errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
if boring.Enabled {
|
||||
bkey, err := boringPrivateKey(priv)
|
||||
@@ -283,6 +322,12 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte)
|
||||
if err := checkPublicKeySize(pub); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := checkFIPS140OnlyPublicKey(pub); err != nil {
|
||||
return err
|
||||
}
|
||||
if fips140only.Enabled && !fips140only.ApprovedHash(hash.New()) {
|
||||
return errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
if boring.Enabled {
|
||||
bkey, err := boringPublicKey(pub)
|
||||
@@ -324,3 +369,38 @@ func fipsError(err error) error {
|
||||
func fipsError2[T any](x T, err error) (T, error) {
|
||||
return x, fipsError(err)
|
||||
}
|
||||
|
||||
func checkFIPS140OnlyPublicKey(pub *PublicKey) error {
|
||||
if !fips140only.Enabled {
|
||||
return nil
|
||||
}
|
||||
if pub.N == nil {
|
||||
return errors.New("crypto/rsa: public key missing N")
|
||||
}
|
||||
if pub.N.BitLen() < 2048 {
|
||||
return errors.New("crypto/rsa: use of keys smaller than 2048 bits is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
if pub.N.BitLen() > 16384 {
|
||||
return errors.New("crypto/rsa: use of keys larger than 16384 bits is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
if pub.E <= 1<<16 {
|
||||
return errors.New("crypto/rsa: use of public exponent <= 2¹⁶ is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
if pub.E&1 == 0 {
|
||||
return errors.New("crypto/rsa: use of even public exponent is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkFIPS140OnlyPrivateKey(priv *PrivateKey) error {
|
||||
if !fips140only.Enabled {
|
||||
return nil
|
||||
}
|
||||
if err := checkFIPS140OnlyPublicKey(&priv.PublicKey); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(priv.Primes) > 2 {
|
||||
return errors.New("crypto/rsa: use of multi-prime keys is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,8 +7,10 @@ package rsa
|
||||
import (
|
||||
"crypto/internal/boring"
|
||||
"crypto/internal/fips140/rsa"
|
||||
"crypto/internal/fips140only"
|
||||
"crypto/internal/randutil"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
@@ -38,6 +40,10 @@ type PKCS1v15DecryptOptions struct {
|
||||
// WARNING: use of this function to encrypt plaintexts other than
|
||||
// session keys is dangerous. Use RSA OAEP in new protocols.
|
||||
func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, error) {
|
||||
if fips140only.Enabled {
|
||||
return nil, errors.New("crypto/rsa: use of PKCS#1 v1.5 encryption is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
if err := checkPublicKeySize(pub); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -187,6 +193,10 @@ func DecryptPKCS1v15SessionKey(random io.Reader, priv *PrivateKey, ciphertext []
|
||||
// access patterns. If the plaintext was valid then index contains the index of
|
||||
// the original message in em, to allow constant time padding removal.
|
||||
func decryptPKCS1v15(priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) {
|
||||
if fips140only.Enabled {
|
||||
return 0, nil, 0, errors.New("crypto/rsa: use of PKCS#1 v1.5 encryption is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
|
||||
k := priv.Size()
|
||||
if k < 11 {
|
||||
err = ErrDecryption
|
||||
|
||||
@@ -11,6 +11,7 @@ package sha1
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/internal/boring"
|
||||
"crypto/internal/fips140only"
|
||||
"errors"
|
||||
"hash"
|
||||
"internal/byteorder"
|
||||
@@ -102,7 +103,7 @@ func (d *digest) Reset() {
|
||||
d.len = 0
|
||||
}
|
||||
|
||||
// New512_224 returns a new [hash.Hash] computing the SHA1 checksum. The Hash
|
||||
// New returns a new [hash.Hash] computing the SHA1 checksum. The Hash
|
||||
// also implements [encoding.BinaryMarshaler], [encoding.BinaryAppender] and
|
||||
// [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal
|
||||
// state of the hash.
|
||||
@@ -110,6 +111,9 @@ func New() hash.Hash {
|
||||
if boring.Enabled {
|
||||
return boring.NewSHA1()
|
||||
}
|
||||
if fips140only.Enabled {
|
||||
panic("crypto/sha1: use of weak SHA-1 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
d := new(digest)
|
||||
d.Reset()
|
||||
return d
|
||||
@@ -257,6 +261,9 @@ func Sum(data []byte) [Size]byte {
|
||||
if boring.Enabled {
|
||||
return boring.SHA1(data)
|
||||
}
|
||||
if fips140only.Enabled {
|
||||
panic("crypto/sha1: use of weak SHA-1 is not allowed in FIPS 140-only mode")
|
||||
}
|
||||
var d digest
|
||||
d.Reset()
|
||||
d.Write(data)
|
||||
|
||||
@@ -491,14 +491,14 @@ var depsRules = `
|
||||
|
||||
FIPS, sync/atomic < crypto/tls/internal/fips140tls;
|
||||
|
||||
FIPS, internal/godebug < crypto/fips140;
|
||||
FIPS, internal/godebug, hash < crypto/fips140, crypto/internal/fips140only;
|
||||
|
||||
NONE < crypto/internal/boring/sig, crypto/internal/boring/syso;
|
||||
sync/atomic < crypto/internal/boring/bcache, crypto/internal/boring/fips140tls;
|
||||
crypto/internal/boring/sig, crypto/tls/internal/fips140tls < crypto/tls/fipsonly;
|
||||
|
||||
# CRYPTO is core crypto algorithms - no cgo, fmt, net.
|
||||
FIPS,
|
||||
FIPS, crypto/internal/fips140only,
|
||||
crypto/internal/boring/sig,
|
||||
crypto/internal/boring/syso,
|
||||
golang.org/x/sys/cpu,
|
||||
|
||||
Reference in New Issue
Block a user