crypto/internal/fips: wrap and lock internal dependencies

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>
This commit is contained in:
Filippo Valsorda 2024-11-14 14:47:55 +01:00 committed by Gopher Robot
parent 349d7d92bb
commit a794fa5f69
38 changed files with 376 additions and 169 deletions

View File

@ -7,10 +7,9 @@
package aes
import (
"crypto/internal/fipsdeps/cpu"
"crypto/internal/fipsdeps/godebug"
"crypto/internal/impl"
"internal/cpu"
"internal/goarch"
"internal/godebug"
)
//go:noescape
@ -22,22 +21,22 @@ func decryptBlockAsm(nr int, xk *uint32, dst, src *byte)
//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)

View File

@ -36,7 +36,7 @@
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) {
@ -44,10 +44,10 @@ 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]
@ -79,10 +79,10 @@ func encryptBlockGeneric(c *blockExpanded, dst, src []byte) {
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.
@ -91,10 +91,10 @@ func decryptBlockGeneric(c *blockExpanded, dst, src []byte) {
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]
@ -126,10 +126,10 @@ func decryptBlockGeneric(c *blockExpanded, dst, src []byte) {
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.
@ -152,7 +152,7 @@ func expandKeyGeneric(c *blockExpanded, key []byte) {
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]

View File

@ -7,8 +7,8 @@
package aes
import (
"crypto/internal/fipsdeps/cpu"
"crypto/internal/impl"
"internal/cpu"
)
type code int
@ -35,7 +35,7 @@ type block struct {
//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)

View File

@ -7,7 +7,7 @@ package aes
import (
"crypto/internal/fips/alias"
"crypto/internal/fips/subtle"
"internal/byteorder"
"crypto/internal/fipsdeps/byteorder"
"math/bits"
)
@ -24,8 +24,8 @@ func NewCTR(b *Block, iv []byte) *CTR {
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,
}
}
@ -122,8 +122,8 @@ func (c *CTR) XORKeyStreamAt(dst, src []byte, offset uint64) {
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:])
}

View File

@ -8,7 +8,7 @@ package aes
import (
"crypto/internal/fips/subtle"
"internal/byteorder"
"crypto/internal/fipsdeps/byteorder"
)
func ctrBlocks1(b *Block, dst, src *[BlockSize]byte, ivlo, ivhi uint64) {
@ -34,8 +34,8 @@ func ctrBlocksS390x(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)
}

View File

@ -9,9 +9,8 @@ package gcm
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.
@ -32,14 +31,14 @@ func gcmAesDec(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []
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)
}
}

View File

@ -7,7 +7,7 @@ package gcm
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) {
@ -58,7 +58,7 @@ func deriveCounterGeneric(H, counter *[gcmBlockSize]byte, nonce []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)
}
}
@ -89,7 +89,7 @@ func gcmCounterCryptGeneric(b *aes.Block, out, src []byte, counter *[gcmBlockSiz
// 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
@ -97,8 +97,8 @@ func gcmInc32(counterBlock *[gcmBlockSize]byte) {
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[:])

View File

@ -9,7 +9,7 @@ import (
"crypto/internal/fips/aes"
"crypto/internal/fips/alias"
"crypto/internal/fips/drbg"
"internal/byteorder"
"crypto/internal/fipsdeps/byteorder"
"math"
)
@ -73,14 +73,14 @@ func (g *GCMWithCounterNonce) Seal(dst, nonce, plaintext, data []byte) []byte {
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
@ -130,7 +130,7 @@ func (g *GCMForTLS12) Seal(dst, nonce, plaintext, data []byte) []byte {
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 {
@ -176,7 +176,7 @@ func (g *GCMForTLS13) Seal(dst, nonce, plaintext, data []byte) []byte {
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
@ -230,7 +230,7 @@ func (g *GCMForSSH) Seal(dst, nonce, plaintext, data []byte) []byte {
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

View File

@ -9,9 +9,9 @@ package gcm
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"
)
@ -29,7 +29,7 @@ func counterCryptASM(nr int, out, in []byte, counter *[gcmBlockSize]byte, key *u
// 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)
@ -57,14 +57,14 @@ func initGCM(g *GCM) {
// 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)
}

View File

@ -9,9 +9,9 @@ package gcm
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
@ -21,8 +21,8 @@ import (
// 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)
@ -38,8 +38,8 @@ func checkGenericIsExpected() {
// 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
}

View File

@ -6,7 +6,7 @@ package gcm
import (
"crypto/internal/fips"
"internal/byteorder"
"crypto/internal/fipsdeps/byteorder"
)
// gcmFieldElement represents a value in GF(2¹²⁸). In order to reflect the GCM
@ -46,8 +46,8 @@ func ghash(out, H *[gcmBlockSize]byte, inputs ...[]byte) {
// 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
@ -61,8 +61,8 @@ func ghash(out, H *[gcmBlockSize]byte, inputs ...[]byte) {
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.
@ -142,8 +142,8 @@ func ghashMul(productTable *[16]gcmFieldElement, y *gcmFieldElement) {
// 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:]
}

View File

@ -5,8 +5,8 @@
package fips
import (
"crypto/internal/fipsdeps/godebug"
"errors"
"internal/godebug"
"strings"
_ "unsafe" // for go:linkname
)
@ -19,7 +19,7 @@ func fatal(string)
// 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
@ -45,7 +45,7 @@ func CAST(name string, f func() error) {
}
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 {

View File

@ -0,0 +1,9 @@
// 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

View File

@ -15,9 +15,8 @@ package check
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"
@ -72,13 +71,13 @@ const fipsMagic = " Go fipsinfo \xff\x00"
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
@ -122,7 +121,7 @@ func init() {
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))
}

View File

@ -0,0 +1,9 @@
// 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

View File

@ -8,7 +8,7 @@ import (
"crypto/internal/fips"
"crypto/internal/fips/aes"
"crypto/internal/fips/subtle"
"internal/byteorder"
"crypto/internal/fipsdeps/byteorder"
"math/bits"
)
@ -77,12 +77,12 @@ func (c *Counter) update(seed *[SeedSize]byte) {
}
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) {

View File

@ -4,14 +4,14 @@
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":

View File

@ -6,8 +6,8 @@ package mlkem
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.
@ -528,8 +528,8 @@ func sampleNTT(rho []byte, ii, jj byte) nttElement {
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)

View File

@ -8,8 +8,8 @@ package sha256
import (
"crypto/internal/fips"
"crypto/internal/fipsdeps/byteorder"
"errors"
"internal/byteorder"
)
// The size of a SHA-256 checksum in bytes.
@ -66,17 +66,17 @@ func (d *Digest) AppendBinary(b []byte) ([]byte, error) {
} 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
}
@ -103,11 +103,11 @@ func (d *Digest) UnmarshalBinary(b []byte) error {
}
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() {
@ -207,7 +207,7 @@ func (d *Digest) checkSum() [size]byte {
// 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 {
@ -216,15 +216,15 @@ func (d *Digest) checkSum() [size]byte {
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

View File

@ -7,12 +7,12 @@
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)

View File

@ -7,11 +7,11 @@
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)

View File

@ -7,15 +7,15 @@
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)

View File

@ -7,11 +7,11 @@
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)

View File

@ -5,8 +5,8 @@
package sha3
import (
"internal/byteorder"
"internal/goarch"
"crypto/internal/fipsdeps/byteorder"
"crypto/internal/fipsdeps/cpu"
"math/bits"
"unsafe"
)
@ -42,14 +42,14 @@ var rc = [24]uint64{
// 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 {

View File

@ -8,8 +8,8 @@ package sha3
import (
"crypto/internal/fips/subtle"
"crypto/internal/fipsdeps/cpu"
"crypto/internal/impl"
"internal/cpu"
)
// This file contains code for using the 'compute intermediate
@ -19,7 +19,7 @@ import (
//
// [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)

View File

@ -7,8 +7,8 @@ package sha3
import (
"bytes"
"crypto/internal/fips"
"crypto/internal/fipsdeps/byteorder"
"errors"
"internal/byteorder"
"math/bits"
)
@ -41,7 +41,7 @@ func leftEncode(x uint64) []byte {
}
// 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

View File

@ -8,8 +8,8 @@ package sha512
import (
"crypto/internal/fips"
"crypto/internal/fipsdeps/byteorder"
"errors"
"internal/byteorder"
)
const (
@ -146,17 +146,17 @@ func (d *Digest) AppendBinary(b []byte) ([]byte, error) {
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
}
@ -191,7 +191,7 @@ func (d *Digest) UnmarshalBinary(b []byte) error {
}
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.
@ -277,8 +277,8 @@ func (d *Digest) checkSum() [size512]byte {
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 {
@ -286,15 +286,15 @@ func (d *Digest) checkSum() [size512]byte {
}
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

View File

@ -7,11 +7,11 @@
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)

View File

@ -7,11 +7,11 @@
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)

View File

@ -7,15 +7,15 @@
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)

View File

@ -7,11 +7,11 @@
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)

View File

@ -9,7 +9,7 @@ package tls13
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
@ -30,7 +30,7 @@ func ExpandLabel[H fips.Hash](hash func() H, secret []byte, label string, contex
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...)

View File

@ -0,0 +1,53 @@
// 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)
}

View File

@ -0,0 +1,37 @@
// 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

View File

@ -0,0 +1,9 @@
// 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

View File

@ -0,0 +1,65 @@
// 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])
}
}
}

View File

@ -0,0 +1,23 @@
// 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()
}

View File

@ -445,11 +445,16 @@ var depsRules = `
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