The changes below src/crypto/internal/fips/ are mechanical.
See fipsdeps.go and fipsdeps_test.go for the rationale.
For #69536
Change-Id: I292ce65237cd8d2fd87fab99814514dd0e69c4a7
Reviewed-on: https://go-review.googlesource.com/c/go/+/627956
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Daniel McCarney <daniel@binaryparadox.net>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
package aes
import (
+ "crypto/internal/fipsdeps/cpu"
+ "crypto/internal/fipsdeps/godebug"
"crypto/internal/impl"
- "internal/cpu"
- "internal/goarch"
- "internal/godebug"
)
//go:noescape
//go:noescape
func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32)
-var supportsAES = cpu.X86.HasAES && cpu.X86.HasSSE41 && cpu.X86.HasSSSE3 ||
- cpu.ARM64.HasAES || goarch.IsPpc64 == 1 || goarch.IsPpc64le == 1
+var supportsAES = cpu.X86HasAES && cpu.X86HasSSE41 && cpu.X86HasSSSE3 ||
+ cpu.ARM64HasAES || cpu.PPC64 || cpu.PPC64le
func init() {
- if goarch.IsAmd64 == 1 {
+ if cpu.AMD64 {
impl.Register("aes", "AES-NI", &supportsAES)
}
- if goarch.IsArm64 == 1 {
+ if cpu.ARM64 {
impl.Register("aes", "Armv8.0", &supportsAES)
}
- if goarch.IsPpc64 == 1 || goarch.IsPpc64le == 1 {
+ if cpu.PPC64 || cpu.PPC64le {
// The POWER architecture doesn't have a way to turn off AES support
// at runtime with GODEBUG=cpu.something=off, so introduce a new GODEBUG
// knob for that. It's intentionally only checked at init() time, to
// avoid the performance overhead of checking it every time.
- if godebug.New("#ppc64aes").Value() == "off" {
+ if godebug.Value("#ppc64aes") == "off" {
supportsAES = false
}
impl.Register("aes", "POWER8", &supportsAES)
package aes
-import "internal/byteorder"
+import "crypto/internal/fipsdeps/byteorder"
// Encrypt one block from src into dst, using the expanded key xk.
func encryptBlockGeneric(c *blockExpanded, dst, src []byte) {
xk := c.enc[:]
_ = src[15] // early bounds check
- s0 := byteorder.BeUint32(src[0:4])
- s1 := byteorder.BeUint32(src[4:8])
- s2 := byteorder.BeUint32(src[8:12])
- s3 := byteorder.BeUint32(src[12:16])
+ s0 := byteorder.BEUint32(src[0:4])
+ s1 := byteorder.BEUint32(src[4:8])
+ s2 := byteorder.BEUint32(src[8:12])
+ s3 := byteorder.BEUint32(src[12:16])
// First round just XORs input with key.
s0 ^= xk[0]
s3 ^= xk[k+3]
_ = dst[15] // early bounds check
- byteorder.BePutUint32(dst[0:4], s0)
- byteorder.BePutUint32(dst[4:8], s1)
- byteorder.BePutUint32(dst[8:12], s2)
- byteorder.BePutUint32(dst[12:16], s3)
+ byteorder.BEPutUint32(dst[0:4], s0)
+ byteorder.BEPutUint32(dst[4:8], s1)
+ byteorder.BEPutUint32(dst[8:12], s2)
+ byteorder.BEPutUint32(dst[12:16], s3)
}
// Decrypt one block from src into dst, using the expanded key xk.
xk := c.dec[:]
_ = src[15] // early bounds check
- s0 := byteorder.BeUint32(src[0:4])
- s1 := byteorder.BeUint32(src[4:8])
- s2 := byteorder.BeUint32(src[8:12])
- s3 := byteorder.BeUint32(src[12:16])
+ s0 := byteorder.BEUint32(src[0:4])
+ s1 := byteorder.BEUint32(src[4:8])
+ s2 := byteorder.BEUint32(src[8:12])
+ s3 := byteorder.BEUint32(src[12:16])
// First round just XORs input with key.
s0 ^= xk[0]
s3 ^= xk[k+3]
_ = dst[15] // early bounds check
- byteorder.BePutUint32(dst[0:4], s0)
- byteorder.BePutUint32(dst[4:8], s1)
- byteorder.BePutUint32(dst[8:12], s2)
- byteorder.BePutUint32(dst[12:16], s3)
+ byteorder.BEPutUint32(dst[0:4], s0)
+ byteorder.BEPutUint32(dst[4:8], s1)
+ byteorder.BEPutUint32(dst[8:12], s2)
+ byteorder.BEPutUint32(dst[12:16], s3)
}
// Apply sbox0 to each byte in w.
var i int
nk := len(key) / 4
for i = 0; i < nk; i++ {
- c.enc[i] = byteorder.BeUint32(key[4*i:])
+ c.enc[i] = byteorder.BEUint32(key[4*i:])
}
for ; i < c.roundKeysSize(); i++ {
t := c.enc[i-1]
package aes
import (
+ "crypto/internal/fipsdeps/cpu"
"crypto/internal/impl"
- "internal/cpu"
)
type code int
//go:noescape
func cryptBlocks(c code, key, dst, src *byte, length int)
-var supportsAES = cpu.S390X.HasAES && cpu.S390X.HasAESCBC
+var supportsAES = cpu.S390XHasAES && cpu.S390XHasAESCBC
func init() {
// CP Assist for Cryptographic Functions (CPACF)
import (
"crypto/internal/fips/alias"
"crypto/internal/fips/subtle"
- "internal/byteorder"
+ "crypto/internal/fipsdeps/byteorder"
"math/bits"
)
return &CTR{
b: *b,
- ivlo: byteorder.BeUint64(iv[8:16]),
- ivhi: byteorder.BeUint64(iv[0:8]),
+ ivlo: byteorder.BEUint64(iv[8:16]),
+ ivhi: byteorder.BEUint64(iv[0:8]),
offset: 0,
}
}
func ctrBlocks(b *Block, dst, src []byte, ivlo, ivhi uint64) {
buf := make([]byte, len(src), 8*BlockSize)
for i := 0; i < len(buf); i += BlockSize {
- byteorder.BePutUint64(buf[i:], ivhi)
- byteorder.BePutUint64(buf[i+8:], ivlo)
+ byteorder.BEPutUint64(buf[i:], ivhi)
+ byteorder.BEPutUint64(buf[i+8:], ivlo)
ivlo, ivhi = add128(ivlo, ivhi, 1)
b.Encrypt(buf[i:], buf[i:])
}
import (
"crypto/internal/fips/subtle"
- "internal/byteorder"
+ "crypto/internal/fipsdeps/byteorder"
)
func ctrBlocks1(b *Block, dst, src *[BlockSize]byte, ivlo, ivhi uint64) {
buf := make([]byte, len(src), 8*BlockSize)
for i := 0; i < len(buf); i += BlockSize {
- byteorder.BePutUint64(buf[i:], ivhi)
- byteorder.BePutUint64(buf[i+8:], ivlo)
+ byteorder.BEPutUint64(buf[i:], ivhi)
+ byteorder.BEPutUint64(buf[i+8:], ivlo)
ivlo, ivhi = add128(ivlo, ivhi, 1)
}
import (
"crypto/internal/fips/aes"
"crypto/internal/fips/subtle"
+ "crypto/internal/fipsdeps/cpu"
"crypto/internal/impl"
- "internal/cpu"
- "internal/goarch"
)
// The following functions are defined in gcm_*.s.
func gcmAesFinish(productTable *[256]byte, tagMask, T *[16]byte, pLen, dLen uint64)
// Keep in sync with crypto/tls.hasAESGCMHardwareSupport.
-var supportsAESGCM = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ && cpu.X86.HasSSE41 && cpu.X86.HasSSSE3 ||
- cpu.ARM64.HasAES && cpu.ARM64.HasPMULL
+var supportsAESGCM = cpu.X86HasAES && cpu.X86HasPCLMULQDQ && cpu.X86HasSSE41 && cpu.X86HasSSSE3 ||
+ cpu.ARM64HasAES && cpu.ARM64HasPMULL
func init() {
- if goarch.IsAmd64 == 1 {
+ if cpu.AMD64 {
impl.Register("gcm", "AES-NI", &supportsAESGCM)
}
- if goarch.IsArm64 == 1 {
+ if cpu.ARM64 {
impl.Register("gcm", "Armv8.0", &supportsAESGCM)
}
}
import (
"crypto/internal/fips/aes"
"crypto/internal/fips/subtle"
- "internal/byteorder"
+ "crypto/internal/fipsdeps/byteorder"
)
func sealGeneric(out []byte, g *GCM, nonce, plaintext, additionalData []byte) {
counter[gcmBlockSize-1] = 1
} else {
lenBlock := make([]byte, 16)
- byteorder.BePutUint64(lenBlock[8:], uint64(len(nonce))*8)
+ byteorder.BEPutUint64(lenBlock[8:], uint64(len(nonce))*8)
ghash(counter, H, nonce, lenBlock)
}
}
// and increments it.
func gcmInc32(counterBlock *[gcmBlockSize]byte) {
ctr := counterBlock[len(counterBlock)-4:]
- byteorder.BePutUint32(ctr, byteorder.BeUint32(ctr)+1)
+ byteorder.BEPutUint32(ctr, byteorder.BEUint32(ctr)+1)
}
// gcmAuthGeneric calculates GHASH(additionalData, ciphertext), masks the result
func gcmAuthGeneric(out []byte, H, tagMask *[gcmBlockSize]byte, ciphertext, additionalData []byte) {
checkGenericIsExpected()
lenBlock := make([]byte, 16)
- byteorder.BePutUint64(lenBlock[:8], uint64(len(additionalData))*8)
- byteorder.BePutUint64(lenBlock[8:], uint64(len(ciphertext))*8)
+ byteorder.BEPutUint64(lenBlock[:8], uint64(len(additionalData))*8)
+ byteorder.BEPutUint64(lenBlock[8:], uint64(len(ciphertext))*8)
var S [gcmBlockSize]byte
ghash(&S, H, additionalData, ciphertext, lenBlock)
subtle.XORBytes(out, S[:], tagMask[:])
"crypto/internal/fips/aes"
"crypto/internal/fips/alias"
"crypto/internal/fips/drbg"
- "internal/byteorder"
+ "crypto/internal/fipsdeps/byteorder"
"math"
)
panic("crypto/cipher: incorrect nonce length given to GCM")
}
- counter := byteorder.BeUint64(nonce[len(nonce)-8:])
+ counter := byteorder.BEUint64(nonce[len(nonce)-8:])
if !g.ready {
// The first invocation sets the fixed name encoding and start counter.
g.ready = true
g.start = counter
- g.fixedName = byteorder.BeUint32(nonce[:4])
+ g.fixedName = byteorder.BEUint32(nonce[:4])
}
- if g.fixedName != byteorder.BeUint32(nonce[:4]) {
+ if g.fixedName != byteorder.BEUint32(nonce[:4]) {
panic("crypto/cipher: incorrect module name given to GCMWithCounterNonce")
}
counter -= g.start
panic("crypto/cipher: incorrect nonce length given to GCM")
}
- counter := byteorder.BeUint64(nonce[len(nonce)-8:])
+ counter := byteorder.BEUint64(nonce[len(nonce)-8:])
// Ensure the counter is monotonically increasing.
if counter == math.MaxUint64 {
panic("crypto/cipher: incorrect nonce length given to GCM")
}
- counter := byteorder.BeUint64(nonce[len(nonce)-8:])
+ counter := byteorder.BEUint64(nonce[len(nonce)-8:])
if !g.ready {
// In the first call, the counter is zero, so we learn the XOR mask.
g.ready = true
panic("crypto/cipher: incorrect nonce length given to GCM")
}
- counter := byteorder.BeUint64(nonce[len(nonce)-8:])
+ counter := byteorder.BEUint64(nonce[len(nonce)-8:])
if !g.ready {
// In the first call we learn the start value.
g.ready = true
import (
"crypto/internal/fips/aes"
"crypto/internal/fips/subtle"
+ "crypto/internal/fipsdeps/byteorder"
+ "crypto/internal/fipsdeps/godebug"
"crypto/internal/impl"
- "internal/byteorder"
- "internal/godebug"
"runtime"
)
// at runtime with GODEBUG=cpu.something=off, so introduce a new GODEBUG
// knob for that. It's intentionally only checked at init() time, to
// avoid the performance overhead of checking it every time.
-var supportsAESGCM = godebug.New("#ppc64gcm").Value() != "off"
+var supportsAESGCM = godebug.Value("#ppc64gcm") != "off"
func init() {
impl.Register("gcm", "POWER8", &supportsAESGCM)
// Load little endian, store big endian
var h1, h2 uint64
if runtime.GOARCH == "ppc64le" {
- h1 = byteorder.LeUint64(hle[:8])
- h2 = byteorder.LeUint64(hle[8:])
+ h1 = byteorder.LEUint64(hle[:8])
+ h2 = byteorder.LEUint64(hle[8:])
} else {
- h1 = byteorder.BeUint64(hle[:8])
- h2 = byteorder.BeUint64(hle[8:])
+ h1 = byteorder.BEUint64(hle[:8])
+ h2 = byteorder.BEUint64(hle[8:])
}
- byteorder.BePutUint64(hle[:8], h1)
- byteorder.BePutUint64(hle[8:], h2)
+ byteorder.BEPutUint64(hle[:8], h1)
+ byteorder.BEPutUint64(hle[8:], h2)
gcmInit(&g.productTable, hle)
}
import (
"crypto/internal/fips/aes"
"crypto/internal/fips/subtle"
+ "crypto/internal/fipsdeps/byteorder"
+ "crypto/internal/fipsdeps/cpu"
"crypto/internal/impl"
- "internal/byteorder"
- "internal/cpu"
)
// This file contains two implementations of AES-GCM. The first implementation
// KIMD to hash large nonces).
// Keep in sync with crypto/tls.hasAESGCMHardwareSupport.
-var useGHASH = cpu.S390X.HasAES && cpu.S390X.HasAESCTR && cpu.S390X.HasGHASH
-var useGCM = useGHASH && cpu.S390X.HasAESGCM
+var useGHASH = cpu.S390XHasAES && cpu.S390XHasAESCTR && cpu.S390XHasGHASH
+var useGCM = useGHASH && cpu.S390XHasAESGCM
func init() {
impl.Register("gcm", "CPACF/KIMD", &useGHASH)
// gcmLengths writes len0 || len1 as big-endian values to a 16-byte array.
func gcmLengths(len0, len1 uint64) [16]byte {
v := [16]byte{}
- byteorder.BePutUint64(v[0:], len0)
- byteorder.BePutUint64(v[8:], len1)
+ byteorder.BEPutUint64(v[0:], len0)
+ byteorder.BEPutUint64(v[8:], len1)
return v
}
import (
"crypto/internal/fips"
- "internal/byteorder"
+ "crypto/internal/fipsdeps/byteorder"
)
// gcmFieldElement represents a value in GF(2¹²⁸). In order to reflect the GCM
// would expect, say, 4*H to be in index 4 of the table but due to
// this bit ordering it will actually be in index 0010 (base 2) = 2.
x := gcmFieldElement{
- byteorder.BeUint64(H[:8]),
- byteorder.BeUint64(H[8:]),
+ byteorder.BEUint64(H[:8]),
+ byteorder.BEUint64(H[8:]),
}
productTable[reverseBits(1)] = x
ghashUpdate(&productTable, &y, input)
}
- byteorder.BePutUint64(out[:], y.low)
- byteorder.BePutUint64(out[8:], y.high)
+ byteorder.BEPutUint64(out[:], y.low)
+ byteorder.BEPutUint64(out[8:], y.high)
}
// reverseBits reverses the order of the bits of 4-bit number in i.
// Horner's rule. There must be a multiple of gcmBlockSize bytes in blocks.
func updateBlocks(productTable *[16]gcmFieldElement, y *gcmFieldElement, blocks []byte) {
for len(blocks) > 0 {
- y.low ^= byteorder.BeUint64(blocks)
- y.high ^= byteorder.BeUint64(blocks[8:])
+ y.low ^= byteorder.BEUint64(blocks)
+ y.high ^= byteorder.BEUint64(blocks[8:])
ghashMul(productTable, y)
blocks = blocks[gcmBlockSize:]
}
package fips
import (
+ "crypto/internal/fipsdeps/godebug"
"errors"
- "internal/godebug"
"strings"
_ "unsafe" // for go:linkname
)
// failfipscast is a GODEBUG key allowing simulation of a Cryptographic Algorithm
// Self-Test (CAST) failure, as required during FIPS 140-3 functional testing.
// The value is a substring of the target CAST name.
-var failfipscast = godebug.New("#failfipscast")
+var failfipscast = godebug.Value("#failfipscast")
// CAST runs the named Cryptographic Algorithm Self-Test or Pairwise Consistency
// Test (if operated in FIPS mode) and aborts the program (stopping the module
}
err := f()
- if failfipscast.Value() != "" && strings.Contains(name, failfipscast.Value()) {
+ if failfipscast != "" && strings.Contains(name, failfipscast) {
err = errors.New("simulated CAST/PCT failure")
}
if err != nil {
--- /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.
+
+//go:build asan
+
+package check
+
+const asanEnabled = true
import (
"crypto/internal/fips/hmac"
"crypto/internal/fips/sha256"
- "internal/asan"
- "internal/byteorder"
- "internal/godebug"
+ "crypto/internal/fipsdeps/byteorder"
+ "crypto/internal/fipsdeps/godebug"
"io"
"runtime"
"unsafe"
var zeroSum [32]byte
func init() {
- v := godebug.New("#fips140").Value()
+ v := godebug.Value("#fips140")
enabled = v != "" && v != "off"
if !enabled {
return
}
- if asan.Enabled {
+ if asanEnabled {
// ASAN disapproves of reading swaths of global memory below.
// One option would be to expose runtime.asanunpoison through
// crypto/internal/fipsdeps and then call it to unpoison the range
var nbuf [8]byte
for _, sect := range Linkinfo.Sects {
n := uintptr(sect.End) - uintptr(sect.Start)
- byteorder.BePutUint64(nbuf[:], uint64(n))
+ byteorder.BEPutUint64(nbuf[:], uint64(n))
w.Write(nbuf[:])
w.Write(unsafe.Slice((*byte)(sect.Start), n))
}
--- /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.
+
+//go:build !asan
+
+package check
+
+const asanEnabled = false
"crypto/internal/fips"
"crypto/internal/fips/aes"
"crypto/internal/fips/subtle"
- "internal/byteorder"
+ "crypto/internal/fipsdeps/byteorder"
"math/bits"
)
}
func increment(v *[aes.BlockSize]byte) {
- hi := byteorder.BeUint64(v[:8])
- lo := byteorder.BeUint64(v[8:])
+ hi := byteorder.BEUint64(v[:8])
+ lo := byteorder.BEUint64(v[8:])
lo, c := bits.Add64(lo, 1, 0)
hi, _ = bits.Add64(hi, 0, c)
- byteorder.BePutUint64(v[:8], hi)
- byteorder.BePutUint64(v[8:], lo)
+ byteorder.BEPutUint64(v[:8], hi)
+ byteorder.BEPutUint64(v[8:], lo)
}
func (c *Counter) Reseed(entropy, additionalInput *[SeedSize]byte) {
package fips
-import "internal/godebug"
+import "crypto/internal/fipsdeps/godebug"
var Enabled bool
var debug bool
func init() {
- switch godebug.New("#fips140").Value() {
+ switch godebug.Value("#fips140") {
case "on", "only":
Enabled = true
case "debug":
import (
"crypto/internal/fips/sha3"
+ "crypto/internal/fipsdeps/byteorder"
"errors"
- "internal/byteorder"
)
// fieldElement is an integer modulo q, an element of ℤ_q. It is always reduced.
B.Read(buf[:])
off = 0
}
- d1 := byteorder.LeUint16(buf[off:]) & 0b1111_1111_1111
- d2 := byteorder.LeUint16(buf[off+1:]) >> 4
+ d1 := byteorder.LEUint16(buf[off:]) & 0b1111_1111_1111
+ d2 := byteorder.LEUint16(buf[off+1:]) >> 4
off += 3
if d1 < q {
a[j] = fieldElement(d1)
import (
"crypto/internal/fips"
+ "crypto/internal/fipsdeps/byteorder"
"errors"
- "internal/byteorder"
)
// The size of a SHA-256 checksum in bytes.
} else {
b = append(b, magic256...)
}
- b = byteorder.BeAppendUint32(b, d.h[0])
- b = byteorder.BeAppendUint32(b, d.h[1])
- b = byteorder.BeAppendUint32(b, d.h[2])
- b = byteorder.BeAppendUint32(b, d.h[3])
- b = byteorder.BeAppendUint32(b, d.h[4])
- b = byteorder.BeAppendUint32(b, d.h[5])
- b = byteorder.BeAppendUint32(b, d.h[6])
- b = byteorder.BeAppendUint32(b, d.h[7])
+ b = byteorder.BEAppendUint32(b, d.h[0])
+ b = byteorder.BEAppendUint32(b, d.h[1])
+ b = byteorder.BEAppendUint32(b, d.h[2])
+ b = byteorder.BEAppendUint32(b, d.h[3])
+ b = byteorder.BEAppendUint32(b, d.h[4])
+ b = byteorder.BEAppendUint32(b, d.h[5])
+ b = byteorder.BEAppendUint32(b, d.h[6])
+ b = byteorder.BEAppendUint32(b, d.h[7])
b = append(b, d.x[:d.nx]...)
b = append(b, make([]byte, len(d.x)-d.nx)...)
- b = byteorder.BeAppendUint64(b, d.len)
+ b = byteorder.BEAppendUint64(b, d.len)
return b, nil
}
}
func consumeUint64(b []byte) ([]byte, uint64) {
- return b[8:], byteorder.BeUint64(b)
+ return b[8:], byteorder.BEUint64(b)
}
func consumeUint32(b []byte) ([]byte, uint32) {
- return b[4:], byteorder.BeUint32(b)
+ return b[4:], byteorder.BEUint32(b)
}
func (d *Digest) Reset() {
// Length in bits.
len <<= 3
padlen := tmp[:t+8]
- byteorder.BePutUint64(padlen[t+0:], len)
+ byteorder.BEPutUint64(padlen[t+0:], len)
d.Write(padlen)
if d.nx != 0 {
var digest [size]byte
- byteorder.BePutUint32(digest[0:], d.h[0])
- byteorder.BePutUint32(digest[4:], d.h[1])
- byteorder.BePutUint32(digest[8:], d.h[2])
- byteorder.BePutUint32(digest[12:], d.h[3])
- byteorder.BePutUint32(digest[16:], d.h[4])
- byteorder.BePutUint32(digest[20:], d.h[5])
- byteorder.BePutUint32(digest[24:], d.h[6])
+ byteorder.BEPutUint32(digest[0:], d.h[0])
+ byteorder.BEPutUint32(digest[4:], d.h[1])
+ byteorder.BEPutUint32(digest[8:], d.h[2])
+ byteorder.BEPutUint32(digest[12:], d.h[3])
+ byteorder.BEPutUint32(digest[16:], d.h[4])
+ byteorder.BEPutUint32(digest[20:], d.h[5])
+ byteorder.BEPutUint32(digest[24:], d.h[6])
if !d.is224 {
- byteorder.BePutUint32(digest[28:], d.h[7])
+ byteorder.BEPutUint32(digest[28:], d.h[7])
}
return digest
package sha256
import (
+ "crypto/internal/fipsdeps/cpu"
"crypto/internal/impl"
- "internal/cpu"
)
-var useAVX2 = cpu.X86.HasAVX && cpu.X86.HasAVX2 && cpu.X86.HasBMI2
-var useSHANI = cpu.X86.HasAVX && cpu.X86.HasSHA && cpu.X86.HasSSE41 && cpu.X86.HasSSSE3
+var useAVX2 = cpu.X86HasAVX && cpu.X86HasAVX2 && cpu.X86HasBMI2
+var useSHANI = cpu.X86HasAVX && cpu.X86HasSHA && cpu.X86HasSSE41 && cpu.X86HasSSSE3
func init() {
impl.Register("sha256", "AVX2", &useAVX2)
package sha256
import (
+ "crypto/internal/fipsdeps/cpu"
"crypto/internal/impl"
- "internal/cpu"
)
-var useSHA2 = cpu.ARM64.HasSHA2
+var useSHA2 = cpu.ARM64HasSHA2
func init() {
impl.Register("sha256", "Armv8.0", &useSHA2)
package sha256
import (
+ "crypto/internal/fipsdeps/godebug"
"crypto/internal/impl"
- "internal/godebug"
)
// The POWER architecture doesn't have a way to turn off SHA-2 support at
// runtime with GODEBUG=cpu.something=off, so introduce a new GODEBUG knob for
// that. It's intentionally only checked at init() time, to avoid the
// performance overhead of checking it on every block.
-var ppc64sha2 = godebug.New("#ppc64sha2").Value() != "off"
+var ppc64sha2 = godebug.Value("#ppc64sha2") != "off"
func init() {
impl.Register("sha256", "POWER8", &ppc64sha2)
package sha256
import (
+ "crypto/internal/fipsdeps/cpu"
"crypto/internal/impl"
- "internal/cpu"
)
-var useSHA256 = cpu.S390X.HasSHA256
+var useSHA256 = cpu.S390XHasSHA256
func init() {
// CP Assist for Cryptographic Functions (CPACF)
package sha3
import (
- "internal/byteorder"
- "internal/goarch"
+ "crypto/internal/fipsdeps/byteorder"
+ "crypto/internal/fipsdeps/cpu"
"math/bits"
"unsafe"
)
// keccakF1600Generic applies the Keccak permutation.
func keccakF1600Generic(da *[200]byte) {
var a *[25]uint64
- if goarch.BigEndian {
+ if cpu.BigEndian {
a = new([25]uint64)
for i := range a {
- a[i] = byteorder.LeUint64(da[i*8:])
+ a[i] = byteorder.LEUint64(da[i*8:])
}
defer func() {
for i := range a {
- byteorder.LePutUint64(da[i*8:], a[i])
+ byteorder.LEPutUint64(da[i*8:], a[i])
}
}()
} else {
import (
"crypto/internal/fips/subtle"
+ "crypto/internal/fipsdeps/cpu"
"crypto/internal/impl"
- "internal/cpu"
)
// This file contains code for using the 'compute intermediate
//
// [z/Architecture Principles of Operation, Fourteen Edition]: https://www.ibm.com/docs/en/module_1678991624569/pdf/SA22-7832-13.pdf
-var useSHA3 = cpu.S390X.HasSHA3
+var useSHA3 = cpu.S390XHasSHA3
func init() {
// CP Assist for Cryptographic Functions (CPACF)
import (
"bytes"
"crypto/internal/fips"
+ "crypto/internal/fipsdeps/byteorder"
"errors"
- "internal/byteorder"
"math/bits"
)
}
// Return n || x with n as a byte and x an n bytes in big-endian order.
b := make([]byte, 9)
- byteorder.BePutUint64(b[1:], x)
+ byteorder.BEPutUint64(b[1:], x)
b = b[9-n-1:]
b[0] = byte(n)
return b
import (
"crypto/internal/fips"
+ "crypto/internal/fipsdeps/byteorder"
"errors"
- "internal/byteorder"
)
const (
default:
panic("unknown size")
}
- b = byteorder.BeAppendUint64(b, d.h[0])
- b = byteorder.BeAppendUint64(b, d.h[1])
- b = byteorder.BeAppendUint64(b, d.h[2])
- b = byteorder.BeAppendUint64(b, d.h[3])
- b = byteorder.BeAppendUint64(b, d.h[4])
- b = byteorder.BeAppendUint64(b, d.h[5])
- b = byteorder.BeAppendUint64(b, d.h[6])
- b = byteorder.BeAppendUint64(b, d.h[7])
+ b = byteorder.BEAppendUint64(b, d.h[0])
+ b = byteorder.BEAppendUint64(b, d.h[1])
+ b = byteorder.BEAppendUint64(b, d.h[2])
+ b = byteorder.BEAppendUint64(b, d.h[3])
+ b = byteorder.BEAppendUint64(b, d.h[4])
+ b = byteorder.BEAppendUint64(b, d.h[5])
+ b = byteorder.BEAppendUint64(b, d.h[6])
+ b = byteorder.BEAppendUint64(b, d.h[7])
b = append(b, d.x[:d.nx]...)
b = append(b, make([]byte, len(d.x)-d.nx)...)
- b = byteorder.BeAppendUint64(b, d.len)
+ b = byteorder.BEAppendUint64(b, d.len)
return b, nil
}
}
func consumeUint64(b []byte) ([]byte, uint64) {
- return b[8:], byteorder.BeUint64(b)
+ return b[8:], byteorder.BEUint64(b)
}
// New returns a new Digest computing the SHA-512 hash.
padlen := tmp[:t+16]
// Upper 64 bits are always zero, because len variable has type uint64,
// and tmp is already zeroed at that index, so we can skip updating it.
- // byteorder.BePutUint64(padlen[t+0:], 0)
- byteorder.BePutUint64(padlen[t+8:], len)
+ // byteorder.BEPutUint64(padlen[t+0:], 0)
+ byteorder.BEPutUint64(padlen[t+8:], len)
d.Write(padlen)
if d.nx != 0 {
}
var digest [size512]byte
- byteorder.BePutUint64(digest[0:], d.h[0])
- byteorder.BePutUint64(digest[8:], d.h[1])
- byteorder.BePutUint64(digest[16:], d.h[2])
- byteorder.BePutUint64(digest[24:], d.h[3])
- byteorder.BePutUint64(digest[32:], d.h[4])
- byteorder.BePutUint64(digest[40:], d.h[5])
+ byteorder.BEPutUint64(digest[0:], d.h[0])
+ byteorder.BEPutUint64(digest[8:], d.h[1])
+ byteorder.BEPutUint64(digest[16:], d.h[2])
+ byteorder.BEPutUint64(digest[24:], d.h[3])
+ byteorder.BEPutUint64(digest[32:], d.h[4])
+ byteorder.BEPutUint64(digest[40:], d.h[5])
if d.size != size384 {
- byteorder.BePutUint64(digest[48:], d.h[6])
- byteorder.BePutUint64(digest[56:], d.h[7])
+ byteorder.BEPutUint64(digest[48:], d.h[6])
+ byteorder.BEPutUint64(digest[56:], d.h[7])
}
return digest
package sha512
import (
+ "crypto/internal/fipsdeps/cpu"
"crypto/internal/impl"
- "internal/cpu"
)
-var useAVX2 = cpu.X86.HasAVX && cpu.X86.HasAVX2 && cpu.X86.HasBMI2
+var useAVX2 = cpu.X86HasAVX && cpu.X86HasAVX2 && cpu.X86HasBMI2
func init() {
impl.Register("sha512", "AVX2", &useAVX2)
package sha512
import (
+ "crypto/internal/fipsdeps/cpu"
"crypto/internal/impl"
- "internal/cpu"
)
-var useSHA512 = cpu.ARM64.HasSHA512
+var useSHA512 = cpu.ARM64HasSHA512
func init() {
impl.Register("sha512", "Armv8.2", &useSHA512)
package sha512
import (
+ "crypto/internal/fipsdeps/godebug"
"crypto/internal/impl"
- "internal/godebug"
)
// The POWER architecture doesn't have a way to turn off SHA-512 support at
// runtime with GODEBUG=cpu.something=off, so introduce a new GODEBUG knob for
// that. It's intentionally only checked at init() time, to avoid the
// performance overhead of checking it on every block.
-var ppc64sha512 = godebug.New("#ppc64sha512").Value() != "off"
+var ppc64sha512 = godebug.Value("#ppc64sha512") != "off"
func init() {
impl.Register("sha512", "POWER8", &ppc64sha512)
package sha512
import (
+ "crypto/internal/fipsdeps/cpu"
"crypto/internal/impl"
- "internal/cpu"
)
-var useSHA512 = cpu.S390X.HasSHA512
+var useSHA512 = cpu.S390XHasSHA512
func init() {
// CP Assist for Cryptographic Functions (CPACF)
import (
"crypto/internal/fips"
"crypto/internal/fips/hkdf"
- "internal/byteorder"
+ "crypto/internal/fipsdeps/byteorder"
)
// We don't set the service indicator in this package but we delegate that to
panic("tls13: label or context too long")
}
hkdfLabel := make([]byte, 0, 2+1+len("tls13 ")+len(label)+1+len(context))
- hkdfLabel = byteorder.BeAppendUint16(hkdfLabel, uint16(length))
+ hkdfLabel = byteorder.BEAppendUint16(hkdfLabel, uint16(length))
hkdfLabel = append(hkdfLabel, byte(len("tls13 ")+len(label)))
hkdfLabel = append(hkdfLabel, "tls13 "...)
hkdfLabel = append(hkdfLabel, label...)
--- /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 byteorder
+
+import (
+ "internal/byteorder"
+)
+
+func LEUint16(b []byte) uint16 {
+ return byteorder.LeUint16(b)
+}
+
+func BEUint32(b []byte) uint32 {
+ return byteorder.BeUint32(b)
+}
+
+func BEUint64(b []byte) uint64 {
+ return byteorder.BeUint64(b)
+}
+
+func LEUint64(b []byte) uint64 {
+ return byteorder.LeUint64(b)
+}
+
+func BEPutUint16(b []byte, v uint16) {
+ byteorder.BePutUint16(b, v)
+}
+
+func BEPutUint32(b []byte, v uint32) {
+ byteorder.BePutUint32(b, v)
+}
+
+func BEPutUint64(b []byte, v uint64) {
+ byteorder.BePutUint64(b, v)
+}
+
+func LEPutUint64(b []byte, v uint64) {
+ byteorder.LePutUint64(b, v)
+}
+
+func BEAppendUint16(b []byte, v uint16) []byte {
+ return byteorder.BeAppendUint16(b, v)
+}
+
+func BEAppendUint32(b []byte, v uint32) []byte {
+ return byteorder.BeAppendUint32(b, v)
+}
+
+func BEAppendUint64(b []byte, v uint64) []byte {
+ return byteorder.BeAppendUint64(b, v)
+}
--- /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 cpu
+
+import (
+ "internal/cpu"
+ "internal/goarch"
+)
+
+const BigEndian = goarch.BigEndian
+const AMD64 = goarch.IsAmd64 == 1
+const ARM64 = goarch.IsArm64 == 1
+const PPC64 = goarch.IsPpc64 == 1
+const PPC64le = goarch.IsPpc64le == 1
+
+var ARM64HasAES = cpu.ARM64.HasAES
+var ARM64HasPMULL = cpu.ARM64.HasPMULL
+var ARM64HasSHA2 = cpu.ARM64.HasSHA2
+var ARM64HasSHA512 = cpu.ARM64.HasSHA512
+var S390XHasAES = cpu.S390X.HasAES
+var S390XHasAESCBC = cpu.S390X.HasAESCBC
+var S390XHasAESCTR = cpu.S390X.HasAESCTR
+var S390XHasAESGCM = cpu.S390X.HasAESGCM
+var S390XHasGHASH = cpu.S390X.HasGHASH
+var S390XHasSHA256 = cpu.S390X.HasSHA256
+var S390XHasSHA3 = cpu.S390X.HasSHA3
+var S390XHasSHA512 = cpu.S390X.HasSHA512
+var X86HasAES = cpu.X86.HasAES
+var X86HasAVX = cpu.X86.HasAVX
+var X86HasAVX2 = cpu.X86.HasAVX2
+var X86HasBMI2 = cpu.X86.HasBMI2
+var X86HasPCLMULQDQ = cpu.X86.HasPCLMULQDQ
+var X86HasSHA = cpu.X86.HasSHA
+var X86HasSSE41 = cpu.X86.HasSSE41
+var X86HasSSSE3 = cpu.X86.HasSSSE3
--- /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 fipsdeps contains wrapper packages for internal APIs that are exposed
+// to the FIPS module. Since modules are frozen upon validation and supported
+// for a number of future versions, APIs exposed by crypto/internal/fipsdeps/...
+// must not be changed until the modules that use them are no longer supported.
+package fipsdeps
--- /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 fipsdeps
+
+import (
+ "internal/testenv"
+ "strings"
+ "testing"
+)
+
+// AllowedInternalPackages are internal packages that can be imported from the
+// FIPS module. The API of these packages ends up locked for the lifetime of the
+// validated module, which can be years.
+//
+// DO NOT add new packages here just to make the tests pass.
+var AllowedInternalPackages = map[string]bool{
+ // entropy.Depleted is the external passive entropy source, and sysrand.Read
+ // is the actual (but uncredited!) random bytes source.
+ "crypto/internal/entropy": true,
+ "crypto/internal/sysrand": true,
+
+ // impl.Register is how the packages expose their alternative
+ // implementations to tests outside the module.
+ "crypto/internal/impl": true,
+}
+
+func TestImports(t *testing.T) {
+ cmd := testenv.Command(t, testenv.GoToolPath(t), "list", "-f", `{{$path := .ImportPath -}}
+{{range .Imports -}}
+{{$path}} {{.}}
+{{end -}}
+{{range .TestImports -}}
+{{$path}} {{.}}
+{{end -}}
+{{range .XTestImports -}}
+{{$path}} {{.}}
+{{end -}}`, "crypto/internal/fips/...")
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Fatalf("go list: %v\n%s", err, out)
+ }
+
+ // Ensure we don't import any unexpected internal package from the FIPS
+ // module, since we can't change the module source after it starts
+ // validation. This locks in the API of otherwise internal packages.
+ for _, line := range strings.Split(string(out), "\n") {
+ if line == "" {
+ continue
+ }
+ parts := strings.Fields(line)
+ if parts[1] == "crypto/internal/fips" ||
+ strings.HasPrefix(parts[1], "crypto/internal/fips/") ||
+ strings.HasPrefix(parts[1], "crypto/internal/fipsdeps/") {
+ continue
+ }
+ if AllowedInternalPackages[parts[1]] {
+ continue
+ }
+ if strings.Contains(parts[1], "internal") {
+ t.Errorf("unexpected import of internal package: %s -> %s", parts[0], parts[1])
+ }
+ }
+}
--- /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 godebug
+
+import (
+ "internal/godebug"
+)
+
+type Setting godebug.Setting
+
+func New(name string) *Setting {
+ return (*Setting)(godebug.New(name))
+}
+
+func (s *Setting) Value() string {
+ return (*godebug.Setting)(s).Value()
+}
+
+func Value(name string) string {
+ return godebug.New(name).Value()
+}
OS < crypto/internal/sysrand
< crypto/internal/entropy;
+ internal/byteorder < crypto/internal/fipsdeps/byteorder;
+ internal/cpu, internal/goarch < crypto/internal/fipsdeps/cpu;
+ internal/godebug < crypto/internal/fipsdeps/godebug;
+
# FIPS is the FIPS 140 module.
# It must not depend on external crypto packages.
- # Internal packages imported by FIPS might need to retain
- # backwards compatibility with older versions of the module.
- STR, crypto/internal/impl, crypto/internal/entropy
+ STR, crypto/internal/impl, crypto/internal/entropy,
+ crypto/internal/fipsdeps/byteorder,
+ crypto/internal/fipsdeps/cpu,
+ crypto/internal/fipsdeps/godebug
< crypto/internal/fips
< crypto/internal/fips/alias
< crypto/internal/fips/subtle