Skip to content

Commit

Permalink
crypto/sha256,crypto/sha512: move implementation to crypto/internal/fips
Browse files Browse the repository at this point in the history
For golang#69536

Change-Id: I1efa916e6e9fcddeffa52bc3d23286e6465dae54
  • Loading branch information
FiloSottile committed Sep 30, 2024
1 parent 53b8834 commit 2adc940
Show file tree
Hide file tree
Showing 44 changed files with 686 additions and 598 deletions.
17 changes: 6 additions & 11 deletions src/cmd/compile/internal/types2/stdlib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"os"
"path/filepath"
"runtime"
"slices"
"strings"
"sync"
"testing"
Expand Down Expand Up @@ -354,17 +355,6 @@ func TestStdKen(t *testing.T) {
// Package paths of excluded packages.
var excluded = map[string]bool{
"builtin": true,

// go.dev/issue/46027: some imports are missing for this submodule.
"crypto/aes/_asm/gcm": true,
"crypto/aes/_asm/standard": true,
"crypto/internal/bigmod/_asm": true,
"crypto/internal/edwards25519/field/_asm": true,
"crypto/internal/nistec/_asm": true,
"crypto/md5/_asm": true,
"crypto/sha1/_asm": true,
"crypto/sha256/_asm": true,
"crypto/sha512/_asm": true,
}

// printPackageMu synchronizes the printing of type-checked package files in
Expand Down Expand Up @@ -447,6 +437,11 @@ func pkgFilenames(dir string, includeTest bool) ([]string, error) {
if excluded[pkg.ImportPath] {
return nil, nil
}
if slices.Contains(strings.Split(pkg.ImportPath, "/"), "_asm") {
// Submodules where not all dependencies are available.
// See go.dev/issue/46027.
return nil, nil
}
var filenames []string
for _, name := range pkg.GoFiles {
filenames = append(filenames, filepath.Join(pkg.Dir, name))
Expand Down
File renamed without changes.
File renamed without changes.
229 changes: 229 additions & 0 deletions src/crypto/internal/fips/sha256/sha256.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
// Copyright 2009 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 sha256 implements the SHA-224 and SHA-256 hash algorithms as defined
// in FIPS 180-4.
package sha256

import (
"errors"
"internal/byteorder"
)

// The size of a SHA-256 checksum in bytes.
const size = 32

// The size of a SHA-224 checksum in bytes.
const size224 = 28

// The block size of SHA-256 and SHA-224 in bytes.
const blockSize = 64

const (
chunk = 64
init0 = 0x6A09E667
init1 = 0xBB67AE85
init2 = 0x3C6EF372
init3 = 0xA54FF53A
init4 = 0x510E527F
init5 = 0x9B05688C
init6 = 0x1F83D9AB
init7 = 0x5BE0CD19
init0_224 = 0xC1059ED8
init1_224 = 0x367CD507
init2_224 = 0x3070DD17
init3_224 = 0xF70E5939
init4_224 = 0xFFC00B31
init5_224 = 0x68581511
init6_224 = 0x64F98FA7
init7_224 = 0xBEFA4FA4
)

// Digest is a SHA-224 or SHA-256 [hash.Hash] implementation.
type Digest struct {
h [8]uint32
x [chunk]byte
nx int
len uint64
is224 bool // mark if this digest is SHA-224
}

const (
magic224 = "sha\x02"
magic256 = "sha\x03"
marshaledSize = len(magic256) + 8*4 + chunk + 8
)

func (d *Digest) MarshalBinary() ([]byte, error) {
return d.AppendBinary(make([]byte, 0, marshaledSize))
}

func (d *Digest) AppendBinary(b []byte) ([]byte, error) {
if d.is224 {
b = append(b, magic224...)
} 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 = append(b, d.x[:d.nx]...)
b = append(b, make([]byte, len(d.x)-d.nx)...)
b = byteorder.BeAppendUint64(b, d.len)
return b, nil
}

func (d *Digest) UnmarshalBinary(b []byte) error {
if len(b) < len(magic224) || (d.is224 && string(b[:len(magic224)]) != magic224) || (!d.is224 && string(b[:len(magic256)]) != magic256) {
return errors.New("crypto/sha256: invalid hash state identifier")
}
if len(b) != marshaledSize {
return errors.New("crypto/sha256: invalid hash state size")
}
b = b[len(magic224):]
b, d.h[0] = consumeUint32(b)
b, d.h[1] = consumeUint32(b)
b, d.h[2] = consumeUint32(b)
b, d.h[3] = consumeUint32(b)
b, d.h[4] = consumeUint32(b)
b, d.h[5] = consumeUint32(b)
b, d.h[6] = consumeUint32(b)
b, d.h[7] = consumeUint32(b)
b = b[copy(d.x[:], b):]
b, d.len = consumeUint64(b)
d.nx = int(d.len % chunk)
return nil
}

func consumeUint64(b []byte) ([]byte, uint64) {
return b[8:], byteorder.BeUint64(b)
}

func consumeUint32(b []byte) ([]byte, uint32) {
return b[4:], byteorder.BeUint32(b)
}

func (d *Digest) Reset() {
if !d.is224 {
d.h[0] = init0
d.h[1] = init1
d.h[2] = init2
d.h[3] = init3
d.h[4] = init4
d.h[5] = init5
d.h[6] = init6
d.h[7] = init7
} else {
d.h[0] = init0_224
d.h[1] = init1_224
d.h[2] = init2_224
d.h[3] = init3_224
d.h[4] = init4_224
d.h[5] = init5_224
d.h[6] = init6_224
d.h[7] = init7_224
}
d.nx = 0
d.len = 0
}

// New returns a new Digest computing the SHA-256 hash.
func New() *Digest {
d := new(Digest)
d.Reset()
return d
}

// New224 returns a new Digest computing the SHA-224 hash.
func New224() *Digest {
d := new(Digest)
d.is224 = true
d.Reset()
return d
}

func (d *Digest) Size() int {
if !d.is224 {
return size
}
return size224
}

func (d *Digest) BlockSize() int { return blockSize }

func (d *Digest) Write(p []byte) (nn int, err error) {
nn = len(p)
d.len += uint64(nn)
if d.nx > 0 {
n := copy(d.x[d.nx:], p)
d.nx += n
if d.nx == chunk {
block(d, d.x[:])
d.nx = 0
}
p = p[n:]
}
if len(p) >= chunk {
n := len(p) &^ (chunk - 1)
block(d, p[:n])
p = p[n:]
}
if len(p) > 0 {
d.nx = copy(d.x[:], p)
}
return
}

func (d *Digest) Sum(in []byte) []byte {
// Make a copy of d so that caller can keep writing and summing.
d0 := *d
hash := d0.checkSum()
if d0.is224 {
return append(in, hash[:size224]...)
}
return append(in, hash[:]...)
}

func (d *Digest) checkSum() [size]byte {
len := d.len
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
var tmp [64 + 8]byte // padding + length buffer
tmp[0] = 0x80
var t uint64
if len%64 < 56 {
t = 56 - len%64
} else {
t = 64 + 56 - len%64
}

// Length in bits.
len <<= 3
padlen := tmp[:t+8]
byteorder.BePutUint64(padlen[t+0:], len)
d.Write(padlen)

if d.nx != 0 {
panic("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])
if !d.is224 {
byteorder.BePutUint32(digest[28:], d.h[7])
}

return digest
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ var _K = []uint32{
0xc67178f2,
}

func blockGeneric(dig *digest, p []byte) {
func blockGeneric(dig *Digest, p []byte) {
var w [64]uint32
h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7]
for len(p) >= chunk {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ func init() {
}

//go:noescape
func blockAMD64(dig *digest, p []byte)
func blockAMD64(dig *Digest, p []byte)

//go:noescape
func blockAVX2(dig *digest, p []byte)
func blockAVX2(dig *Digest, p []byte)

//go:noescape
func blockSHANI(dig *digest, p []byte)
func blockSHANI(dig *Digest, p []byte)

func block(dig *digest, p []byte) {
func block(dig *Digest, p []byte) {
if useSHANI {
blockSHANI(dig, p)
} else if useAVX2 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include "textflag.h"

// func blockAMD64(dig *digest, p []byte)
// func blockAMD64(dig *Digest, p []byte)
TEXT ·blockAMD64(SB), $264-32
MOVQ p_base+8(FP), SI
MOVQ p_len+16(FP), DX
Expand Down Expand Up @@ -3490,7 +3490,7 @@ loop:
end:
RET

// func blockAVX2(dig *digest, p []byte)
// func blockAVX2(dig *Digest, p []byte)
// Requires: AVX, AVX2, BMI2
TEXT ·blockAVX2(SB), $536-32
MOVQ dig+0(FP), SI
Expand Down Expand Up @@ -4772,7 +4772,7 @@ DATA shuff_DC00<>+16(SB)/8, $0xffffffffffffffff
DATA shuff_DC00<>+24(SB)/8, $0x0b0a090803020100
GLOBL shuff_DC00<>(SB), RODATA, $32

// func blockSHANI(dig *digest, p []byte)
// func blockSHANI(dig *Digest, p []byte)
// Requires: AVX, SHA, SSE2, SSE4.1, SSSE3
TEXT ·blockSHANI(SB), $0-32
MOVQ dig+0(FP), DI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ func init() {
}

//go:noescape
func blockSHA2(dig *digest, p []byte)
func blockSHA2(dig *Digest, p []byte)

func block(dig *digest, p []byte) {
func block(dig *Digest, p []byte) {
if useSHA2 {
blockSHA2(dig, p)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
SHA256H2 V9.S4, V8, V3 \
VMOV V2.B16, V8.B16

// func blockSHA2(dig *digest, p []byte)
// func blockSHA2(dig *Digest, p []byte)
TEXT ·blockSHA2(SB),NOSPLIT,$0
MOVD dig+0(FP), R0 // Hash value first address
MOVD p_base+8(FP), R1 // message first address
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
package sha256

//go:noescape
func block(dig *digest, p []byte)
func block(dig *Digest, p []byte)
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@
// the frame size used for data expansion is 64 bytes.
// See the definition of the macro LOAD1 above (4 bytes * 16 entries).
//
//func block(dig *digest, p []byte)
//func block(dig *Digest, p []byte)
TEXT ·block(SB),NOSPLIT,$64-32
MOVV p_base+8(FP), R5
MOVV p_len+16(FP), R6
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@

package sha256

func block(dig *digest, p []byte) {
func block(dig *Digest, p []byte) {
blockGeneric(dig, p)
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ func init() {
}

//go:noescape
func blockPOWER(dig *digest, p []byte)
func blockPOWER(dig *Digest, p []byte)

func block(dig *digest, p []byte) {
func block(dig *Digest, p []byte) {
if ppc64sha2 {
blockPOWER(dig, p)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ GLOBL ·kcon(SB), RODATA, $1088
#define VPERMLE(va,vb,vc,vt)
#endif

// func blockPOWER(dig *digest, p []byte)
// func blockPOWER(dig *Digest, p []byte)
TEXT ·blockPOWER(SB),0,$0-32
MOVD dig+0(FP), CTX
MOVD p_base+8(FP), INP
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@
// Note that 64 bytes of stack space is used as a circular buffer
// for the message schedule (4 bytes * 16 entries).
//
// func block(dig *digest, p []byte)
// func block(dig *Digest, p []byte)
TEXT ·block(SB),0,$64-32
MOV p_base+8(FP), X29
MOV p_len+16(FP), X30
Expand Down
Loading

0 comments on commit 2adc940

Please sign in to comment.