import (
"crypto/internal/fips140/alias"
+ "crypto/internal/fips140only"
"crypto/subtle"
)
// 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)
}
// 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)
}
"crypto/internal/fips140/aes"
"crypto/internal/fips140/aes/gcm"
"crypto/internal/fips140/alias"
+ "crypto/internal/fips140only"
"crypto/subtle"
"errors"
"internal/byteorder"
// 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)
}
// 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)
}
// 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
import (
"crypto/internal/fips140/alias"
+ "crypto/internal/fips140only"
"crypto/subtle"
)
// 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")
import (
"crypto/cipher"
"crypto/internal/fips140/alias"
+ "crypto/internal/fips140only"
+ "errors"
"internal/byteorder"
"strconv"
)
// 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))
}
// 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))
}
"io"
"math/big"
+ "crypto/internal/fips140only"
"crypto/internal/randutil"
)
// 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
// 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")
}
// 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
// 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 {
import (
"bytes"
"crypto/internal/fips140/edwards25519/field"
+ "crypto/internal/fips140only"
"crypto/internal/randutil"
"errors"
"io"
}
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 {
}
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")
}
}
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")
}
import (
"crypto/elliptic"
+ "crypto/internal/fips140only"
"errors"
"io"
"math/big"
// 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
}
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.
}
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
import (
"crypto"
"crypto/internal/fips140/ed25519"
+ "crypto/internal/fips140only"
cryptorand "crypto/rand"
"crypto/subtle"
"errors"
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
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)
import (
"crypto/internal/fips140/hkdf"
+ "crypto/internal/fips140only"
"errors"
"hash"
)
// 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
}
// 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")
// 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")
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
+}
import (
"crypto/internal/boring"
"crypto/internal/fips140/hmac"
+ "crypto/internal/fips140only"
"crypto/subtle"
"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)
}
--- /dev/null
+// 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
+ }
+}
import (
"crypto"
+ "crypto/internal/fips140only"
"errors"
"hash"
"internal/byteorder"
// [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
// 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)
import (
"crypto/internal/fips140/pbkdf2"
+ "crypto/internal/fips140only"
+ "errors"
"hash"
)
// 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)
}
package rand
import (
+ "crypto/internal/fips140only"
"crypto/internal/randutil"
"errors"
"io"
// 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")
}
import (
"crypto/internal/fips140/alias"
+ "crypto/internal/fips140only"
+ "errors"
"strconv"
)
// 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)
"crypto"
"crypto/internal/boring"
"crypto/internal/fips140/rsa"
+ "crypto/internal/fips140only"
"errors"
"hash"
"io"
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
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)
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)
}
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))
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()
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()
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)
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)
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
+}
import (
"crypto/internal/boring"
"crypto/internal/fips140/rsa"
+ "crypto/internal/fips140only"
"crypto/internal/randutil"
"crypto/subtle"
+ "errors"
"io"
)
// 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
}
// 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
import (
"crypto"
"crypto/internal/boring"
+ "crypto/internal/fips140only"
"errors"
"hash"
"internal/byteorder"
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.
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
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)
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,