all: REVERSE MERGE dev.boringcrypto (cdcb4b6) into master

This commit is a REVERSE MERGE.
It merges dev.boringcrypto back into its parent branch, master.
This marks the end of development on dev.boringcrypto.

Manual Changes:
- git rm README.boringcrypto.md
- git rm -r misc/boring
- git rm src/cmd/internal/notsha256/sha256block_arm64.s
- git cherry-pick -n 5856aa74  # remove GOEXPERIMENT=boringcrypto forcing in cmd/dist

There are some minor cleanups like merging import statements
that I will apply in a follow-up CL.

Merge List:

+ 2022-04-29 cdcb4b6ef3 [dev.boringcrypto] cmd/compile: remove the awful boringcrypto kludge
+ 2022-04-29 e845f572ec [dev.boringcrypto] crypto/ecdsa, crypto/rsa: use boring.Cache
+ 2022-04-29 a840bf871e [dev.boringcrypto] crypto/internal/boring: add GC-aware cache
+ 2022-04-29 0184fe5ece [dev.boringcrypto] crypto/x509: remove VerifyOptions.IsBoring
+ 2022-04-29 9e9c7a0aec [dev.boringcrypto] crypto/..., go/build: align deps test with standard rules
+ 2022-04-29 0ec08283c8 [dev.boringcrypto] crypto/internal/boring: make SHA calls allocation-free
+ 2022-04-29 3cb10d14b7 [dev.boringcrypto] crypto/internal/boring: avoid allocation in big.Int conversion
+ 2022-04-29 509776be5d [dev.boringcrypto] cmd/dist: default to use of boringcrypto
+ 2022-04-29 f4c0f42f99 [dev.boringcrypto] all: add boringcrypto build tags
+ 2022-04-29 1f0547c4ec [dev.boringcrypto] cmd/go: pass dependency syso to cgo too
+ 2022-04-29 e5407501cb [dev.boringcrypto] cmd: use notsha256 instead of md5, sha1, sha256
+ 2022-04-29 fe006d6410 [dev.boringcrypto] cmd/internal/notsha256: add new package
+ 2022-04-27 ec7f5165dd [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2022-04-22 ca6fd39cf6 [dev.boringcrypto] misc/boring: skip long tests during build.release
+ 2022-04-21 19e4b10f2f [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2022-04-20 e07d63964b [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2022-04-13 1f11660f54 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2022-04-13 bc3e5d0ab7 [dev.boringcrypto] misc/boring: remove -trust and individual reviewers
+ 2022-04-05 4739b353bb [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2022-03-30 9d6ab825f6 [dev.boringcrypto] make.bash: disable GOEXPERIMENT when using bootstrap toolchain
+ 2022-03-30 d1405d7410 [dev.boringcrypto] crypto/internal/boring: update build instructions to use podman
+ 2022-03-29 50b8f490e1 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2022-03-15 0af0e19368 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2022-03-07 f492793839 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2022-03-07 768804dfdd [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2022-02-11 8521d1ea34 [dev.boringcrypto] misc/boring: use go install cmd@latest for installing command
+ 2022-02-11 b75258fdd8 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2022-02-08 74d25c624c [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2022-02-03 e14fee553a [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2022-01-14 d382493a20 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-12-09 069bbf5434 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-12-06 21fa0b2199 [dev.boringcrypto] crypto/internal/boring: add -pthread linker flag
+ 2021-12-03 a38b43e4ab [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-11-09 16215e5340 [dev.boringcrypto] cmd/compile: disable version test on boringcrypto
+ 2021-11-08 c9858c7bdc [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2021-11-05 ed07c49cb6 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2021-11-05 dc2658558d [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-10-28 69d5e469a4 [dev.boringcrypto] all: convert +build to //go:build lines in boring-specific files
+ 2021-10-08 2840ccbc05 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-10-08 114aa69932 [dev.boringcrypto] misc/boring: fix Docker Hub references
+ 2021-10-08 7d26add6d5 [dev.boringcrypto] misc/boring: publish to Artifact Registry
+ 2021-08-27 5ae200d526 [dev.boringcrypto] crypto/tls: permit P-521 in FIPS mode
+ 2021-08-26 083811d079 [dev.boringcrypto] crypto/tls: use correct config in TestBoringClientHello
+ 2021-08-16 c7e7ce5ec1 [dev.boringcrypto] all: merge commit 57c115e1 into dev.boringcrypto
+ 2021-08-10 1fb58d6cad [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-07-14 934db9f0d6 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-06-08 a890a4de30 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-05-13 ed1f812cef [dev.boringcrypto] all: merge commit 9d0819b27c (CL 314609) into dev.boringcrypto
+ 2021-05-10 ad1b6f3ee0 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-04-21 11061407d6 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-03-23 b397e0c028 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-03-15 128cecc70b [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-03-10 5e2f5a38c4 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-02-26 42089e72fd [dev.boringcrypto] api: add crypto/boring.Enabled
+ 2021-02-24 03cd666173 [dev.boringcrypto] all: merge master (5b76343) into dev.boringcrypto
+ 2021-02-17 0f210b75f9 [dev.boringcrypto] all: merge master (2f0da6d) into dev.boringcrypto
+ 2021-02-12 1aea1b199f [dev.boringcrypto] misc/boring: support codereview.cfg in merge.sh
+ 2021-02-07 0d34d85dee [dev.boringcrypto] crypto/internal/boring: remove .llvm_addrsig section
+ 2021-02-07 325e03a64f [dev.boringcrypto] all: add codereview.cfg
+ 2021-02-05 d4f73546c8 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-01-20 cf8ed7cca4 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2021-01-20 f22137d785 [dev.boringcrypto] misc/boring: add -trust and roland@ to merge.sh and release.sh
+ 2020-12-12 e5c7bd0efa [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2020-12-02 5934c434c1 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2020-12-01 dea96ada17 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2020-11-18 906d6e362b [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2020-11-18 95ceba18d3 [dev.boringcrypto] crypto/hmac: merge up to 2a206c7 and skip test
+ 2020-11-17 0985c1bd2d [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2020-11-16 af814af6e7 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2020-11-05 f42bd50779 [dev.boringcrypto] crypto/internal/boring: update BoringCrypto module to certificate 3678
+ 2020-10-19 ceda58bfd0 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2020-09-29 af85c47233 [dev.boringcrypto] misc/boring: bump version to b6
+ 2020-09-29 f9b86a6562 [dev.boringcrypto] go/build: satisfy the boringcrypto build tag
+ 2020-09-29 ef2b318974 [dev.boringcrypto] crypto/boring: expose boring.Enabled()
+ 2020-09-14 3782421230 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2020-08-18 6bbe47ccb6 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2020-07-21 6e6e0b73d6 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2020-07-09 d85ef2b979 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2020-07-09 a91ad4250c [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2020-06-10 5beb39baf8 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2020-05-07 dd98c0ca3f [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2020-05-07 a9d2e3abf7 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2020-05-07 c19c0a047b [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2020-05-07 36c94f8421 [dev.boringcrypto] crypto/internal/boring: reject short signatures in VerifyRSAPKCS1v15
+ 2020-05-07 ee159d2f35 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2020-04-08 e067ce5225 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2020-03-03 79284c2873 [dev.boringcrypto] crypto/internal/boring: make accesses to RSA types with finalizers safer
+ 2020-03-02 6c64b188a5 [dev.boringcrypto] crypto/internal/boring: update BoringCrypto module to certificate 3318
+ 2020-02-28 13355c78ff [dev.boringcrypto] misc/boring: add go1.14b4 to RELEASES file
+ 2020-02-28 4980c6b317 [dev.boringcrypto] misc/boring: x/build/cmd/release doesn't take subrepo flags anymore
+ 2020-02-28 601da81916 [dev.boringcrypto] misc/boring: make merge.sh and release.sh a little more robust
+ 2020-02-14 09bc5e8723 [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2020-02-06 f96dfe6b73 [dev.boringcrypto] misc/boring: add go1.13.7b4 and go1.12.16b4 releases to RELEASES file
+ 2020-02-05 2f9b2e75c4 [dev.boringcrypto] misc/docker: update Dockerfile to match recent Buster based golang images
+ 2020-02-05 527880d05c [dev.boringcrypto] misc/boring: update default CL reviewer to katie@golang.org
+ 2019-11-25 50ada481fb [dev.boringcrypto] misc/boring: add new releases to RELEASES file
+ 2019-11-20 6657395adf [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2019-11-20 ab0a649d44 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2019-11-19 62ce702c77 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2019-10-25 e8f14494a0 [dev.boringcrypto] misc/boring: add go1.13.3b4 and go1.12.12b4 to RELEASES file
+ 2019-10-17 988e4d832e [dev.boringcrypto] misc/boring: add go1.13.2b4 and go1.12.11b4 to RELEASES file
+ 2019-10-11 974fd1301a [dev.boringcrypto] misc/boring: publish to Docker Hub all releases, not only the latest
+ 2019-09-27 62ce8cd3ad [dev.boringcrypto] misc/boring: add go1.13.1b4 and go1.12.10b4 to RELEASES file
+ 2019-09-10 489d268683 [dev.boringcrypto] misc/boring: add Go+BoringCrypto 1.13b4 to RELEASES file
+ 2019-09-04 e0ee09095c [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2019-09-03 ff197f326f [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2019-08-21 5a1705286e [dev.boringcrypto] misc/boring: add go1.12.9b4 to RELEASES
+ 2019-08-15 1ebc594b3c [dev.boringcrypto] misc/boring: add go1.12.8b4 and go1.11.13b4 to RELEASES
+ 2019-08-13 9417029290 [dev.boringcrypto] misc/boring: remove download of releaselet.go in build.release
+ 2019-08-05 2691091a4a misc/boring: add Go 1.11.12b4 and 1.12.7b4 to RELEASES
+ 2019-07-19 6eccf6a6cd [dev.boringcrypto] misc/boring: add scripts to automate merges and releases
+ 2019-06-27 98188f3001 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2019-06-13 5c354e66d1 [dev.boringcrypto] misc/boring: add go1.12.6b4 and go1.11.11b4 releases
+ 2019-06-09 9bf9e7d4b2 [dev.boringcrypto] crypto: move crypto/internal/boring imports to reduce merge conflicts
+ 2019-06-05 324f8365be [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2019-05-28 e48f228c9b [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2019-05-14 42e353245c [dev.boringcrypto] misc/boring: add go1.12.5b4 release
+ 2019-03-29 211a13fd44 [dev.boringcrypto] misc/boring: add go1.11.6b4 to RELEASES
+ 2019-03-28 347af7f060 [dev.boringcrypto] misc/boring: add go1.12.1b4 and update build scripts
+ 2019-02-27 a10558f870 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2019-02-08 4ed8ad4d69 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2019-01-24 14c64dbc4a [dev.boringcrypto] misc/boring: add go1.10.8b4 and go1.11.5b4
+ 2018-12-15 3f9e53f346 [dev.boringcrypto] misc/boring: add go1.10.7b4 and go1.11.4b4 releases
+ 2018-12-14 92d975e906 [dev.boringcrypto] misc/boring: add go1.11.2b4 release
+ 2018-11-14 c524da4917 [dev.boringcrypto] crypto/tls: test for TLS 1.3 to be disabled in FIPS mode
+ 2018-11-14 bfd6d30118 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-11-14 0007017f96 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-11-14 3169778c15 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-11-14 ab37582eb0 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-11-14 e8b3500d5c [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-11-14 de153ac2a1 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-11-14 0cbb11c720 [dev.boringcrypto] cmd/compile: by default accept any language
+ 2018-11-13 11e916773e [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-11-13 af07f7734b [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-10-25 13bf5b80e8 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-10-15 623650b27a [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-10-01 36c789b1fd [dev.boringcrypto] misc/boring: add go1.10.4b4 and go1.11b4 releases
+ 2018-09-07 693875e3f2 [dev.boringcrypto] crypto/internal/boring: avoid an allocation in AES-GCM Seal and Open
+ 2018-09-06 4d1aa482b8 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-08-04 7eb1677c01 [dev.boringcrypto] crypto/internal/boring: fix aesCipher implementation of gcmAble
+ 2018-07-11 eaa3e94eb8 [dev.boringcrypto] misc/boring: add go1.9.7b4 and go1.10.3b4 releases
+ 2018-07-11 5f0402a26b [dev.boringcrypto] misc/boring: support build.release on macOS
+ 2018-07-03 77db076129 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-06-13 b77f5e4c85 [dev.boringcrypto] crypto/rsa: drop random source reading emulation
+ 2018-06-08 a4b7722ffa [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-05-29 18db93d7e6 [dev.boringcrypto] crypto/tls: restore AES-GCM priority when BoringCrypto is enabled
+ 2018-05-25 3d9a6ac709 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-05-18 019a994e32 [dev.boringcrypto] crypto/rsa: fix boringFakeRandomBlind to work with (*big.Int).ModInverse
+ 2018-05-17 a3f9ce3313 [dev.boringcrypto] all: merge master into dev.boringcrypto
+ 2018-02-09 528dad8c72 [dev.cryptoboring] misc/boring: update README for Bazel
+ 2018-02-06 c3d83ee31c [dev.boringcrypto] misc/boring: add go1.9.3b4 to RELEASES
+ 2017-12-13 f62a24349d [dev.boringcrypto] all: merge go1.10beta1 into dev.boringcrypto
+ 2017-12-06 3e52f22ece [dev.boringcrypto] crypto/internal/boring: add MarshalBinary/UnmarshalBinary to hashes
+ 2017-12-06 5379f7847f [dev.boringcrypto] all: merge master (more nearly Go 1.10 beta 1) into dev.boringcrypto
+ 2017-12-06 185e6094fd [dev.boringcrypto] all: merge master (nearly Go 1.10 beta 1) into dev.boringcrypto
+ 2017-11-20 c36033a379 [dev.boringcrypto] misc/boring: add go1.9.2b4 release
+ 2017-11-20 cda3c6f91d [dev.boringcrypto] all: merge go1.9.2 into dev.boringcrypto
+ 2017-10-25 2ea7d3461b [release-branch.go1.9] go1.9.2
+ 2017-10-25 d93cb46280 [release-branch.go1.9] runtime: use simple, more robust fastrandn
+ 2017-10-25 78952c06c5 [release-branch.go1.9] cmd/compile: fix sign-extension merging rules
+ 2017-10-25 79996e4a1d [release-branch.go1.9] cmd/compile: avoid generating large offsets
+ 2017-10-25 f36b12657c [release-branch.go1.9] runtime: in cpuProfile.addExtra, set p.lostExtra to 0 after flush
+ 2017-10-25 dffc9319f1 [release-branch.go1.9] cmd/cgo: support large unsigned macro again
+ 2017-10-25 33ce1682c7 [release-branch.go1.9] cmd/cgo: avoid using common names for sniffing
+ 2017-10-25 f69668e1d0 [release-branch.go1.9] os: skip TestPipeThreads as flaky for 1.9
+ 2017-10-25 9be38a15e4 [release-branch.go1.9] runtime: avoid monotonic time zero on systems with low-res timers
+ 2017-10-25 8bb333a9c0 [release-branch.go1.9] doc: document Go 1.9.2
+ 2017-10-25 0758d2b9da [release-branch.go1.9] cmd/go: clean up x.exe properly in TestImportMain
+ 2017-10-25 d487b15a61 [release-branch.go1.9] cmd/compile: omit ICE diagnostics after normal error messages
+ 2017-10-25 fd17253587 [release-branch.go1.9] database/sql: prevent race in driver by locking dc in Next
+ 2017-10-25 7e7cb30475 [release-branch.go1.9] internal/poll: only call SetFileCompletionNotificationModes for sockets
+ 2017-10-25 f259aed082 [release-branch.go1.9] internal/poll: do not call SetFileCompletionNotificationModes if it is broken
+ 2017-10-25 39d4bb9c0f [release-branch.go1.9] cmd/go: correct directory used in checkNestedVCS test
+ 2017-10-25 bfc22319aa [release-branch.go1.9] crypto/x509: reject intermediates with unknown critical extensions.
+ 2017-10-25 a1e34abfb3 [release-branch.go1.9] net/smtp: NewClient: set tls field to true when already using a TLS connection
+ 2017-10-25 7dadd8d517 [release-branch.go1.9] net: increase expected time to dial a closed port on all Darwin ports
+ 2017-10-25 d80889341c [release-branch.go1.9] cmd/compile: fix merge rules for panic calls
+ 2017-10-25 87b3a27839 [release-branch.go1.9] net: bump TestDialerDualStackFDLeak timeout on iOS
+ 2017-10-25 ebfcdef901 [release-branch.go1.9] runtime: make runtime.GC() trigger GC even if GOGC=off
+ 2017-10-25 0ab99b396d [release-branch.go1.9] cmd/compile: fix regression in PPC64.rules move zero
+ 2017-10-25 8d4279c111 [release-branch.go1.9] internal/poll: be explicit when using runtime netpoller
+ 2017-10-25 1ded8334f7 [release-branch.go1.9] cmd/compile/internal/syntax: fix source buffer refilling
+ 2017-10-25 ff8289f879 [release-branch.go1.9] reflect: fix pointer past-the-end in Call with zero-sized return value
+ 2017-10-25 bd34e74134 [release-branch.go1.9] log: fix data race on log.Output
+ 2017-10-25 0b55d8dbfc [release-branch.go1.9] cmd/compile: replace GOROOT in //line directives
+ 2017-10-25 5c48811aec [release-branch.go1.9] cmd/compile: limit the number of simultaneously opened files to avoid EMFILE/ENFILE errors
+ 2017-10-25 8c7fa95ad3 [release-branch.go1.9] expvar: make (*Map).Init clear existing keys
+ 2017-10-25 ccd5abc105 [release-branch.go1.9] cmd/compile: simplify "missing function body" error message
+ 2017-10-25 2e4358c960 [release-branch.go1.9] time: fix documentation of Round, Truncate behavior for d <= 0
+ 2017-10-25 c6388d381e [release-branch.go1.9] runtime: capture runtimeInitTime after nanotime is initialized
+ 2017-10-25 724638c9d8 [release-branch.go1.9] crypto/x509: skip TestSystemRoots
+ 2017-10-25 ed3b0d63b7 [release-branch.go1.9] internal/poll: add tests for Windows file and serial ports
+ 2017-10-04 93322a5b3d [release-branch.go1.9] doc: add missing "Minor revisions" header for 1.9
+ 2017-10-04 7f40c1214d [release-branch.go1.9] go1.9.1
+ 2017-10-04 598433b17a [release-branch.go1.9] doc: document go1.9.1 and go1.8.4
+ 2017-10-04 815cad3ed0 [release-branch.go1.9] doc/1.9: add mention of net/http.LocalAddrContextKey
+ 2017-10-04 1900d34a10 [release-branch.go1.9] net/smtp: fix PlainAuth to refuse to send passwords to non-TLS servers
+ 2017-10-04 a39bcecea6 [release-branch.go1.9] cmd/go: reject update of VCS inside VCS
+ 2017-10-04 d9e64910af [release-branch.go1.9] runtime: deflake TestPeriodicGC
+ 2017-09-28 adc1f587ac [dev.boringcrypto] misc/boring: add src releases
+ 2017-09-25 4038503543 [dev.boringcrypto] misc/boring: add go1.8.3b4
+ 2017-09-25 d724c60b4d [dev.boringcrypto] misc/boring: update README
+ 2017-09-22 70bada9db3 [dev.boringcrypto] misc/boring: add go1.9b4 release
+ 2017-09-22 e6ad24cde7 [dev.boringcrypto] all: merge go1.9 into dev.boringcrypto
+ 2017-09-22 431e071eed [dev.boringcrypto] misc/boring: add go1.9rc2b4 release
+ 2017-09-22 cc6e26b2e1 [dev.boringcrypto] api: add crypto/x509.VerifyOptions.IsBoring to make release builder happy
+ 2017-09-22 bac02b14b5 [dev.boringcrypto] misc/boring: update VERSION
+ 2017-09-22 3ed08db261 [dev.boringcrypto] crypto/tls/fipsonly: new package to force FIPS-allowed TLS settings
+ 2017-09-20 2ba76155cd [dev.boringcrypto] crypto/internal/boring: fix finalizer-induced crashes
+ 2017-09-18 32dc9b247f [dev.boringcrypto] cmd/go: exclude SysoFiles when using -msan
+ 2017-09-18 9f025cbdeb [dev.boringcrypto] crypto/internal/boring: fall back to standard crypto when using -msan
+ 2017-09-18 89ba9e3541 [dev.boringcrypto] crypto/aes: panic on invalid dst, src overlap
+ 2017-09-18 a929f3a04d [dev.boringcrypto] crypto/rsa: fix boring GenerateKey to set non-nil Precomputed.CRTValues
+ 2017-09-18 aa4a4a80ff [dev.boringcrypto] crypto/internal/boring: fix detection of tests to allow *.test and *_test
+ 2017-09-18 c9e2d9eb06 [dev.boringcrypto] crypto/rsa: add test for, fix observable reads from custom randomness
+ 2017-09-18 e773ea9aa3 [dev.boringcrypto] crypto/hmac: add test for Write/Sum after Sum
+ 2017-09-18 8fa8f42cb3 [dev.boringcrypto] crypto/internal/boring: allow hmac operations after Sum
+ 2017-09-18 07f6ce9d39 [dev.boringcrypto] crypto/internal/boring: handle RSA verification of short signatures
+ 2017-09-14 e8eec3fbdb [dev.boringcrypto] cmd/compile: refine BoringCrypto kludge
+ 2017-08-30 7b49445d0f [dev.boringcrypto] cmd/compile: hide new boring fields from reflection
+ 2017-08-30 81b9d733b0 [dev.boringcrypto] crypto/hmac: test empty key
+ 2017-08-30 f6358bdb6c [dev.boringcrypto] crypto/internal/boring: fix NewHMAC with empty key
+ 2017-08-30 9c307d8039 [dev.boringcrypto] crypto/internal/cipherhw: fix AESGCMSupport for BoringCrypto
+ 2017-08-26 f48a9fb815 [dev.boringcrypto] misc/boring: release packaging
+ 2017-08-25 94fb8224b2 [dev.boringcrypto] crypto/internal/boring: disable for android & non-cgo builds
+ 2017-08-25 7ff9fcafbd [dev.boringcrypto] crypto/internal/boring: clear "executable stack" bit from syso
+ 2017-08-24 c8aec4095e [release-branch.go1.9] go1.9
+ 2017-08-24 b8c9ef9f09 [release-branch.go1.9] doc: add go1.9 to golang.org/project
+ 2017-08-24 136f4a6b2a [release-branch.go1.9] doc: document go1.9
+ 2017-08-24 867be4c60c [release-branch.go1.9] doc/go1.9: fix typo in Moved GOROOT
+ 2017-08-24 d1351fbc31 [dev.boringcrypto] cmd/link: allow internal linking for crypto/internal/boring
+ 2017-08-24 991652dcf0 [dev.boringcrypto] cmd/link: work around DWARF symbol bug
+ 2017-08-22 9a4e7942ea [release-branch.go1.9] cmd/compile: remove gc.Sysfunc calls from 387 backend
+ 2017-08-22 ff38035a62 [release-branch.go1.9] doc/go1.9: fix typo in crypto/x509 of "Minor changes to the library".
+ 2017-08-19 7e9e3a06cb [dev.boringcrypto] crypto/rsa: use BoringCrypto
+ 2017-08-19 bc38fda367 [dev.boringcrypto] crypto/ecdsa: use unsafe.Pointer instead of atomic.Value
+ 2017-08-18 42046e8989 [release-branch.go1.9] runtime: fix false positive race in profile label reading
+ 2017-08-18 fbf7e1f295 [release-branch.go1.9] testing: don't fail all tests after racy test failure
+ 2017-08-18 21312a4b5e [release-branch.go1.9] cmd/dist: update deps.go for current dependencies
+ 2017-08-18 5927854f7d [release-branch.go1.9] cmd/compile: add rules handling unsigned div/mod by constant 1<<63
+ 2017-08-18 65717b2dca [release-branch.go1.9] runtime: fix usleep by correctly setting nanoseconds parameter for pselect6
+ 2017-08-17 b1f201e951 [dev.boringcrypto] crypto/ecdsa: use BoringCrypto
+ 2017-08-17 2efded1cd2 [dev.boringcrypto] crypto/tls: use TLS-specific AES-GCM mode if available
+ 2017-08-17 335a0f87bf [dev.boringcrypto] crypto/aes: implement TLS-specific AES-GCM mode from BoringCrypto
+ 2017-08-17 8d05ec9e58 [dev.boringcrypto] crypto/aes: use BoringCrypto
+ 2017-08-17 74e33c43e9 [dev.boringcrypto] crypto/hmac: use BoringCrypto
+ 2017-08-17 96d6718e4f [dev.boringcrypto] crypto/sha1,sha256,sha512: use BoringCrypto
+ 2017-08-17 e0e2bbdd00 [dev.boringcrypto] runtime/race: move TestRaceIssue5567 from sha1 to crc32
+ 2017-08-17 fe02ba30f1 [dev.boringcrypto] crypto/rand: use BoringCrypto
+ 2017-08-17 6e70f88f84 [dev.boringcrypto] crypto/internal/boring: add initial BoringCrypto access
+ 2017-08-16 dcdcc38440 [dev.boringcrypto] add README.boringcrypto.md, update VERSION
+ 2017-08-16 19b89a22df [dev.boringcrypto] cmd/link: implement R_X86_64_PC64 relocations
+ 2017-08-07 048c9cfaac [release-branch.go1.9] go1.9rc2
+ 2017-08-07 cff0de3da3 [release-branch.go1.9] all: merge master into release-branch.go1.9
+ 2017-07-31 196492a299 [release-branch.go1.9] runtime: map bitmap and spans during heap initialization
+ 2017-07-31 1a6d87d4bf [release-branch.go1.9] runtime: fall back to small mmaps if we fail to grow reservation
+ 2017-07-27 7320506bc5 [release-branch.go1.9] cmd/dist: skip moved GOROOT on Go's Windows builders when not sharding tests
+ 2017-07-24 65c6c88a94 [release-branch.go1.9] go1.9rc1
+ 2017-07-24 fbc9b49790 [release-branch.go1.9] cmd/compile: consider exported flag in namedata

Change-Id: I5344e8e4813a9a0900f6633499a3ddf22895a4d5
This commit is contained in:
Russ Cox 2022-05-02 22:12:30 -04:00
commit f771edd7f9
112 changed files with 7065 additions and 110 deletions

View file

@ -57,7 +57,7 @@ func runWithEnv(t *testing.T, msg string, env []string, args ...string) {
func goCmd(t *testing.T, args ...string) string {
newargs := []string{args[0]}
if *testX && args[0] != "env" {
newargs = append(newargs, "-x")
newargs = append(newargs, "-x", "-ldflags=-v")
}
newargs = append(newargs, args[1:]...)
c := exec.Command("go", newargs...)

View file

@ -0,0 +1,17 @@
// Copyright 2022 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 boringcrypto
package main
import (
"fmt"
"os"
)
func init() {
fmt.Printf("SKIP with boringcrypto enabled\n")
os.Exit(0)
}

View file

@ -11,7 +11,6 @@
package main
import (
"crypto/md5"
"flag"
"fmt"
"go/ast"
@ -28,6 +27,7 @@ import (
"strings"
"cmd/internal/edit"
"cmd/internal/notsha256"
"cmd/internal/objabi"
)
@ -331,8 +331,8 @@ func main() {
// we use to coordinate between gcc and ourselves.
// We already put _cgo_ at the beginning, so the main
// concern is other cgo wrappers for the same functions.
// Use the beginning of the md5 of the input to disambiguate.
h := md5.New()
// Use the beginning of the notsha256 of the input to disambiguate.
h := notsha256.New()
io.WriteString(h, *importPath)
fs := make([]*File, len(goFiles))
for i, input := range goFiles {

View file

@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// When using GOEXPERIMENT=boringcrypto, the test program links in the boringcrypto syso,
// which does not respect GOAMD64, so we skip the test if boringcrypto is enabled.
//go:build !boringcrypto
package amd64_test
import (

View file

@ -15,7 +15,6 @@
package liveness
import (
"crypto/sha1"
"fmt"
"os"
"sort"
@ -30,6 +29,7 @@ import (
"cmd/compile/internal/ssa"
"cmd/compile/internal/typebits"
"cmd/compile/internal/types"
"cmd/internal/notsha256"
"cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/src"
@ -959,7 +959,7 @@ func (lv *liveness) enableClobber() {
// Clobber only functions where the hash of the function name matches a pattern.
// Useful for binary searching for a miscompiled function.
hstr := ""
for _, b := range sha1.Sum([]byte(lv.f.Name)) {
for _, b := range notsha256.Sum256([]byte(lv.f.Name)) {
hstr += fmt.Sprintf("%08b", b)
}
if !strings.HasSuffix(hstr, h) {

View file

@ -8,8 +8,8 @@ import (
"cmd/compile/internal/abi"
"cmd/compile/internal/base"
"cmd/compile/internal/types"
"cmd/internal/notsha256"
"cmd/internal/src"
"crypto/sha1"
"fmt"
"io"
"math"
@ -854,7 +854,7 @@ func (f *Func) DebugHashMatch(evname string) bool {
// We use this feature to do a binary search to
// find a function that is incorrectly compiled.
hstr := ""
for _, b := range sha1.Sum([]byte(name)) {
for _, b := range notsha256.Sum256([]byte(name)) {
hstr += fmt.Sprintf("%08b", b)
}

View file

@ -6,10 +6,11 @@ package ssa
import (
"bytes"
"cmd/internal/src"
"crypto/sha256"
"fmt"
"io"
"cmd/internal/notsha256"
"cmd/internal/src"
)
func printFunc(f *Func) {
@ -17,7 +18,7 @@ func printFunc(f *Func) {
}
func hashFunc(f *Func) []byte {
h := sha256.New()
h := notsha256.New()
p := stringFuncPrinter{w: h, printDead: true}
fprintFunc(p, f)
return h.Sum(nil)
@ -32,7 +33,7 @@ func (f *Func) String() string {
// rewriteHash returns a hash of f suitable for detecting rewrite cycles.
func (f *Func) rewriteHash() string {
h := sha256.New()
h := notsha256.New()
p := stringFuncPrinter{w: h, printDead: false}
fprintFunc(p, f)
return fmt.Sprintf("%x", h.Sum(nil))

View file

@ -5,7 +5,6 @@
package staticdata
import (
"crypto/sha256"
"fmt"
"go/constant"
"io"
@ -20,6 +19,7 @@ import (
"cmd/compile/internal/objw"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/internal/notsha256"
"cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/src"
@ -73,7 +73,7 @@ func StringSym(pos src.XPos, s string) (data *obj.LSym) {
// Indulge in some paranoia by writing the length of s, too,
// as protection against length extension attacks.
// Same pattern is known to fileStringSym below.
h := sha256.New()
h := notsha256.New()
io.WriteString(h, s)
symname = fmt.Sprintf(stringSymPattern, len(s), h.Sum(nil))
} else {
@ -131,7 +131,7 @@ func fileStringSym(pos src.XPos, file string, readonly bool, hash []byte) (*obj.
sym = slicedata(pos, string(data)).Linksym()
}
if len(hash) > 0 {
sum := sha256.Sum256(data)
sum := notsha256.Sum256(data)
copy(hash, sum[:])
}
return sym, size, nil
@ -148,7 +148,7 @@ func fileStringSym(pos src.XPos, file string, readonly bool, hash []byte) (*obj.
// Compute hash if needed for read-only content hashing or if the caller wants it.
var sum []byte
if readonly || len(hash) > 0 {
h := sha256.New()
h := notsha256.New()
n, err := io.Copy(h, f)
if err != nil {
return nil, 0, err

View file

@ -236,7 +236,6 @@ package typecheck
import (
"bytes"
"crypto/md5"
"encoding/binary"
"fmt"
"go/constant"
@ -250,6 +249,7 @@ import (
"cmd/compile/internal/ir"
"cmd/compile/internal/types"
"cmd/internal/goobj"
"cmd/internal/notsha256"
"cmd/internal/src"
)
@ -353,7 +353,7 @@ func WriteExports(out io.Writer, extensions bool) {
hdr.uint64(dataLen)
// Flush output.
h := md5.New()
h := notsha256.New()
wr := io.MultiWriter(out, h)
io.Copy(wr, &hdr)
io.Copy(wr, &p.strings)

View file

@ -6,7 +6,6 @@ package types
import (
"bytes"
"crypto/md5"
"encoding/binary"
"fmt"
"go/constant"
@ -15,6 +14,7 @@ import (
"sync"
"cmd/compile/internal/base"
"cmd/internal/notsha256"
)
// BuiltinPkg is a fake package that declares the universe block.
@ -771,7 +771,7 @@ func FmtConst(v constant.Value, sharp bool) string {
func TypeHash(t *Type) uint32 {
p := tconv(t, 0, fmtTypeIDHash)
// Using MD5 is overkill, but reduces accidental collisions.
h := md5.Sum([]byte(p))
// Using SHA256 is overkill, but reduces accidental collisions.
h := notsha256.Sum256([]byte(p))
return binary.LittleEndian.Uint32(h[:4])
}

View file

@ -44,6 +44,7 @@ var bootstrapDirs = []string{
"cmd/internal/edit",
"cmd/internal/gcprog",
"cmd/internal/goobj",
"cmd/internal/notsha256",
"cmd/internal/obj/...",
"cmd/internal/objabi",
"cmd/internal/pkgpath",

View file

@ -0,0 +1,22 @@
// Copyright 2015 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 boringcrypto
package main_test
import "testing"
func TestBoringInternalLink(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempFile("main.go", `package main
import "crypto/sha1"
func main() {
sha1.New()
}`)
tg.run("build", "-ldflags=-w -extld=false", tg.path("main.go"))
tg.run("build", "-ldflags=-extld=false", tg.path("main.go"))
}

View file

@ -1903,8 +1903,12 @@ func TestBinaryOnlyPackages(t *testing.T) {
tg.grepStdout("p2: false", "p2 listed as BinaryOnly")
}
// Issue 16050.
func TestAlwaysLinkSysoFiles(t *testing.T) {
// Issue 16050 and 21884.
func TestLinkSysoFiles(t *testing.T) {
if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
t.Skip("not linux/amd64")
}
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
@ -1923,6 +1927,10 @@ func TestAlwaysLinkSysoFiles(t *testing.T) {
tg.setenv("CGO_ENABLED", "0")
tg.run("list", "-f", "{{.SysoFiles}}", "syso")
tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
tg.setenv("CGO_ENABLED", "1")
tg.run("list", "-msan", "-f", "{{.SysoFiles}}", "syso")
tg.grepStdoutNot("a.syso", "unexpected syso file with -msan")
}
// Issue 16120.

View file

@ -401,6 +401,12 @@ func (p *Package) copyBuild(opts PackageOpts, pp *build.Package) {
p.SwigFiles = pp.SwigFiles
p.SwigCXXFiles = pp.SwigCXXFiles
p.SysoFiles = pp.SysoFiles
if cfg.BuildMSan {
// There's no way for .syso files to be built both with and without
// support for memory sanitizer. Assume they are built without,
// and drop them.
p.SysoFiles = nil
}
p.CgoCFLAGS = pp.CgoCFLAGS
p.CgoCPPFLAGS = pp.CgoCPPFLAGS
p.CgoCXXFLAGS = pp.CgoCXXFLAGS

View file

@ -22,6 +22,7 @@ import (
"path/filepath"
"regexp"
"runtime"
"sort"
"strconv"
"strings"
"sync"
@ -2993,7 +2994,26 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe
return err
}
linkobj := str.StringList(ofile, outObj, mkAbsFiles(p.Dir, p.SysoFiles))
// Gather .syso files from this package and all (transitive) dependencies.
var syso []string
seen := make(map[*Action]bool)
var gatherSyso func(*Action)
gatherSyso = func(a1 *Action) {
if seen[a1] {
return
}
seen[a1] = true
if p1 := a1.Package; p1 != nil {
syso = append(syso, mkAbsFiles(p1.Dir, p1.SysoFiles)...)
}
for _, a2 := range a1.Deps {
gatherSyso(a2)
}
}
gatherSyso(a)
sort.Strings(syso)
str.Uniq(&syso)
linkobj := str.StringList(ofile, outObj, syso)
dynobj := objdir + "_cgo_.o"
ldflags := cgoLDFLAGS

View file

@ -0,0 +1,54 @@
# Test that syso in deps is available to cgo.
[!gc] skip
[!cgo] skip
# External linking is not supported on linux/ppc64.
# See: https://github.com/golang/go/issues/8912
[linux] [ppc64] skip
cc -c -o syso/x.syso syso/x.c
cc -c -o syso2/x.syso syso2/x.c
go build m/cgo
-- go.mod --
module m
go 1.18
-- cgo/x.go --
package cgo
// extern void f(void);
// extern void g(void);
import "C"
func F() {
C.f()
}
func G() {
C.g()
}
-- cgo/x2.go --
package cgo
import _ "m/syso"
-- syso/x.c --
//go:build ignore
void f() {}
-- syso/x.go --
package syso
import _ "m/syso2"
-- syso2/x.c --
//go:build ignore
void g() {}
-- syso2/x.go --
package syso2

View file

@ -11,10 +11,11 @@
package codesign
import (
"crypto/sha256"
"debug/macho"
"encoding/binary"
"io"
"cmd/internal/notsha256"
)
// Code signature layout.
@ -190,7 +191,7 @@ func Size(codeSize int64, id string) int64 {
nhashes := (codeSize + pageSize - 1) / pageSize
idOff := int64(codeDirectorySize)
hashOff := idOff + int64(len(id)+1)
cdirSz := hashOff + nhashes*sha256.Size
cdirSz := hashOff + nhashes*notsha256.Size
return int64(superBlobSize+blobSize) + cdirSz
}
@ -226,7 +227,7 @@ func Sign(out []byte, data io.Reader, id string, codeSize, textOff, textSize int
identOffset: uint32(idOff),
nCodeSlots: uint32(nhashes),
codeLimit: uint32(codeSize),
hashSize: sha256.Size,
hashSize: notsha256.Size,
hashType: CS_HASHTYPE_SHA256,
pageSize: uint8(pageSizeBits),
execSegBase: uint64(textOff),
@ -245,8 +246,12 @@ func Sign(out []byte, data io.Reader, id string, codeSize, textOff, textSize int
outp = puts(outp, []byte(id+"\000"))
// emit hashes
// NOTE(rsc): These must be SHA256, but for cgo bootstrap reasons
// we cannot import crypto/sha256 when GOEXPERIMENT=boringcrypto
// and the host is linux/amd64. So we use NOT-SHA256
// and then apply a NOT ourselves to get SHA256. Sigh.
var buf [pageSize]byte
h := sha256.New()
h := notsha256.New()
p := 0
for p < int(codeSize) {
n, err := io.ReadFull(data, buf[:])
@ -263,6 +268,9 @@ func Sign(out []byte, data io.Reader, id string, codeSize, textOff, textSize int
h.Reset()
h.Write(buf[:n])
b := h.Sum(nil)
for i := range b {
b[i] ^= 0xFF // convert notsha256 to sha256
}
outp = puts(outp, b[:])
}
}

View file

@ -20,7 +20,7 @@ package goobj
import (
"cmd/internal/bio"
"crypto/sha1"
"cmd/internal/notsha256"
"encoding/binary"
"errors"
"fmt"
@ -367,7 +367,7 @@ const Hash64Size = 8
// Hash
type HashType [HashSize]byte
const HashSize = sha1.Size
const HashSize = notsha256.Size
// Relocation.
//

View file

@ -0,0 +1,41 @@
// Copyright 2016 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 notsha256_test
import (
"crypto/sha256"
"fmt"
"io"
"log"
"os"
)
func ExampleSum256() {
sum := sha256.Sum256([]byte("hello world\n"))
fmt.Printf("%x", sum)
// Output: a948904f2f0f479b8f8197694b30184b0d2ed1c1cd2a1ec0fb85d299a192a447
}
func ExampleNew() {
h := sha256.New()
h.Write([]byte("hello world\n"))
fmt.Printf("%x", h.Sum(nil))
// Output: a948904f2f0f479b8f8197694b30184b0d2ed1c1cd2a1ec0fb85d299a192a447
}
func ExampleNew_file() {
f, err := os.Open("file.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
h := sha256.New()
if _, err := io.Copy(h, f); err != nil {
log.Fatal(err)
}
fmt.Printf("%x", h.Sum(nil))
}

View file

@ -0,0 +1,141 @@
// 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 notsha256 implements the NOTSHA256 algorithm,
// a hash defined as bitwise NOT of SHA256.
// It is used in situations where exact fidelity to SHA256 is unnecessary.
// In particular, it is used in the compiler toolchain,
// which cannot depend directly on cgo when GOEXPERIMENT=boringcrypto
// (and in that mode the real sha256 uses cgo).
package notsha256
import (
"encoding/binary"
"hash"
)
// The size of a checksum in bytes.
const Size = 32
// The blocksize in bytes.
const BlockSize = 64
const (
chunk = 64
init0 = 0x6A09E667
init1 = 0xBB67AE85
init2 = 0x3C6EF372
init3 = 0xA54FF53A
init4 = 0x510E527F
init5 = 0x9B05688C
init6 = 0x1F83D9AB
init7 = 0x5BE0CD19
)
// digest represents the partial evaluation of a checksum.
type digest struct {
h [8]uint32
x [chunk]byte
nx int
len uint64
}
func (d *digest) Reset() {
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
d.nx = 0
d.len = 0
}
// New returns a new hash.Hash computing the NOTSHA256 checksum.
// state of the hash.
func New() hash.Hash {
d := new(digest)
d.Reset()
return d
}
func (d *digest) Size() int {
return Size
}
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()
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]byte
tmp[0] = 0x80
if len%64 < 56 {
d.Write(tmp[0 : 56-len%64])
} else {
d.Write(tmp[0 : 64+56-len%64])
}
// Length in bits.
len <<= 3
binary.BigEndian.PutUint64(tmp[:], len)
d.Write(tmp[0:8])
if d.nx != 0 {
panic("d.nx != 0")
}
var digest [Size]byte
binary.BigEndian.PutUint32(digest[0:], d.h[0]^0xFFFFFFFF)
binary.BigEndian.PutUint32(digest[4:], d.h[1]^0xFFFFFFFF)
binary.BigEndian.PutUint32(digest[8:], d.h[2]^0xFFFFFFFF)
binary.BigEndian.PutUint32(digest[12:], d.h[3]^0xFFFFFFFF)
binary.BigEndian.PutUint32(digest[16:], d.h[4]^0xFFFFFFFF)
binary.BigEndian.PutUint32(digest[20:], d.h[5]^0xFFFFFFFF)
binary.BigEndian.PutUint32(digest[24:], d.h[6]^0xFFFFFFFF)
binary.BigEndian.PutUint32(digest[28:], d.h[7]^0xFFFFFFFF)
return digest
}
// Sum256 returns the SHA256 checksum of the data.
func Sum256(data []byte) [Size]byte {
var d digest
d.Reset()
d.Write(data)
return d.checkSum()
}

View file

@ -0,0 +1,175 @@
// 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.
// SHA256 hash algorithm. See FIPS 180-2.
package notsha256
import (
"crypto/rand"
"fmt"
"io"
"strings"
"testing"
)
type sha256Test struct {
out string
in string
unused string // marshal state, to keep table in sync with crypto/sha256
}
var golden = []sha256Test{
{"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
{"ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb", "a", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
{"fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603", "ab", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"},
{"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", "abc", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"},
{"88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589", "abcd", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19ab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"},
{"36bbe50ed96841d10443bcb670d6554f0a34b761be67ec9c4a8ad2c0c44ca42c", "abcde", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19ab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"},
{"bef57ec7f53a6d40beb640a780a639c83bc29ac8a9816f1fc6c5c6dcd93c4721", "abcdef", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19abc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"},
{"7d1a54127b222502f5b79b5fb0803061152a44f92b37e23c6527baf665d4da9a", "abcdefg", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19abc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"},
{"9c56cc51b374c3ba189210d5b6d4bf57790d351c96c47c02190ecf1e430635ab", "abcdefgh", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19abcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04"},
{"19cc02f26df43cc571bc9ed7b0c4d29224a3ec229529221725ef76d021c8326f", "abcdefghi", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19abcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04"},
{"72399361da6a7754fec986dca5b7cbaf1c810a28ded4abaf56b2106d06cb78b0", "abcdefghij", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19abcde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05"},
{"a144061c271f152da4d151034508fed1c138b8c976339de229c3bb6d4bbb4fce", "Discard medicine more than two years old.", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19Discard medicine mor\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14"},
{"6dae5caa713a10ad04b46028bf6dad68837c581616a1589a265a11288d4bb5c4", "He who has a shady past knows that nice guys finish last.", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19He who has a shady past know\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"},
{"ae7a702a9509039ddbf29f0765e70d0001177914b86459284dab8b348c2dce3f", "I wouldn't marry him with a ten foot pole.", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19I wouldn't marry him \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15"},
{"6748450b01c568586715291dfa3ee018da07d36bb7ea6f180c1af6270215c64f", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19Free! Free!/A trip/to Mars/f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"},
{"14b82014ad2b11f661b5ae6a99b75105c2ffac278cd071cd6c05832793635774", "The days of the digital watch are numbered. -Tom Stoppard", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19The days of the digital watch\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d"},
{"7102cfd76e2e324889eece5d6c41921b1e142a4ac5a2692be78803097f6a48d8", "Nepal premier won't resign.", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19Nepal premier\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r"},
{"23b1018cd81db1d67983c5f7417c44da9deb582459e378d7a068552ea649dc9f", "For every action there is an equal and opposite government program.", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19For every action there is an equa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!"},
{"8001f190dfb527261c4cfcab70c98e8097a7a1922129bc4096950e57c7999a5a", "His money is twice tainted: 'taint yours and 'taint mine.", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19His money is twice tainted: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"},
{"8c87deb65505c3993eb24b7a150c4155e82eee6960cf0c3a8114ff736d69cad5", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19There is no reason for any individual to hav\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,"},
{"bfb0a67a19cdec3646498b2e0f751bddc41bba4b7f30081b0b932aad214d16d7", "It's a tiny change to the code and not completely disgusting. - Bob Manchek", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19It's a tiny change to the code and no\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%"},
{"7f9a0b9bf56332e19f5a0ec1ad9c1425a153da1c624868fda44561d6b74daf36", "size: a.out: bad magic", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19size: a.out\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\f"},
{"b13f81b8aad9e3666879af19886140904f7f429ef083286195982a7588858cfc", "The major problem is with sendmail. -Mark Horton", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19The major problem is wit\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18"},
{"b26c38d61519e894480c70c8374ea35aa0ad05b2ae3d6674eec5f52a69305ed4", "Give me a rock, paper and scissors and I will move the world. CCFestoon", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19Give me a rock, paper and scissors a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$"},
{"049d5e26d4f10222cd841a119e38bd8d2e0d1129728688449575d4ff42b842c1", "If the enemy is within range, then so are you.", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19If the enemy is within \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17"},
{"0e116838e3cc1c1a14cd045397e29b4d087aa11b0853fc69ec82e90330d60949", "It's well we cannot hear the screams/That we create in others' dreams.", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19It's well we cannot hear the scream\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#"},
{"4f7d8eb5bcf11de2a56b971021a444aa4eafd6ecd0f307b5109e4e776cd0fe46", "You remind me of a TV show, but that's all right: I watch it anyway.", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19You remind me of a TV show, but th\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\""},
{"61c0cc4c4bd8406d5120b3fb4ebc31ce87667c162f29468b3c779675a85aebce", "C is as portable as Stonehedge!!", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19C is as portable\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10"},
{"1fb2eb3688093c4a3f80cd87a5547e2ce940a4f923243a79a2a1e242220693ac", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19Even if I could be Shakespeare, I think I sh\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,"},
{"395585ce30617b62c80b93e8208ce866d4edc811a177fdb4b82d3911d8696423", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule", "sha\x03\x93\x14\xc8z\x87\x0e\vo\xf1E\x0f\xa4V\xb2a\x00\x87\xb5ǔ\xfc\xeaV\u009eg\xbc\x17\xb1\x85њem\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B"},
{"4f9b189a13d030838269dce846b16a1ce9ce81fe63e65de2f636863336a98fe6", "How can you write a big system without C++? -Paul Glick", "sha\x03j\t\xe6g\xbbg\xae\x85<n\xf3r\xa5O\xf5:Q\x0eR\u007f\x9b\x05h\x8c\x1f\x83٫[\xe0\xcd\x19How can you write a big syst\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"},
}
var not = strings.NewReplacer(
"0", "f",
"1", "e",
"2", "d",
"3", "c",
"4", "b",
"5", "a",
"6", "9",
"7", "8",
"8", "7",
"9", "6",
"a", "5",
"b", "4",
"c", "3",
"d", "2",
"e", "1",
"f", "0",
)
func TestGolden(t *testing.T) {
for i := 0; i < len(golden); i++ {
g := golden[i]
gout := not.Replace(g.out)
s := fmt.Sprintf("%x", Sum256([]byte(g.in)))
if s != gout {
t.Fatalf("Sum256 function: sha256(%s) = %s want %s", g.in, s, gout)
}
c := New()
for j := 0; j < 3; j++ {
if j < 2 {
io.WriteString(c, g.in)
} else {
io.WriteString(c, g.in[0:len(g.in)/2])
c.Sum(nil)
io.WriteString(c, g.in[len(g.in)/2:])
}
s := fmt.Sprintf("%x", c.Sum(nil))
if s != gout {
t.Fatalf("sha256[%d](%s) = %s want %s", j, g.in, s, gout)
}
c.Reset()
}
}
}
func TestSize(t *testing.T) {
c := New()
if got := c.Size(); got != Size {
t.Errorf("Size = %d; want %d", got, Size)
}
}
func TestBlockSize(t *testing.T) {
c := New()
if got := c.BlockSize(); got != BlockSize {
t.Errorf("BlockSize = %d want %d", got, BlockSize)
}
}
// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match.
func TestBlockGeneric(t *testing.T) {
gen, asm := New().(*digest), New().(*digest)
buf := make([]byte, BlockSize*20) // arbitrary factor
rand.Read(buf)
blockGeneric(gen, buf)
block(asm, buf)
if *gen != *asm {
t.Error("block and blockGeneric resulted in different states")
}
}
func TestAllocations(t *testing.T) {
in := []byte("hello, world!")
out := make([]byte, 0, Size)
h := New()
n := int(testing.AllocsPerRun(10, func() {
h.Reset()
h.Write(in)
out = h.Sum(out[:0])
}))
if n > 0 {
t.Errorf("allocs = %d, want 0", n)
}
}
var bench = New()
var buf = make([]byte, 8192)
func benchmarkSize(b *testing.B, size int) {
sum := make([]byte, bench.Size())
b.Run("New", func(b *testing.B) {
b.ReportAllocs()
b.SetBytes(int64(size))
for i := 0; i < b.N; i++ {
bench.Reset()
bench.Write(buf[:size])
bench.Sum(sum[:0])
}
})
b.Run("Sum256", func(b *testing.B) {
b.ReportAllocs()
b.SetBytes(int64(size))
for i := 0; i < b.N; i++ {
Sum256(buf[:size])
}
})
}
func BenchmarkHash8Bytes(b *testing.B) {
benchmarkSize(b, 8)
}
func BenchmarkHash1K(b *testing.B) {
benchmarkSize(b, 1024)
}
func BenchmarkHash8K(b *testing.B) {
benchmarkSize(b, 8192)
}

View file

@ -0,0 +1,128 @@
// 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.
// SHA256 block step.
// In its own file so that a faster assembly or C version
// can be substituted easily.
package notsha256
import "math/bits"
var _K = []uint32{
0x428a2f98,
0x71374491,
0xb5c0fbcf,
0xe9b5dba5,
0x3956c25b,
0x59f111f1,
0x923f82a4,
0xab1c5ed5,
0xd807aa98,
0x12835b01,
0x243185be,
0x550c7dc3,
0x72be5d74,
0x80deb1fe,
0x9bdc06a7,
0xc19bf174,
0xe49b69c1,
0xefbe4786,
0x0fc19dc6,
0x240ca1cc,
0x2de92c6f,
0x4a7484aa,
0x5cb0a9dc,
0x76f988da,
0x983e5152,
0xa831c66d,
0xb00327c8,
0xbf597fc7,
0xc6e00bf3,
0xd5a79147,
0x06ca6351,
0x14292967,
0x27b70a85,
0x2e1b2138,
0x4d2c6dfc,
0x53380d13,
0x650a7354,
0x766a0abb,
0x81c2c92e,
0x92722c85,
0xa2bfe8a1,
0xa81a664b,
0xc24b8b70,
0xc76c51a3,
0xd192e819,
0xd6990624,
0xf40e3585,
0x106aa070,
0x19a4c116,
0x1e376c08,
0x2748774c,
0x34b0bcb5,
0x391c0cb3,
0x4ed8aa4a,
0x5b9cca4f,
0x682e6ff3,
0x748f82ee,
0x78a5636f,
0x84c87814,
0x8cc70208,
0x90befffa,
0xa4506ceb,
0xbef9a3f7,
0xc67178f2,
}
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 {
// Can interlace the computation of w with the
// rounds below if needed for speed.
for i := 0; i < 16; i++ {
j := i * 4
w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
}
for i := 16; i < 64; i++ {
v1 := w[i-2]
t1 := (bits.RotateLeft32(v1, -17)) ^ (bits.RotateLeft32(v1, -19)) ^ (v1 >> 10)
v2 := w[i-15]
t2 := (bits.RotateLeft32(v2, -7)) ^ (bits.RotateLeft32(v2, -18)) ^ (v2 >> 3)
w[i] = t1 + w[i-7] + t2 + w[i-16]
}
a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7
for i := 0; i < 64; i++ {
t1 := h + ((bits.RotateLeft32(e, -6)) ^ (bits.RotateLeft32(e, -11)) ^ (bits.RotateLeft32(e, -25))) + ((e & f) ^ (^e & g)) + _K[i] + w[i]
t2 := ((bits.RotateLeft32(a, -2)) ^ (bits.RotateLeft32(a, -13)) ^ (bits.RotateLeft32(a, -22))) + ((a & b) ^ (a & c) ^ (b & c))
h = g
g = f
f = e
e = d + t1
d = c
c = b
b = a
a = t1 + t2
}
h0 += a
h1 += b
h2 += c
h3 += d
h4 += e
h5 += f
h6 += g
h7 += h
p = p[chunk:]
}
dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
}

View file

@ -0,0 +1,283 @@
// Copyright 2013 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.
// SHA256 block routine. See sha256block.go for Go equivalent.
//
// The algorithm is detailed in FIPS 180-4:
//
// https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
//
// Wt = Mt; for 0 <= t <= 15
// Wt = SIGMA1(Wt-2) + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63
//
// a = H0
// b = H1
// c = H2
// d = H3
// e = H4
// f = H5
// g = H6
// h = H7
//
// for t = 0 to 63 {
// T1 = h + BIGSIGMA1(e) + Ch(e,f,g) + Kt + Wt
// T2 = BIGSIGMA0(a) + Maj(a,b,c)
// h = g
// g = f
// f = e
// e = d + T1
// d = c
// c = b
// b = a
// a = T1 + T2
// }
//
// H0 = a + H0
// H1 = b + H1
// H2 = c + H2
// H3 = d + H3
// H4 = e + H4
// H5 = f + H5
// H6 = g + H6
// H7 = h + H7
// Wt = Mt; for 0 <= t <= 15
#define MSGSCHEDULE0(index) \
MOVL (index*4)(SI), AX; \
BSWAPL AX; \
MOVL AX, (index*4)(BP)
// Wt = SIGMA1(Wt-2) + Wt-7 + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63
// SIGMA0(x) = ROTR(7,x) XOR ROTR(18,x) XOR SHR(3,x)
// SIGMA1(x) = ROTR(17,x) XOR ROTR(19,x) XOR SHR(10,x)
#define MSGSCHEDULE1(index) \
MOVL ((index-2)*4)(BP), AX; \
MOVL AX, CX; \
RORL $17, AX; \
MOVL CX, DX; \
RORL $19, CX; \
SHRL $10, DX; \
MOVL ((index-15)*4)(BP), BX; \
XORL CX, AX; \
MOVL BX, CX; \
XORL DX, AX; \
RORL $7, BX; \
MOVL CX, DX; \
SHRL $3, DX; \
RORL $18, CX; \
ADDL ((index-7)*4)(BP), AX; \
XORL CX, BX; \
XORL DX, BX; \
ADDL ((index-16)*4)(BP), BX; \
ADDL BX, AX; \
MOVL AX, ((index)*4)(BP)
// Calculate T1 in AX - uses AX, BX, CX and DX registers.
// Wt is passed in AX.
// T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + Kt + Wt
// BIGSIGMA1(x) = ROTR(6,x) XOR ROTR(11,x) XOR ROTR(25,x)
// Ch(x, y, z) = (x AND y) XOR (NOT x AND z)
#define SHA256T1(const, e, f, g, h) \
MOVL (h*4)(DI), BX; \
ADDL AX, BX; \
MOVL (e*4)(DI), AX; \
ADDL $const, BX; \
MOVL (e*4)(DI), CX; \
RORL $6, AX; \
MOVL (e*4)(DI), DX; \
RORL $11, CX; \
XORL CX, AX; \
MOVL (e*4)(DI), CX; \
RORL $25, DX; \
ANDL (f*4)(DI), CX; \
XORL AX, DX; \
MOVL (e*4)(DI), AX; \
NOTL AX; \
ADDL DX, BX; \
ANDL (g*4)(DI), AX; \
XORL CX, AX; \
ADDL BX, AX
// Calculate T2 in BX - uses AX, BX, CX and DX registers.
// T2 = BIGSIGMA0(a) + Maj(a, b, c)
// BIGSIGMA0(x) = ROTR(2,x) XOR ROTR(13,x) XOR ROTR(22,x)
// Maj(x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z)
#define SHA256T2(a, b, c) \
MOVL (a*4)(DI), AX; \
MOVL (c*4)(DI), BX; \
RORL $2, AX; \
MOVL (a*4)(DI), DX; \
ANDL (b*4)(DI), BX; \
RORL $13, DX; \
MOVL (a*4)(DI), CX; \
ANDL (c*4)(DI), CX; \
XORL DX, AX; \
XORL CX, BX; \
MOVL (a*4)(DI), DX; \
MOVL (b*4)(DI), CX; \
RORL $22, DX; \
ANDL (a*4)(DI), CX; \
XORL CX, BX; \
XORL DX, AX; \
ADDL AX, BX
// Calculate T1 and T2, then e = d + T1 and a = T1 + T2.
// The values for e and a are stored in d and h, ready for rotation.
#define SHA256ROUND(index, const, a, b, c, d, e, f, g, h) \
SHA256T1(const, e, f, g, h); \
MOVL AX, 292(SP); \
SHA256T2(a, b, c); \
MOVL 292(SP), AX; \
ADDL AX, BX; \
ADDL AX, (d*4)(DI); \
MOVL BX, (h*4)(DI)
#define SHA256ROUND0(index, const, a, b, c, d, e, f, g, h) \
MSGSCHEDULE0(index); \
SHA256ROUND(index, const, a, b, c, d, e, f, g, h)
#define SHA256ROUND1(index, const, a, b, c, d, e, f, g, h) \
MSGSCHEDULE1(index); \
SHA256ROUND(index, const, a, b, c, d, e, f, g, h)
TEXT ·block(SB),0,$296-16
MOVL p_base+4(FP), SI
MOVL p_len+8(FP), DX
SHRL $6, DX
SHLL $6, DX
LEAL (SI)(DX*1), DI
MOVL DI, 288(SP)
CMPL SI, DI
JEQ end
LEAL 256(SP), DI // variables
MOVL dig+0(FP), BP
MOVL (0*4)(BP), AX // a = H0
MOVL AX, (0*4)(DI)
MOVL (1*4)(BP), BX // b = H1
MOVL BX, (1*4)(DI)
MOVL (2*4)(BP), CX // c = H2
MOVL CX, (2*4)(DI)
MOVL (3*4)(BP), DX // d = H3
MOVL DX, (3*4)(DI)
MOVL (4*4)(BP), AX // e = H4
MOVL AX, (4*4)(DI)
MOVL (5*4)(BP), BX // f = H5
MOVL BX, (5*4)(DI)
MOVL (6*4)(BP), CX // g = H6
MOVL CX, (6*4)(DI)
MOVL (7*4)(BP), DX // h = H7
MOVL DX, (7*4)(DI)
loop:
MOVL SP, BP // message schedule
SHA256ROUND0(0, 0x428a2f98, 0, 1, 2, 3, 4, 5, 6, 7)
SHA256ROUND0(1, 0x71374491, 7, 0, 1, 2, 3, 4, 5, 6)
SHA256ROUND0(2, 0xb5c0fbcf, 6, 7, 0, 1, 2, 3, 4, 5)
SHA256ROUND0(3, 0xe9b5dba5, 5, 6, 7, 0, 1, 2, 3, 4)
SHA256ROUND0(4, 0x3956c25b, 4, 5, 6, 7, 0, 1, 2, 3)
SHA256ROUND0(5, 0x59f111f1, 3, 4, 5, 6, 7, 0, 1, 2)
SHA256ROUND0(6, 0x923f82a4, 2, 3, 4, 5, 6, 7, 0, 1)
SHA256ROUND0(7, 0xab1c5ed5, 1, 2, 3, 4, 5, 6, 7, 0)
SHA256ROUND0(8, 0xd807aa98, 0, 1, 2, 3, 4, 5, 6, 7)
SHA256ROUND0(9, 0x12835b01, 7, 0, 1, 2, 3, 4, 5, 6)
SHA256ROUND0(10, 0x243185be, 6, 7, 0, 1, 2, 3, 4, 5)
SHA256ROUND0(11, 0x550c7dc3, 5, 6, 7, 0, 1, 2, 3, 4)
SHA256ROUND0(12, 0x72be5d74, 4, 5, 6, 7, 0, 1, 2, 3)
SHA256ROUND0(13, 0x80deb1fe, 3, 4, 5, 6, 7, 0, 1, 2)
SHA256ROUND0(14, 0x9bdc06a7, 2, 3, 4, 5, 6, 7, 0, 1)
SHA256ROUND0(15, 0xc19bf174, 1, 2, 3, 4, 5, 6, 7, 0)
SHA256ROUND1(16, 0xe49b69c1, 0, 1, 2, 3, 4, 5, 6, 7)
SHA256ROUND1(17, 0xefbe4786, 7, 0, 1, 2, 3, 4, 5, 6)
SHA256ROUND1(18, 0x0fc19dc6, 6, 7, 0, 1, 2, 3, 4, 5)
SHA256ROUND1(19, 0x240ca1cc, 5, 6, 7, 0, 1, 2, 3, 4)
SHA256ROUND1(20, 0x2de92c6f, 4, 5, 6, 7, 0, 1, 2, 3)
SHA256ROUND1(21, 0x4a7484aa, 3, 4, 5, 6, 7, 0, 1, 2)
SHA256ROUND1(22, 0x5cb0a9dc, 2, 3, 4, 5, 6, 7, 0, 1)
SHA256ROUND1(23, 0x76f988da, 1, 2, 3, 4, 5, 6, 7, 0)
SHA256ROUND1(24, 0x983e5152, 0, 1, 2, 3, 4, 5, 6, 7)
SHA256ROUND1(25, 0xa831c66d, 7, 0, 1, 2, 3, 4, 5, 6)
SHA256ROUND1(26, 0xb00327c8, 6, 7, 0, 1, 2, 3, 4, 5)
SHA256ROUND1(27, 0xbf597fc7, 5, 6, 7, 0, 1, 2, 3, 4)
SHA256ROUND1(28, 0xc6e00bf3, 4, 5, 6, 7, 0, 1, 2, 3)
SHA256ROUND1(29, 0xd5a79147, 3, 4, 5, 6, 7, 0, 1, 2)
SHA256ROUND1(30, 0x06ca6351, 2, 3, 4, 5, 6, 7, 0, 1)
SHA256ROUND1(31, 0x14292967, 1, 2, 3, 4, 5, 6, 7, 0)
SHA256ROUND1(32, 0x27b70a85, 0, 1, 2, 3, 4, 5, 6, 7)
SHA256ROUND1(33, 0x2e1b2138, 7, 0, 1, 2, 3, 4, 5, 6)
SHA256ROUND1(34, 0x4d2c6dfc, 6, 7, 0, 1, 2, 3, 4, 5)
SHA256ROUND1(35, 0x53380d13, 5, 6, 7, 0, 1, 2, 3, 4)
SHA256ROUND1(36, 0x650a7354, 4, 5, 6, 7, 0, 1, 2, 3)
SHA256ROUND1(37, 0x766a0abb, 3, 4, 5, 6, 7, 0, 1, 2)
SHA256ROUND1(38, 0x81c2c92e, 2, 3, 4, 5, 6, 7, 0, 1)
SHA256ROUND1(39, 0x92722c85, 1, 2, 3, 4, 5, 6, 7, 0)
SHA256ROUND1(40, 0xa2bfe8a1, 0, 1, 2, 3, 4, 5, 6, 7)
SHA256ROUND1(41, 0xa81a664b, 7, 0, 1, 2, 3, 4, 5, 6)
SHA256ROUND1(42, 0xc24b8b70, 6, 7, 0, 1, 2, 3, 4, 5)
SHA256ROUND1(43, 0xc76c51a3, 5, 6, 7, 0, 1, 2, 3, 4)
SHA256ROUND1(44, 0xd192e819, 4, 5, 6, 7, 0, 1, 2, 3)
SHA256ROUND1(45, 0xd6990624, 3, 4, 5, 6, 7, 0, 1, 2)
SHA256ROUND1(46, 0xf40e3585, 2, 3, 4, 5, 6, 7, 0, 1)
SHA256ROUND1(47, 0x106aa070, 1, 2, 3, 4, 5, 6, 7, 0)
SHA256ROUND1(48, 0x19a4c116, 0, 1, 2, 3, 4, 5, 6, 7)
SHA256ROUND1(49, 0x1e376c08, 7, 0, 1, 2, 3, 4, 5, 6)
SHA256ROUND1(50, 0x2748774c, 6, 7, 0, 1, 2, 3, 4, 5)
SHA256ROUND1(51, 0x34b0bcb5, 5, 6, 7, 0, 1, 2, 3, 4)
SHA256ROUND1(52, 0x391c0cb3, 4, 5, 6, 7, 0, 1, 2, 3)
SHA256ROUND1(53, 0x4ed8aa4a, 3, 4, 5, 6, 7, 0, 1, 2)
SHA256ROUND1(54, 0x5b9cca4f, 2, 3, 4, 5, 6, 7, 0, 1)
SHA256ROUND1(55, 0x682e6ff3, 1, 2, 3, 4, 5, 6, 7, 0)
SHA256ROUND1(56, 0x748f82ee, 0, 1, 2, 3, 4, 5, 6, 7)
SHA256ROUND1(57, 0x78a5636f, 7, 0, 1, 2, 3, 4, 5, 6)
SHA256ROUND1(58, 0x84c87814, 6, 7, 0, 1, 2, 3, 4, 5)
SHA256ROUND1(59, 0x8cc70208, 5, 6, 7, 0, 1, 2, 3, 4)
SHA256ROUND1(60, 0x90befffa, 4, 5, 6, 7, 0, 1, 2, 3)
SHA256ROUND1(61, 0xa4506ceb, 3, 4, 5, 6, 7, 0, 1, 2)
SHA256ROUND1(62, 0xbef9a3f7, 2, 3, 4, 5, 6, 7, 0, 1)
SHA256ROUND1(63, 0xc67178f2, 1, 2, 3, 4, 5, 6, 7, 0)
MOVL dig+0(FP), BP
MOVL (0*4)(BP), AX // H0 = a + H0
ADDL (0*4)(DI), AX
MOVL AX, (0*4)(DI)
MOVL AX, (0*4)(BP)
MOVL (1*4)(BP), BX // H1 = b + H1
ADDL (1*4)(DI), BX
MOVL BX, (1*4)(DI)
MOVL BX, (1*4)(BP)
MOVL (2*4)(BP), CX // H2 = c + H2
ADDL (2*4)(DI), CX
MOVL CX, (2*4)(DI)
MOVL CX, (2*4)(BP)
MOVL (3*4)(BP), DX // H3 = d + H3
ADDL (3*4)(DI), DX
MOVL DX, (3*4)(DI)
MOVL DX, (3*4)(BP)
MOVL (4*4)(BP), AX // H4 = e + H4
ADDL (4*4)(DI), AX
MOVL AX, (4*4)(DI)
MOVL AX, (4*4)(BP)
MOVL (5*4)(BP), BX // H5 = f + H5
ADDL (5*4)(DI), BX
MOVL BX, (5*4)(DI)
MOVL BX, (5*4)(BP)
MOVL (6*4)(BP), CX // H6 = g + H6
ADDL (6*4)(DI), CX
MOVL CX, (6*4)(DI)
MOVL CX, (6*4)(BP)
MOVL (7*4)(BP), DX // H7 = h + H7
ADDL (7*4)(DI), DX
MOVL DX, (7*4)(DI)
MOVL DX, (7*4)(BP)
ADDL $64, SI
CMPL SI, 288(SP)
JB loop
end:
RET

View file

@ -0,0 +1,7 @@
// Copyright 2017 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 notsha256
var useAVX2 = false

View file

@ -0,0 +1,424 @@
// Copyright 2013 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.
#include "textflag.h"
// SHA256 block routine. See sha256block.go for Go equivalent.
//
// The algorithm is detailed in FIPS 180-4:
//
// https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
// Wt = Mt; for 0 <= t <= 15
// Wt = SIGMA1(Wt-2) + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63
//
// a = H0
// b = H1
// c = H2
// d = H3
// e = H4
// f = H5
// g = H6
// h = H7
//
// for t = 0 to 63 {
// T1 = h + BIGSIGMA1(e) + Ch(e,f,g) + Kt + Wt
// T2 = BIGSIGMA0(a) + Maj(a,b,c)
// h = g
// g = f
// f = e
// e = d + T1
// d = c
// c = b
// b = a
// a = T1 + T2
// }
//
// H0 = a + H0
// H1 = b + H1
// H2 = c + H2
// H3 = d + H3
// H4 = e + H4
// H5 = f + H5
// H6 = g + H6
// H7 = h + H7
// Wt = Mt; for 0 <= t <= 15
#define MSGSCHEDULE0(index) \
MOVL (index*4)(SI), AX; \
BSWAPL AX; \
MOVL AX, (index*4)(BP)
// Wt = SIGMA1(Wt-2) + Wt-7 + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63
// SIGMA0(x) = ROTR(7,x) XOR ROTR(18,x) XOR SHR(3,x)
// SIGMA1(x) = ROTR(17,x) XOR ROTR(19,x) XOR SHR(10,x)
#define MSGSCHEDULE1(index) \
MOVL ((index-2)*4)(BP), AX; \
MOVL AX, CX; \
RORL $17, AX; \
MOVL CX, DX; \
RORL $19, CX; \
SHRL $10, DX; \
MOVL ((index-15)*4)(BP), BX; \
XORL CX, AX; \
MOVL BX, CX; \
XORL DX, AX; \
RORL $7, BX; \
MOVL CX, DX; \
SHRL $3, DX; \
RORL $18, CX; \
ADDL ((index-7)*4)(BP), AX; \
XORL CX, BX; \
XORL DX, BX; \
ADDL ((index-16)*4)(BP), BX; \
ADDL BX, AX; \
MOVL AX, ((index)*4)(BP)
// Calculate T1 in AX - uses AX, CX and DX registers.
// h is also used as an accumulator. Wt is passed in AX.
// T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + Kt + Wt
// BIGSIGMA1(x) = ROTR(6,x) XOR ROTR(11,x) XOR ROTR(25,x)
// Ch(x, y, z) = (x AND y) XOR (NOT x AND z)
#define SHA256T1(const, e, f, g, h) \
ADDL AX, h; \
MOVL e, AX; \
ADDL $const, h; \
MOVL e, CX; \
RORL $6, AX; \
MOVL e, DX; \
RORL $11, CX; \
XORL CX, AX; \
MOVL e, CX; \
RORL $25, DX; \
ANDL f, CX; \
XORL AX, DX; \
MOVL e, AX; \
NOTL AX; \
ADDL DX, h; \
ANDL g, AX; \
XORL CX, AX; \
ADDL h, AX
// Calculate T2 in BX - uses BX, CX, DX and DI registers.
// T2 = BIGSIGMA0(a) + Maj(a, b, c)
// BIGSIGMA0(x) = ROTR(2,x) XOR ROTR(13,x) XOR ROTR(22,x)
// Maj(x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z)
#define SHA256T2(a, b, c) \
MOVL a, DI; \
MOVL c, BX; \
RORL $2, DI; \
MOVL a, DX; \
ANDL b, BX; \
RORL $13, DX; \
MOVL a, CX; \
ANDL c, CX; \
XORL DX, DI; \
XORL CX, BX; \
MOVL a, DX; \
MOVL b, CX; \
RORL $22, DX; \
ANDL a, CX; \
XORL CX, BX; \
XORL DX, DI; \
ADDL DI, BX
// Calculate T1 and T2, then e = d + T1 and a = T1 + T2.
// The values for e and a are stored in d and h, ready for rotation.
#define SHA256ROUND(index, const, a, b, c, d, e, f, g, h) \
SHA256T1(const, e, f, g, h); \
SHA256T2(a, b, c); \
MOVL BX, h; \
ADDL AX, d; \
ADDL AX, h
#define SHA256ROUND0(index, const, a, b, c, d, e, f, g, h) \
MSGSCHEDULE0(index); \
SHA256ROUND(index, const, a, b, c, d, e, f, g, h)
#define SHA256ROUND1(index, const, a, b, c, d, e, f, g, h) \
MSGSCHEDULE1(index); \
SHA256ROUND(index, const, a, b, c, d, e, f, g, h)
TEXT ·block(SB), 0, $536-32
MOVQ p_base+8(FP), SI
MOVQ p_len+16(FP), DX
SHRQ $6, DX
SHLQ $6, DX
LEAQ (SI)(DX*1), DI
MOVQ DI, 256(SP)
CMPQ SI, DI
JEQ end
MOVQ dig+0(FP), BP
MOVL (0*4)(BP), R8 // a = H0
MOVL (1*4)(BP), R9 // b = H1
MOVL (2*4)(BP), R10 // c = H2
MOVL (3*4)(BP), R11 // d = H3
MOVL (4*4)(BP), R12 // e = H4
MOVL (5*4)(BP), R13 // f = H5
MOVL (6*4)(BP), R14 // g = H6
MOVL (7*4)(BP), R15 // h = H7
loop:
MOVQ SP, BP
SHA256ROUND0(0, 0x428a2f98, R8, R9, R10, R11, R12, R13, R14, R15)
SHA256ROUND0(1, 0x71374491, R15, R8, R9, R10, R11, R12, R13, R14)
SHA256ROUND0(2, 0xb5c0fbcf, R14, R15, R8, R9, R10, R11, R12, R13)
SHA256ROUND0(3, 0xe9b5dba5, R13, R14, R15, R8, R9, R10, R11, R12)
SHA256ROUND0(4, 0x3956c25b, R12, R13, R14, R15, R8, R9, R10, R11)
SHA256ROUND0(5, 0x59f111f1, R11, R12, R13, R14, R15, R8, R9, R10)
SHA256ROUND0(6, 0x923f82a4, R10, R11, R12, R13, R14, R15, R8, R9)
SHA256ROUND0(7, 0xab1c5ed5, R9, R10, R11, R12, R13, R14, R15, R8)
SHA256ROUND0(8, 0xd807aa98, R8, R9, R10, R11, R12, R13, R14, R15)
SHA256ROUND0(9, 0x12835b01, R15, R8, R9, R10, R11, R12, R13, R14)
SHA256ROUND0(10, 0x243185be, R14, R15, R8, R9, R10, R11, R12, R13)
SHA256ROUND0(11, 0x550c7dc3, R13, R14, R15, R8, R9, R10, R11, R12)
SHA256ROUND0(12, 0x72be5d74, R12, R13, R14, R15, R8, R9, R10, R11)
SHA256ROUND0(13, 0x80deb1fe, R11, R12, R13, R14, R15, R8, R9, R10)
SHA256ROUND0(14, 0x9bdc06a7, R10, R11, R12, R13, R14, R15, R8, R9)
SHA256ROUND0(15, 0xc19bf174, R9, R10, R11, R12, R13, R14, R15, R8)
SHA256ROUND1(16, 0xe49b69c1, R8, R9, R10, R11, R12, R13, R14, R15)
SHA256ROUND1(17, 0xefbe4786, R15, R8, R9, R10, R11, R12, R13, R14)
SHA256ROUND1(18, 0x0fc19dc6, R14, R15, R8, R9, R10, R11, R12, R13)
SHA256ROUND1(19, 0x240ca1cc, R13, R14, R15, R8, R9, R10, R11, R12)
SHA256ROUND1(20, 0x2de92c6f, R12, R13, R14, R15, R8, R9, R10, R11)
SHA256ROUND1(21, 0x4a7484aa, R11, R12, R13, R14, R15, R8, R9, R10)
SHA256ROUND1(22, 0x5cb0a9dc, R10, R11, R12, R13, R14, R15, R8, R9)
SHA256ROUND1(23, 0x76f988da, R9, R10, R11, R12, R13, R14, R15, R8)
SHA256ROUND1(24, 0x983e5152, R8, R9, R10, R11, R12, R13, R14, R15)
SHA256ROUND1(25, 0xa831c66d, R15, R8, R9, R10, R11, R12, R13, R14)
SHA256ROUND1(26, 0xb00327c8, R14, R15, R8, R9, R10, R11, R12, R13)
SHA256ROUND1(27, 0xbf597fc7, R13, R14, R15, R8, R9, R10, R11, R12)
SHA256ROUND1(28, 0xc6e00bf3, R12, R13, R14, R15, R8, R9, R10, R11)
SHA256ROUND1(29, 0xd5a79147, R11, R12, R13, R14, R15, R8, R9, R10)
SHA256ROUND1(30, 0x06ca6351, R10, R11, R12, R13, R14, R15, R8, R9)
SHA256ROUND1(31, 0x14292967, R9, R10, R11, R12, R13, R14, R15, R8)
SHA256ROUND1(32, 0x27b70a85, R8, R9, R10, R11, R12, R13, R14, R15)
SHA256ROUND1(33, 0x2e1b2138, R15, R8, R9, R10, R11, R12, R13, R14)
SHA256ROUND1(34, 0x4d2c6dfc, R14, R15, R8, R9, R10, R11, R12, R13)
SHA256ROUND1(35, 0x53380d13, R13, R14, R15, R8, R9, R10, R11, R12)
SHA256ROUND1(36, 0x650a7354, R12, R13, R14, R15, R8, R9, R10, R11)
SHA256ROUND1(37, 0x766a0abb, R11, R12, R13, R14, R15, R8, R9, R10)
SHA256ROUND1(38, 0x81c2c92e, R10, R11, R12, R13, R14, R15, R8, R9)
SHA256ROUND1(39, 0x92722c85, R9, R10, R11, R12, R13, R14, R15, R8)
SHA256ROUND1(40, 0xa2bfe8a1, R8, R9, R10, R11, R12, R13, R14, R15)
SHA256ROUND1(41, 0xa81a664b, R15, R8, R9, R10, R11, R12, R13, R14)
SHA256ROUND1(42, 0xc24b8b70, R14, R15, R8, R9, R10, R11, R12, R13)
SHA256ROUND1(43, 0xc76c51a3, R13, R14, R15, R8, R9, R10, R11, R12)
SHA256ROUND1(44, 0xd192e819, R12, R13, R14, R15, R8, R9, R10, R11)
SHA256ROUND1(45, 0xd6990624, R11, R12, R13, R14, R15, R8, R9, R10)
SHA256ROUND1(46, 0xf40e3585, R10, R11, R12, R13, R14, R15, R8, R9)
SHA256ROUND1(47, 0x106aa070, R9, R10, R11, R12, R13, R14, R15, R8)
SHA256ROUND1(48, 0x19a4c116, R8, R9, R10, R11, R12, R13, R14, R15)
SHA256ROUND1(49, 0x1e376c08, R15, R8, R9, R10, R11, R12, R13, R14)
SHA256ROUND1(50, 0x2748774c, R14, R15, R8, R9, R10, R11, R12, R13)
SHA256ROUND1(51, 0x34b0bcb5, R13, R14, R15, R8, R9, R10, R11, R12)
SHA256ROUND1(52, 0x391c0cb3, R12, R13, R14, R15, R8, R9, R10, R11)
SHA256ROUND1(53, 0x4ed8aa4a, R11, R12, R13, R14, R15, R8, R9, R10)
SHA256ROUND1(54, 0x5b9cca4f, R10, R11, R12, R13, R14, R15, R8, R9)
SHA256ROUND1(55, 0x682e6ff3, R9, R10, R11, R12, R13, R14, R15, R8)
SHA256ROUND1(56, 0x748f82ee, R8, R9, R10, R11, R12, R13, R14, R15)
SHA256ROUND1(57, 0x78a5636f, R15, R8, R9, R10, R11, R12, R13, R14)
SHA256ROUND1(58, 0x84c87814, R14, R15, R8, R9, R10, R11, R12, R13)
SHA256ROUND1(59, 0x8cc70208, R13, R14, R15, R8, R9, R10, R11, R12)
SHA256ROUND1(60, 0x90befffa, R12, R13, R14, R15, R8, R9, R10, R11)
SHA256ROUND1(61, 0xa4506ceb, R11, R12, R13, R14, R15, R8, R9, R10)
SHA256ROUND1(62, 0xbef9a3f7, R10, R11, R12, R13, R14, R15, R8, R9)
SHA256ROUND1(63, 0xc67178f2, R9, R10, R11, R12, R13, R14, R15, R8)
MOVQ dig+0(FP), BP
ADDL (0*4)(BP), R8 // H0 = a + H0
MOVL R8, (0*4)(BP)
ADDL (1*4)(BP), R9 // H1 = b + H1
MOVL R9, (1*4)(BP)
ADDL (2*4)(BP), R10 // H2 = c + H2
MOVL R10, (2*4)(BP)
ADDL (3*4)(BP), R11 // H3 = d + H3
MOVL R11, (3*4)(BP)
ADDL (4*4)(BP), R12 // H4 = e + H4
MOVL R12, (4*4)(BP)
ADDL (5*4)(BP), R13 // H5 = f + H5
MOVL R13, (5*4)(BP)
ADDL (6*4)(BP), R14 // H6 = g + H6
MOVL R14, (6*4)(BP)
ADDL (7*4)(BP), R15 // H7 = h + H7
MOVL R15, (7*4)(BP)
ADDQ $64, SI
CMPQ SI, 256(SP)
JB loop
end:
RET
// shuffle byte order from LE to BE
DATA flip_mask<>+0x00(SB)/8, $0x0405060700010203
DATA flip_mask<>+0x08(SB)/8, $0x0c0d0e0f08090a0b
DATA flip_mask<>+0x10(SB)/8, $0x0405060700010203
DATA flip_mask<>+0x18(SB)/8, $0x0c0d0e0f08090a0b
GLOBL flip_mask<>(SB), 8, $32
// shuffle xBxA -> 00BA
DATA shuff_00BA<>+0x00(SB)/8, $0x0b0a090803020100
DATA shuff_00BA<>+0x08(SB)/8, $0xFFFFFFFFFFFFFFFF
DATA shuff_00BA<>+0x10(SB)/8, $0x0b0a090803020100
DATA shuff_00BA<>+0x18(SB)/8, $0xFFFFFFFFFFFFFFFF
GLOBL shuff_00BA<>(SB), 8, $32
// shuffle xDxC -> DC00
DATA shuff_DC00<>+0x00(SB)/8, $0xFFFFFFFFFFFFFFFF
DATA shuff_DC00<>+0x08(SB)/8, $0x0b0a090803020100
DATA shuff_DC00<>+0x10(SB)/8, $0xFFFFFFFFFFFFFFFF
DATA shuff_DC00<>+0x18(SB)/8, $0x0b0a090803020100
GLOBL shuff_DC00<>(SB), 8, $32
// Round specific constants
DATA K256<>+0x00(SB)/4, $0x428a2f98 // k1
DATA K256<>+0x04(SB)/4, $0x71374491 // k2
DATA K256<>+0x08(SB)/4, $0xb5c0fbcf // k3
DATA K256<>+0x0c(SB)/4, $0xe9b5dba5 // k4
DATA K256<>+0x10(SB)/4, $0x428a2f98 // k1
DATA K256<>+0x14(SB)/4, $0x71374491 // k2
DATA K256<>+0x18(SB)/4, $0xb5c0fbcf // k3
DATA K256<>+0x1c(SB)/4, $0xe9b5dba5 // k4
DATA K256<>+0x20(SB)/4, $0x3956c25b // k5 - k8
DATA K256<>+0x24(SB)/4, $0x59f111f1
DATA K256<>+0x28(SB)/4, $0x923f82a4
DATA K256<>+0x2c(SB)/4, $0xab1c5ed5
DATA K256<>+0x30(SB)/4, $0x3956c25b
DATA K256<>+0x34(SB)/4, $0x59f111f1
DATA K256<>+0x38(SB)/4, $0x923f82a4
DATA K256<>+0x3c(SB)/4, $0xab1c5ed5
DATA K256<>+0x40(SB)/4, $0xd807aa98 // k9 - k12
DATA K256<>+0x44(SB)/4, $0x12835b01
DATA K256<>+0x48(SB)/4, $0x243185be
DATA K256<>+0x4c(SB)/4, $0x550c7dc3
DATA K256<>+0x50(SB)/4, $0xd807aa98
DATA K256<>+0x54(SB)/4, $0x12835b01
DATA K256<>+0x58(SB)/4, $0x243185be
DATA K256<>+0x5c(SB)/4, $0x550c7dc3
DATA K256<>+0x60(SB)/4, $0x72be5d74 // k13 - k16
DATA K256<>+0x64(SB)/4, $0x80deb1fe
DATA K256<>+0x68(SB)/4, $0x9bdc06a7
DATA K256<>+0x6c(SB)/4, $0xc19bf174
DATA K256<>+0x70(SB)/4, $0x72be5d74
DATA K256<>+0x74(SB)/4, $0x80deb1fe
DATA K256<>+0x78(SB)/4, $0x9bdc06a7
DATA K256<>+0x7c(SB)/4, $0xc19bf174
DATA K256<>+0x80(SB)/4, $0xe49b69c1 // k17 - k20
DATA K256<>+0x84(SB)/4, $0xefbe4786
DATA K256<>+0x88(SB)/4, $0x0fc19dc6
DATA K256<>+0x8c(SB)/4, $0x240ca1cc
DATA K256<>+0x90(SB)/4, $0xe49b69c1
DATA K256<>+0x94(SB)/4, $0xefbe4786
DATA K256<>+0x98(SB)/4, $0x0fc19dc6
DATA K256<>+0x9c(SB)/4, $0x240ca1cc
DATA K256<>+0xa0(SB)/4, $0x2de92c6f // k21 - k24
DATA K256<>+0xa4(SB)/4, $0x4a7484aa
DATA K256<>+0xa8(SB)/4, $0x5cb0a9dc
DATA K256<>+0xac(SB)/4, $0x76f988da
DATA K256<>+0xb0(SB)/4, $0x2de92c6f
DATA K256<>+0xb4(SB)/4, $0x4a7484aa
DATA K256<>+0xb8(SB)/4, $0x5cb0a9dc
DATA K256<>+0xbc(SB)/4, $0x76f988da
DATA K256<>+0xc0(SB)/4, $0x983e5152 // k25 - k28
DATA K256<>+0xc4(SB)/4, $0xa831c66d
DATA K256<>+0xc8(SB)/4, $0xb00327c8
DATA K256<>+0xcc(SB)/4, $0xbf597fc7
DATA K256<>+0xd0(SB)/4, $0x983e5152
DATA K256<>+0xd4(SB)/4, $0xa831c66d
DATA K256<>+0xd8(SB)/4, $0xb00327c8
DATA K256<>+0xdc(SB)/4, $0xbf597fc7
DATA K256<>+0xe0(SB)/4, $0xc6e00bf3 // k29 - k32
DATA K256<>+0xe4(SB)/4, $0xd5a79147
DATA K256<>+0xe8(SB)/4, $0x06ca6351
DATA K256<>+0xec(SB)/4, $0x14292967
DATA K256<>+0xf0(SB)/4, $0xc6e00bf3
DATA K256<>+0xf4(SB)/4, $0xd5a79147
DATA K256<>+0xf8(SB)/4, $0x06ca6351
DATA K256<>+0xfc(SB)/4, $0x14292967
DATA K256<>+0x100(SB)/4, $0x27b70a85
DATA K256<>+0x104(SB)/4, $0x2e1b2138
DATA K256<>+0x108(SB)/4, $0x4d2c6dfc
DATA K256<>+0x10c(SB)/4, $0x53380d13
DATA K256<>+0x110(SB)/4, $0x27b70a85
DATA K256<>+0x114(SB)/4, $0x2e1b2138
DATA K256<>+0x118(SB)/4, $0x4d2c6dfc
DATA K256<>+0x11c(SB)/4, $0x53380d13
DATA K256<>+0x120(SB)/4, $0x650a7354
DATA K256<>+0x124(SB)/4, $0x766a0abb
DATA K256<>+0x128(SB)/4, $0x81c2c92e
DATA K256<>+0x12c(SB)/4, $0x92722c85
DATA K256<>+0x130(SB)/4, $0x650a7354
DATA K256<>+0x134(SB)/4, $0x766a0abb
DATA K256<>+0x138(SB)/4, $0x81c2c92e
DATA K256<>+0x13c(SB)/4, $0x92722c85
DATA K256<>+0x140(SB)/4, $0xa2bfe8a1
DATA K256<>+0x144(SB)/4, $0xa81a664b
DATA K256<>+0x148(SB)/4, $0xc24b8b70
DATA K256<>+0x14c(SB)/4, $0xc76c51a3
DATA K256<>+0x150(SB)/4, $0xa2bfe8a1
DATA K256<>+0x154(SB)/4, $0xa81a664b
DATA K256<>+0x158(SB)/4, $0xc24b8b70
DATA K256<>+0x15c(SB)/4, $0xc76c51a3
DATA K256<>+0x160(SB)/4, $0xd192e819
DATA K256<>+0x164(SB)/4, $0xd6990624
DATA K256<>+0x168(SB)/4, $0xf40e3585
DATA K256<>+0x16c(SB)/4, $0x106aa070
DATA K256<>+0x170(SB)/4, $0xd192e819
DATA K256<>+0x174(SB)/4, $0xd6990624
DATA K256<>+0x178(SB)/4, $0xf40e3585
DATA K256<>+0x17c(SB)/4, $0x106aa070
DATA K256<>+0x180(SB)/4, $0x19a4c116
DATA K256<>+0x184(SB)/4, $0x1e376c08
DATA K256<>+0x188(SB)/4, $0x2748774c
DATA K256<>+0x18c(SB)/4, $0x34b0bcb5
DATA K256<>+0x190(SB)/4, $0x19a4c116
DATA K256<>+0x194(SB)/4, $0x1e376c08
DATA K256<>+0x198(SB)/4, $0x2748774c
DATA K256<>+0x19c(SB)/4, $0x34b0bcb5
DATA K256<>+0x1a0(SB)/4, $0x391c0cb3
DATA K256<>+0x1a4(SB)/4, $0x4ed8aa4a
DATA K256<>+0x1a8(SB)/4, $0x5b9cca4f
DATA K256<>+0x1ac(SB)/4, $0x682e6ff3
DATA K256<>+0x1b0(SB)/4, $0x391c0cb3
DATA K256<>+0x1b4(SB)/4, $0x4ed8aa4a
DATA K256<>+0x1b8(SB)/4, $0x5b9cca4f
DATA K256<>+0x1bc(SB)/4, $0x682e6ff3
DATA K256<>+0x1c0(SB)/4, $0x748f82ee
DATA K256<>+0x1c4(SB)/4, $0x78a5636f
DATA K256<>+0x1c8(SB)/4, $0x84c87814
DATA K256<>+0x1cc(SB)/4, $0x8cc70208
DATA K256<>+0x1d0(SB)/4, $0x748f82ee
DATA K256<>+0x1d4(SB)/4, $0x78a5636f
DATA K256<>+0x1d8(SB)/4, $0x84c87814
DATA K256<>+0x1dc(SB)/4, $0x8cc70208
DATA K256<>+0x1e0(SB)/4, $0x90befffa
DATA K256<>+0x1e4(SB)/4, $0xa4506ceb
DATA K256<>+0x1e8(SB)/4, $0xbef9a3f7
DATA K256<>+0x1ec(SB)/4, $0xc67178f2
DATA K256<>+0x1f0(SB)/4, $0x90befffa
DATA K256<>+0x1f4(SB)/4, $0xa4506ceb
DATA K256<>+0x1f8(SB)/4, $0xbef9a3f7
DATA K256<>+0x1fc(SB)/4, $0xc67178f2
GLOBL K256<>(SB), (NOPTR + RODATA), $512

View file

@ -0,0 +1,12 @@
// Copyright 2013 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 386 || amd64 || ppc64le || ppc64
// +build 386 amd64 ppc64le ppc64
package notsha256
//go:noescape
func block(dig *digest, p []byte)

View file

@ -0,0 +1,12 @@
// Copyright 2016 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 !amd64 && !386 && !ppc64le && !ppc64
// +build !amd64,!386,!ppc64le,!ppc64
package notsha256
func block(dig *digest, p []byte) {
blockGeneric(dig, p)
}

View file

@ -0,0 +1,424 @@
// Copyright 2016 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 ppc64 || ppc64le
// +build ppc64 ppc64le
// Based on CRYPTOGAMS code with the following comment:
// # ====================================================================
// # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
// # project. The module is, however, dual licensed under OpenSSL and
// # CRYPTOGAMS licenses depending on where you obtain it. For further
// # details see http://www.openssl.org/~appro/cryptogams/.
// # ====================================================================
#include "textflag.h"
// SHA256 block routine. See sha256block.go for Go equivalent.
//
// The algorithm is detailed in FIPS 180-4:
//
// https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
//
// Wt = Mt; for 0 <= t <= 15
// Wt = SIGMA1(Wt-2) + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63
//
// a = H0
// b = H1
// c = H2
// d = H3
// e = H4
// f = H5
// g = H6
// h = H7
//
// for t = 0 to 63 {
// T1 = h + BIGSIGMA1(e) + Ch(e,f,g) + Kt + Wt
// T2 = BIGSIGMA0(a) + Maj(a,b,c)
// h = g
// g = f
// f = e
// e = d + T1
// d = c
// c = b
// b = a
// a = T1 + T2
// }
//
// H0 = a + H0
// H1 = b + H1
// H2 = c + H2
// H3 = d + H3
// H4 = e + H4
// H5 = f + H5
// H6 = g + H6
// H7 = h + H7
#define CTX R3
#define INP R4
#define END R5
#define TBL R6
#define IDX R7
#define LEN R9
#define TEMP R12
#define HEX00 R0
#define HEX10 R10
// V0-V7 are A-H
// V8-V23 are used for the message schedule
#define KI V24
#define FUNC V25
#define S0 V26
#define S1 V27
#define s0 V28
#define s1 V29
#define LEMASK V31 // Permutation control register for little endian
// 4 copies of each Kt, to fill all 4 words of a vector register
DATA ·kcon+0x000(SB)/8, $0x428a2f98428a2f98
DATA ·kcon+0x008(SB)/8, $0x428a2f98428a2f98
DATA ·kcon+0x010(SB)/8, $0x7137449171374491
DATA ·kcon+0x018(SB)/8, $0x7137449171374491
DATA ·kcon+0x020(SB)/8, $0xb5c0fbcfb5c0fbcf
DATA ·kcon+0x028(SB)/8, $0xb5c0fbcfb5c0fbcf
DATA ·kcon+0x030(SB)/8, $0xe9b5dba5e9b5dba5
DATA ·kcon+0x038(SB)/8, $0xe9b5dba5e9b5dba5
DATA ·kcon+0x040(SB)/8, $0x3956c25b3956c25b
DATA ·kcon+0x048(SB)/8, $0x3956c25b3956c25b
DATA ·kcon+0x050(SB)/8, $0x59f111f159f111f1
DATA ·kcon+0x058(SB)/8, $0x59f111f159f111f1
DATA ·kcon+0x060(SB)/8, $0x923f82a4923f82a4
DATA ·kcon+0x068(SB)/8, $0x923f82a4923f82a4
DATA ·kcon+0x070(SB)/8, $0xab1c5ed5ab1c5ed5
DATA ·kcon+0x078(SB)/8, $0xab1c5ed5ab1c5ed5
DATA ·kcon+0x080(SB)/8, $0xd807aa98d807aa98
DATA ·kcon+0x088(SB)/8, $0xd807aa98d807aa98
DATA ·kcon+0x090(SB)/8, $0x12835b0112835b01
DATA ·kcon+0x098(SB)/8, $0x12835b0112835b01
DATA ·kcon+0x0A0(SB)/8, $0x243185be243185be
DATA ·kcon+0x0A8(SB)/8, $0x243185be243185be
DATA ·kcon+0x0B0(SB)/8, $0x550c7dc3550c7dc3
DATA ·kcon+0x0B8(SB)/8, $0x550c7dc3550c7dc3
DATA ·kcon+0x0C0(SB)/8, $0x72be5d7472be5d74
DATA ·kcon+0x0C8(SB)/8, $0x72be5d7472be5d74
DATA ·kcon+0x0D0(SB)/8, $0x80deb1fe80deb1fe
DATA ·kcon+0x0D8(SB)/8, $0x80deb1fe80deb1fe
DATA ·kcon+0x0E0(SB)/8, $0x9bdc06a79bdc06a7
DATA ·kcon+0x0E8(SB)/8, $0x9bdc06a79bdc06a7
DATA ·kcon+0x0F0(SB)/8, $0xc19bf174c19bf174
DATA ·kcon+0x0F8(SB)/8, $0xc19bf174c19bf174
DATA ·kcon+0x100(SB)/8, $0xe49b69c1e49b69c1
DATA ·kcon+0x108(SB)/8, $0xe49b69c1e49b69c1
DATA ·kcon+0x110(SB)/8, $0xefbe4786efbe4786
DATA ·kcon+0x118(SB)/8, $0xefbe4786efbe4786
DATA ·kcon+0x120(SB)/8, $0x0fc19dc60fc19dc6
DATA ·kcon+0x128(SB)/8, $0x0fc19dc60fc19dc6
DATA ·kcon+0x130(SB)/8, $0x240ca1cc240ca1cc
DATA ·kcon+0x138(SB)/8, $0x240ca1cc240ca1cc
DATA ·kcon+0x140(SB)/8, $0x2de92c6f2de92c6f
DATA ·kcon+0x148(SB)/8, $0x2de92c6f2de92c6f
DATA ·kcon+0x150(SB)/8, $0x4a7484aa4a7484aa
DATA ·kcon+0x158(SB)/8, $0x4a7484aa4a7484aa
DATA ·kcon+0x160(SB)/8, $0x5cb0a9dc5cb0a9dc
DATA ·kcon+0x168(SB)/8, $0x5cb0a9dc5cb0a9dc
DATA ·kcon+0x170(SB)/8, $0x76f988da76f988da
DATA ·kcon+0x178(SB)/8, $0x76f988da76f988da
DATA ·kcon+0x180(SB)/8, $0x983e5152983e5152
DATA ·kcon+0x188(SB)/8, $0x983e5152983e5152
DATA ·kcon+0x190(SB)/8, $0xa831c66da831c66d
DATA ·kcon+0x198(SB)/8, $0xa831c66da831c66d
DATA ·kcon+0x1A0(SB)/8, $0xb00327c8b00327c8
DATA ·kcon+0x1A8(SB)/8, $0xb00327c8b00327c8
DATA ·kcon+0x1B0(SB)/8, $0xbf597fc7bf597fc7
DATA ·kcon+0x1B8(SB)/8, $0xbf597fc7bf597fc7
DATA ·kcon+0x1C0(SB)/8, $0xc6e00bf3c6e00bf3
DATA ·kcon+0x1C8(SB)/8, $0xc6e00bf3c6e00bf3
DATA ·kcon+0x1D0(SB)/8, $0xd5a79147d5a79147
DATA ·kcon+0x1D8(SB)/8, $0xd5a79147d5a79147
DATA ·kcon+0x1E0(SB)/8, $0x06ca635106ca6351
DATA ·kcon+0x1E8(SB)/8, $0x06ca635106ca6351
DATA ·kcon+0x1F0(SB)/8, $0x1429296714292967
DATA ·kcon+0x1F8(SB)/8, $0x1429296714292967
DATA ·kcon+0x200(SB)/8, $0x27b70a8527b70a85
DATA ·kcon+0x208(SB)/8, $0x27b70a8527b70a85
DATA ·kcon+0x210(SB)/8, $0x2e1b21382e1b2138
DATA ·kcon+0x218(SB)/8, $0x2e1b21382e1b2138
DATA ·kcon+0x220(SB)/8, $0x4d2c6dfc4d2c6dfc
DATA ·kcon+0x228(SB)/8, $0x4d2c6dfc4d2c6dfc
DATA ·kcon+0x230(SB)/8, $0x53380d1353380d13
DATA ·kcon+0x238(SB)/8, $0x53380d1353380d13
DATA ·kcon+0x240(SB)/8, $0x650a7354650a7354
DATA ·kcon+0x248(SB)/8, $0x650a7354650a7354
DATA ·kcon+0x250(SB)/8, $0x766a0abb766a0abb
DATA ·kcon+0x258(SB)/8, $0x766a0abb766a0abb
DATA ·kcon+0x260(SB)/8, $0x81c2c92e81c2c92e
DATA ·kcon+0x268(SB)/8, $0x81c2c92e81c2c92e
DATA ·kcon+0x270(SB)/8, $0x92722c8592722c85
DATA ·kcon+0x278(SB)/8, $0x92722c8592722c85
DATA ·kcon+0x280(SB)/8, $0xa2bfe8a1a2bfe8a1
DATA ·kcon+0x288(SB)/8, $0xa2bfe8a1a2bfe8a1
DATA ·kcon+0x290(SB)/8, $0xa81a664ba81a664b
DATA ·kcon+0x298(SB)/8, $0xa81a664ba81a664b
DATA ·kcon+0x2A0(SB)/8, $0xc24b8b70c24b8b70
DATA ·kcon+0x2A8(SB)/8, $0xc24b8b70c24b8b70
DATA ·kcon+0x2B0(SB)/8, $0xc76c51a3c76c51a3
DATA ·kcon+0x2B8(SB)/8, $0xc76c51a3c76c51a3
DATA ·kcon+0x2C0(SB)/8, $0xd192e819d192e819
DATA ·kcon+0x2C8(SB)/8, $0xd192e819d192e819
DATA ·kcon+0x2D0(SB)/8, $0xd6990624d6990624
DATA ·kcon+0x2D8(SB)/8, $0xd6990624d6990624
DATA ·kcon+0x2E0(SB)/8, $0xf40e3585f40e3585
DATA ·kcon+0x2E8(SB)/8, $0xf40e3585f40e3585
DATA ·kcon+0x2F0(SB)/8, $0x106aa070106aa070
DATA ·kcon+0x2F8(SB)/8, $0x106aa070106aa070
DATA ·kcon+0x300(SB)/8, $0x19a4c11619a4c116
DATA ·kcon+0x308(SB)/8, $0x19a4c11619a4c116
DATA ·kcon+0x310(SB)/8, $0x1e376c081e376c08
DATA ·kcon+0x318(SB)/8, $0x1e376c081e376c08
DATA ·kcon+0x320(SB)/8, $0x2748774c2748774c
DATA ·kcon+0x328(SB)/8, $0x2748774c2748774c
DATA ·kcon+0x330(SB)/8, $0x34b0bcb534b0bcb5
DATA ·kcon+0x338(SB)/8, $0x34b0bcb534b0bcb5
DATA ·kcon+0x340(SB)/8, $0x391c0cb3391c0cb3
DATA ·kcon+0x348(SB)/8, $0x391c0cb3391c0cb3
DATA ·kcon+0x350(SB)/8, $0x4ed8aa4a4ed8aa4a
DATA ·kcon+0x358(SB)/8, $0x4ed8aa4a4ed8aa4a
DATA ·kcon+0x360(SB)/8, $0x5b9cca4f5b9cca4f
DATA ·kcon+0x368(SB)/8, $0x5b9cca4f5b9cca4f
DATA ·kcon+0x370(SB)/8, $0x682e6ff3682e6ff3
DATA ·kcon+0x378(SB)/8, $0x682e6ff3682e6ff3
DATA ·kcon+0x380(SB)/8, $0x748f82ee748f82ee
DATA ·kcon+0x388(SB)/8, $0x748f82ee748f82ee
DATA ·kcon+0x390(SB)/8, $0x78a5636f78a5636f
DATA ·kcon+0x398(SB)/8, $0x78a5636f78a5636f
DATA ·kcon+0x3A0(SB)/8, $0x84c8781484c87814
DATA ·kcon+0x3A8(SB)/8, $0x84c8781484c87814
DATA ·kcon+0x3B0(SB)/8, $0x8cc702088cc70208
DATA ·kcon+0x3B8(SB)/8, $0x8cc702088cc70208
DATA ·kcon+0x3C0(SB)/8, $0x90befffa90befffa
DATA ·kcon+0x3C8(SB)/8, $0x90befffa90befffa
DATA ·kcon+0x3D0(SB)/8, $0xa4506ceba4506ceb
DATA ·kcon+0x3D8(SB)/8, $0xa4506ceba4506ceb
DATA ·kcon+0x3E0(SB)/8, $0xbef9a3f7bef9a3f7
DATA ·kcon+0x3E8(SB)/8, $0xbef9a3f7bef9a3f7
DATA ·kcon+0x3F0(SB)/8, $0xc67178f2c67178f2
DATA ·kcon+0x3F8(SB)/8, $0xc67178f2c67178f2
DATA ·kcon+0x400(SB)/8, $0x0000000000000000
DATA ·kcon+0x408(SB)/8, $0x0000000000000000
#ifdef GOARCH_ppc64le
DATA ·kcon+0x410(SB)/8, $0x1011121310111213 // permutation control vectors
DATA ·kcon+0x418(SB)/8, $0x1011121300010203
DATA ·kcon+0x420(SB)/8, $0x1011121310111213
DATA ·kcon+0x428(SB)/8, $0x0405060700010203
DATA ·kcon+0x430(SB)/8, $0x1011121308090a0b
DATA ·kcon+0x438(SB)/8, $0x0405060700010203
#else
DATA ·kcon+0x410(SB)/8, $0x1011121300010203
DATA ·kcon+0x418(SB)/8, $0x1011121310111213 // permutation control vectors
DATA ·kcon+0x420(SB)/8, $0x0405060700010203
DATA ·kcon+0x428(SB)/8, $0x1011121310111213
DATA ·kcon+0x430(SB)/8, $0x0001020304050607
DATA ·kcon+0x438(SB)/8, $0x08090a0b10111213
#endif
GLOBL ·kcon(SB), RODATA, $1088
#define SHA256ROUND0(a, b, c, d, e, f, g, h, xi) \
VSEL g, f, e, FUNC; \
VSHASIGMAW $15, e, $1, S1; \
VADDUWM xi, h, h; \
VSHASIGMAW $0, a, $1, S0; \
VADDUWM FUNC, h, h; \
VXOR b, a, FUNC; \
VADDUWM S1, h, h; \
VSEL b, c, FUNC, FUNC; \
VADDUWM KI, g, g; \
VADDUWM h, d, d; \
VADDUWM FUNC, S0, S0; \
LVX (TBL)(IDX), KI; \
ADD $16, IDX; \
VADDUWM S0, h, h
#define SHA256ROUND1(a, b, c, d, e, f, g, h, xi, xj, xj_1, xj_9, xj_14) \
VSHASIGMAW $0, xj_1, $0, s0; \
VSEL g, f, e, FUNC; \
VSHASIGMAW $15, e, $1, S1; \
VADDUWM xi, h, h; \
VSHASIGMAW $0, a, $1, S0; \
VSHASIGMAW $15, xj_14, $0, s1; \
VADDUWM FUNC, h, h; \
VXOR b, a, FUNC; \
VADDUWM xj_9, xj, xj; \
VADDUWM S1, h, h; \
VSEL b, c, FUNC, FUNC; \
VADDUWM KI, g, g; \
VADDUWM h, d, d; \
VADDUWM FUNC, S0, S0; \
VADDUWM s0, xj, xj; \
LVX (TBL)(IDX), KI; \
ADD $16, IDX; \
VADDUWM S0, h, h; \
VADDUWM s1, xj, xj
#ifdef GOARCH_ppc64le
#define VPERMLE(va,vb,vc,vt) VPERM va, vb, vc, vt
#else
#define VPERMLE(va,vb,vc,vt)
#endif
// func block(dig *digest, p []byte)
TEXT ·block(SB),0,$0-32
MOVD dig+0(FP), CTX
MOVD p_base+8(FP), INP
MOVD p_len+16(FP), LEN
SRD $6, LEN
SLD $6, LEN
ADD INP, LEN, END
CMP INP, END
BEQ end
MOVD $·kcon(SB), TBL
MOVWZ $0x10, HEX10
MOVWZ $8, IDX
#ifdef GOARCH_ppc64le
LVSL (IDX)(R0), LEMASK
VSPLTISB $0x0F, KI
VXOR KI, LEMASK, LEMASK
#endif
LXVW4X (CTX)(HEX00), VS32 // v0 = vs32
LXVW4X (CTX)(HEX10), VS36 // v4 = vs36
// unpack the input values into vector registers
VSLDOI $4, V0, V0, V1
VSLDOI $8, V0, V0, V2
VSLDOI $12, V0, V0, V3
VSLDOI $4, V4, V4, V5
VSLDOI $8, V4, V4, V6
VSLDOI $12, V4, V4, V7
loop:
LVX (TBL)(HEX00), KI
MOVWZ $16, IDX
LXVD2X (INP)(R0), VS40 // load v8 (=vs40) in advance
ADD $16, INP
// Offload to VSR24-31 (aka FPR24-31)
XXLOR V0, V0, VS24
XXLOR V1, V1, VS25
XXLOR V2, V2, VS26
XXLOR V3, V3, VS27
XXLOR V4, V4, VS28
XXLOR V5, V5, VS29
XXLOR V6, V6, VS30
XXLOR V7, V7, VS31
VADDUWM KI, V7, V7 // h+K[i]
LVX (TBL)(IDX), KI
ADD $16, IDX
VPERMLE(V8, V8, LEMASK, V8)
SHA256ROUND0(V0, V1, V2, V3, V4, V5, V6, V7, V8)
VSLDOI $4, V8, V8, V9
SHA256ROUND0(V7, V0, V1, V2, V3, V4, V5, V6, V9)
VSLDOI $4, V9, V9, V10
SHA256ROUND0(V6, V7, V0, V1, V2, V3, V4, V5, V10)
LXVD2X (INP)(R0), VS44 // load v12 (=vs44) in advance
ADD $16, INP, INP
VSLDOI $4, V10, V10, V11
SHA256ROUND0(V5, V6, V7, V0, V1, V2, V3, V4, V11)
VPERMLE(V12, V12, LEMASK, V12)
SHA256ROUND0(V4, V5, V6, V7, V0, V1, V2, V3, V12)
VSLDOI $4, V12, V12, V13
SHA256ROUND0(V3, V4, V5, V6, V7, V0, V1, V2, V13)
VSLDOI $4, V13, V13, V14
SHA256ROUND0(V2, V3, V4, V5, V6, V7, V0, V1, V14)
LXVD2X (INP)(R0), VS48 // load v16 (=vs48) in advance
ADD $16, INP, INP
VSLDOI $4, V14, V14, V15
SHA256ROUND0(V1, V2, V3, V4, V5, V6, V7, V0, V15)
VPERMLE(V16, V16, LEMASK, V16)
SHA256ROUND0(V0, V1, V2, V3, V4, V5, V6, V7, V16)
VSLDOI $4, V16, V16, V17
SHA256ROUND0(V7, V0, V1, V2, V3, V4, V5, V6, V17)
VSLDOI $4, V17, V17, V18
SHA256ROUND0(V6, V7, V0, V1, V2, V3, V4, V5, V18)
VSLDOI $4, V18, V18, V19
LXVD2X (INP)(R0), VS52 // load v20 (=vs52) in advance
ADD $16, INP, INP
SHA256ROUND0(V5, V6, V7, V0, V1, V2, V3, V4, V19)
VPERMLE(V20, V20, LEMASK, V20)
SHA256ROUND0(V4, V5, V6, V7, V0, V1, V2, V3, V20)
VSLDOI $4, V20, V20, V21
SHA256ROUND0(V3, V4, V5, V6, V7, V0, V1, V2, V21)
VSLDOI $4, V21, V21, V22
SHA256ROUND0(V2, V3, V4, V5, V6, V7, V0, V1, V22)
VSLDOI $4, V22, V22, V23
SHA256ROUND1(V1, V2, V3, V4, V5, V6, V7, V0, V23, V8, V9, V17, V22)
MOVWZ $3, TEMP
MOVWZ TEMP, CTR
L16_xx:
SHA256ROUND1(V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V18, V23)
SHA256ROUND1(V7, V0, V1, V2, V3, V4, V5, V6, V9, V10, V11, V19, V8)
SHA256ROUND1(V6, V7, V0, V1, V2, V3, V4, V5, V10, V11, V12, V20, V9)
SHA256ROUND1(V5, V6, V7, V0, V1, V2, V3, V4, V11, V12, V13, V21, V10)
SHA256ROUND1(V4, V5, V6, V7, V0, V1, V2, V3, V12, V13, V14, V22, V11)
SHA256ROUND1(V3, V4, V5, V6, V7, V0, V1, V2, V13, V14, V15, V23, V12)
SHA256ROUND1(V2, V3, V4, V5, V6, V7, V0, V1, V14, V15, V16, V8, V13)
SHA256ROUND1(V1, V2, V3, V4, V5, V6, V7, V0, V15, V16, V17, V9, V14)
SHA256ROUND1(V0, V1, V2, V3, V4, V5, V6, V7, V16, V17, V18, V10, V15)
SHA256ROUND1(V7, V0, V1, V2, V3, V4, V5, V6, V17, V18, V19, V11, V16)
SHA256ROUND1(V6, V7, V0, V1, V2, V3, V4, V5, V18, V19, V20, V12, V17)
SHA256ROUND1(V5, V6, V7, V0, V1, V2, V3, V4, V19, V20, V21, V13, V18)
SHA256ROUND1(V4, V5, V6, V7, V0, V1, V2, V3, V20, V21, V22, V14, V19)
SHA256ROUND1(V3, V4, V5, V6, V7, V0, V1, V2, V21, V22, V23, V15, V20)
SHA256ROUND1(V2, V3, V4, V5, V6, V7, V0, V1, V22, V23, V8, V16, V21)
SHA256ROUND1(V1, V2, V3, V4, V5, V6, V7, V0, V23, V8, V9, V17, V22)
BC 0x10, 0, L16_xx // bdnz
XXLOR VS24, VS24, V10
XXLOR VS25, VS25, V11
VADDUWM V10, V0, V0
XXLOR VS26, VS26, V12
VADDUWM V11, V1, V1
XXLOR VS27, VS27, V13
VADDUWM V12, V2, V2
XXLOR VS28, VS28, V14
VADDUWM V13, V3, V3
XXLOR VS29, VS29, V15
VADDUWM V14, V4, V4
XXLOR VS30, VS30, V16
VADDUWM V15, V5, V5
XXLOR VS31, VS31, V17
VADDUWM V16, V6, V6
VADDUWM V17, V7, V7
CMPU INP, END
BLT loop
LVX (TBL)(IDX), V8
ADD $16, IDX
VPERM V0, V1, KI, V0
LVX (TBL)(IDX), V9
VPERM V4, V5, KI, V4
VPERM V0, V2, V8, V0
VPERM V4, V6, V8, V4
VPERM V0, V3, V9, V0
VPERM V4, V7, V9, V4
STXVD2X VS32, (CTX+HEX00) // v0 = vs32
STXVD2X VS36, (CTX+HEX10) // v4 = vs36
end:
RET

View file

@ -10,9 +10,9 @@ import (
"bytes"
"cmd/internal/bio"
"cmd/internal/goobj"
"cmd/internal/notsha256"
"cmd/internal/objabi"
"cmd/internal/sys"
"crypto/sha1"
"encoding/binary"
"fmt"
"io"
@ -460,7 +460,7 @@ func contentHash64(s *LSym) goobj.Hash64Type {
// For now, we assume there is no circular dependencies among
// hashed symbols.
func (w *writer) contentHash(s *LSym) goobj.HashType {
h := sha1.New()
h := notsha256.New()
var tmp [14]byte
// Include the size of the symbol in the hash.

View file

@ -33,8 +33,8 @@ package obj
import (
"cmd/internal/goobj"
"cmd/internal/notsha256"
"cmd/internal/objabi"
"crypto/md5"
"fmt"
"internal/buildcfg"
"log"
@ -175,7 +175,7 @@ func (ctxt *Link) Int64Sym(i int64) *LSym {
// GCLocalsSym generates a content-addressable sym containing data.
func (ctxt *Link) GCLocalsSym(data []byte) *LSym {
return ctxt.LookupInit(fmt.Sprintf("gclocals·%x", md5.Sum(data)), func(lsym *LSym) {
return ctxt.LookupInit(fmt.Sprintf("gclocals·%x", notsha256.Sum256(data)), func(lsym *LSym) {
lsym.P = data
lsym.Set(AttrContentAddressable, true)
})

View file

@ -5,11 +5,11 @@
package ld
import (
"cmd/internal/notsha256"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
"crypto/sha1"
"debug/elf"
"encoding/binary"
"encoding/hex"
@ -1533,10 +1533,10 @@ func (ctxt *Link) doelf() {
sb.SetType(sym.SRODATA)
ldr.SetAttrSpecial(s, true)
sb.SetReachable(true)
sb.SetSize(sha1.Size)
sb.SetSize(notsha256.Size)
sort.Sort(byPkg(ctxt.Library))
h := sha1.New()
h := notsha256.New()
for _, l := range ctxt.Library {
h.Write(l.Fingerprint[:])
}

View file

@ -34,6 +34,7 @@ import (
"bytes"
"cmd/internal/bio"
"cmd/internal/goobj"
"cmd/internal/notsha256"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/loadelf"
@ -42,7 +43,6 @@ import (
"cmd/link/internal/loadpe"
"cmd/link/internal/loadxcoff"
"cmd/link/internal/sym"
"crypto/sha1"
"debug/elf"
"debug/macho"
"encoding/base64"
@ -929,7 +929,7 @@ func typeSymbolMangle(name string) string {
if len(name) <= 14 && !strings.Contains(name, "@") { // Issue 19529
return name
}
hash := sha1.Sum([]byte(name))
hash := notsha256.Sum256([]byte(name))
prefix := "type."
if name[5] == '.' {
prefix = "type.."
@ -1059,6 +1059,8 @@ var hostobj []Hostobj
// These packages can use internal linking mode.
// Others trigger external mode.
var internalpkg = []string{
"crypto/internal/boring",
"crypto/internal/boring/syso",
"crypto/x509",
"net",
"os/user",

View file

@ -5,7 +5,7 @@
package main
import (
"crypto/md5"
"cmd/internal/notsha256"
"flag"
"fmt"
"go/build"
@ -142,7 +142,7 @@ func testDisasm(t *testing.T, srcfname string, printCode bool, printGnuAsm bool,
goarch = f[1]
}
hash := md5.Sum([]byte(fmt.Sprintf("%v-%v-%v-%v", srcfname, flags, printCode, printGnuAsm)))
hash := notsha256.Sum256([]byte(fmt.Sprintf("%v-%v-%v-%v", srcfname, flags, printCode, printGnuAsm)))
hello := filepath.Join(tmp, fmt.Sprintf("hello-%x.exe", hash))
args := []string{"build", "-o", hello}
args = append(args, flags...)

View file

@ -10,6 +10,8 @@ import (
"strconv"
)
import "crypto/internal/boring"
// The AES block size in bytes.
const BlockSize = 16
@ -37,6 +39,9 @@ func NewCipher(key []byte) (cipher.Block, error) {
case 16, 24, 32:
break
}
if boring.Enabled {
return boring.NewAESCipher(key)
}
return newCipher(key)
}

View file

@ -12,6 +12,8 @@ import (
"internal/cpu"
)
import "crypto/internal/boring"
// defined in asm_*.s
//go:noescape
@ -56,6 +58,7 @@ func newCipher(key []byte) (cipher.Block, error) {
func (c *aesCipherAsm) BlockSize() int { return BlockSize }
func (c *aesCipherAsm) Encrypt(dst, src []byte) {
boring.Unreachable()
if len(src) < BlockSize {
panic("crypto/aes: input not full block")
}
@ -69,6 +72,7 @@ func (c *aesCipherAsm) Encrypt(dst, src []byte) {
}
func (c *aesCipherAsm) Decrypt(dst, src []byte) {
boring.Unreachable()
if len(src) < BlockSize {
panic("crypto/aes: input not full block")
}

View file

@ -0,0 +1,21 @@
// Copyright 2020 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 boringcrypto
// Package boring exposes functions that are only available when building with
// Go+BoringCrypto. This package is available on all targets as long as the
// Go+BoringCrypto toolchain is used. Use the Enabled function to determine
// whether the BoringCrypto core is actually in use.
//
// Any time the Go+BoringCrypto toolchain is used, the "boringcrypto" build tag
// is satisfied, so that applications can tag files that use this package.
package boring
import "crypto/internal/boring"
// Enabled reports whether BoringCrypto handles supported crypto operations.
func Enabled() bool {
return boring.Enabled
}

View file

@ -0,0 +1,22 @@
// Copyright 2020 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 boringcrypto
package boring_test
import (
"crypto/boring"
"runtime"
"testing"
)
func TestEnabled(t *testing.T) {
supportedPlatform := runtime.GOOS == "linux" && runtime.GOARCH == "amd64"
if supportedPlatform && !boring.Enabled() {
t.Error("Enabled returned false on a supported platform")
} else if !supportedPlatform && boring.Enabled() {
t.Error("Enabled returned true on an unsupported platform")
}
}

View file

@ -0,0 +1,14 @@
// Copyright 2020 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 (goexperiment.boringcrypto && !boringcrypto) || (!goexperiment.boringcrypto && boringcrypto)
// +build goexperiment.boringcrypto,!boringcrypto !goexperiment.boringcrypto,boringcrypto
package boring_test
import "testing"
func TestNotBoring(t *testing.T) {
t.Error("goexperiment.boringcrypto and boringcrypto should be equivalent build tags")
}

106
src/crypto/ecdsa/boring.go Normal file
View file

@ -0,0 +1,106 @@
// Copyright 2017 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 boringcrypto
package ecdsa
import (
"crypto/internal/boring"
"crypto/internal/boring/bbig"
"math/big"
"unsafe"
)
// Cached conversions from Go PublicKey/PrivateKey to BoringCrypto.
//
// The first operation on a PublicKey or PrivateKey makes a parallel
// BoringCrypto key and saves it in pubCache or privCache.
//
// We could just assume that once used in a Sign or Verify operation,
// a particular key is never again modified, but that has not been a
// stated assumption before. Just in case there is any existing code that
// does modify the key between operations, we save the original values
// alongside the cached BoringCrypto key and check that the real key
// still matches before using the cached key. The theory is that the real
// operations are significantly more expensive than the comparison.
var pubCache boring.Cache
var privCache boring.Cache
func init() {
pubCache.Register()
privCache.Register()
}
type boringPub struct {
key *boring.PublicKeyECDSA
orig PublicKey
}
func boringPublicKey(pub *PublicKey) (*boring.PublicKeyECDSA, error) {
b := (*boringPub)(pubCache.Get(unsafe.Pointer(pub)))
if b != nil && publicKeyEqual(&b.orig, pub) {
return b.key, nil
}
b = new(boringPub)
b.orig = copyPublicKey(pub)
key, err := boring.NewPublicKeyECDSA(b.orig.Curve.Params().Name, bbig.Enc(b.orig.X), bbig.Enc(b.orig.Y))
if err != nil {
return nil, err
}
b.key = key
pubCache.Put(unsafe.Pointer(pub), unsafe.Pointer(b))
return key, nil
}
type boringPriv struct {
key *boring.PrivateKeyECDSA
orig PrivateKey
}
func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyECDSA, error) {
b := (*boringPriv)(privCache.Get(unsafe.Pointer(priv)))
if b != nil && privateKeyEqual(&b.orig, priv) {
return b.key, nil
}
b = new(boringPriv)
b.orig = copyPrivateKey(priv)
key, err := boring.NewPrivateKeyECDSA(b.orig.Curve.Params().Name, bbig.Enc(b.orig.X), bbig.Enc(b.orig.Y), bbig.Enc(b.orig.D))
if err != nil {
return nil, err
}
b.key = key
privCache.Put(unsafe.Pointer(priv), unsafe.Pointer(b))
return key, nil
}
func publicKeyEqual(k1, k2 *PublicKey) bool {
return k1.X != nil &&
k1.Curve.Params() == k2.Curve.Params() &&
k1.X.Cmp(k2.X) == 0 &&
k1.Y.Cmp(k2.Y) == 0
}
func privateKeyEqual(k1, k2 *PrivateKey) bool {
return publicKeyEqual(&k1.PublicKey, &k2.PublicKey) &&
k1.D.Cmp(k2.D) == 0
}
func copyPublicKey(k *PublicKey) PublicKey {
return PublicKey{
Curve: k.Curve,
X: new(big.Int).Set(k.X),
Y: new(big.Int).Set(k.Y),
}
}
func copyPrivateKey(k *PrivateKey) PrivateKey {
return PrivateKey{
PublicKey: copyPublicKey(&k.PublicKey),
D: new(big.Int).Set(k.D),
}
}

View file

@ -24,12 +24,15 @@ import (
"crypto/aes"
"crypto/cipher"
"crypto/elliptic"
"crypto/internal/boring/bbig"
"crypto/internal/randutil"
"crypto/sha512"
"errors"
"io"
"math/big"
"crypto/internal/boring"
"golang.org/x/crypto/cryptobyte"
"golang.org/x/crypto/cryptobyte/asn1"
)
@ -107,6 +110,15 @@ func (priv *PrivateKey) Equal(x crypto.PrivateKey) bool {
// where the private part is kept in, for example, a hardware module. Common
// uses can use the SignASN1 function in this package directly.
func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
if boring.Enabled && rand == boring.RandReader {
b, err := boringPrivateKey(priv)
if err != nil {
return nil, err
}
return boring.SignMarshalECDSA(b, digest)
}
boring.UnreachableExceptTests()
r, s, err := Sign(rand, priv, digest)
if err != nil {
return nil, err
@ -143,6 +155,15 @@ func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error)
// GenerateKey generates a public and private key pair.
func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) {
if boring.Enabled && rand == boring.RandReader {
x, y, d, err := boring.GenerateKeyECDSA(c.Params().Name)
if err != nil {
return nil, err
}
return &PrivateKey{PublicKey: PublicKey{Curve: c, X: bbig.Dec(x), Y: bbig.Dec(y)}, D: bbig.Dec(d)}, nil
}
boring.UnreachableExceptTests()
k, err := randFieldElement(c, rand)
if err != nil {
return nil, err
@ -194,6 +215,29 @@ var errZeroParam = errors.New("zero parameter")
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
randutil.MaybeReadByte(rand)
if boring.Enabled && rand == boring.RandReader {
b, err := boringPrivateKey(priv)
if err != nil {
return nil, nil, err
}
sig, err := boring.SignMarshalECDSA(b, hash)
if err != nil {
return nil, nil, err
}
var r, s big.Int
var inner cryptobyte.String
input := cryptobyte.String(sig)
if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
!input.Empty() ||
!inner.ReadASN1Integer(&r) ||
!inner.ReadASN1Integer(&s) ||
!inner.Empty() {
return nil, nil, errors.New("invalid ASN.1 from boringcrypto")
}
return &r, &s, nil
}
boring.UnreachableExceptTests()
// This implementation derives the nonce from an AES-CTR CSPRNG keyed by:
//
// SHA2-512(priv.D || entropy || hash)[:32]
@ -290,6 +334,24 @@ func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) {
// return value records whether the signature is valid. Most applications should
// use VerifyASN1 instead of dealing directly with r, s.
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
if boring.Enabled {
key, err := boringPublicKey(pub)
if err != nil {
return false
}
var b cryptobyte.Builder
b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
b.AddASN1BigInt(r)
b.AddASN1BigInt(s)
})
sig, err := b.Bytes()
if err != nil {
return false
}
return boring.VerifyECDSA(key, hash, sig)
}
boring.UnreachableExceptTests()
c := pub.Curve
N := c.Params().N

View file

@ -0,0 +1,16 @@
// Copyright 2022 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 !boringcrypto
package ecdsa
import "crypto/internal/boring"
func boringPublicKey(*PublicKey) (*boring.PublicKeyECDSA, error) {
panic("boringcrypto: not available")
}
func boringPrivateKey(*PrivateKey) (*boring.PrivateKeyECDSA, error) {
panic("boringcrypto: not available")
}

View file

@ -9,6 +9,7 @@ import (
"bytes"
"compress/gzip"
"crypto"
"crypto/internal/boring"
"crypto/rand"
"encoding/hex"
"os"
@ -186,6 +187,9 @@ func TestMalleability(t *testing.T) {
}
func TestAllocations(t *testing.T) {
if boring.Enabled {
t.Skip("skipping allocations test with BoringCrypto")
}
if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") {
t.Skip("skipping allocations test without relevant optimizations")
}
@ -199,7 +203,7 @@ func TestAllocations(t *testing.T) {
t.Fatal("signature didn't verify")
}
}); allocs > 0 {
t.Errorf("expected zero allocations, got %0.1v", allocs)
t.Errorf("expected zero allocations, got %0.1f", allocs)
}
}

View file

@ -26,6 +26,8 @@ import (
"hash"
)
import "crypto/internal/boring"
// FIPS 198-1:
// https://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf
@ -126,6 +128,13 @@ func (h *hmac) Reset() {
// the returned Hash does not implement encoding.BinaryMarshaler
// or encoding.BinaryUnmarshaler.
func New(h func() hash.Hash, key []byte) hash.Hash {
if boring.Enabled {
hm := boring.NewHMAC(h, key)
if hm != nil {
return hm
}
// BoringCrypto did not recognize h, so fall through to standard Go code.
}
hm := new(hmac)
hm.outer = h()
hm.inner = h()

View file

@ -5,6 +5,8 @@
package hmac
import (
"bytes"
"crypto/internal/boring"
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
@ -518,6 +520,31 @@ var hmacTests = []hmacTest{
sha512.Size,
sha512.BlockSize,
},
// HMAC without key is dumb but should probably not fail.
{
sha1.New,
[]byte{},
[]byte("message"),
"d5d1ed05121417247616cfc8378f360a39da7cfa",
sha1.Size,
sha1.BlockSize,
},
{
sha256.New,
[]byte{},
[]byte("message"),
"eb08c1f56d5ddee07f7bdf80468083da06b64cf4fac64fe3a90883df5feacae4",
sha256.Size,
sha256.BlockSize,
},
{
sha512.New,
[]byte{},
[]byte("message"),
"08fce52f6395d59c2a3fb8abb281d74ad6f112b9a9c787bcea290d94dadbc82b2ca3e5e12bf2277c7fedbb0154d5493e41bb7459f63c8e39554ea3651b812492",
sha512.Size,
sha512.BlockSize,
},
}
func TestHMAC(t *testing.T) {
@ -557,6 +584,9 @@ func TestHMAC(t *testing.T) {
}
func TestNonUniqueHash(t *testing.T) {
if boring.Enabled {
t.Skip("hash.Hash provided by boringcrypto are not comparable")
}
sha := sha256.New()
defer func() {
err := recover()
@ -591,6 +621,42 @@ func TestEqual(t *testing.T) {
}
}
func TestWriteAfterSum(t *testing.T) {
h := New(sha1.New, nil)
h.Write([]byte("hello"))
sumHello := h.Sum(nil)
h = New(sha1.New, nil)
h.Write([]byte("hello world"))
sumHelloWorld := h.Sum(nil)
// Test that Sum has no effect on future Sum or Write operations.
// This is a bit unusual as far as usage, but it's allowed
// by the definition of Go hash.Hash, and some clients expect it to work.
h = New(sha1.New, nil)
h.Write([]byte("hello"))
if sum := h.Sum(nil); !bytes.Equal(sum, sumHello) {
t.Fatalf("1st Sum after hello = %x, want %x", sum, sumHello)
}
if sum := h.Sum(nil); !bytes.Equal(sum, sumHello) {
t.Fatalf("2nd Sum after hello = %x, want %x", sum, sumHello)
}
h.Write([]byte(" world"))
if sum := h.Sum(nil); !bytes.Equal(sum, sumHelloWorld) {
t.Fatalf("1st Sum after hello world = %x, want %x", sum, sumHelloWorld)
}
if sum := h.Sum(nil); !bytes.Equal(sum, sumHelloWorld) {
t.Fatalf("2nd Sum after hello world = %x, want %x", sum, sumHelloWorld)
}
h.Reset()
h.Write([]byte("hello"))
if sum := h.Sum(nil); !bytes.Equal(sum, sumHello) {
t.Fatalf("Sum after Reset + hello = %x, want %x", sum, sumHello)
}
}
func BenchmarkHMACSHA256_1K(b *testing.B) {
key := make([]byte, 32)
buf := make([]byte, 1024)

View file

@ -0,0 +1,44 @@
# Copyright 2020 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.
# This Docker image builds goboringcrypto_linux_amd64.syso according to the
# Security Policy. To use it, build the image, run it, and then extract
# /boring/godriver/goboringcrypto_linux_amd64.syso.
#
# $ podman build -t goboring:140sp3678 .
# $ podman run -it --name goboring-140sp3678 goboring:140sp3678
# $ podman cp goboring-140sp3678:/boring/godriver/goboringcrypto_linux_amd64.syso syso
# $ sha256sum syso/goboringcrypto_linux_amd64.syso # compare to docker output
#
# The podman commands may need to run under sudo to work around a subuid/subgid bug.
FROM ubuntu:focal
RUN mkdir /boring
WORKDIR /boring
# Following 140sp3678.pdf [0] page 19, install clang 7.0.1, Go 1.12.7, and
# Ninja 1.9.0, then download and verify BoringSSL.
#
# [0]: https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp3678.pdf
RUN apt-get update && \
apt-get install --no-install-recommends -y cmake xz-utils wget unzip ca-certificates clang-7
RUN wget https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-linux.zip && \
unzip ninja-linux.zip && \
rm ninja-linux.zip && \
mv ninja /usr/local/bin/
RUN wget https://golang.org/dl/go1.12.7.linux-amd64.tar.gz && \
tar -C /usr/local -xzf go1.12.7.linux-amd64.tar.gz && \
rm go1.12.7.linux-amd64.tar.gz && \
ln -s /usr/local/go/bin/go /usr/local/bin/
RUN wget https://commondatastorage.googleapis.com/chromium-boringssl-fips/boringssl-ae223d6138807a13006342edfeef32e813246b39.tar.xz
RUN [ "$(sha256sum boringssl-ae223d6138807a13006342edfeef32e813246b39.tar.xz | awk '{print $1}')" = \
3b5fdf23274d4179c2077b5e8fa625d9debd7a390aac1d165b7e47234f648bb8 ]
ADD goboringcrypto.h /boring/godriver/goboringcrypto.h
ADD build.sh /boring/build.sh
ENTRYPOINT ["/boring/build.sh"]

View file

@ -0,0 +1,202 @@
The Go source code and supporting files in this directory
are covered by the usual Go license (see ../../../../LICENSE).
When building with GOEXPERIMENT=boringcrypto, the following applies.
The goboringcrypto_linux_amd64.syso object file is built
from BoringSSL source code by build/build.sh and is covered
by the BoringSSL license reproduced below and also at
https://boringssl.googlesource.com/boringssl/+/fips-20190808/LICENSE.
BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL
licensing. Files that are completely new have a Google copyright and an ISC
license. This license is reproduced at the bottom of this file.
Contributors to BoringSSL are required to follow the CLA rules for Chromium:
https://cla.developers.google.com/clas
Some files from Intel are under yet another license, which is also included
underneath.
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the
OpenSSL License and the original SSLeay license apply to the toolkit. See below
for the actual license texts. Actually both licenses are BSD-style Open Source
licenses. In case of any license issues related to OpenSSL please contact
openssl-core@openssl.org.
The following are Google-internal bug numbers where explicit permission from
some authors is recorded for use of their work. (This is purely for our own
record keeping.)
27287199
27287880
27287883
OpenSSL License
---------------
/* ====================================================================
* Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
Original SSLeay License
-----------------------
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
ISC license used for completely new code in BoringSSL:
/* Copyright (c) 2015, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
Some files from Intel carry the following license:
# Copyright (c) 2012, Intel Corporation
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the
# distribution.
#
# * Neither the name of the Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
#
# THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,389 @@
// Copyright 2017 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 boringcrypto && linux && amd64 && !android && !cmd_go_bootstrap && !msan
// +build boringcrypto,linux,amd64,!android,!cmd_go_bootstrap,!msan
package boring
/*
#include "goboringcrypto.h"
// These wrappers allocate out_len on the C stack, and check that it matches the expected
// value, to avoid having to pass a pointer from Go, which would escape to the heap.
int EVP_AEAD_CTX_seal_wrapper(const GO_EVP_AEAD_CTX *ctx, uint8_t *out,
size_t exp_out_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
size_t out_len;
int ok = _goboringcrypto_EVP_AEAD_CTX_seal(ctx, out, &out_len, exp_out_len,
nonce, nonce_len, in, in_len, ad, ad_len);
if (out_len != exp_out_len) {
return 0;
}
return ok;
};
int EVP_AEAD_CTX_open_wrapper(const GO_EVP_AEAD_CTX *ctx, uint8_t *out,
size_t exp_out_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
size_t out_len;
int ok = _goboringcrypto_EVP_AEAD_CTX_open(ctx, out, &out_len, exp_out_len,
nonce, nonce_len, in, in_len, ad, ad_len);
if (out_len != exp_out_len) {
return 0;
}
return ok;
};
*/
import "C"
import (
"crypto/cipher"
"errors"
"runtime"
"strconv"
"unsafe"
)
type aesKeySizeError int
func (k aesKeySizeError) Error() string {
return "crypto/aes: invalid key size " + strconv.Itoa(int(k))
}
const aesBlockSize = 16
type aesCipher struct {
key []byte
enc C.GO_AES_KEY
dec C.GO_AES_KEY
}
type extraModes interface {
// Copied out of crypto/aes/modes.go.
NewCBCEncrypter(iv []byte) cipher.BlockMode
NewCBCDecrypter(iv []byte) cipher.BlockMode
NewCTR(iv []byte) cipher.Stream
NewGCM(nonceSize, tagSize int) (cipher.AEAD, error)
// Invented for BoringCrypto.
NewGCMTLS() (cipher.AEAD, error)
}
var _ extraModes = (*aesCipher)(nil)
func NewAESCipher(key []byte) (cipher.Block, error) {
c := &aesCipher{key: make([]byte, len(key))}
copy(c.key, key)
// Note: 0 is success, contradicting the usual BoringCrypto convention.
if C._goboringcrypto_AES_set_decrypt_key((*C.uint8_t)(unsafe.Pointer(&c.key[0])), C.uint(8*len(c.key)), &c.dec) != 0 ||
C._goboringcrypto_AES_set_encrypt_key((*C.uint8_t)(unsafe.Pointer(&c.key[0])), C.uint(8*len(c.key)), &c.enc) != 0 {
return nil, aesKeySizeError(len(key))
}
return c, nil
}
func (c *aesCipher) BlockSize() int { return aesBlockSize }
func (c *aesCipher) Encrypt(dst, src []byte) {
if inexactOverlap(dst, src) {
panic("crypto/cipher: invalid buffer overlap")
}
if len(src) < aesBlockSize {
panic("crypto/aes: input not full block")
}
if len(dst) < aesBlockSize {
panic("crypto/aes: output not full block")
}
C._goboringcrypto_AES_encrypt(
(*C.uint8_t)(unsafe.Pointer(&src[0])),
(*C.uint8_t)(unsafe.Pointer(&dst[0])),
&c.enc)
}
func (c *aesCipher) Decrypt(dst, src []byte) {
if inexactOverlap(dst, src) {
panic("crypto/cipher: invalid buffer overlap")
}
if len(src) < aesBlockSize {
panic("crypto/aes: input not full block")
}
if len(dst) < aesBlockSize {
panic("crypto/aes: output not full block")
}
C._goboringcrypto_AES_decrypt(
(*C.uint8_t)(unsafe.Pointer(&src[0])),
(*C.uint8_t)(unsafe.Pointer(&dst[0])),
&c.dec)
}
type aesCBC struct {
key *C.GO_AES_KEY
mode C.int
iv [aesBlockSize]byte
}
func (x *aesCBC) BlockSize() int { return aesBlockSize }
func (x *aesCBC) CryptBlocks(dst, src []byte) {
if inexactOverlap(dst, src) {
panic("crypto/cipher: invalid buffer overlap")
}
if len(src)%aesBlockSize != 0 {
panic("crypto/cipher: input not full blocks")
}
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
if len(src) > 0 {
C._goboringcrypto_AES_cbc_encrypt(
(*C.uint8_t)(unsafe.Pointer(&src[0])),
(*C.uint8_t)(unsafe.Pointer(&dst[0])),
C.size_t(len(src)), x.key,
(*C.uint8_t)(unsafe.Pointer(&x.iv[0])), x.mode)
}
}
func (x *aesCBC) SetIV(iv []byte) {
if len(iv) != aesBlockSize {
panic("cipher: incorrect length IV")
}
copy(x.iv[:], iv)
}
func (c *aesCipher) NewCBCEncrypter(iv []byte) cipher.BlockMode {
x := &aesCBC{key: &c.enc, mode: C.GO_AES_ENCRYPT}
copy(x.iv[:], iv)
return x
}
func (c *aesCipher) NewCBCDecrypter(iv []byte) cipher.BlockMode {
x := &aesCBC{key: &c.dec, mode: C.GO_AES_DECRYPT}
copy(x.iv[:], iv)
return x
}
type aesCTR struct {
key *C.GO_AES_KEY
iv [aesBlockSize]byte
num C.uint
ecount_buf [16]C.uint8_t
}
func (x *aesCTR) XORKeyStream(dst, src []byte) {
if inexactOverlap(dst, src) {
panic("crypto/cipher: invalid buffer overlap")
}
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
if len(src) == 0 {
return
}
C._goboringcrypto_AES_ctr128_encrypt(
(*C.uint8_t)(unsafe.Pointer(&src[0])),
(*C.uint8_t)(unsafe.Pointer(&dst[0])),
C.size_t(len(src)), x.key, (*C.uint8_t)(unsafe.Pointer(&x.iv[0])),
&x.ecount_buf[0], &x.num)
}
func (c *aesCipher) NewCTR(iv []byte) cipher.Stream {
x := &aesCTR{key: &c.enc}
copy(x.iv[:], iv)
return x
}
type aesGCM struct {
ctx C.GO_EVP_AEAD_CTX
aead *C.GO_EVP_AEAD
}
const (
gcmBlockSize = 16
gcmTagSize = 16
gcmStandardNonceSize = 12
)
type aesNonceSizeError int
func (n aesNonceSizeError) Error() string {
return "crypto/aes: invalid GCM nonce size " + strconv.Itoa(int(n))
}
type noGCM struct {
cipher.Block
}
func (c *aesCipher) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) {
if nonceSize != gcmStandardNonceSize && tagSize != gcmTagSize {
return nil, errors.New("crypto/aes: GCM tag and nonce sizes can't be non-standard at the same time")
}
// Fall back to standard library for GCM with non-standard nonce or tag size.
if nonceSize != gcmStandardNonceSize {
return cipher.NewGCMWithNonceSize(&noGCM{c}, nonceSize)
}
if tagSize != gcmTagSize {
return cipher.NewGCMWithTagSize(&noGCM{c}, tagSize)
}
return c.newGCM(false)
}
func (c *aesCipher) NewGCMTLS() (cipher.AEAD, error) {
return c.newGCM(true)
}
func (c *aesCipher) newGCM(tls bool) (cipher.AEAD, error) {
var aead *C.GO_EVP_AEAD
switch len(c.key) * 8 {
case 128:
if tls {
aead = C._goboringcrypto_EVP_aead_aes_128_gcm_tls12()
} else {
aead = C._goboringcrypto_EVP_aead_aes_128_gcm()
}
case 256:
if tls {
aead = C._goboringcrypto_EVP_aead_aes_256_gcm_tls12()
} else {
aead = C._goboringcrypto_EVP_aead_aes_256_gcm()
}
default:
// Fall back to standard library for GCM with non-standard key size.
return cipher.NewGCMWithNonceSize(&noGCM{c}, gcmStandardNonceSize)
}
g := &aesGCM{aead: aead}
if C._goboringcrypto_EVP_AEAD_CTX_init(&g.ctx, aead, (*C.uint8_t)(unsafe.Pointer(&c.key[0])), C.size_t(len(c.key)), C.GO_EVP_AEAD_DEFAULT_TAG_LENGTH, nil) == 0 {
return nil, fail("EVP_AEAD_CTX_init")
}
// Note: Because of the finalizer, any time g.ctx is passed to cgo,
// that call must be followed by a call to runtime.KeepAlive(g),
// to make sure g is not collected (and finalized) before the cgo
// call returns.
runtime.SetFinalizer(g, (*aesGCM).finalize)
if g.NonceSize() != gcmStandardNonceSize {
panic("boringcrypto: internal confusion about nonce size")
}
if g.Overhead() != gcmTagSize {
panic("boringcrypto: internal confusion about tag size")
}
return g, nil
}
func (g *aesGCM) finalize() {
C._goboringcrypto_EVP_AEAD_CTX_cleanup(&g.ctx)
}
func (g *aesGCM) NonceSize() int {
return int(C._goboringcrypto_EVP_AEAD_nonce_length(g.aead))
}
func (g *aesGCM) Overhead() int {
return int(C._goboringcrypto_EVP_AEAD_max_overhead(g.aead))
}
// base returns the address of the underlying array in b,
// being careful not to panic when b has zero length.
func base(b []byte) *C.uint8_t {
if len(b) == 0 {
return nil
}
return (*C.uint8_t)(unsafe.Pointer(&b[0]))
}
func (g *aesGCM) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
if len(nonce) != gcmStandardNonceSize {
panic("cipher: incorrect nonce length given to GCM")
}
if uint64(len(plaintext)) > ((1<<32)-2)*aesBlockSize || len(plaintext)+gcmTagSize < len(plaintext) {
panic("cipher: message too large for GCM")
}
if len(dst)+len(plaintext)+gcmTagSize < len(dst) {
panic("cipher: message too large for buffer")
}
// Make room in dst to append plaintext+overhead.
n := len(dst)
for cap(dst) < n+len(plaintext)+gcmTagSize {
dst = append(dst[:cap(dst)], 0)
}
dst = dst[:n+len(plaintext)+gcmTagSize]
// Check delayed until now to make sure len(dst) is accurate.
if inexactOverlap(dst[n:], plaintext) {
panic("cipher: invalid buffer overlap")
}
outLen := C.size_t(len(plaintext) + gcmTagSize)
ok := C.EVP_AEAD_CTX_seal_wrapper(
&g.ctx,
(*C.uint8_t)(unsafe.Pointer(&dst[n])), outLen,
base(nonce), C.size_t(len(nonce)),
base(plaintext), C.size_t(len(plaintext)),
base(additionalData), C.size_t(len(additionalData)))
runtime.KeepAlive(g)
if ok == 0 {
panic(fail("EVP_AEAD_CTX_seal"))
}
return dst[:n+int(outLen)]
}
var errOpen = errors.New("cipher: message authentication failed")
func (g *aesGCM) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
if len(nonce) != gcmStandardNonceSize {
panic("cipher: incorrect nonce length given to GCM")
}
if len(ciphertext) < gcmTagSize {
return nil, errOpen
}
if uint64(len(ciphertext)) > ((1<<32)-2)*aesBlockSize+gcmTagSize {
return nil, errOpen
}
// Make room in dst to append ciphertext without tag.
n := len(dst)
for cap(dst) < n+len(ciphertext)-gcmTagSize {
dst = append(dst[:cap(dst)], 0)
}
dst = dst[:n+len(ciphertext)-gcmTagSize]
// Check delayed until now to make sure len(dst) is accurate.
if inexactOverlap(dst[n:], ciphertext) {
panic("cipher: invalid buffer overlap")
}
outLen := C.size_t(len(ciphertext) - gcmTagSize)
ok := C.EVP_AEAD_CTX_open_wrapper(
&g.ctx,
base(dst[n:]), outLen,
base(nonce), C.size_t(len(nonce)),
base(ciphertext), C.size_t(len(ciphertext)),
base(additionalData), C.size_t(len(additionalData)))
runtime.KeepAlive(g)
if ok == 0 {
return nil, errOpen
}
return dst[:n+int(outLen)], nil
}
func anyOverlap(x, y []byte) bool {
return len(x) > 0 && len(y) > 0 &&
uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) &&
uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1]))
}
func inexactOverlap(x, y []byte) bool {
if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] {
return false
}
return anyOverlap(x, y)
}

View file

@ -0,0 +1,33 @@
// Copyright 2022 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 bbig
import (
"crypto/internal/boring"
"math/big"
"unsafe"
)
func Enc(b *big.Int) boring.BigInt {
if b == nil {
return nil
}
x := b.Bits()
if len(x) == 0 {
return boring.BigInt{}
}
return unsafe.Slice((*uint)(&x[0]), len(x))
}
func Dec(b boring.BigInt) *big.Int {
if b == nil {
return nil
}
if len(b) == 0 {
return new(big.Int)
}
x := unsafe.Slice((*big.Word)(&b[0]), len(b))
return new(big.Int).SetBits(x)
}

View file

@ -0,0 +1,109 @@
// Copyright 2017 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 boringcrypto && linux && amd64 && !android && !cmd_go_bootstrap && !msan
// +build boringcrypto,linux,amd64,!android,!cmd_go_bootstrap,!msan
package boring
/*
// goboringcrypto_linux_amd64.syso references pthread functions.
#cgo LDFLAGS: "-pthread"
#include "goboringcrypto.h"
*/
import "C"
import (
"crypto/internal/boring/sig"
_ "crypto/internal/boring/syso"
"math/bits"
"unsafe"
)
const available = true
func init() {
C._goboringcrypto_BORINGSSL_bcm_power_on_self_test()
if C._goboringcrypto_FIPS_mode() != 1 {
panic("boringcrypto: not in FIPS mode")
}
sig.BoringCrypto()
}
// Unreachable marks code that should be unreachable
// when BoringCrypto is in use. It panics.
func Unreachable() {
panic("boringcrypto: invalid code execution")
}
// provided by runtime to avoid os import
func runtime_arg0() string
func hasSuffix(s, t string) bool {
return len(s) > len(t) && s[len(s)-len(t):] == t
}
// UnreachableExceptTests marks code that should be unreachable
// when BoringCrypto is in use. It panics.
func UnreachableExceptTests() {
name := runtime_arg0()
// If BoringCrypto ran on Windows we'd need to allow _test.exe and .test.exe as well.
if !hasSuffix(name, "_test") && !hasSuffix(name, ".test") {
println("boringcrypto: unexpected code execution in", name)
panic("boringcrypto: invalid code execution")
}
}
type fail string
func (e fail) Error() string { return "boringcrypto: " + string(e) + " failed" }
func wbase(b BigInt) *C.uint8_t {
if len(b) == 0 {
return nil
}
return (*C.uint8_t)(unsafe.Pointer(&b[0]))
}
const wordBytes = bits.UintSize / 8
func bigToBN(x BigInt) *C.GO_BIGNUM {
return C._goboringcrypto_BN_le2bn(wbase(x), C.size_t(len(x)*wordBytes), nil)
}
func bnToBig(bn *C.GO_BIGNUM) BigInt {
x := make(BigInt, (C._goboringcrypto_BN_num_bytes(bn)+wordBytes-1)/wordBytes)
if C._goboringcrypto_BN_bn2le_padded(wbase(x), C.size_t(len(x)*wordBytes), bn) == 0 {
panic("boringcrypto: bignum conversion failed")
}
return x
}
func bigToBn(bnp **C.GO_BIGNUM, b BigInt) bool {
if *bnp != nil {
C._goboringcrypto_BN_free(*bnp)
*bnp = nil
}
if b == nil {
return true
}
bn := bigToBN(b)
if bn == nil {
return false
}
*bnp = bn
return true
}
// noescape hides a pointer from escape analysis. noescape is
// the identity function but escape analysis doesn't think the
// output depends on the input. noescape is inlined and currently
// compiles down to zero instructions.
// USE CAREFULLY!
//
//go:nosplit
func noescape(p unsafe.Pointer) unsafe.Pointer {
x := uintptr(p)
return unsafe.Pointer(x ^ 0)
}

View file

@ -0,0 +1,34 @@
// Copyright 2017 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.
// Most functionality in this package is tested by replacing existing code
// and inheriting that code's tests.
package boring
import "testing"
// Test that func init does not panic.
func TestInit(t *testing.T) {}
// Test that Unreachable panics.
func TestUnreachable(t *testing.T) {
defer func() {
if Enabled {
if err := recover(); err == nil {
t.Fatal("expected Unreachable to panic")
}
} else {
if err := recover(); err != nil {
t.Fatalf("expected Unreachable to be a no-op")
}
}
}()
Unreachable()
}
// Test that UnreachableExceptTests does not panic (this is a test).
func TestUnreachableExceptTests(t *testing.T) {
UnreachableExceptTests()
}

View file

@ -0,0 +1,196 @@
#!/bin/bash
# Copyright 2020 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.
set -e
id
date
export LANG=C
unset LANGUAGE
# Build BoringCrypto libcrypto.a.
# Following https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp3678.pdf page 19.
tar xJf boringssl-*z
# Go requires -fPIC for linux/amd64 cgo builds.
# Setting -fPIC only affects the compilation of the non-module code in libcrypto.a,
# because the FIPS module itself is already built with -fPIC.
echo '#!/bin/bash
exec clang-7 -fPIC "$@"
' >/usr/local/bin/clang
echo '#!/bin/bash
exec clang++-7 -fPIC "$@"
' >/usr/local/bin/clang++
chmod +x /usr/local/bin/clang /usr/local/bin/clang++
# The BoringSSL tests use Go, and cgo would look for gcc.
export CGO_ENABLED=0
# Verbatim instructions from BoringCrypto build docs.
printf "set(CMAKE_C_COMPILER \"clang\")\nset(CMAKE_CXX_COMPILER \"clang++\")\n" >${HOME}/toolchain
cd boringssl
mkdir build && cd build && cmake -GNinja -DCMAKE_TOOLCHAIN_FILE=${HOME}/toolchain -DFIPS=1 -DCMAKE_BUILD_TYPE=Release ..
ninja
ninja run_tests
cd ../..
if [ "$(./boringssl/build/tool/bssl isfips)" != 1 ]; then
echo "NOT FIPS"
exit 2
fi
# Build and run test C++ program to make sure goboringcrypto.h matches openssl/*.h.
# Also collect list of checked symbols in syms.txt
set -x
set -e
cd godriver
cat >goboringcrypto.cc <<'EOF'
#include <cassert>
#include "goboringcrypto0.h"
#include "goboringcrypto1.h"
#define check_size(t) if(sizeof(t) != sizeof(GO_ ## t)) {printf("sizeof(" #t ")=%d, but sizeof(GO_" #t ")=%d\n", (int)sizeof(t), (int)sizeof(GO_ ## t)); ret=1;}
#define check_func(f) { auto x = f; x = _goboringcrypto_ ## f ; }
#define check_value(n, v) if(n != v) {printf(#n "=%d, but goboringcrypto.h defines it as %d\n", (int)n, (int)v); ret=1;}
int main() {
int ret = 0;
#include "goboringcrypto.x"
return ret;
}
EOF
awk '
BEGIN {
exitcode = 0
}
# Ignore comments, #includes, blank lines.
/^\/\// || /^#/ || NF == 0 { next }
# Ignore unchecked declarations.
/\/\*unchecked/ { next }
# Check enum values.
!enum && $1 == "enum" && $NF == "{" {
enum = 1
next
}
enum && $1 == "};" {
enum = 0
next
}
enum && NF == 3 && $2 == "=" {
name = $1
sub(/^GO_/, "", name)
val = $3
sub(/,$/, "", val)
print "check_value(" name ", " val ")" > "goboringcrypto.x"
next
}
enum {
print FILENAME ":" NR ": unexpected line in enum: " $0 > "/dev/stderr"
exitcode = 1
next
}
# Check struct sizes.
/^typedef struct / && $NF ~ /^GO_/ {
name = $NF
sub(/^GO_/, "", name)
sub(/;$/, "", name)
print "check_size(" name ")" > "goboringcrypto.x"
next
}
# Check function prototypes.
/^(const )?[^ ]+ \**_goboringcrypto_.*\(/ {
name = $2
if($1 == "const")
name = $3
sub(/^\**_goboringcrypto_/, "", name)
sub(/\(.*/, "", name)
print "check_func(" name ")" > "goboringcrypto.x"
print name > "syms.txt"
next
}
{
print FILENAME ":" NR ": unexpected line: " $0 > "/dev/stderr"
exitcode = 1
}
END {
exit exitcode
}
' goboringcrypto.h
cat goboringcrypto.h | awk '
/^\/\/ #include/ {sub(/\/\//, ""); print > "goboringcrypto0.h"; next}
/typedef struct|enum ([a-z_]+ )?{|^[ \t]/ {print;next}
{gsub(/GO_/, ""); gsub(/enum go_/, "enum "); print}
' >goboringcrypto1.h
clang++ -std=c++11 -fPIC -I../boringssl/include -O2 -o a.out goboringcrypto.cc
./a.out || exit 2
# Prepare copy of libcrypto.a with only the checked functions renamed and exported.
# All other symbols are left alone and hidden.
echo BORINGSSL_bcm_power_on_self_test >>syms.txt
awk '{print "_goboringcrypto_" $0 }' syms.txt >globals.txt
awk '{print $0 " _goboringcrypto_" $0 }' syms.txt >renames.txt
objcopy --globalize-symbol=BORINGSSL_bcm_power_on_self_test ../boringssl/build/crypto/libcrypto.a libcrypto.a
# clang implements u128 % u128 -> u128 by calling __umodti3,
# which is in libgcc. To make the result self-contained even if linking
# against a different compiler version, link our own __umodti3 into the syso.
# This one is specialized so it only expects divisors below 2^64,
# which is all BoringCrypto uses. (Otherwise it will seg fault.)
cat >umod.s <<'EOF'
# tu_int __umodti3(tu_int x, tu_int y)
# x is rsi:rdi, y is rcx:rdx, return result is rdx:rax.
.globl __umodti3
__umodti3:
# specialized to u128 % u64, so verify that
test %rcx,%rcx
jne 1f
# save divisor
movq %rdx, %r8
# reduce top 64 bits mod divisor
movq %rsi, %rax
xorl %edx, %edx
divq %r8
# reduce full 128-bit mod divisor
# quotient fits in 64 bits because top 64 bits have been reduced < divisor.
# (even though we only care about the remainder, divq also computes
# the quotient, and it will trap if the quotient is too large.)
movq %rdi, %rax
divq %r8
# expand remainder to 128 for return
movq %rdx, %rax
xorl %edx, %edx
ret
1:
# crash - only want 64-bit divisor
xorl %ecx, %ecx
movl %ecx, 0(%ecx)
jmp 1b
.section .note.GNU-stack,"",@progbits
EOF
clang -c -o umod.o umod.s
ld -r -nostdlib --whole-archive -o goboringcrypto.o libcrypto.a umod.o
echo __umodti3 _goboringcrypto___umodti3 >>renames.txt
objcopy --remove-section=.llvm_addrsig goboringcrypto.o goboringcrypto1.o # b/179161016
objcopy --redefine-syms=renames.txt goboringcrypto1.o goboringcrypto2.o
objcopy --keep-global-symbols=globals.txt goboringcrypto2.o goboringcrypto_linux_amd64.syso
# Done!
ls -l goboringcrypto_linux_amd64.syso
sha256sum goboringcrypto_linux_amd64.syso

View file

@ -0,0 +1,140 @@
// Copyright 2022 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 boring
import (
"sync/atomic"
"unsafe"
)
// A Cache is a GC-friendly concurrent map from unsafe.Pointer to
// unsafe.Pointer. It is meant to be used for maintaining shadow
// BoringCrypto state associated with certain allocated structs, in
// particular public and private RSA and ECDSA keys.
//
// The cache is GC-friendly in the sense that the keys do not
// indefinitely prevent the garbage collector from collecting them.
// Instead, at the start of each GC, the cache is cleared entirely. That
// is, the cache is lossy, and the loss happens at the start of each GC.
// This means that clients need to be able to cope with cache entries
// disappearing, but it also means that clients don't need to worry about
// cache entries keeping the keys from being collected.
//
// TODO(rsc): Make Cache generic once consumers can handle that.
type Cache struct {
// ptable is an atomic *[cacheSize]unsafe.Pointer,
// where each unsafe.Pointer is an atomic *cacheEntry.
// The runtime atomically stores nil to ptable at the start of each GC.
ptable unsafe.Pointer
}
// A cacheEntry is a single entry in the linked list for a given hash table entry.
type cacheEntry struct {
k unsafe.Pointer // immutable once created
v unsafe.Pointer // read and written atomically to allow updates
next *cacheEntry // immutable once linked into table
}
func registerCache(unsafe.Pointer) // provided by runtime
// Register registers the cache with the runtime,
// so that c.ptable can be cleared at the start of each GC.
// Register must be called during package initialization.
func (c *Cache) Register() {
registerCache(unsafe.Pointer(&c.ptable))
}
// cacheSize is the number of entries in the hash table.
// The hash is the pointer value mod cacheSize, a prime.
// Collisions are resolved by maintaining a linked list in each hash slot.
const cacheSize = 1021
// table returns a pointer to the current cache hash table,
// coping with the possibility of the GC clearing it out from under us.
func (c *Cache) table() *[cacheSize]unsafe.Pointer {
for {
p := atomic.LoadPointer(&c.ptable)
if p == nil {
p = unsafe.Pointer(new([cacheSize]unsafe.Pointer))
if !atomic.CompareAndSwapPointer(&c.ptable, nil, p) {
continue
}
}
return (*[cacheSize]unsafe.Pointer)(p)
}
}
// Clear clears the cache.
// The runtime does this automatically at each garbage collection;
// this method is exposed only for testing.
func (c *Cache) Clear() {
// The runtime does this at the start of every garbage collection
// (itself, not by calling this function).
atomic.StorePointer(&c.ptable, nil)
}
// Get returns the cached value associated with v,
// which is either the value v corresponding to the most recent call to Put(k, v)
// or nil if that cache entry has been dropped.
func (c *Cache) Get(k unsafe.Pointer) unsafe.Pointer {
head := &c.table()[uintptr(k)%cacheSize]
e := (*cacheEntry)(atomic.LoadPointer(head))
for ; e != nil; e = e.next {
if e.k == k {
return atomic.LoadPointer(&e.v)
}
}
return nil
}
// Put sets the cached value associated with k to v.
func (c *Cache) Put(k, v unsafe.Pointer) {
head := &c.table()[uintptr(k)%cacheSize]
// Strategy is to walk the linked list at head,
// same as in Get, to look for existing entry.
// If we find one, we update v atomically in place.
// If not, then we race to replace the start = *head
// we observed with a new k, v entry.
// If we win that race, we're done.
// Otherwise, we try the whole thing again,
// with two optimizations:
//
// 1. We track in noK the start of the section of
// the list that we've confirmed has no entry for k.
// The next time down the list, we can stop at noK,
// because new entries are inserted at the front of the list.
// This guarantees we never traverse an entry
// multiple times.
//
// 2. We only allocate the entry to be added once,
// saving it in add for the next attempt.
var add, noK *cacheEntry
n := 0
for {
e := (*cacheEntry)(atomic.LoadPointer(head))
start := e
for ; e != nil && e != noK; e = e.next {
if e.k == k {
atomic.StorePointer(&e.v, v)
return
}
n++
}
if add == nil {
add = &cacheEntry{k, v, nil}
}
add.next = start
if n >= 1000 {
// If an individual list gets too long, which shouldn't happen,
// throw it away to avoid quadratic lookup behavior.
add.next = nil
}
if atomic.CompareAndSwapPointer(head, unsafe.Pointer(start), unsafe.Pointer(add)) {
return
}
noK = start
}
}

View file

@ -0,0 +1,120 @@
// Copyright 2022 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 boring
import (
"fmt"
"runtime"
"sync"
"sync/atomic"
"testing"
"unsafe"
)
var registeredCache Cache
func init() {
registeredCache.Register()
}
func TestCache(t *testing.T) {
// Use unregistered cache for functionality tests,
// to keep the runtime from clearing behind our backs.
c := new(Cache)
// Create many entries.
seq := uint32(0)
next := func() unsafe.Pointer {
x := new(int)
*x = int(atomic.AddUint32(&seq, 1))
return unsafe.Pointer(x)
}
m := make(map[unsafe.Pointer]unsafe.Pointer)
for i := 0; i < 10000; i++ {
k := next()
v := next()
m[k] = v
c.Put(k, v)
}
// Overwrite a random 20% of those.
n := 0
for k := range m {
v := next()
m[k] = v
c.Put(k, v)
if n++; n >= 2000 {
break
}
}
// Check results.
str := func(p unsafe.Pointer) string {
if p == nil {
return "nil"
}
return fmt.Sprint(*(*int)(p))
}
for k, v := range m {
if cv := c.Get(k); cv != v {
t.Fatalf("c.Get(%v) = %v, want %v", str(k), str(cv), str(v))
}
}
c.Clear()
for k := range m {
if cv := c.Get(k); cv != nil {
t.Fatalf("after GC, c.Get(%v) = %v, want nil", str(k), str(cv))
}
}
// Check that registered cache is cleared at GC.
c = &registeredCache
for k, v := range m {
c.Put(k, v)
}
runtime.GC()
for k := range m {
if cv := c.Get(k); cv != nil {
t.Fatalf("after Clear, c.Get(%v) = %v, want nil", str(k), str(cv))
}
}
// Check that cache works for concurrent access.
// Lists are discarded if they reach 1000 entries,
// and there are cacheSize list heads, so we should be
// able to do 100 * cacheSize entries with no problem at all.
c = new(Cache)
var barrier, wg sync.WaitGroup
const N = 100
barrier.Add(N)
wg.Add(N)
var lost int32
for i := 0; i < N; i++ {
go func() {
defer wg.Done()
m := make(map[unsafe.Pointer]unsafe.Pointer)
for j := 0; j < cacheSize; j++ {
k, v := next(), next()
m[k] = v
c.Put(k, v)
}
barrier.Done()
barrier.Wait()
for k, v := range m {
if cv := c.Get(k); cv != v {
t.Errorf("c.Get(%v) = %v, want %v", str(k), str(cv), str(v))
atomic.AddInt32(&lost, +1)
}
}
}()
}
wg.Wait()
if lost != 0 {
t.Errorf("lost %d entries", lost)
}
}

View file

@ -0,0 +1,19 @@
// Copyright 2017 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 boring provides access to BoringCrypto implementation functions.
// Check the constant Enabled to find out whether BoringCrypto is available.
// If BoringCrypto is not available, the functions in this package all panic.
package boring
// Enabled reports whether BoringCrypto is available.
// When enabled is false, all functions in this package panic.
//
// BoringCrypto is only available on linux/amd64 systems.
const Enabled = available
// A BigInt is the raw words from a BigInt.
// This definition allows us to avoid importing math/big.
// Conversion between BigInt and *big.Int is in crypto/internal/boring/bbig.
type BigInt []uint

View file

@ -0,0 +1,174 @@
// Copyright 2017 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 boringcrypto && linux && amd64 && !android && !cmd_go_bootstrap && !msan
// +build boringcrypto,linux,amd64,!android,!cmd_go_bootstrap,!msan
package boring
// #include "goboringcrypto.h"
import "C"
import (
"errors"
"runtime"
"unsafe"
)
type ecdsaSignature struct {
R, S BigInt
}
type PrivateKeyECDSA struct {
key *C.GO_EC_KEY
}
func (k *PrivateKeyECDSA) finalize() {
C._goboringcrypto_EC_KEY_free(k.key)
}
type PublicKeyECDSA struct {
key *C.GO_EC_KEY
}
func (k *PublicKeyECDSA) finalize() {
C._goboringcrypto_EC_KEY_free(k.key)
}
var errUnknownCurve = errors.New("boringcrypto: unknown elliptic curve")
func curveNID(curve string) (C.int, error) {
switch curve {
case "P-224":
return C.GO_NID_secp224r1, nil
case "P-256":
return C.GO_NID_X9_62_prime256v1, nil
case "P-384":
return C.GO_NID_secp384r1, nil
case "P-521":
return C.GO_NID_secp521r1, nil
}
return 0, errUnknownCurve
}
func NewPublicKeyECDSA(curve string, X, Y BigInt) (*PublicKeyECDSA, error) {
key, err := newECKey(curve, X, Y)
if err != nil {
return nil, err
}
k := &PublicKeyECDSA{key}
// Note: Because of the finalizer, any time k.key is passed to cgo,
// that call must be followed by a call to runtime.KeepAlive(k),
// to make sure k is not collected (and finalized) before the cgo
// call returns.
runtime.SetFinalizer(k, (*PublicKeyECDSA).finalize)
return k, nil
}
func newECKey(curve string, X, Y BigInt) (*C.GO_EC_KEY, error) {
nid, err := curveNID(curve)
if err != nil {
return nil, err
}
key := C._goboringcrypto_EC_KEY_new_by_curve_name(nid)
if key == nil {
return nil, fail("EC_KEY_new_by_curve_name")
}
group := C._goboringcrypto_EC_KEY_get0_group(key)
pt := C._goboringcrypto_EC_POINT_new(group)
if pt == nil {
C._goboringcrypto_EC_KEY_free(key)
return nil, fail("EC_POINT_new")
}
bx := bigToBN(X)
by := bigToBN(Y)
ok := bx != nil && by != nil && C._goboringcrypto_EC_POINT_set_affine_coordinates_GFp(group, pt, bx, by, nil) != 0 &&
C._goboringcrypto_EC_KEY_set_public_key(key, pt) != 0
if bx != nil {
C._goboringcrypto_BN_free(bx)
}
if by != nil {
C._goboringcrypto_BN_free(by)
}
C._goboringcrypto_EC_POINT_free(pt)
if !ok {
C._goboringcrypto_EC_KEY_free(key)
return nil, fail("EC_POINT_set_affine_coordinates_GFp")
}
return key, nil
}
func NewPrivateKeyECDSA(curve string, X, Y BigInt, D BigInt) (*PrivateKeyECDSA, error) {
key, err := newECKey(curve, X, Y)
if err != nil {
return nil, err
}
bd := bigToBN(D)
ok := bd != nil && C._goboringcrypto_EC_KEY_set_private_key(key, bd) != 0
if bd != nil {
C._goboringcrypto_BN_free(bd)
}
if !ok {
C._goboringcrypto_EC_KEY_free(key)
return nil, fail("EC_KEY_set_private_key")
}
k := &PrivateKeyECDSA{key}
// Note: Because of the finalizer, any time k.key is passed to cgo,
// that call must be followed by a call to runtime.KeepAlive(k),
// to make sure k is not collected (and finalized) before the cgo
// call returns.
runtime.SetFinalizer(k, (*PrivateKeyECDSA).finalize)
return k, nil
}
func SignMarshalECDSA(priv *PrivateKeyECDSA, hash []byte) ([]byte, error) {
size := C._goboringcrypto_ECDSA_size(priv.key)
sig := make([]byte, size)
var sigLen C.uint
if C._goboringcrypto_ECDSA_sign(0, base(hash), C.size_t(len(hash)), (*C.uint8_t)(unsafe.Pointer(&sig[0])), &sigLen, priv.key) == 0 {
return nil, fail("ECDSA_sign")
}
runtime.KeepAlive(priv)
return sig[:sigLen], nil
}
func VerifyECDSA(pub *PublicKeyECDSA, hash []byte, sig []byte) bool {
ok := C._goboringcrypto_ECDSA_verify(0, base(hash), C.size_t(len(hash)), (*C.uint8_t)(unsafe.Pointer(&sig[0])), C.size_t(len(sig)), pub.key) != 0
runtime.KeepAlive(pub)
return ok
}
func GenerateKeyECDSA(curve string) (X, Y, D BigInt, err error) {
nid, err := curveNID(curve)
if err != nil {
return nil, nil, nil, err
}
key := C._goboringcrypto_EC_KEY_new_by_curve_name(nid)
if key == nil {
return nil, nil, nil, fail("EC_KEY_new_by_curve_name")
}
defer C._goboringcrypto_EC_KEY_free(key)
if C._goboringcrypto_EC_KEY_generate_key_fips(key) == 0 {
return nil, nil, nil, fail("EC_KEY_generate_key_fips")
}
group := C._goboringcrypto_EC_KEY_get0_group(key)
pt := C._goboringcrypto_EC_KEY_get0_public_key(key)
bd := C._goboringcrypto_EC_KEY_get0_private_key(key)
if pt == nil || bd == nil {
return nil, nil, nil, fail("EC_KEY_get0_private_key")
}
bx := C._goboringcrypto_BN_new()
if bx == nil {
return nil, nil, nil, fail("BN_new")
}
defer C._goboringcrypto_BN_free(bx)
by := C._goboringcrypto_BN_new()
if by == nil {
return nil, nil, nil, fail("BN_new")
}
defer C._goboringcrypto_BN_free(by)
if C._goboringcrypto_EC_POINT_get_affine_coordinates_GFp(group, pt, bx, by, nil) == 0 {
return nil, nil, nil, fail("EC_POINT_get_affine_coordinates_GFp")
}
return bnToBig(bx), bnToBig(by), bnToBig(bd), nil
}

View file

@ -0,0 +1,12 @@
// Copyright 2017 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 boringcrypto
// runtime_arg0 is declared in tls.go without a body.
// It's provided by package runtime,
// but the go command doesn't know that.
// Having this assembly file keeps the go command
// from complaining about the missing body
// (because the implementation might be here).

View file

@ -0,0 +1,52 @@
// Copyright 2017 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 boringcrypto
// Package fipstls allows control over whether crypto/tls requires FIPS-approved settings.
// This package only exists with GOEXPERIMENT=boringcrypto, but the effects are independent
// of the use of BoringCrypto.
package fipstls
import "sync/atomic"
var required uint32
// Force forces crypto/tls to restrict TLS configurations to FIPS-approved settings.
// By design, this call is impossible to undo (except in tests).
//
// Note that this call has an effect even in programs using
// standard crypto (that is, even when Enabled = false).
func Force() {
atomic.StoreUint32(&required, 1)
}
// Abandon allows non-FIPS-approved settings.
// If called from a non-test binary, it panics.
func Abandon() {
// Note: Not using boring.UnreachableExceptTests because we want
// this test to happen even when boring.Enabled = false.
name := runtime_arg0()
// Allow _test for Go command, .test for Bazel,
// NaClMain for NaCl (where all binaries run as NaClMain),
// and empty string for Windows (where runtime_arg0 can't easily find the name).
// Since this is an internal package, testing that this isn't used on the
// other operating systems should suffice to catch any mistakes.
if !hasSuffix(name, "_test") && !hasSuffix(name, ".test") && name != "NaClMain" && name != "" {
panic("fipstls: invalid use of Abandon in " + name)
}
atomic.StoreUint32(&required, 0)
}
// provided by runtime
func runtime_arg0() string
func hasSuffix(s, t string) bool {
return len(s) > len(t) && s[len(s)-len(t):] == t
}
// Required reports whether FIPS-approved settings are required.
func Required() bool {
return atomic.LoadUint32(&required) != 0
}

View file

@ -0,0 +1,239 @@
// Copyright 2017 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.
// This header file describes the BoringCrypto ABI as built for use in Go.
// The BoringCrypto build for Go (which generates goboringcrypto_*.syso)
// takes the standard libcrypto.a from BoringCrypto and adds the prefix
// _goboringcrypto_ to every symbol, to avoid possible conflicts with
// code wrapping a different BoringCrypto or OpenSSL.
//
// To make this header standalone (so that building Go does not require
// having a full set of BoringCrypto headers), the struct details are not here.
// Instead, while building the syso, we compile and run a C++ program
// that checks that the sizes match. The program also checks (during compilation)
// that all the function prototypes match the BoringCrypto equivalents.
// The generation of the checking program depends on the declaration
// forms used below (one line for most, multiline for enums).
#include <stdlib.h> // size_t
#include <stdint.h> // uint8_t
// This symbol is hidden in BoringCrypto and marked as a constructor,
// but cmd/link's internal linking mode doesn't handle constructors.
// Until it does, we've exported the symbol and can call it explicitly.
// (If using external linking mode, it will therefore be called twice,
// once explicitly and once as a constructor, but that's OK.)
/*unchecked*/ void _goboringcrypto_BORINGSSL_bcm_power_on_self_test(void);
// #include <openssl/crypto.h>
int _goboringcrypto_FIPS_mode(void);
void* _goboringcrypto_OPENSSL_malloc(size_t);
// #include <openssl/rand.h>
int _goboringcrypto_RAND_bytes(uint8_t*, size_t);
// #include <openssl/nid.h>
enum {
GO_NID_md5_sha1 = 114,
GO_NID_secp224r1 = 713,
GO_NID_X9_62_prime256v1 = 415,
GO_NID_secp384r1 = 715,
GO_NID_secp521r1 = 716,
GO_NID_sha224 = 675,
GO_NID_sha256 = 672,
GO_NID_sha384 = 673,
GO_NID_sha512 = 674,
};
// #include <openssl/sha.h>
typedef struct GO_SHA_CTX { char data[96]; } GO_SHA_CTX;
int _goboringcrypto_SHA1_Init(GO_SHA_CTX*);
int _goboringcrypto_SHA1_Update(GO_SHA_CTX*, const void*, size_t);
int _goboringcrypto_SHA1_Final(uint8_t*, GO_SHA_CTX*);
typedef struct GO_SHA256_CTX { char data[48+64]; } GO_SHA256_CTX;
int _goboringcrypto_SHA224_Init(GO_SHA256_CTX*);
int _goboringcrypto_SHA224_Update(GO_SHA256_CTX*, const void*, size_t);
int _goboringcrypto_SHA224_Final(uint8_t*, GO_SHA256_CTX*);
int _goboringcrypto_SHA256_Init(GO_SHA256_CTX*);
int _goboringcrypto_SHA256_Update(GO_SHA256_CTX*, const void*, size_t);
int _goboringcrypto_SHA256_Final(uint8_t*, GO_SHA256_CTX*);
typedef struct GO_SHA512_CTX { char data[88+128]; } GO_SHA512_CTX;
int _goboringcrypto_SHA384_Init(GO_SHA512_CTX*);
int _goboringcrypto_SHA384_Update(GO_SHA512_CTX*, const void*, size_t);
int _goboringcrypto_SHA384_Final(uint8_t*, GO_SHA512_CTX*);
int _goboringcrypto_SHA512_Init(GO_SHA512_CTX*);
int _goboringcrypto_SHA512_Update(GO_SHA512_CTX*, const void*, size_t);
int _goboringcrypto_SHA512_Final(uint8_t*, GO_SHA512_CTX*);
// #include <openssl/digest.h>
/*unchecked (opaque)*/ typedef struct GO_EVP_MD { char data[1]; } GO_EVP_MD;
const GO_EVP_MD* _goboringcrypto_EVP_md4(void);
const GO_EVP_MD* _goboringcrypto_EVP_md5(void);
const GO_EVP_MD* _goboringcrypto_EVP_md5_sha1(void);
const GO_EVP_MD* _goboringcrypto_EVP_sha1(void);
const GO_EVP_MD* _goboringcrypto_EVP_sha224(void);
const GO_EVP_MD* _goboringcrypto_EVP_sha256(void);
const GO_EVP_MD* _goboringcrypto_EVP_sha384(void);
const GO_EVP_MD* _goboringcrypto_EVP_sha512(void);
int _goboringcrypto_EVP_MD_type(const GO_EVP_MD*);
size_t _goboringcrypto_EVP_MD_size(const GO_EVP_MD*);
// #include <openssl/hmac.h>
typedef struct GO_HMAC_CTX { char data[104]; } GO_HMAC_CTX;
void _goboringcrypto_HMAC_CTX_init(GO_HMAC_CTX*);
void _goboringcrypto_HMAC_CTX_cleanup(GO_HMAC_CTX*);
int _goboringcrypto_HMAC_Init(GO_HMAC_CTX*, const void*, int, const GO_EVP_MD*);
int _goboringcrypto_HMAC_Update(GO_HMAC_CTX*, const uint8_t*, size_t);
int _goboringcrypto_HMAC_Final(GO_HMAC_CTX*, uint8_t*, unsigned int*);
size_t _goboringcrypto_HMAC_size(const GO_HMAC_CTX*);
int _goboringcrypto_HMAC_CTX_copy_ex(GO_HMAC_CTX *dest, const GO_HMAC_CTX *src);
// #include <openssl/aes.h>
typedef struct GO_AES_KEY { char data[244]; } GO_AES_KEY;
int _goboringcrypto_AES_set_encrypt_key(const uint8_t*, unsigned int, GO_AES_KEY*);
int _goboringcrypto_AES_set_decrypt_key(const uint8_t*, unsigned int, GO_AES_KEY*);
void _goboringcrypto_AES_encrypt(const uint8_t*, uint8_t*, const GO_AES_KEY*);
void _goboringcrypto_AES_decrypt(const uint8_t*, uint8_t*, const GO_AES_KEY*);
void _goboringcrypto_AES_ctr128_encrypt(const uint8_t*, uint8_t*, size_t, const GO_AES_KEY*, uint8_t*, uint8_t*, unsigned int*);
enum {
GO_AES_ENCRYPT = 1,
GO_AES_DECRYPT = 0
};
void _goboringcrypto_AES_cbc_encrypt(const uint8_t*, uint8_t*, size_t, const GO_AES_KEY*, uint8_t*, const int);
// #include <openssl/aead.h>
/*unchecked (opaque)*/ typedef struct GO_EVP_AEAD { char data[1]; } GO_EVP_AEAD;
/*unchecked (opaque)*/ typedef struct GO_ENGINE { char data[1]; } GO_ENGINE;
const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_128_gcm(void);
const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_256_gcm(void);
enum {
GO_EVP_AEAD_DEFAULT_TAG_LENGTH = 0
};
size_t _goboringcrypto_EVP_AEAD_key_length(const GO_EVP_AEAD*);
size_t _goboringcrypto_EVP_AEAD_nonce_length(const GO_EVP_AEAD*);
size_t _goboringcrypto_EVP_AEAD_max_overhead(const GO_EVP_AEAD*);
size_t _goboringcrypto_EVP_AEAD_max_tag_len(const GO_EVP_AEAD*);
typedef struct GO_EVP_AEAD_CTX { char data[600]; } GO_EVP_AEAD_CTX;
void _goboringcrypto_EVP_AEAD_CTX_zero(GO_EVP_AEAD_CTX*);
int _goboringcrypto_EVP_AEAD_CTX_init(GO_EVP_AEAD_CTX*, const GO_EVP_AEAD*, const uint8_t*, size_t, size_t, GO_ENGINE*);
void _goboringcrypto_EVP_AEAD_CTX_cleanup(GO_EVP_AEAD_CTX*);
int _goboringcrypto_EVP_AEAD_CTX_seal(const GO_EVP_AEAD_CTX*, uint8_t*, size_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t);
int _goboringcrypto_EVP_AEAD_CTX_open(const GO_EVP_AEAD_CTX*, uint8_t*, size_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t);
const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_128_gcm_tls12(void);
const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_256_gcm_tls12(void);
enum go_evp_aead_direction_t {
go_evp_aead_open = 0,
go_evp_aead_seal = 1
};
int _goboringcrypto_EVP_AEAD_CTX_init_with_direction(GO_EVP_AEAD_CTX*, const GO_EVP_AEAD*, const uint8_t*, size_t, size_t, enum go_evp_aead_direction_t);
// #include <openssl/bn.h>
/*unchecked (opaque)*/ typedef struct GO_BN_CTX { char data[1]; } GO_BN_CTX;
typedef struct GO_BIGNUM { char data[24]; } GO_BIGNUM;
GO_BIGNUM* _goboringcrypto_BN_new(void);
void _goboringcrypto_BN_free(GO_BIGNUM*);
unsigned _goboringcrypto_BN_num_bits(const GO_BIGNUM*);
unsigned _goboringcrypto_BN_num_bytes(const GO_BIGNUM*);
int _goboringcrypto_BN_is_negative(const GO_BIGNUM*);
GO_BIGNUM* _goboringcrypto_BN_bin2bn(const uint8_t*, size_t, GO_BIGNUM*);
GO_BIGNUM* _goboringcrypto_BN_le2bn(const uint8_t*, size_t, GO_BIGNUM*);
size_t _goboringcrypto_BN_bn2bin(const GO_BIGNUM*, uint8_t*);
int _goboringcrypto_BN_bn2le_padded(uint8_t*, size_t, const GO_BIGNUM*);
// #include <openssl/ec.h>
/*unchecked (opaque)*/ typedef struct GO_EC_GROUP { char data[1]; } GO_EC_GROUP;
GO_EC_GROUP* _goboringcrypto_EC_GROUP_new_by_curve_name(int);
void _goboringcrypto_EC_GROUP_free(GO_EC_GROUP*);
/*unchecked (opaque)*/ typedef struct GO_EC_POINT { char data[1]; } GO_EC_POINT;
GO_EC_POINT* _goboringcrypto_EC_POINT_new(const GO_EC_GROUP*);
void _goboringcrypto_EC_POINT_free(GO_EC_POINT*);
int _goboringcrypto_EC_POINT_get_affine_coordinates_GFp(const GO_EC_GROUP*, const GO_EC_POINT*, GO_BIGNUM*, GO_BIGNUM*, GO_BN_CTX*);
int _goboringcrypto_EC_POINT_set_affine_coordinates_GFp(const GO_EC_GROUP*, GO_EC_POINT*, const GO_BIGNUM*, const GO_BIGNUM*, GO_BN_CTX*);
// #include <openssl/ec_key.h>
/*unchecked (opaque)*/ typedef struct GO_EC_KEY { char data[1]; } GO_EC_KEY;
GO_EC_KEY* _goboringcrypto_EC_KEY_new(void);
GO_EC_KEY* _goboringcrypto_EC_KEY_new_by_curve_name(int);
void _goboringcrypto_EC_KEY_free(GO_EC_KEY*);
const GO_EC_GROUP* _goboringcrypto_EC_KEY_get0_group(const GO_EC_KEY*);
int _goboringcrypto_EC_KEY_generate_key_fips(GO_EC_KEY*);
int _goboringcrypto_EC_KEY_set_private_key(GO_EC_KEY*, const GO_BIGNUM*);
int _goboringcrypto_EC_KEY_set_public_key(GO_EC_KEY*, const GO_EC_POINT*);
int _goboringcrypto_EC_KEY_is_opaque(const GO_EC_KEY*);
const GO_BIGNUM* _goboringcrypto_EC_KEY_get0_private_key(const GO_EC_KEY*);
const GO_EC_POINT* _goboringcrypto_EC_KEY_get0_public_key(const GO_EC_KEY*);
// TODO: EC_KEY_check_fips?
// #include <openssl/ecdsa.h>
typedef struct GO_ECDSA_SIG { char data[16]; } GO_ECDSA_SIG;
GO_ECDSA_SIG* _goboringcrypto_ECDSA_SIG_new(void);
void _goboringcrypto_ECDSA_SIG_free(GO_ECDSA_SIG*);
GO_ECDSA_SIG* _goboringcrypto_ECDSA_do_sign(const uint8_t*, size_t, const GO_EC_KEY*);
int _goboringcrypto_ECDSA_do_verify(const uint8_t*, size_t, const GO_ECDSA_SIG*, const GO_EC_KEY*);
int _goboringcrypto_ECDSA_sign(int, const uint8_t*, size_t, uint8_t*, unsigned int*, const GO_EC_KEY*);
size_t _goboringcrypto_ECDSA_size(const GO_EC_KEY*);
int _goboringcrypto_ECDSA_verify(int, const uint8_t*, size_t, const uint8_t*, size_t, const GO_EC_KEY*);
// #include <openssl/rsa.h>
// Note: order of struct fields here is unchecked.
typedef struct GO_RSA { void *meth; GO_BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp; char data[160]; } GO_RSA;
/*unchecked (opaque)*/ typedef struct GO_BN_GENCB { char data[1]; } GO_BN_GENCB;
GO_RSA* _goboringcrypto_RSA_new(void);
void _goboringcrypto_RSA_free(GO_RSA*);
void _goboringcrypto_RSA_get0_key(const GO_RSA*, const GO_BIGNUM **n, const GO_BIGNUM **e, const GO_BIGNUM **d);
void _goboringcrypto_RSA_get0_factors(const GO_RSA*, const GO_BIGNUM **p, const GO_BIGNUM **q);
void _goboringcrypto_RSA_get0_crt_params(const GO_RSA*, const GO_BIGNUM **dmp1, const GO_BIGNUM **dmp2, const GO_BIGNUM **iqmp);
int _goboringcrypto_RSA_generate_key_ex(GO_RSA*, int, const GO_BIGNUM*, GO_BN_GENCB*);
int _goboringcrypto_RSA_generate_key_fips(GO_RSA*, int, GO_BN_GENCB*);
enum {
GO_RSA_PKCS1_PADDING = 1,
GO_RSA_NO_PADDING = 3,
GO_RSA_PKCS1_OAEP_PADDING = 4,
GO_RSA_PKCS1_PSS_PADDING = 6,
};
int _goboringcrypto_RSA_encrypt(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding);
int _goboringcrypto_RSA_decrypt(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding);
int _goboringcrypto_RSA_sign(int hash_nid, const uint8_t* in, unsigned int in_len, uint8_t *out, unsigned int *out_len, GO_RSA*);
int _goboringcrypto_RSA_sign_pss_mgf1(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, const GO_EVP_MD *md, const GO_EVP_MD *mgf1_md, int salt_len);
int _goboringcrypto_RSA_sign_raw(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding);
int _goboringcrypto_RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len, GO_RSA*);
int _goboringcrypto_RSA_verify_pss_mgf1(GO_RSA*, const uint8_t *msg, size_t msg_len, const GO_EVP_MD *md, const GO_EVP_MD *mgf1_md, int salt_len, const uint8_t *sig, size_t sig_len);
int _goboringcrypto_RSA_verify_raw(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding);
unsigned _goboringcrypto_RSA_size(const GO_RSA*);
int _goboringcrypto_RSA_is_opaque(const GO_RSA*);
int _goboringcrypto_RSA_check_key(const GO_RSA*);
int _goboringcrypto_RSA_check_fips(GO_RSA*);
GO_RSA* _goboringcrypto_RSA_public_key_from_bytes(const uint8_t*, size_t);
GO_RSA* _goboringcrypto_RSA_private_key_from_bytes(const uint8_t*, size_t);
int _goboringcrypto_RSA_public_key_to_bytes(uint8_t**, size_t*, const GO_RSA*);
int _goboringcrypto_RSA_private_key_to_bytes(uint8_t**, size_t*, const GO_RSA*);
// #include <openssl/evp.h>
/*unchecked (opaque)*/ typedef struct GO_EVP_PKEY { char data[1]; } GO_EVP_PKEY;
GO_EVP_PKEY* _goboringcrypto_EVP_PKEY_new(void);
void _goboringcrypto_EVP_PKEY_free(GO_EVP_PKEY*);
int _goboringcrypto_EVP_PKEY_set1_RSA(GO_EVP_PKEY*, GO_RSA*);
/*unchecked (opaque)*/ typedef struct GO_EVP_PKEY_CTX { char data[1]; } GO_EVP_PKEY_CTX;
GO_EVP_PKEY_CTX* _goboringcrypto_EVP_PKEY_CTX_new(GO_EVP_PKEY*, GO_ENGINE*);
void _goboringcrypto_EVP_PKEY_CTX_free(GO_EVP_PKEY_CTX*);
int _goboringcrypto_EVP_PKEY_CTX_set0_rsa_oaep_label(GO_EVP_PKEY_CTX*, uint8_t*, size_t);
int _goboringcrypto_EVP_PKEY_CTX_set_rsa_oaep_md(GO_EVP_PKEY_CTX*, const GO_EVP_MD*);
int _goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(GO_EVP_PKEY_CTX*, int padding);
int _goboringcrypto_EVP_PKEY_decrypt(GO_EVP_PKEY_CTX*, uint8_t*, size_t*, const uint8_t*, size_t);
int _goboringcrypto_EVP_PKEY_encrypt(GO_EVP_PKEY_CTX*, uint8_t*, size_t*, const uint8_t*, size_t);
int _goboringcrypto_EVP_PKEY_decrypt_init(GO_EVP_PKEY_CTX*);
int _goboringcrypto_EVP_PKEY_encrypt_init(GO_EVP_PKEY_CTX*);
int _goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(GO_EVP_PKEY_CTX*, const GO_EVP_MD*);
int _goboringcrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(GO_EVP_PKEY_CTX*, int);
int _goboringcrypto_EVP_PKEY_sign_init(GO_EVP_PKEY_CTX*);
int _goboringcrypto_EVP_PKEY_verify_init(GO_EVP_PKEY_CTX*);
int _goboringcrypto_EVP_PKEY_sign(GO_EVP_PKEY_CTX*, uint8_t*, size_t*, const uint8_t*, size_t);

View file

@ -0,0 +1,154 @@
// Copyright 2017 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 boringcrypto && linux && amd64 && !android && !cmd_go_bootstrap && !msan
// +build boringcrypto,linux,amd64,!android,!cmd_go_bootstrap,!msan
package boring
// #include "goboringcrypto.h"
import "C"
import (
"crypto"
"hash"
"runtime"
"unsafe"
)
// hashToMD converts a hash.Hash implementation from this package
// to a BoringCrypto *C.GO_EVP_MD.
func hashToMD(h hash.Hash) *C.GO_EVP_MD {
switch h.(type) {
case *sha1Hash:
return C._goboringcrypto_EVP_sha1()
case *sha224Hash:
return C._goboringcrypto_EVP_sha224()
case *sha256Hash:
return C._goboringcrypto_EVP_sha256()
case *sha384Hash:
return C._goboringcrypto_EVP_sha384()
case *sha512Hash:
return C._goboringcrypto_EVP_sha512()
}
return nil
}
// cryptoHashToMD converts a crypto.Hash
// to a BoringCrypto *C.GO_EVP_MD.
func cryptoHashToMD(ch crypto.Hash) *C.GO_EVP_MD {
switch ch {
case crypto.MD5:
return C._goboringcrypto_EVP_md5()
case crypto.MD5SHA1:
return C._goboringcrypto_EVP_md5_sha1()
case crypto.SHA1:
return C._goboringcrypto_EVP_sha1()
case crypto.SHA224:
return C._goboringcrypto_EVP_sha224()
case crypto.SHA256:
return C._goboringcrypto_EVP_sha256()
case crypto.SHA384:
return C._goboringcrypto_EVP_sha384()
case crypto.SHA512:
return C._goboringcrypto_EVP_sha512()
}
return nil
}
// NewHMAC returns a new HMAC using BoringCrypto.
// The function h must return a hash implemented by
// BoringCrypto (for example, h could be boring.NewSHA256).
// If h is not recognized, NewHMAC returns nil.
func NewHMAC(h func() hash.Hash, key []byte) hash.Hash {
ch := h()
md := hashToMD(ch)
if md == nil {
return nil
}
// Note: Could hash down long keys here using EVP_Digest.
hkey := make([]byte, len(key))
copy(hkey, key)
hmac := &boringHMAC{
md: md,
size: ch.Size(),
blockSize: ch.BlockSize(),
key: hkey,
}
hmac.Reset()
return hmac
}
type boringHMAC struct {
md *C.GO_EVP_MD
ctx C.GO_HMAC_CTX
ctx2 C.GO_HMAC_CTX
size int
blockSize int
key []byte
sum []byte
needCleanup bool
}
func (h *boringHMAC) Reset() {
if h.needCleanup {
C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx)
} else {
h.needCleanup = true
// Note: Because of the finalizer, any time h.ctx is passed to cgo,
// that call must be followed by a call to runtime.KeepAlive(h),
// to make sure h is not collected (and finalized) before the cgo
// call returns.
runtime.SetFinalizer(h, (*boringHMAC).finalize)
}
C._goboringcrypto_HMAC_CTX_init(&h.ctx)
if C._goboringcrypto_HMAC_Init(&h.ctx, unsafe.Pointer(base(h.key)), C.int(len(h.key)), h.md) == 0 {
panic("boringcrypto: HMAC_Init failed")
}
if int(C._goboringcrypto_HMAC_size(&h.ctx)) != h.size {
println("boringcrypto: HMAC size:", C._goboringcrypto_HMAC_size(&h.ctx), "!=", h.size)
panic("boringcrypto: HMAC size mismatch")
}
runtime.KeepAlive(h) // Next line will keep h alive too; just making doubly sure.
h.sum = nil
}
func (h *boringHMAC) finalize() {
C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx)
}
func (h *boringHMAC) Write(p []byte) (int, error) {
if len(p) > 0 {
C._goboringcrypto_HMAC_Update(&h.ctx, (*C.uint8_t)(unsafe.Pointer(&p[0])), C.size_t(len(p)))
}
runtime.KeepAlive(h)
return len(p), nil
}
func (h *boringHMAC) Size() int {
return h.size
}
func (h *boringHMAC) BlockSize() int {
return h.blockSize
}
func (h *boringHMAC) Sum(in []byte) []byte {
if h.sum == nil {
size := h.Size()
h.sum = make([]byte, size)
}
// Make copy of context because Go hash.Hash mandates
// that Sum has no effect on the underlying stream.
// In particular it is OK to Sum, then Write more, then Sum again,
// and the second Sum acts as if the first didn't happen.
C._goboringcrypto_HMAC_CTX_init(&h.ctx2)
if C._goboringcrypto_HMAC_CTX_copy_ex(&h.ctx2, &h.ctx) == 0 {
panic("boringcrypto: HMAC_CTX_copy_ex failed")
}
C._goboringcrypto_HMAC_Final(&h.ctx2, (*C.uint8_t)(unsafe.Pointer(&h.sum[0])), nil)
C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx2)
return append(in, h.sum...)
}

View file

@ -0,0 +1,112 @@
// Copyright 2017 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 !boringcrypto || !linux || !amd64 || !cgo || android || cmd_go_bootstrap || msan
// +build !boringcrypto !linux !amd64 !cgo android cmd_go_bootstrap msan
package boring
import (
"crypto"
"crypto/cipher"
"crypto/internal/boring/sig"
"hash"
)
const available = false
// Unreachable marks code that should be unreachable
// when BoringCrypto is in use. It is a no-op without BoringCrypto.
func Unreachable() {
// Code that's unreachable when using BoringCrypto
// is exactly the code we want to detect for reporting
// standard Go crypto.
sig.StandardCrypto()
}
// UnreachableExceptTests marks code that should be unreachable
// when BoringCrypto is in use. It is a no-op without BoringCrypto.
func UnreachableExceptTests() {}
type randReader int
func (randReader) Read(b []byte) (int, error) { panic("boringcrypto: not available") }
const RandReader = randReader(0)
func NewSHA1() hash.Hash { panic("boringcrypto: not available") }
func NewSHA224() hash.Hash { panic("boringcrypto: not available") }
func NewSHA256() hash.Hash { panic("boringcrypto: not available") }
func NewSHA384() hash.Hash { panic("boringcrypto: not available") }
func NewSHA512() hash.Hash { panic("boringcrypto: not available") }
func SHA1([]byte) [20]byte { panic("boringcrypto: not available") }
func SHA224([]byte) [28]byte { panic("boringcrypto: not available") }
func SHA256([]byte) [32]byte { panic("boringcrypto: not available") }
func SHA384([]byte) [48]byte { panic("boringcrypto: not available") }
func SHA512([]byte) [64]byte { panic("boringcrypto: not available") }
func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { panic("boringcrypto: not available") }
func NewAESCipher(key []byte) (cipher.Block, error) { panic("boringcrypto: not available") }
type PublicKeyECDSA struct{ _ int }
type PrivateKeyECDSA struct{ _ int }
func GenerateKeyECDSA(curve string) (X, Y, D BigInt, err error) {
panic("boringcrypto: not available")
}
func NewPrivateKeyECDSA(curve string, X, Y, D BigInt) (*PrivateKeyECDSA, error) {
panic("boringcrypto: not available")
}
func NewPublicKeyECDSA(curve string, X, Y BigInt) (*PublicKeyECDSA, error) {
panic("boringcrypto: not available")
}
func SignMarshalECDSA(priv *PrivateKeyECDSA, hash []byte) ([]byte, error) {
panic("boringcrypto: not available")
}
func VerifyECDSA(pub *PublicKeyECDSA, hash []byte, sig []byte) bool {
panic("boringcrypto: not available")
}
type PublicKeyRSA struct{ _ int }
type PrivateKeyRSA struct{ _ int }
func DecryptRSAOAEP(h hash.Hash, priv *PrivateKeyRSA, ciphertext, label []byte) ([]byte, error) {
panic("boringcrypto: not available")
}
func DecryptRSAPKCS1(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) {
panic("boringcrypto: not available")
}
func DecryptRSANoPadding(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) {
panic("boringcrypto: not available")
}
func EncryptRSAOAEP(h hash.Hash, pub *PublicKeyRSA, msg, label []byte) ([]byte, error) {
panic("boringcrypto: not available")
}
func EncryptRSAPKCS1(pub *PublicKeyRSA, msg []byte) ([]byte, error) {
panic("boringcrypto: not available")
}
func EncryptRSANoPadding(pub *PublicKeyRSA, msg []byte) ([]byte, error) {
panic("boringcrypto: not available")
}
func GenerateKeyRSA(bits int) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) {
panic("boringcrypto: not available")
}
func NewPrivateKeyRSA(N, E, D, P, Q, Dp, Dq, Qinv BigInt) (*PrivateKeyRSA, error) {
panic("boringcrypto: not available")
}
func NewPublicKeyRSA(N, E BigInt) (*PublicKeyRSA, error) { panic("boringcrypto: not available") }
func SignRSAPKCS1v15(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte) ([]byte, error) {
panic("boringcrypto: not available")
}
func SignRSAPSS(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte, saltLen int) ([]byte, error) {
panic("boringcrypto: not available")
}
func VerifyRSAPKCS1v15(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte) error {
panic("boringcrypto: not available")
}
func VerifyRSAPSS(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte, saltLen int) error {
panic("boringcrypto: not available")
}

View file

@ -0,0 +1,25 @@
// Copyright 2017 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 boringcrypto && linux && amd64 && !android && !cmd_go_bootstrap && !msan
// +build boringcrypto,linux,amd64,!android,!cmd_go_bootstrap,!msan
package boring
// #include "goboringcrypto.h"
import "C"
import "unsafe"
type randReader int
func (randReader) Read(b []byte) (int, error) {
// Note: RAND_bytes should never fail; the return value exists only for historical reasons.
// We check it even so.
if len(b) > 0 && C._goboringcrypto_RAND_bytes((*C.uint8_t)(unsafe.Pointer(&b[0])), C.size_t(len(b))) == 0 {
return 0, fail("RAND_bytes")
}
return len(b), nil
}
const RandReader = randReader(0)

View file

@ -0,0 +1,347 @@
// Copyright 2017 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 boringcrypto && linux && amd64 && !android && !cmd_go_bootstrap && !msan
// +build boringcrypto,linux,amd64,!android,!cmd_go_bootstrap,!msan
package boring
// #include "goboringcrypto.h"
import "C"
import (
"crypto"
"crypto/subtle"
"errors"
"hash"
"runtime"
"strconv"
"unsafe"
)
func GenerateKeyRSA(bits int) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) {
bad := func(e error) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) {
return nil, nil, nil, nil, nil, nil, nil, nil, e
}
key := C._goboringcrypto_RSA_new()
if key == nil {
return bad(fail("RSA_new"))
}
defer C._goboringcrypto_RSA_free(key)
if C._goboringcrypto_RSA_generate_key_fips(key, C.int(bits), nil) == 0 {
return bad(fail("RSA_generate_key_fips"))
}
var n, e, d, p, q, dp, dq, qinv *C.GO_BIGNUM
C._goboringcrypto_RSA_get0_key(key, &n, &e, &d)
C._goboringcrypto_RSA_get0_factors(key, &p, &q)
C._goboringcrypto_RSA_get0_crt_params(key, &dp, &dq, &qinv)
return bnToBig(n), bnToBig(e), bnToBig(d), bnToBig(p), bnToBig(q), bnToBig(dp), bnToBig(dq), bnToBig(qinv), nil
}
type PublicKeyRSA struct {
// _key MUST NOT be accessed directly. Instead, use the withKey method.
_key *C.GO_RSA
}
func NewPublicKeyRSA(N, E BigInt) (*PublicKeyRSA, error) {
key := C._goboringcrypto_RSA_new()
if key == nil {
return nil, fail("RSA_new")
}
if !bigToBn(&key.n, N) ||
!bigToBn(&key.e, E) {
return nil, fail("BN_bin2bn")
}
k := &PublicKeyRSA{_key: key}
runtime.SetFinalizer(k, (*PublicKeyRSA).finalize)
return k, nil
}
func (k *PublicKeyRSA) finalize() {
C._goboringcrypto_RSA_free(k._key)
}
func (k *PublicKeyRSA) withKey(f func(*C.GO_RSA) C.int) C.int {
// Because of the finalizer, any time _key is passed to cgo, that call must
// be followed by a call to runtime.KeepAlive, to make sure k is not
// collected (and finalized) before the cgo call returns.
defer runtime.KeepAlive(k)
return f(k._key)
}
type PrivateKeyRSA struct {
// _key MUST NOT be accessed directly. Instead, use the withKey method.
_key *C.GO_RSA
}
func NewPrivateKeyRSA(N, E, D, P, Q, Dp, Dq, Qinv BigInt) (*PrivateKeyRSA, error) {
key := C._goboringcrypto_RSA_new()
if key == nil {
return nil, fail("RSA_new")
}
if !bigToBn(&key.n, N) ||
!bigToBn(&key.e, E) ||
!bigToBn(&key.d, D) ||
!bigToBn(&key.p, P) ||
!bigToBn(&key.q, Q) ||
!bigToBn(&key.dmp1, Dp) ||
!bigToBn(&key.dmq1, Dq) ||
!bigToBn(&key.iqmp, Qinv) {
return nil, fail("BN_bin2bn")
}
k := &PrivateKeyRSA{_key: key}
runtime.SetFinalizer(k, (*PrivateKeyRSA).finalize)
return k, nil
}
func (k *PrivateKeyRSA) finalize() {
C._goboringcrypto_RSA_free(k._key)
}
func (k *PrivateKeyRSA) withKey(f func(*C.GO_RSA) C.int) C.int {
// Because of the finalizer, any time _key is passed to cgo, that call must
// be followed by a call to runtime.KeepAlive, to make sure k is not
// collected (and finalized) before the cgo call returns.
defer runtime.KeepAlive(k)
return f(k._key)
}
func setupRSA(withKey func(func(*C.GO_RSA) C.int) C.int,
padding C.int, h hash.Hash, label []byte, saltLen int, ch crypto.Hash,
init func(*C.GO_EVP_PKEY_CTX) C.int) (pkey *C.GO_EVP_PKEY, ctx *C.GO_EVP_PKEY_CTX, err error) {
defer func() {
if err != nil {
if pkey != nil {
C._goboringcrypto_EVP_PKEY_free(pkey)
pkey = nil
}
if ctx != nil {
C._goboringcrypto_EVP_PKEY_CTX_free(ctx)
ctx = nil
}
}
}()
pkey = C._goboringcrypto_EVP_PKEY_new()
if pkey == nil {
return nil, nil, fail("EVP_PKEY_new")
}
if withKey(func(key *C.GO_RSA) C.int {
return C._goboringcrypto_EVP_PKEY_set1_RSA(pkey, key)
}) == 0 {
return nil, nil, fail("EVP_PKEY_set1_RSA")
}
ctx = C._goboringcrypto_EVP_PKEY_CTX_new(pkey, nil)
if ctx == nil {
return nil, nil, fail("EVP_PKEY_CTX_new")
}
if init(ctx) == 0 {
return nil, nil, fail("EVP_PKEY_operation_init")
}
if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(ctx, padding) == 0 {
return nil, nil, fail("EVP_PKEY_CTX_set_rsa_padding")
}
if padding == C.GO_RSA_PKCS1_OAEP_PADDING {
md := hashToMD(h)
if md == nil {
return nil, nil, errors.New("crypto/rsa: unsupported hash function")
}
if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) == 0 {
return nil, nil, fail("EVP_PKEY_set_rsa_oaep_md")
}
// ctx takes ownership of label, so malloc a copy for BoringCrypto to free.
clabel := (*C.uint8_t)(C._goboringcrypto_OPENSSL_malloc(C.size_t(len(label))))
if clabel == nil {
return nil, nil, fail("OPENSSL_malloc")
}
copy((*[1 << 30]byte)(unsafe.Pointer(clabel))[:len(label)], label)
if C._goboringcrypto_EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, clabel, C.size_t(len(label))) == 0 {
return nil, nil, fail("EVP_PKEY_CTX_set0_rsa_oaep_label")
}
}
if padding == C.GO_RSA_PKCS1_PSS_PADDING {
if saltLen != 0 {
if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, C.int(saltLen)) == 0 {
return nil, nil, fail("EVP_PKEY_set_rsa_pss_saltlen")
}
}
md := cryptoHashToMD(ch)
if md == nil {
return nil, nil, errors.New("crypto/rsa: unsupported hash function")
}
if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) == 0 {
return nil, nil, fail("EVP_PKEY_set_rsa_mgf1_md")
}
}
return pkey, ctx, nil
}
func cryptRSA(withKey func(func(*C.GO_RSA) C.int) C.int,
padding C.int, h hash.Hash, label []byte, saltLen int, ch crypto.Hash,
init func(*C.GO_EVP_PKEY_CTX) C.int,
crypt func(*C.GO_EVP_PKEY_CTX, *C.uint8_t, *C.size_t, *C.uint8_t, C.size_t) C.int,
in []byte) ([]byte, error) {
pkey, ctx, err := setupRSA(withKey, padding, h, label, saltLen, ch, init)
if err != nil {
return nil, err
}
defer C._goboringcrypto_EVP_PKEY_free(pkey)
defer C._goboringcrypto_EVP_PKEY_CTX_free(ctx)
var outLen C.size_t
if crypt(ctx, nil, &outLen, base(in), C.size_t(len(in))) == 0 {
return nil, fail("EVP_PKEY_decrypt/encrypt")
}
out := make([]byte, outLen)
if crypt(ctx, base(out), &outLen, base(in), C.size_t(len(in))) == 0 {
return nil, fail("EVP_PKEY_decrypt/encrypt")
}
return out[:outLen], nil
}
func DecryptRSAOAEP(h hash.Hash, priv *PrivateKeyRSA, ciphertext, label []byte) ([]byte, error) {
return cryptRSA(priv.withKey, C.GO_RSA_PKCS1_OAEP_PADDING, h, label, 0, 0, decryptInit, decrypt, ciphertext)
}
func EncryptRSAOAEP(h hash.Hash, pub *PublicKeyRSA, msg, label []byte) ([]byte, error) {
return cryptRSA(pub.withKey, C.GO_RSA_PKCS1_OAEP_PADDING, h, label, 0, 0, encryptInit, encrypt, msg)
}
func DecryptRSAPKCS1(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) {
return cryptRSA(priv.withKey, C.GO_RSA_PKCS1_PADDING, nil, nil, 0, 0, decryptInit, decrypt, ciphertext)
}
func EncryptRSAPKCS1(pub *PublicKeyRSA, msg []byte) ([]byte, error) {
return cryptRSA(pub.withKey, C.GO_RSA_PKCS1_PADDING, nil, nil, 0, 0, encryptInit, encrypt, msg)
}
func DecryptRSANoPadding(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) {
return cryptRSA(priv.withKey, C.GO_RSA_NO_PADDING, nil, nil, 0, 0, decryptInit, decrypt, ciphertext)
}
func EncryptRSANoPadding(pub *PublicKeyRSA, msg []byte) ([]byte, error) {
return cryptRSA(pub.withKey, C.GO_RSA_NO_PADDING, nil, nil, 0, 0, encryptInit, encrypt, msg)
}
// These dumb wrappers work around the fact that cgo functions cannot be used as values directly.
func decryptInit(ctx *C.GO_EVP_PKEY_CTX) C.int {
return C._goboringcrypto_EVP_PKEY_decrypt_init(ctx)
}
func decrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.size_t, in *C.uint8_t, inLen C.size_t) C.int {
return C._goboringcrypto_EVP_PKEY_decrypt(ctx, out, outLen, in, inLen)
}
func encryptInit(ctx *C.GO_EVP_PKEY_CTX) C.int {
return C._goboringcrypto_EVP_PKEY_encrypt_init(ctx)
}
func encrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.size_t, in *C.uint8_t, inLen C.size_t) C.int {
return C._goboringcrypto_EVP_PKEY_encrypt(ctx, out, outLen, in, inLen)
}
func SignRSAPSS(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte, saltLen int) ([]byte, error) {
md := cryptoHashToMD(h)
if md == nil {
return nil, errors.New("crypto/rsa: unsupported hash function")
}
if saltLen == 0 {
saltLen = -1
}
var out []byte
var outLen C.size_t
if priv.withKey(func(key *C.GO_RSA) C.int {
out = make([]byte, C._goboringcrypto_RSA_size(key))
return C._goboringcrypto_RSA_sign_pss_mgf1(key, &outLen, base(out), C.size_t(len(out)),
base(hashed), C.size_t(len(hashed)), md, nil, C.int(saltLen))
}) == 0 {
return nil, fail("RSA_sign_pss_mgf1")
}
return out[:outLen], nil
}
func VerifyRSAPSS(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte, saltLen int) error {
md := cryptoHashToMD(h)
if md == nil {
return errors.New("crypto/rsa: unsupported hash function")
}
if saltLen == 0 {
saltLen = -2 // auto-recover
}
if pub.withKey(func(key *C.GO_RSA) C.int {
return C._goboringcrypto_RSA_verify_pss_mgf1(key, base(hashed), C.size_t(len(hashed)),
md, nil, C.int(saltLen), base(sig), C.size_t(len(sig)))
}) == 0 {
return fail("RSA_verify_pss_mgf1")
}
return nil
}
func SignRSAPKCS1v15(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte) ([]byte, error) {
if h == 0 {
// No hashing.
var out []byte
var outLen C.size_t
if priv.withKey(func(key *C.GO_RSA) C.int {
out = make([]byte, C._goboringcrypto_RSA_size(key))
return C._goboringcrypto_RSA_sign_raw(key, &outLen, base(out), C.size_t(len(out)),
base(hashed), C.size_t(len(hashed)), C.GO_RSA_PKCS1_PADDING)
}) == 0 {
return nil, fail("RSA_sign_raw")
}
return out[:outLen], nil
}
md := cryptoHashToMD(h)
if md == nil {
return nil, errors.New("crypto/rsa: unsupported hash function: " + strconv.Itoa(int(h)))
}
nid := C._goboringcrypto_EVP_MD_type(md)
var out []byte
var outLen C.uint
if priv.withKey(func(key *C.GO_RSA) C.int {
out = make([]byte, C._goboringcrypto_RSA_size(key))
return C._goboringcrypto_RSA_sign(nid, base(hashed), C.uint(len(hashed)),
base(out), &outLen, key)
}) == 0 {
return nil, fail("RSA_sign")
}
return out[:outLen], nil
}
func VerifyRSAPKCS1v15(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte) error {
if h == 0 {
var out []byte
var outLen C.size_t
if pub.withKey(func(key *C.GO_RSA) C.int {
out = make([]byte, C._goboringcrypto_RSA_size(key))
return C._goboringcrypto_RSA_verify_raw(key, &outLen, base(out),
C.size_t(len(out)), base(sig), C.size_t(len(sig)), C.GO_RSA_PKCS1_PADDING)
}) == 0 {
return fail("RSA_verify")
}
if subtle.ConstantTimeCompare(hashed, out[:outLen]) != 1 {
return fail("RSA_verify")
}
return nil
}
md := cryptoHashToMD(h)
if md == nil {
return errors.New("crypto/rsa: unsupported hash function")
}
nid := C._goboringcrypto_EVP_MD_type(md)
if pub.withKey(func(key *C.GO_RSA) C.int {
return C._goboringcrypto_RSA_verify(nid, base(hashed), C.size_t(len(hashed)),
base(sig), C.size_t(len(sig)), key)
}) == 0 {
return fail("RSA_verify")
}
return nil
}

View file

@ -0,0 +1,597 @@
// Copyright 2017 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 boringcrypto && linux && amd64 && !android && !cmd_go_bootstrap && !msan
// +build boringcrypto,linux,amd64,!android,!cmd_go_bootstrap,!msan
package boring
/*
#include "goboringcrypto.h"
int
_goboringcrypto_gosha1(void *p, size_t n, void *out)
{
GO_SHA_CTX ctx;
_goboringcrypto_SHA1_Init(&ctx);
return _goboringcrypto_SHA1_Update(&ctx, p, n) &&
_goboringcrypto_SHA1_Final(out, &ctx);
}
int
_goboringcrypto_gosha224(void *p, size_t n, void *out)
{
GO_SHA256_CTX ctx;
_goboringcrypto_SHA224_Init(&ctx);
return _goboringcrypto_SHA224_Update(&ctx, p, n) &&
_goboringcrypto_SHA224_Final(out, &ctx);
}
int
_goboringcrypto_gosha256(void *p, size_t n, void *out)
{
GO_SHA256_CTX ctx;
_goboringcrypto_SHA256_Init(&ctx);
return _goboringcrypto_SHA256_Update(&ctx, p, n) &&
_goboringcrypto_SHA256_Final(out, &ctx);
}
int
_goboringcrypto_gosha384(void *p, size_t n, void *out)
{
GO_SHA512_CTX ctx;
_goboringcrypto_SHA384_Init(&ctx);
return _goboringcrypto_SHA384_Update(&ctx, p, n) &&
_goboringcrypto_SHA384_Final(out, &ctx);
}
int
_goboringcrypto_gosha512(void *p, size_t n, void *out)
{
GO_SHA512_CTX ctx;
_goboringcrypto_SHA512_Init(&ctx);
return _goboringcrypto_SHA512_Update(&ctx, p, n) &&
_goboringcrypto_SHA512_Final(out, &ctx);
}
*/
import "C"
import (
"errors"
"hash"
"unsafe"
)
func addr(p []byte) unsafe.Pointer {
if len(p) == 0 {
return nil
}
return unsafe.Pointer(&p[0])
}
func SHA1(p []byte) (sum [20]byte) {
if C._goboringcrypto_gosha1(noescape(addr(p)), C.size_t(len(p)), noescape(unsafe.Pointer(&sum[0]))) == 0 {
panic("boringcrypto: SHA1 failed")
}
return
}
func SHA224(p []byte) (sum [28]byte) {
if C._goboringcrypto_gosha224(noescape(addr(p)), C.size_t(len(p)), noescape(unsafe.Pointer(&sum[0]))) == 0 {
panic("boringcrypto: SHA224 failed")
}
return
}
func SHA256(p []byte) (sum [32]byte) {
if C._goboringcrypto_gosha256(noescape(addr(p)), C.size_t(len(p)), noescape(unsafe.Pointer(&sum[0]))) == 0 {
panic("boringcrypto: SHA256 failed")
}
return
}
func SHA384(p []byte) (sum [48]byte) {
if C._goboringcrypto_gosha384(noescape(addr(p)), C.size_t(len(p)), noescape(unsafe.Pointer(&sum[0]))) == 0 {
panic("boringcrypto: SHA384 failed")
}
return
}
func SHA512(p []byte) (sum [64]byte) {
if C._goboringcrypto_gosha512(noescape(addr(p)), C.size_t(len(p)), noescape(unsafe.Pointer(&sum[0]))) == 0 {
panic("boringcrypto: SHA512 failed")
}
return
}
// NewSHA1 returns a new SHA1 hash.
func NewSHA1() hash.Hash {
h := new(sha1Hash)
h.Reset()
return h
}
type sha1Hash struct {
ctx C.GO_SHA_CTX
out [20]byte
}
type sha1Ctx struct {
h [5]uint32
nl, nh uint32
x [64]byte
nx uint32
}
func (h *sha1Hash) noescapeCtx() *C.GO_SHA_CTX {
return (*C.GO_SHA_CTX)(noescape(unsafe.Pointer(&h.ctx)))
}
func (h *sha1Hash) Reset() {
C._goboringcrypto_SHA1_Init(h.noescapeCtx())
}
func (h *sha1Hash) Size() int { return 20 }
func (h *sha1Hash) BlockSize() int { return 64 }
func (h *sha1Hash) Sum(dst []byte) []byte { return h.sum(dst) }
func (h *sha1Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA1_Update(h.noescapeCtx(), noescape(addr(p)), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA1_Update failed")
}
return len(p), nil
}
func (h0 *sha1Hash) sum(dst []byte) []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA1_Final((*C.uint8_t)(noescape(unsafe.Pointer(&h.out[0]))), h.noescapeCtx()) == 0 {
panic("boringcrypto: SHA1_Final failed")
}
return append(dst, h.out[:]...)
}
const (
sha1Magic = "sha\x01"
sha1MarshaledSize = len(sha1Magic) + 5*4 + 64 + 8
)
func (h *sha1Hash) MarshalBinary() ([]byte, error) {
d := (*sha1Ctx)(unsafe.Pointer(&h.ctx))
b := make([]byte, 0, sha1MarshaledSize)
b = append(b, sha1Magic...)
b = appendUint32(b, d.h[0])
b = appendUint32(b, d.h[1])
b = appendUint32(b, d.h[2])
b = appendUint32(b, d.h[3])
b = appendUint32(b, d.h[4])
b = append(b, d.x[:d.nx]...)
b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
b = appendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29)
return b, nil
}
func (h *sha1Hash) UnmarshalBinary(b []byte) error {
if len(b) < len(sha1Magic) || string(b[:len(sha1Magic)]) != sha1Magic {
return errors.New("crypto/sha1: invalid hash state identifier")
}
if len(b) != sha1MarshaledSize {
return errors.New("crypto/sha1: invalid hash state size")
}
d := (*sha1Ctx)(unsafe.Pointer(&h.ctx))
b = b[len(sha1Magic):]
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 = b[copy(d.x[:], b):]
b, n := consumeUint64(b)
d.nl = uint32(n << 3)
d.nh = uint32(n >> 29)
d.nx = uint32(n) % 64
return nil
}
// NewSHA224 returns a new SHA224 hash.
func NewSHA224() hash.Hash {
h := new(sha224Hash)
h.Reset()
return h
}
type sha224Hash struct {
ctx C.GO_SHA256_CTX
out [224 / 8]byte
}
func (h *sha224Hash) noescapeCtx() *C.GO_SHA256_CTX {
return (*C.GO_SHA256_CTX)(noescape(unsafe.Pointer(&h.ctx)))
}
func (h *sha224Hash) Reset() {
C._goboringcrypto_SHA224_Init(h.noescapeCtx())
}
func (h *sha224Hash) Size() int { return 224 / 8 }
func (h *sha224Hash) BlockSize() int { return 64 }
func (h *sha224Hash) Sum(dst []byte) []byte { return h.sum(dst) }
func (h *sha224Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA224_Update(h.noescapeCtx(), noescape(addr(p)), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA224_Update failed")
}
return len(p), nil
}
func (h0 *sha224Hash) sum(dst []byte) []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA224_Final((*C.uint8_t)(noescape(unsafe.Pointer(&h.out[0]))), h.noescapeCtx()) == 0 {
panic("boringcrypto: SHA224_Final failed")
}
return append(dst, h.out[:]...)
}
// NewSHA256 returns a new SHA256 hash.
func NewSHA256() hash.Hash {
h := new(sha256Hash)
h.Reset()
return h
}
type sha256Hash struct {
ctx C.GO_SHA256_CTX
out [256 / 8]byte
}
func (h *sha256Hash) noescapeCtx() *C.GO_SHA256_CTX {
return (*C.GO_SHA256_CTX)(noescape(unsafe.Pointer(&h.ctx)))
}
func (h *sha256Hash) Reset() {
C._goboringcrypto_SHA256_Init(h.noescapeCtx())
}
func (h *sha256Hash) Size() int { return 256 / 8 }
func (h *sha256Hash) BlockSize() int { return 64 }
func (h *sha256Hash) Sum(dst []byte) []byte { return h.sum(dst) }
func (h *sha256Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA256_Update(h.noescapeCtx(), noescape(addr(p)), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA256_Update failed")
}
return len(p), nil
}
func (h0 *sha256Hash) sum(dst []byte) []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA256_Final((*C.uint8_t)(noescape(unsafe.Pointer(&h.out[0]))), h.noescapeCtx()) == 0 {
panic("boringcrypto: SHA256_Final failed")
}
return append(dst, h.out[:]...)
}
const (
magic224 = "sha\x02"
magic256 = "sha\x03"
marshaledSize256 = len(magic256) + 8*4 + 64 + 8
)
type sha256Ctx struct {
h [8]uint32
nl, nh uint32
x [64]byte
nx uint32
}
func (h *sha224Hash) MarshalBinary() ([]byte, error) {
d := (*sha256Ctx)(unsafe.Pointer(&h.ctx))
b := make([]byte, 0, marshaledSize256)
b = append(b, magic224...)
b = appendUint32(b, d.h[0])
b = appendUint32(b, d.h[1])
b = appendUint32(b, d.h[2])
b = appendUint32(b, d.h[3])
b = appendUint32(b, d.h[4])
b = appendUint32(b, d.h[5])
b = appendUint32(b, d.h[6])
b = appendUint32(b, d.h[7])
b = append(b, d.x[:d.nx]...)
b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
b = appendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29)
return b, nil
}
func (h *sha256Hash) MarshalBinary() ([]byte, error) {
d := (*sha256Ctx)(unsafe.Pointer(&h.ctx))
b := make([]byte, 0, marshaledSize256)
b = append(b, magic256...)
b = appendUint32(b, d.h[0])
b = appendUint32(b, d.h[1])
b = appendUint32(b, d.h[2])
b = appendUint32(b, d.h[3])
b = appendUint32(b, d.h[4])
b = appendUint32(b, d.h[5])
b = appendUint32(b, d.h[6])
b = appendUint32(b, d.h[7])
b = append(b, d.x[:d.nx]...)
b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
b = appendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29)
return b, nil
}
func (h *sha224Hash) UnmarshalBinary(b []byte) error {
if len(b) < len(magic224) || string(b[:len(magic224)]) != magic224 {
return errors.New("crypto/sha256: invalid hash state identifier")
}
if len(b) != marshaledSize256 {
return errors.New("crypto/sha256: invalid hash state size")
}
d := (*sha256Ctx)(unsafe.Pointer(&h.ctx))
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, n := consumeUint64(b)
d.nl = uint32(n << 3)
d.nh = uint32(n >> 29)
d.nx = uint32(n) % 64
return nil
}
func (h *sha256Hash) UnmarshalBinary(b []byte) error {
if len(b) < len(magic256) || string(b[:len(magic256)]) != magic256 {
return errors.New("crypto/sha256: invalid hash state identifier")
}
if len(b) != marshaledSize256 {
return errors.New("crypto/sha256: invalid hash state size")
}
d := (*sha256Ctx)(unsafe.Pointer(&h.ctx))
b = b[len(magic256):]
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, n := consumeUint64(b)
d.nl = uint32(n << 3)
d.nh = uint32(n >> 29)
d.nx = uint32(n) % 64
return nil
}
// NewSHA384 returns a new SHA384 hash.
func NewSHA384() hash.Hash {
h := new(sha384Hash)
h.Reset()
return h
}
type sha384Hash struct {
ctx C.GO_SHA512_CTX
out [384 / 8]byte
}
func (h *sha384Hash) noescapeCtx() *C.GO_SHA512_CTX {
return (*C.GO_SHA512_CTX)(noescape(unsafe.Pointer(&h.ctx)))
}
func (h *sha384Hash) Reset() {
C._goboringcrypto_SHA384_Init(h.noescapeCtx())
}
func (h *sha384Hash) Size() int { return 384 / 8 }
func (h *sha384Hash) BlockSize() int { return 128 }
func (h *sha384Hash) Sum(dst []byte) []byte { return h.sum(dst) }
func (h *sha384Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA384_Update(h.noescapeCtx(), noescape(addr(p)), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA384_Update failed")
}
return len(p), nil
}
func (h0 *sha384Hash) sum(dst []byte) []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA384_Final((*C.uint8_t)(noescape(unsafe.Pointer(&h.out[0]))), h.noescapeCtx()) == 0 {
panic("boringcrypto: SHA384_Final failed")
}
return append(dst, h.out[:]...)
}
// NewSHA512 returns a new SHA512 hash.
func NewSHA512() hash.Hash {
h := new(sha512Hash)
h.Reset()
return h
}
type sha512Hash struct {
ctx C.GO_SHA512_CTX
out [512 / 8]byte
}
func (h *sha512Hash) noescapeCtx() *C.GO_SHA512_CTX {
return (*C.GO_SHA512_CTX)(noescape(unsafe.Pointer(&h.ctx)))
}
func (h *sha512Hash) Reset() {
C._goboringcrypto_SHA512_Init(h.noescapeCtx())
}
func (h *sha512Hash) Size() int { return 512 / 8 }
func (h *sha512Hash) BlockSize() int { return 128 }
func (h *sha512Hash) Sum(dst []byte) []byte { return h.sum(dst) }
func (h *sha512Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA512_Update(h.noescapeCtx(), noescape(addr(p)), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA512_Update failed")
}
return len(p), nil
}
func (h0 *sha512Hash) sum(dst []byte) []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA512_Final((*C.uint8_t)(noescape(unsafe.Pointer(&h.out[0]))), h.noescapeCtx()) == 0 {
panic("boringcrypto: SHA512_Final failed")
}
return append(dst, h.out[:]...)
}
type sha512Ctx struct {
h [8]uint64
nl, nh uint64
x [128]byte
nx uint32
}
const (
magic384 = "sha\x04"
magic512_224 = "sha\x05"
magic512_256 = "sha\x06"
magic512 = "sha\x07"
marshaledSize512 = len(magic512) + 8*8 + 128 + 8
)
func (h *sha384Hash) MarshalBinary() ([]byte, error) {
d := (*sha512Ctx)(unsafe.Pointer(&h.ctx))
b := make([]byte, 0, marshaledSize512)
b = append(b, magic384...)
b = appendUint64(b, d.h[0])
b = appendUint64(b, d.h[1])
b = appendUint64(b, d.h[2])
b = appendUint64(b, d.h[3])
b = appendUint64(b, d.h[4])
b = appendUint64(b, d.h[5])
b = appendUint64(b, d.h[6])
b = appendUint64(b, d.h[7])
b = append(b, d.x[:d.nx]...)
b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
b = appendUint64(b, d.nl>>3|d.nh<<61)
return b, nil
}
func (h *sha512Hash) MarshalBinary() ([]byte, error) {
d := (*sha512Ctx)(unsafe.Pointer(&h.ctx))
b := make([]byte, 0, marshaledSize512)
b = append(b, magic512...)
b = appendUint64(b, d.h[0])
b = appendUint64(b, d.h[1])
b = appendUint64(b, d.h[2])
b = appendUint64(b, d.h[3])
b = appendUint64(b, d.h[4])
b = appendUint64(b, d.h[5])
b = appendUint64(b, d.h[6])
b = appendUint64(b, d.h[7])
b = append(b, d.x[:d.nx]...)
b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
b = appendUint64(b, d.nl>>3|d.nh<<61)
return b, nil
}
func (h *sha384Hash) UnmarshalBinary(b []byte) error {
if len(b) < len(magic512) {
return errors.New("crypto/sha512: invalid hash state identifier")
}
if string(b[:len(magic384)]) != magic384 {
return errors.New("crypto/sha512: invalid hash state identifier")
}
if len(b) != marshaledSize512 {
return errors.New("crypto/sha512: invalid hash state size")
}
d := (*sha512Ctx)(unsafe.Pointer(&h.ctx))
b = b[len(magic512):]
b, d.h[0] = consumeUint64(b)
b, d.h[1] = consumeUint64(b)
b, d.h[2] = consumeUint64(b)
b, d.h[3] = consumeUint64(b)
b, d.h[4] = consumeUint64(b)
b, d.h[5] = consumeUint64(b)
b, d.h[6] = consumeUint64(b)
b, d.h[7] = consumeUint64(b)
b = b[copy(d.x[:], b):]
b, n := consumeUint64(b)
d.nl = n << 3
d.nh = n >> 61
d.nx = uint32(n) % 128
return nil
}
func (h *sha512Hash) UnmarshalBinary(b []byte) error {
if len(b) < len(magic512) {
return errors.New("crypto/sha512: invalid hash state identifier")
}
if string(b[:len(magic512)]) != magic512 {
return errors.New("crypto/sha512: invalid hash state identifier")
}
if len(b) != marshaledSize512 {
return errors.New("crypto/sha512: invalid hash state size")
}
d := (*sha512Ctx)(unsafe.Pointer(&h.ctx))
b = b[len(magic512):]
b, d.h[0] = consumeUint64(b)
b, d.h[1] = consumeUint64(b)
b, d.h[2] = consumeUint64(b)
b, d.h[3] = consumeUint64(b)
b, d.h[4] = consumeUint64(b)
b, d.h[5] = consumeUint64(b)
b, d.h[6] = consumeUint64(b)
b, d.h[7] = consumeUint64(b)
b = b[copy(d.x[:], b):]
b, n := consumeUint64(b)
d.nl = n << 3
d.nh = n >> 61
d.nx = uint32(n) % 128
return nil
}
func appendUint64(b []byte, x uint64) []byte {
var a [8]byte
putUint64(a[:], x)
return append(b, a[:]...)
}
func appendUint32(b []byte, x uint32) []byte {
var a [4]byte
putUint32(a[:], x)
return append(b, a[:]...)
}
func consumeUint64(b []byte) ([]byte, uint64) {
_ = b[7]
x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
return b[8:], x
}
func consumeUint32(b []byte) ([]byte, uint32) {
_ = b[3]
x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
return b[4:], x
}
func putUint64(x []byte, s uint64) {
_ = x[7]
x[0] = byte(s >> 56)
x[1] = byte(s >> 48)
x[2] = byte(s >> 40)
x[3] = byte(s >> 32)
x[4] = byte(s >> 24)
x[5] = byte(s >> 16)
x[6] = byte(s >> 8)
x[7] = byte(s)
}
func putUint32(x []byte, s uint32) {
_ = x[3]
x[0] = byte(s >> 24)
x[1] = byte(s >> 16)
x[2] = byte(s >> 8)
x[3] = byte(s)
}

View file

@ -0,0 +1,17 @@
// Copyright 2017 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 sig holds “code signatures” that can be called
// and will result in certain code sequences being linked into
// the final binary. The functions themselves are no-ops.
package sig
// BoringCrypto indicates that the BoringCrypto module is present.
func BoringCrypto()
// FIPSOnly indicates that package crypto/tls/fipsonly is present.
func FIPSOnly()
// StandardCrypto indicates that standard Go crypto is present.
func StandardCrypto()

View file

@ -0,0 +1,54 @@
// Copyright 2017 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.
#include "textflag.h"
// These functions are no-ops, but you can search for their implementations
// to find out whether they are linked into a particular binary.
//
// Each function consists of a two-byte jump over the next 29-bytes,
// then a 5-byte indicator sequence unlikely to occur in real x86 instructions,
// then a randomly-chosen 24-byte sequence, and finally a return instruction
// (the target of the jump).
//
// These sequences are known to rsc.io/goversion.
#define START \
BYTE $0xEB; BYTE $0x1D; BYTE $0xF4; BYTE $0x48; BYTE $0xF4; BYTE $0x4B; BYTE $0xF4
#define END \
BYTE $0xC3
// BoringCrypto indicates that BoringCrypto (in particular, its func init) is present.
TEXT ·BoringCrypto(SB),NOSPLIT,$0
START
BYTE $0xB3; BYTE $0x32; BYTE $0xF5; BYTE $0x28;
BYTE $0x13; BYTE $0xA3; BYTE $0xB4; BYTE $0x50;
BYTE $0xD4; BYTE $0x41; BYTE $0xCC; BYTE $0x24;
BYTE $0x85; BYTE $0xF0; BYTE $0x01; BYTE $0x45;
BYTE $0x4E; BYTE $0x92; BYTE $0x10; BYTE $0x1B;
BYTE $0x1D; BYTE $0x2F; BYTE $0x19; BYTE $0x50;
END
// StandardCrypto indicates that standard Go crypto is present.
TEXT ·StandardCrypto(SB),NOSPLIT,$0
START
BYTE $0xba; BYTE $0xee; BYTE $0x4d; BYTE $0xfa;
BYTE $0x98; BYTE $0x51; BYTE $0xca; BYTE $0x56;
BYTE $0xa9; BYTE $0x11; BYTE $0x45; BYTE $0xe8;
BYTE $0x3e; BYTE $0x99; BYTE $0xc5; BYTE $0x9c;
BYTE $0xf9; BYTE $0x11; BYTE $0xcb; BYTE $0x8e;
BYTE $0x80; BYTE $0xda; BYTE $0xf1; BYTE $0x2f;
END
// FIPSOnly indicates that crypto/tls/fipsonly is present.
TEXT ·FIPSOnly(SB),NOSPLIT,$0
START
BYTE $0x36; BYTE $0x3C; BYTE $0xB9; BYTE $0xCE;
BYTE $0x9D; BYTE $0x68; BYTE $0x04; BYTE $0x7D;
BYTE $0x31; BYTE $0xF2; BYTE $0x8D; BYTE $0x32;
BYTE $0x5D; BYTE $0x5C; BYTE $0xA5; BYTE $0x87;
BYTE $0x3F; BYTE $0x5D; BYTE $0x80; BYTE $0xCA;
BYTE $0xF6; BYTE $0xD6; BYTE $0x15; BYTE $0x1B;
END

View file

@ -0,0 +1,20 @@
// Copyright 2017 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.
// These functions are no-ops.
// On amd64 they have recognizable implementations, so that you can
// search a particular binary to see if they are present.
// On other platforms (those using this source file), they don't.
//go:build !amd64
// +build !amd64
TEXT ·BoringCrypto(SB),$0
RET
TEXT ·FIPSOnly(SB),$0
RET
TEXT ·StandardCrypto(SB),$0
RET

View file

@ -0,0 +1,6 @@
// Copyright 2022 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.
// This file is here to silence an error about registerCache not having a body.
// (The body is provided by package runtime.)

View file

@ -0,0 +1,9 @@
// Copyright 2022 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 boringcrypto
// This package only exists with GOEXPERIMENT=boringcrypto.
// It provides the actual syso file.
package syso

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package crypto
package crypto_test
import (
"crypto/aes"

View file

@ -19,9 +19,15 @@ import (
"time"
)
import "crypto/internal/boring"
const urandomDevice = "/dev/urandom"
func init() {
if boring.Enabled {
Reader = boring.RandReader
return
}
Reader = &reader{}
}
@ -59,6 +65,7 @@ func warnBlocked() {
}
func (r *reader) Read(b []byte) (n int, err error) {
boring.Unreachable()
if atomic.CompareAndSwapUint32(&r.used, 0, 1) {
// First use of randomness. Start timer to warn about
// being blocked on entropy not being available.

130
src/crypto/rsa/boring.go Normal file
View file

@ -0,0 +1,130 @@
// Copyright 2017 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 boringcrypto
package rsa
import (
"crypto/internal/boring"
"crypto/internal/boring/bbig"
"math/big"
"unsafe"
)
// Cached conversions from Go PublicKey/PrivateKey to BoringCrypto.
//
// The first operation on a PublicKey or PrivateKey makes a parallel
// BoringCrypto key and saves it in pubCache or privCache.
//
// We could just assume that once used in a sign/verify/encrypt/decrypt operation,
// a particular key is never again modified, but that has not been a
// stated assumption before. Just in case there is any existing code that
// does modify the key between operations, we save the original values
// alongside the cached BoringCrypto key and check that the real key
// still matches before using the cached key. The theory is that the real
// operations are significantly more expensive than the comparison.
type boringPub struct {
key *boring.PublicKeyRSA
orig PublicKey
}
var pubCache boring.Cache
var privCache boring.Cache
func init() {
pubCache.Register()
privCache.Register()
}
func boringPublicKey(pub *PublicKey) (*boring.PublicKeyRSA, error) {
b := (*boringPub)(pubCache.Get(unsafe.Pointer(pub)))
if b != nil && publicKeyEqual(&b.orig, pub) {
return b.key, nil
}
b = new(boringPub)
b.orig = copyPublicKey(pub)
key, err := boring.NewPublicKeyRSA(bbig.Enc(b.orig.N), bbig.Enc(big.NewInt(int64(b.orig.E))))
if err != nil {
return nil, err
}
b.key = key
pubCache.Put(unsafe.Pointer(pub), unsafe.Pointer(b))
return key, nil
}
type boringPriv struct {
key *boring.PrivateKeyRSA
orig PrivateKey
}
func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyRSA, error) {
b := (*boringPriv)(privCache.Get(unsafe.Pointer(priv)))
if b != nil && privateKeyEqual(&b.orig, priv) {
return b.key, nil
}
b = new(boringPriv)
b.orig = copyPrivateKey(priv)
var N, E, D, P, Q, Dp, Dq, Qinv *big.Int
N = b.orig.N
E = big.NewInt(int64(b.orig.E))
D = b.orig.D
if len(b.orig.Primes) == 2 {
P = b.orig.Primes[0]
Q = b.orig.Primes[1]
Dp = b.orig.Precomputed.Dp
Dq = b.orig.Precomputed.Dq
Qinv = b.orig.Precomputed.Qinv
}
key, err := boring.NewPrivateKeyRSA(bbig.Enc(N), bbig.Enc(E), bbig.Enc(D), bbig.Enc(P), bbig.Enc(Q), bbig.Enc(Dp), bbig.Enc(Dq), bbig.Enc(Qinv))
if err != nil {
return nil, err
}
b.key = key
privCache.Put(unsafe.Pointer(priv), unsafe.Pointer(b))
return key, nil
}
func publicKeyEqual(k1, k2 *PublicKey) bool {
return k1.N != nil &&
k1.N.Cmp(k2.N) == 0 &&
k1.E == k2.E
}
func copyPublicKey(k *PublicKey) PublicKey {
return PublicKey{
N: new(big.Int).Set(k.N),
E: k.E,
}
}
func privateKeyEqual(k1, k2 *PrivateKey) bool {
return publicKeyEqual(&k1.PublicKey, &k2.PublicKey) &&
k1.D.Cmp(k2.D) == 0
}
func copyPrivateKey(k *PrivateKey) PrivateKey {
dst := PrivateKey{
PublicKey: copyPublicKey(&k.PublicKey),
D: new(big.Int).Set(k.D),
}
dst.Primes = make([]*big.Int, len(k.Primes))
for i, p := range k.Primes {
dst.Primes[i] = new(big.Int).Set(p)
}
if x := k.Precomputed.Dp; x != nil {
dst.Precomputed.Dp = new(big.Int).Set(x)
}
if x := k.Precomputed.Dq; x != nil {
dst.Precomputed.Dq = new(big.Int).Set(x)
}
if x := k.Precomputed.Qinv; x != nil {
dst.Precomputed.Qinv = new(big.Int).Set(x)
}
return dst
}

View file

@ -0,0 +1,130 @@
// Copyright 2017 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 boringcrypto
// Note: Can run these tests against the non-BoringCrypto
// version of the code by using "CGO_ENABLED=0 go test".
package rsa
import (
"crypto"
"crypto/rand"
"encoding/asn1"
"runtime"
"runtime/debug"
"sync"
"testing"
)
func TestBoringASN1Marshal(t *testing.T) {
k, err := GenerateKey(rand.Reader, 128)
if err != nil {
t.Fatal(err)
}
_, err = asn1.Marshal(k.PublicKey)
if err != nil {
t.Fatal(err)
}
}
func TestBoringVerify(t *testing.T) {
// Check that signatures that lack leading zeroes don't verify.
key := &PublicKey{
N: bigFromHex("c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be1"),
E: 65537,
}
hash := fromHex("019c5571724fb5d0e47a4260c940e9803ba05a44")
paddedHash := fromHex("3021300906052b0e03021a05000414019c5571724fb5d0e47a4260c940e9803ba05a44")
// signature is one byte shorter than key.N.
sig := fromHex("5edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56")
err := VerifyPKCS1v15(key, 0, paddedHash, sig)
if err == nil {
t.Errorf("raw: expected verification error")
}
err = VerifyPKCS1v15(key, crypto.SHA1, hash, sig)
if err == nil {
t.Errorf("sha1: expected verification error")
}
}
func BenchmarkBoringVerify(b *testing.B) {
// Check that signatures that lack leading zeroes don't verify.
key := &PublicKey{
N: bigFromHex("c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be1"),
E: 65537,
}
hash := fromHex("019c5571724fb5d0e47a4260c940e9803ba05a44")
// signature is one byte shorter than key.N.
sig := fromHex("5edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56")
b.ReportAllocs()
for i := 0; i < b.N; i++ {
err := VerifyPKCS1v15(key, crypto.SHA1, hash, sig)
if err == nil {
b.Fatalf("sha1: expected verification error")
}
}
}
func TestBoringGenerateKey(t *testing.T) {
k, err := GenerateKey(rand.Reader, 2048) // 2048 is smallest size BoringCrypto might kick in for
if err != nil {
t.Fatal(err)
}
// Non-Boring GenerateKey always sets CRTValues to a non-nil (possibly empty) slice.
if k.Precomputed.CRTValues == nil {
t.Fatalf("GenerateKey: Precomputed.CRTValues = nil")
}
}
func TestBoringFinalizers(t *testing.T) {
if runtime.GOOS == "nacl" || runtime.GOOS == "js" {
// Times out on nacl and js/wasm (without BoringCrypto)
// but not clear why - probably consuming rand.Reader too quickly
// and being throttled. Also doesn't really matter.
t.Skipf("skipping on %s/%s", runtime.GOOS, runtime.GOARCH)
}
k, err := GenerateKey(rand.Reader, 2048)
if err != nil {
t.Fatal(err)
}
// Run test with GOGC=10, to make bug more likely.
// Without the KeepAlives, the loop usually dies after
// about 30 iterations.
defer debug.SetGCPercent(debug.SetGCPercent(10))
for n := 0; n < 200; n++ {
// Clear the underlying BoringCrypto object cache.
privCache.Clear()
// Race to create the underlying BoringCrypto object.
// The ones that lose the race are prime candidates for
// being GC'ed too early if the finalizers are not being
// used correctly.
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
sum := make([]byte, 32)
_, err := SignPKCS1v15(rand.Reader, k, crypto.SHA256, sum)
if err != nil {
panic(err) // usually caused by memory corruption, so hard stop
}
}()
}
wg.Wait()
}
}

View file

@ -0,0 +1,16 @@
// Copyright 2022 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 !boringcrypto
package rsa
import "crypto/internal/boring"
func boringPublicKey(*PublicKey) (*boring.PublicKeyRSA, error) {
panic("boringcrypto: not available")
}
func boringPrivateKey(*PrivateKey) (*boring.PrivateKeyRSA, error) {
panic("boringcrypto: not available")
}

View file

@ -14,6 +14,8 @@ import (
"crypto/internal/randutil"
)
import "crypto/internal/boring"
// This file implements encryption and decryption using PKCS #1 v1.5 padding.
// PKCS1v15DecrypterOpts is for passing options to PKCS #1 v1.5 decryption using
@ -36,8 +38,8 @@ type PKCS1v15DecryptOptions struct {
//
// WARNING: use of this function to encrypt plaintexts other than
// session keys is dangerous. Use RSA OAEP in new protocols.
func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error) {
randutil.MaybeReadByte(rand)
func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, error) {
randutil.MaybeReadByte(random)
if err := checkPub(pub); err != nil {
return nil, err
@ -47,20 +49,37 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error)
return nil, ErrMessageTooLong
}
if boring.Enabled && random == boring.RandReader {
bkey, err := boringPublicKey(pub)
if err != nil {
return nil, err
}
return boring.EncryptRSAPKCS1(bkey, msg)
}
boring.UnreachableExceptTests()
// EM = 0x00 || 0x02 || PS || 0x00 || M
em := make([]byte, k)
em[1] = 2
ps, mm := em[2:len(em)-len(msg)-1], em[len(em)-len(msg):]
err := nonZeroRandomBytes(ps, rand)
err := nonZeroRandomBytes(ps, random)
if err != nil {
return nil, err
}
em[len(em)-len(msg)-1] = 0
copy(mm, msg)
if boring.Enabled {
var bkey *boring.PublicKeyRSA
bkey, err = boringPublicKey(pub)
if err != nil {
return nil, err
}
return boring.EncryptRSANoPadding(bkey, em)
}
m := new(big.Int).SetBytes(em)
c := encrypt(new(big.Int), pub, m)
return c.FillBytes(em), nil
}
@ -76,6 +95,19 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byt
if err := checkPub(&priv.PublicKey); err != nil {
return nil, err
}
if boring.Enabled {
bkey, err := boringPrivateKey(priv)
if err != nil {
return nil, err
}
out, err := boring.DecryptRSAPKCS1(bkey, ciphertext)
if err != nil {
return nil, ErrDecryption
}
return out, nil
}
valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext)
if err != nil {
return nil, err
@ -143,13 +175,26 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid
return
}
c := new(big.Int).SetBytes(ciphertext)
m, err := decrypt(rand, priv, c)
if err != nil {
return
if boring.Enabled {
var bkey *boring.PrivateKeyRSA
bkey, err = boringPrivateKey(priv)
if err != nil {
return
}
em, err = boring.DecryptRSANoPadding(bkey, ciphertext)
if err != nil {
return
}
} else {
c := new(big.Int).SetBytes(ciphertext)
var m *big.Int
m, err = decrypt(rand, priv, c)
if err != nil {
return
}
em = m.FillBytes(make([]byte, k))
}
em = m.FillBytes(make([]byte, k))
firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2)
@ -230,7 +275,7 @@ var hashPrefixes = map[crypto.Hash][]byte{
// messages is small, an attacker may be able to build a map from
// messages to signatures and identify the signed messages. As ever,
// signatures provide authenticity, not confidentiality.
func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
if err != nil {
return nil, err
@ -242,6 +287,14 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
return nil, ErrMessageTooLong
}
if boring.Enabled {
bkey, err := boringPrivateKey(priv)
if err != nil {
return nil, err
}
return boring.SignRSAPKCS1v15(bkey, hash, hashed)
}
// EM = 0x00 || 0x01 || PS || 0x00 || T
em := make([]byte, k)
em[1] = 1
@ -252,7 +305,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
copy(em[k-hashLen:k], hashed)
m := new(big.Int).SetBytes(em)
c, err := decryptAndCheck(rand, priv, m)
c, err := decryptAndCheck(random, priv, m)
if err != nil {
return nil, err
}
@ -266,6 +319,17 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
// returning a nil error. If hash is zero then hashed is used directly. This
// isn't advisable except for interoperability.
func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error {
if boring.Enabled {
bkey, err := boringPublicKey(pub)
if err != nil {
return err
}
if err := boring.VerifyRSAPKCS1v15(bkey, hash, hashed, sig); err != nil {
return ErrVerification
}
return nil
}
hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
if err != nil {
return err

View file

@ -65,7 +65,7 @@ func TestDecryptPKCS1v15(t *testing.T) {
for i, test := range decryptPKCS1v15Tests {
out, err := decryptFunc(decodeBase64(test.in))
if err != nil {
t.Errorf("#%d error decrypting", i)
t.Errorf("#%d error decrypting: %v", i, err)
}
want := []byte(test.out)
if !bytes.Equal(out, want) {

View file

@ -15,6 +15,8 @@ import (
"math/big"
)
import "crypto/internal/boring"
// Per RFC 8017, Section 9.1
//
// EM = MGF1 xor DB || H( 8*0x00 || mHash || salt ) || 0xbc
@ -213,6 +215,21 @@ func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed,
if err != nil {
return nil, err
}
if boring.Enabled {
bkey, err := boringPrivateKey(priv)
if err != nil {
return nil, err
}
// Note: BoringCrypto takes care of the "AndCheck" part of "decryptAndCheck".
// (It's not just decrypt.)
s, err := boring.DecryptRSANoPadding(bkey, em)
if err != nil {
return nil, err
}
return s, nil
}
m := new(big.Int).SetBytes(em)
c, err := decryptAndCheck(rand, priv, m)
if err != nil {
@ -274,6 +291,14 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
saltLength = hash.Size()
}
if boring.Enabled && rand == boring.RandReader {
bkey, err := boringPrivateKey(priv)
if err != nil {
return nil, err
}
return boring.SignRSAPSS(bkey, hash, digest, saltLength)
}
salt := make([]byte, saltLength)
if _, err := io.ReadFull(rand, salt); err != nil {
return nil, err
@ -288,6 +313,16 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
// argument may be nil, in which case sensible defaults are used. opts.Hash is
// ignored.
func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error {
if boring.Enabled {
bkey, err := boringPublicKey(pub)
if err != nil {
return err
}
if err := boring.VerifyRSAPSS(bkey, hash, digest, sig, opts.saltLength()); err != nil {
return ErrVerification
}
return nil
}
if len(sig) != pub.Size() {
return ErrVerification
}

View file

@ -9,7 +9,6 @@ import (
"bytes"
"compress/bzip2"
"crypto"
_ "crypto/md5"
"crypto/rand"
"crypto/sha1"
"crypto/sha256"
@ -211,7 +210,7 @@ func TestPSSSigning(t *testing.T) {
{8, 8, true},
}
hash := crypto.MD5
hash := crypto.SHA1
h := hash.New()
h.Write([]byte("testing"))
hashed := h.Sum(nil)

View file

@ -24,6 +24,9 @@ package rsa
import (
"crypto"
"crypto/internal/boring"
"crypto/internal/boring/bbig"
"crypto/internal/randutil"
"crypto/rand"
"crypto/subtle"
"errors"
@ -31,8 +34,6 @@ import (
"io"
"math"
"math/big"
"crypto/internal/randutil"
)
var bigZero = big.NewInt(0)
@ -256,6 +257,40 @@ func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) {
func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error) {
randutil.MaybeReadByte(random)
if boring.Enabled && random == boring.RandReader && nprimes == 2 && (bits == 2048 || bits == 3072) {
bN, bE, bD, bP, bQ, bDp, bDq, bQinv, err := boring.GenerateKeyRSA(bits)
if err != nil {
return nil, err
}
N := bbig.Dec(bN)
E := bbig.Dec(bE)
D := bbig.Dec(bD)
P := bbig.Dec(bP)
Q := bbig.Dec(bQ)
Dp := bbig.Dec(bDp)
Dq := bbig.Dec(bDq)
Qinv := bbig.Dec(bQinv)
e64 := E.Int64()
if !E.IsInt64() || int64(int(e64)) != e64 {
return nil, errors.New("crypto/rsa: generated key exponent too large")
}
key := &PrivateKey{
PublicKey: PublicKey{
N: N,
E: int(e64),
},
D: D,
Primes: []*big.Int{P, Q},
Precomputed: PrecomputedValues{
Dp: Dp,
Dq: Dq,
Qinv: Qinv,
CRTValues: make([]CRTValue, 0), // non-nil, to match Precompute
},
}
return key, nil
}
priv := new(PrivateKey)
priv.E = 65537
@ -385,6 +420,7 @@ func mgf1XOR(out []byte, hash hash.Hash, seed []byte) {
var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA public key size")
func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
boring.Unreachable()
e := big.NewInt(int64(pub.E))
c.Exp(m, e, pub.N)
return c
@ -417,6 +453,15 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
return nil, ErrMessageTooLong
}
if boring.Enabled && random == boring.RandReader {
bkey, err := boringPublicKey(pub)
if err != nil {
return nil, err
}
return boring.EncryptRSAOAEP(hash, bkey, msg, label)
}
boring.UnreachableExceptTests()
hash.Write(label)
lHash := hash.Sum(nil)
hash.Reset()
@ -437,6 +482,15 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
mgf1XOR(db, hash, seed)
mgf1XOR(seed, hash, db)
if boring.Enabled {
var bkey *boring.PublicKeyRSA
bkey, err = boringPublicKey(pub)
if err != nil {
return nil, err
}
return boring.EncryptRSANoPadding(bkey, em)
}
m := new(big.Int)
m.SetBytes(em)
c := encrypt(new(big.Int), pub, m)
@ -487,6 +541,9 @@ func (priv *PrivateKey) Precompute() {
// decrypt performs an RSA decryption, resulting in a plaintext integer. If a
// random source is given, RSA blinding is used.
func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
if len(priv.Primes) <= 2 {
boring.Unreachable()
}
// TODO(agl): can we get away with reusing blinds?
if c.Cmp(priv.N) > 0 {
err = ErrDecryption
@ -603,6 +660,17 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
return nil, ErrDecryption
}
if boring.Enabled {
bkey, err := boringPrivateKey(priv)
if err != nil {
return nil, err
}
out, err := boring.DecryptRSAOAEP(hash, bkey, ciphertext, label)
if err != nil {
return nil, ErrDecryption
}
return out, nil
}
c := new(big.Int).SetBytes(ciphertext)
m, err := decrypt(random, priv, c)

View file

@ -10,23 +10,27 @@ import (
"crypto/rand"
"crypto/sha1"
"crypto/sha256"
"fmt"
"math/big"
"testing"
)
import "crypto/internal/boring"
func TestKeyGeneration(t *testing.T) {
size := 1024
if testing.Short() {
size = 128
for _, size := range []int{128, 1024, 2048, 3072} {
priv, err := GenerateKey(rand.Reader, size)
if err != nil {
t.Errorf("GenerateKey(%d): %v", size, err)
}
if bits := priv.N.BitLen(); bits != size {
t.Errorf("key too short (%d vs %d)", bits, size)
}
testKeyBasics(t, priv)
if testing.Short() {
break
}
}
priv, err := GenerateKey(rand.Reader, size)
if err != nil {
t.Errorf("failed to generate key")
}
if bits := priv.N.BitLen(); bits != size {
t.Errorf("key too short (%d vs %d)", bits, size)
}
testKeyBasics(t, priv)
}
func Test3PrimeKeyGeneration(t *testing.T) {
@ -110,6 +114,25 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) {
t.Errorf("private exponent too large")
}
if boring.Enabled {
// Cannot call encrypt/decrypt directly. Test via PKCS1v15.
msg := []byte("hi!")
enc, err := EncryptPKCS1v15(rand.Reader, &priv.PublicKey, msg)
if err != nil {
t.Errorf("EncryptPKCS1v15: %v", err)
return
}
dec, err := DecryptPKCS1v15(rand.Reader, priv, enc)
if err != nil {
t.Errorf("DecryptPKCS1v15: %v", err)
return
}
if !bytes.Equal(dec, msg) {
t.Errorf("got:%x want:%x (%+v)", dec, msg, priv)
}
return
}
pub := &priv.PublicKey
m := big.NewInt(42)
c := encrypt(new(big.Int), pub, m)
@ -158,6 +181,10 @@ func init() {
}
func BenchmarkRSA2048Decrypt(b *testing.B) {
if boring.Enabled {
b.Skip("no raw decrypt in BoringCrypto")
}
b.StopTimer()
c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313")
@ -180,6 +207,10 @@ func BenchmarkRSA2048Sign(b *testing.B) {
}
func Benchmark3PrimeRSA2048Decrypt(b *testing.B) {
if boring.Enabled {
b.Skip("no raw decrypt in BoringCrypto")
}
b.StopTimer()
priv := &PrivateKey{
PublicKey: PublicKey{
@ -222,7 +253,7 @@ func TestEncryptOAEP(t *testing.T) {
n := new(big.Int)
for i, test := range testEncryptOAEPData {
n.SetString(test.modulus, 16)
public := PublicKey{n, test.e}
public := PublicKey{N: n, E: test.e}
for j, message := range test.msgs {
randomSource := bytes.NewReader(message.seed)
@ -247,7 +278,7 @@ func TestDecryptOAEP(t *testing.T) {
n.SetString(test.modulus, 16)
d.SetString(test.d, 16)
private := new(PrivateKey)
private.PublicKey = PublicKey{n, test.e}
private.PublicKey = PublicKey{N: n, E: test.e}
private.D = d
for j, message := range test.msgs {
@ -272,6 +303,36 @@ func TestDecryptOAEP(t *testing.T) {
}
}
func TestEncryptDecryptOAEP(t *testing.T) {
sha256 := sha256.New()
n := new(big.Int)
d := new(big.Int)
for i, test := range testEncryptOAEPData {
n.SetString(test.modulus, 16)
d.SetString(test.d, 16)
priv := new(PrivateKey)
priv.PublicKey = PublicKey{N: n, E: test.e}
priv.D = d
for j, message := range test.msgs {
label := []byte(fmt.Sprintf("hi#%d", j))
enc, err := EncryptOAEP(sha256, rand.Reader, &priv.PublicKey, message.in, label)
if err != nil {
t.Errorf("#%d,%d: EncryptOAEP: %v", i, j, err)
continue
}
dec, err := DecryptOAEP(sha256, rand.Reader, priv, enc, label)
if err != nil {
t.Errorf("#%d,%d: DecryptOAEP: %v", i, j, err)
continue
}
if !bytes.Equal(dec, message.in) {
t.Errorf("#%d,%d: round trip %q -> %q", i, j, message.in, dec)
}
}
}
}
// testEncryptOAEPData contains a subset of the vectors from RSA's "Test vectors for RSA-OAEP".
var testEncryptOAEPData = []testEncryptOAEPStruct{
// Key 1

25
src/crypto/sha1/boring.go Normal file
View file

@ -0,0 +1,25 @@
// 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.
// Extra indirection here so that when building go_bootstrap
// cmd/internal/boring is not even imported, so that we don't
// have to maintain changes to cmd/dist's deps graph.
//go:build !cmd_go_bootstrap && cgo
// +build !cmd_go_bootstrap,cgo
package sha1
import (
"crypto/internal/boring"
"hash"
)
const boringEnabled = boring.Enabled
func boringNewSHA1() hash.Hash { return boring.NewSHA1() }
func boringUnreachable() { boring.Unreachable() }
func boringSHA1(p []byte) [20]byte { return boring.SHA1(p) }

View file

@ -0,0 +1,20 @@
// 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.
//go:build cmd_go_bootstrap || !cgo
// +build cmd_go_bootstrap !cgo
package sha1
import (
"hash"
)
const boringEnabled = false
func boringNewSHA1() hash.Hash { panic("boringcrypto: not available") }
func boringUnreachable() {}
func boringSHA1([]byte) [20]byte { panic("boringcrypto: not available") }

View file

@ -119,6 +119,9 @@ func (d *digest) Reset() {
// implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to
// marshal and unmarshal the internal state of the hash.
func New() hash.Hash {
if boringEnabled {
return boringNewSHA1()
}
d := new(digest)
d.Reset()
return d
@ -129,6 +132,7 @@ func (d *digest) Size() int { return Size }
func (d *digest) BlockSize() int { return BlockSize }
func (d *digest) Write(p []byte) (nn int, err error) {
boringUnreachable()
nn = len(p)
d.len += uint64(nn)
if d.nx > 0 {
@ -152,6 +156,7 @@ func (d *digest) Write(p []byte) (nn int, err error) {
}
func (d *digest) Sum(in []byte) []byte {
boringUnreachable()
// Make a copy of d so that caller can keep writing and summing.
d0 := *d
hash := d0.checkSum()
@ -259,6 +264,9 @@ func (d *digest) constSum() [Size]byte {
// Sum returns the SHA-1 checksum of the data.
func Sum(data []byte) [Size]byte {
if boringEnabled {
return boringSHA1(data)
}
var d digest
d.Reset()
d.Write(data)

View file

@ -8,6 +8,7 @@ package sha1
import (
"bytes"
"crypto/internal/boring"
"crypto/rand"
"encoding"
"fmt"
@ -77,6 +78,9 @@ func TestGolden(t *testing.T) {
io.WriteString(c, g.in[len(g.in)/2:])
sum = c.Sum(nil)
case 3:
if boring.Enabled {
continue
}
io.WriteString(c, g.in[0:len(g.in)/2])
c.(*digest).ConstantTimeSum(nil)
io.WriteString(c, g.in[len(g.in)/2:])
@ -141,6 +145,9 @@ func TestBlockSize(t *testing.T) {
// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match.
func TestBlockGeneric(t *testing.T) {
if boring.Enabled {
t.Skip("BoringCrypto doesn't expose digest")
}
for i := 1; i < 30; i++ { // arbitrary factor
gen, asm := New().(*digest), New().(*digest)
buf := make([]byte, BlockSize*i)
@ -211,6 +218,9 @@ func TestLargeHashes(t *testing.T) {
}
func TestAllocations(t *testing.T) {
if boring.Enabled {
t.Skip("BoringCrypto doesn't allocate the same way as stdlib")
}
in := []byte("hello, world!")
out := make([]byte, 0, Size)
h := New()
@ -228,13 +238,23 @@ var bench = New()
var buf = make([]byte, 8192)
func benchmarkSize(b *testing.B, size int) {
b.SetBytes(int64(size))
sum := make([]byte, bench.Size())
for i := 0; i < b.N; i++ {
bench.Reset()
bench.Write(buf[:size])
bench.Sum(sum[:0])
}
b.Run("New", func(b *testing.B) {
b.ReportAllocs()
b.SetBytes(int64(size))
for i := 0; i < b.N; i++ {
bench.Reset()
bench.Write(buf[:size])
bench.Sum(sum[:0])
}
})
b.Run("Sum", func(b *testing.B) {
b.ReportAllocs()
b.SetBytes(int64(size))
for i := 0; i < b.N; i++ {
Sum(buf[:size])
}
})
}
func BenchmarkHash8Bytes(b *testing.B) {

View file

@ -8,6 +8,7 @@ package sha256
import (
"crypto"
"crypto/internal/boring"
"encoding/binary"
"errors"
"hash"
@ -159,6 +160,9 @@ func (d *digest) Reset() {
// encoding.BinaryUnmarshaler to marshal and unmarshal the internal
// state of the hash.
func New() hash.Hash {
if boring.Enabled {
return boring.NewSHA256()
}
d := new(digest)
d.Reset()
return d
@ -166,6 +170,9 @@ func New() hash.Hash {
// New224 returns a new hash.Hash computing the SHA224 checksum.
func New224() hash.Hash {
if boring.Enabled {
return boring.NewSHA224()
}
d := new(digest)
d.is224 = true
d.Reset()
@ -182,6 +189,7 @@ func (d *digest) Size() int {
func (d *digest) BlockSize() int { return BlockSize }
func (d *digest) Write(p []byte) (nn int, err error) {
boring.Unreachable()
nn = len(p)
d.len += uint64(nn)
if d.nx > 0 {
@ -205,6 +213,7 @@ func (d *digest) Write(p []byte) (nn int, err error) {
}
func (d *digest) Sum(in []byte) []byte {
boring.Unreachable()
// Make a copy of d so that caller can keep writing and summing.
d0 := *d
hash := d0.checkSum()
@ -252,6 +261,9 @@ func (d *digest) checkSum() [Size]byte {
// Sum256 returns the SHA256 checksum of the data.
func Sum256(data []byte) [Size]byte {
if boring.Enabled {
return boring.SHA256(data)
}
var d digest
d.Reset()
d.Write(data)
@ -260,6 +272,9 @@ func Sum256(data []byte) [Size]byte {
// Sum224 returns the SHA224 checksum of the data.
func Sum224(data []byte) [Size224]byte {
if boring.Enabled {
return boring.SHA224(data)
}
var d digest
d.is224 = true
d.Reset()

View file

@ -8,6 +8,7 @@ package sha256
import (
"bytes"
"crypto/internal/boring"
"crypto/rand"
"encoding"
"fmt"
@ -216,6 +217,9 @@ func TestBlockSize(t *testing.T) {
// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match.
func TestBlockGeneric(t *testing.T) {
if boring.Enabled {
t.Skip("BoringCrypto doesn't expose digest")
}
gen, asm := New().(*digest), New().(*digest)
buf := make([]byte, BlockSize*20) // arbitrary factor
rand.Read(buf)
@ -290,6 +294,9 @@ func TestLargeHashes(t *testing.T) {
}
func TestAllocations(t *testing.T) {
if boring.Enabled {
t.Skip("BoringCrypto doesn't allocate the same way as stdlib")
}
in := []byte("hello, world!")
out := make([]byte, 0, Size)
h := New()
@ -307,13 +314,30 @@ var bench = New()
var buf = make([]byte, 8192)
func benchmarkSize(b *testing.B, size int) {
b.SetBytes(int64(size))
sum := make([]byte, bench.Size())
for i := 0; i < b.N; i++ {
bench.Reset()
bench.Write(buf[:size])
bench.Sum(sum[:0])
}
b.Run("New", func(b *testing.B) {
b.ReportAllocs()
b.SetBytes(int64(size))
for i := 0; i < b.N; i++ {
bench.Reset()
bench.Write(buf[:size])
bench.Sum(sum[:0])
}
})
b.Run("Sum224", func(b *testing.B) {
b.ReportAllocs()
b.SetBytes(int64(size))
for i := 0; i < b.N; i++ {
Sum224(buf[:size])
}
})
b.Run("Sum256", func(b *testing.B) {
b.ReportAllocs()
b.SetBytes(int64(size))
for i := 0; i < b.N; i++ {
Sum256(buf[:size])
}
})
}
func BenchmarkHash8Bytes(b *testing.B) {

View file

@ -12,6 +12,7 @@ package sha512
import (
"crypto"
"crypto/internal/boring"
"encoding/binary"
"errors"
"hash"
@ -211,6 +212,9 @@ func consumeUint64(b []byte) ([]byte, uint64) {
// New returns a new hash.Hash computing the SHA-512 checksum.
func New() hash.Hash {
if boring.Enabled {
return boring.NewSHA512()
}
d := &digest{function: crypto.SHA512}
d.Reset()
return d
@ -232,6 +236,9 @@ func New512_256() hash.Hash {
// New384 returns a new hash.Hash computing the SHA-384 checksum.
func New384() hash.Hash {
if boring.Enabled {
return boring.NewSHA384()
}
d := &digest{function: crypto.SHA384}
d.Reset()
return d
@ -253,6 +260,9 @@ func (d *digest) Size() int {
func (d *digest) BlockSize() int { return BlockSize }
func (d *digest) Write(p []byte) (nn int, err error) {
if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 {
boring.Unreachable()
}
nn = len(p)
d.len += uint64(nn)
if d.nx > 0 {
@ -276,6 +286,9 @@ func (d *digest) Write(p []byte) (nn int, err error) {
}
func (d *digest) Sum(in []byte) []byte {
if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 {
boring.Unreachable()
}
// Make a copy of d so that caller can keep writing and summing.
d0 := new(digest)
*d0 = *d
@ -330,6 +343,9 @@ func (d *digest) checkSum() [Size]byte {
// Sum512 returns the SHA512 checksum of the data.
func Sum512(data []byte) [Size]byte {
if boring.Enabled {
return boring.SHA512(data)
}
d := digest{function: crypto.SHA512}
d.Reset()
d.Write(data)
@ -338,6 +354,9 @@ func Sum512(data []byte) [Size]byte {
// Sum384 returns the SHA384 checksum of the data.
func Sum384(data []byte) [Size384]byte {
if boring.Enabled {
return boring.SHA384(data)
}
d := digest{function: crypto.SHA384}
d.Reset()
d.Write(data)

View file

@ -8,6 +8,7 @@ package sha512
import (
"bytes"
"crypto/internal/boring"
"crypto/rand"
"encoding"
"encoding/hex"
@ -822,6 +823,9 @@ func TestBlockSize(t *testing.T) {
// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match.
func TestBlockGeneric(t *testing.T) {
if boring.Enabled {
t.Skip("BoringCrypto doesn't expose digest")
}
gen, asm := New().(*digest), New().(*digest)
buf := make([]byte, BlockSize*20) // arbitrary factor
rand.Read(buf)
@ -889,6 +893,9 @@ func TestLargeHashes(t *testing.T) {
}
func TestAllocations(t *testing.T) {
if boring.Enabled {
t.Skip("BoringCrypto doesn't allocate the same way as stdlib")
}
in := []byte("hello, world!")
out := make([]byte, 0, Size)
h := New()
@ -906,13 +913,30 @@ var bench = New()
var buf = make([]byte, 8192)
func benchmarkSize(b *testing.B, size int) {
b.SetBytes(int64(size))
sum := make([]byte, bench.Size())
for i := 0; i < b.N; i++ {
bench.Reset()
bench.Write(buf[:size])
bench.Sum(sum[:0])
}
b.Run("New", func(b *testing.B) {
b.ReportAllocs()
b.SetBytes(int64(size))
for i := 0; i < b.N; i++ {
bench.Reset()
bench.Write(buf[:size])
bench.Sum(sum[:0])
}
})
b.Run("Sum384", func(b *testing.B) {
b.ReportAllocs()
b.SetBytes(int64(size))
for i := 0; i < b.N; i++ {
Sum384(buf[:size])
}
})
b.Run("Sum512", func(b *testing.B) {
b.ReportAllocs()
b.SetBytes(int64(size))
for i := 0; i < b.N; i++ {
Sum512(buf[:size])
}
})
}
func BenchmarkHash8Bytes(b *testing.B) {

View file

@ -169,6 +169,7 @@ var rsaSignatureSchemes = []struct {
// and optionally filtered by its explicit SupportedSignatureAlgorithms.
//
// This function must be kept in sync with supportedSignatureAlgorithms.
// FIPS filtering is applied in the caller, selectSignatureScheme.
func signatureSchemesForCertificate(version uint16, cert *Certificate) []SignatureScheme {
priv, ok := cert.PrivateKey.(crypto.Signer)
if !ok {
@ -241,6 +242,9 @@ func selectSignatureScheme(vers uint16, c *Certificate, peerAlgs []SignatureSche
// Pick signature scheme in the peer's preference order, as our
// preference order is not configurable.
for _, preferredAlg := range peerAlgs {
if needFIPS() && !isSupportedSignatureAlgorithm(preferredAlg, fipsSupportedSignatureAlgorithms) {
continue
}
if isSupportedSignatureAlgorithm(preferredAlg, supportedAlgs) {
return preferredAlg, nil
}

View file

@ -153,7 +153,7 @@ func TestLegacyTypeAndHash(t *testing.T) {
// TestSupportedSignatureAlgorithms checks that all supportedSignatureAlgorithms
// have valid type and hash information.
func TestSupportedSignatureAlgorithms(t *testing.T) {
for _, sigAlg := range supportedSignatureAlgorithms {
for _, sigAlg := range supportedSignatureAlgorithms() {
sigType, hash, err := typeAndHashFromSignatureScheme(sigAlg)
if err != nil {
t.Errorf("%v: unexpected error: %v", sigAlg, err)

98
src/crypto/tls/boring.go Normal file
View file

@ -0,0 +1,98 @@
// Copyright 2017 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 boringcrypto
package tls
import (
"crypto/internal/boring/fipstls"
)
// needFIPS returns fipstls.Required(); it avoids a new import in common.go.
func needFIPS() bool {
return fipstls.Required()
}
// fipsMinVersion replaces c.minVersion in FIPS-only mode.
func fipsMinVersion(c *Config) uint16 {
// FIPS requires TLS 1.2.
return VersionTLS12
}
// fipsMaxVersion replaces c.maxVersion in FIPS-only mode.
func fipsMaxVersion(c *Config) uint16 {
// FIPS requires TLS 1.2.
return VersionTLS12
}
// default defaultFIPSCurvePreferences is the FIPS-allowed curves,
// in preference order (most preferable first).
var defaultFIPSCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521}
// fipsCurvePreferences replaces c.curvePreferences in FIPS-only mode.
func fipsCurvePreferences(c *Config) []CurveID {
if c == nil || len(c.CurvePreferences) == 0 {
return defaultFIPSCurvePreferences
}
var list []CurveID
for _, id := range c.CurvePreferences {
for _, allowed := range defaultFIPSCurvePreferences {
if id == allowed {
list = append(list, id)
break
}
}
}
return list
}
// defaultCipherSuitesFIPS are the FIPS-allowed cipher suites.
var defaultCipherSuitesFIPS = []uint16{
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_RSA_WITH_AES_128_GCM_SHA256,
TLS_RSA_WITH_AES_256_GCM_SHA384,
}
// fipsCipherSuites replaces c.cipherSuites in FIPS-only mode.
func fipsCipherSuites(c *Config) []uint16 {
if c == nil || c.CipherSuites == nil {
return defaultCipherSuitesFIPS
}
list := make([]uint16, 0, len(defaultCipherSuitesFIPS))
for _, id := range c.CipherSuites {
for _, allowed := range defaultCipherSuitesFIPS {
if id == allowed {
list = append(list, id)
break
}
}
}
return list
}
// fipsSupportedSignatureAlgorithms currently are a subset of
// defaultSupportedSignatureAlgorithms without Ed25519 and SHA-1.
var fipsSupportedSignatureAlgorithms = []SignatureScheme{
PSSWithSHA256,
PSSWithSHA384,
PSSWithSHA512,
PKCS1WithSHA256,
ECDSAWithP256AndSHA256,
PKCS1WithSHA384,
ECDSAWithP384AndSHA384,
PKCS1WithSHA512,
ECDSAWithP521AndSHA512,
}
// supportedSignatureAlgorithms returns the supported signature algorithms.
func supportedSignatureAlgorithms() []SignatureScheme {
if !needFIPS() {
return defaultSupportedSignatureAlgorithms
}
return fipsSupportedSignatureAlgorithms
}

View file

@ -0,0 +1,616 @@
// Copyright 2017 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 boringcrypto
package tls
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/internal/boring/fipstls"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"net"
"runtime"
"strings"
"testing"
"time"
)
func TestBoringServerProtocolVersion(t *testing.T) {
test := func(name string, v uint16, msg string) {
t.Run(name, func(t *testing.T) {
serverConfig := testConfig.Clone()
serverConfig.MinVersion = VersionSSL30
clientHello := &clientHelloMsg{
vers: v,
random: make([]byte, 32),
cipherSuites: allCipherSuites(),
compressionMethods: []uint8{compressionNone},
supportedVersions: []uint16{v},
}
testClientHelloFailure(t, serverConfig, clientHello, msg)
})
}
test("VersionTLS10", VersionTLS10, "")
test("VersionTLS11", VersionTLS11, "")
test("VersionTLS12", VersionTLS12, "")
test("VersionTLS13", VersionTLS13, "")
fipstls.Force()
defer fipstls.Abandon()
test("VersionSSL30", VersionSSL30, "client offered only unsupported versions")
test("VersionTLS10", VersionTLS10, "client offered only unsupported versions")
test("VersionTLS11", VersionTLS11, "client offered only unsupported versions")
test("VersionTLS12", VersionTLS12, "")
test("VersionTLS13", VersionTLS13, "client offered only unsupported versions")
}
func isBoringVersion(v uint16) bool {
return v == VersionTLS12
}
func isBoringCipherSuite(id uint16) bool {
switch id {
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_RSA_WITH_AES_128_GCM_SHA256,
TLS_RSA_WITH_AES_256_GCM_SHA384:
return true
}
return false
}
func isBoringCurve(id CurveID) bool {
switch id {
case CurveP256, CurveP384, CurveP521:
return true
}
return false
}
func isECDSA(id uint16) bool {
for _, suite := range cipherSuites {
if suite.id == id {
return suite.flags&suiteECSign == suiteECSign
}
}
panic(fmt.Sprintf("unknown cipher suite %#x", id))
}
func isBoringSignatureScheme(alg SignatureScheme) bool {
switch alg {
default:
return false
case PKCS1WithSHA256,
ECDSAWithP256AndSHA256,
PKCS1WithSHA384,
ECDSAWithP384AndSHA384,
PKCS1WithSHA512,
ECDSAWithP521AndSHA512,
PSSWithSHA256,
PSSWithSHA384,
PSSWithSHA512:
// ok
}
return true
}
func TestBoringServerCipherSuites(t *testing.T) {
serverConfig := testConfig.Clone()
serverConfig.CipherSuites = allCipherSuites()
serverConfig.Certificates = make([]Certificate, 1)
for _, id := range allCipherSuites() {
if isECDSA(id) {
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
} else {
serverConfig.Certificates[0].Certificate = [][]byte{testRSACertificate}
serverConfig.Certificates[0].PrivateKey = testRSAPrivateKey
}
serverConfig.BuildNameToCertificate()
t.Run(fmt.Sprintf("suite=%#x", id), func(t *testing.T) {
clientHello := &clientHelloMsg{
vers: VersionTLS12,
random: make([]byte, 32),
cipherSuites: []uint16{id},
compressionMethods: []uint8{compressionNone},
supportedCurves: defaultCurvePreferences,
supportedPoints: []uint8{pointFormatUncompressed},
}
testClientHello(t, serverConfig, clientHello)
t.Run("fipstls", func(t *testing.T) {
fipstls.Force()
defer fipstls.Abandon()
msg := ""
if !isBoringCipherSuite(id) {
msg = "no cipher suite supported by both client and server"
}
testClientHelloFailure(t, serverConfig, clientHello, msg)
})
})
}
}
func TestBoringServerCurves(t *testing.T) {
serverConfig := testConfig.Clone()
serverConfig.Certificates = make([]Certificate, 1)
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
serverConfig.BuildNameToCertificate()
for _, curveid := range defaultCurvePreferences {
t.Run(fmt.Sprintf("curve=%d", curveid), func(t *testing.T) {
clientHello := &clientHelloMsg{
vers: VersionTLS12,
random: make([]byte, 32),
cipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
compressionMethods: []uint8{compressionNone},
supportedCurves: []CurveID{curveid},
supportedPoints: []uint8{pointFormatUncompressed},
}
testClientHello(t, serverConfig, clientHello)
// With fipstls forced, bad curves should be rejected.
t.Run("fipstls", func(t *testing.T) {
fipstls.Force()
defer fipstls.Abandon()
msg := ""
if !isBoringCurve(curveid) {
msg = "no cipher suite supported by both client and server"
}
testClientHelloFailure(t, serverConfig, clientHello, msg)
})
})
}
}
func boringHandshake(t *testing.T, clientConfig, serverConfig *Config) (clientErr, serverErr error) {
c, s := localPipe(t)
client := Client(c, clientConfig)
server := Server(s, serverConfig)
done := make(chan error, 1)
go func() {
done <- client.Handshake()
c.Close()
}()
serverErr = server.Handshake()
s.Close()
clientErr = <-done
return
}
func TestBoringServerSignatureAndHash(t *testing.T) {
defer func() {
testingOnlyForceClientHelloSignatureAlgorithms = nil
}()
for _, sigHash := range defaultSupportedSignatureAlgorithms {
t.Run(fmt.Sprintf("%#x", sigHash), func(t *testing.T) {
serverConfig := testConfig.Clone()
serverConfig.Certificates = make([]Certificate, 1)
testingOnlyForceClientHelloSignatureAlgorithms = []SignatureScheme{sigHash}
sigType, _, _ := typeAndHashFromSignatureScheme(sigHash)
switch sigType {
case signaturePKCS1v15, signatureRSAPSS:
serverConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
serverConfig.Certificates[0].Certificate = [][]byte{testRSA2048Certificate}
serverConfig.Certificates[0].PrivateKey = testRSA2048PrivateKey
case signatureEd25519:
serverConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}
serverConfig.Certificates[0].Certificate = [][]byte{testEd25519Certificate}
serverConfig.Certificates[0].PrivateKey = testEd25519PrivateKey
case signatureECDSA:
serverConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
}
serverConfig.BuildNameToCertificate()
// PKCS#1 v1.5 signature algorithms can't be used standalone in TLS
// 1.3, and the ECDSA ones bind to the curve used.
serverConfig.MaxVersion = VersionTLS12
clientErr, serverErr := boringHandshake(t, testConfig, serverConfig)
if clientErr != nil {
t.Fatalf("expected handshake with %#x to succeed; client error: %v; server error: %v", sigHash, clientErr, serverErr)
}
// With fipstls forced, bad curves should be rejected.
t.Run("fipstls", func(t *testing.T) {
fipstls.Force()
defer fipstls.Abandon()
clientErr, _ := boringHandshake(t, testConfig, serverConfig)
if isBoringSignatureScheme(sigHash) {
if clientErr != nil {
t.Fatalf("expected handshake with %#x to succeed; err=%v", sigHash, clientErr)
}
} else {
if clientErr == nil {
t.Fatalf("expected handshake with %#x to fail, but it succeeded", sigHash)
}
}
})
})
}
}
func TestBoringClientHello(t *testing.T) {
// Test that no matter what we put in the client config,
// the client does not offer non-FIPS configurations.
fipstls.Force()
defer fipstls.Abandon()
c, s := net.Pipe()
defer c.Close()
defer s.Close()
clientConfig := testConfig.Clone()
// All sorts of traps for the client to avoid.
clientConfig.MinVersion = VersionSSL30
clientConfig.MaxVersion = VersionTLS13
clientConfig.CipherSuites = allCipherSuites()
clientConfig.CurvePreferences = defaultCurvePreferences
go Client(c, clientConfig).Handshake()
srv := Server(s, testConfig)
msg, err := srv.readHandshake()
if err != nil {
t.Fatal(err)
}
hello, ok := msg.(*clientHelloMsg)
if !ok {
t.Fatalf("unexpected message type %T", msg)
}
if !isBoringVersion(hello.vers) {
t.Errorf("client vers=%#x, want %#x (TLS 1.2)", hello.vers, VersionTLS12)
}
for _, v := range hello.supportedVersions {
if !isBoringVersion(v) {
t.Errorf("client offered disallowed version %#x", v)
}
}
for _, id := range hello.cipherSuites {
if !isBoringCipherSuite(id) {
t.Errorf("client offered disallowed suite %#x", id)
}
}
for _, id := range hello.supportedCurves {
if !isBoringCurve(id) {
t.Errorf("client offered disallowed curve %d", id)
}
}
for _, sigHash := range hello.supportedSignatureAlgorithms {
if !isBoringSignatureScheme(sigHash) {
t.Errorf("client offered disallowed signature-and-hash %v", sigHash)
}
}
}
func TestBoringCertAlgs(t *testing.T) {
// NaCl, arm and wasm time out generating keys. Nothing in this test is architecture-specific, so just don't bother on those.
if runtime.GOOS == "nacl" || runtime.GOARCH == "arm" || runtime.GOOS == "js" {
t.Skipf("skipping on %s/%s because key generation takes too long", runtime.GOOS, runtime.GOARCH)
}
// Set up some roots, intermediate CAs, and leaf certs with various algorithms.
// X_Y is X signed by Y.
R1 := boringCert(t, "R1", boringRSAKey(t, 2048), nil, boringCertCA|boringCertFIPSOK)
R2 := boringCert(t, "R2", boringRSAKey(t, 4096), nil, boringCertCA)
M1_R1 := boringCert(t, "M1_R1", boringECDSAKey(t, elliptic.P256()), R1, boringCertCA|boringCertFIPSOK)
M2_R1 := boringCert(t, "M2_R1", boringECDSAKey(t, elliptic.P224()), R1, boringCertCA)
I_R1 := boringCert(t, "I_R1", boringRSAKey(t, 3072), R1, boringCertCA|boringCertFIPSOK)
I_R2 := boringCert(t, "I_R2", I_R1.key, R2, boringCertCA|boringCertFIPSOK)
I_M1 := boringCert(t, "I_M1", I_R1.key, M1_R1, boringCertCA|boringCertFIPSOK)
I_M2 := boringCert(t, "I_M2", I_R1.key, M2_R1, boringCertCA|boringCertFIPSOK)
L1_I := boringCert(t, "L1_I", boringECDSAKey(t, elliptic.P384()), I_R1, boringCertLeaf|boringCertFIPSOK)
L2_I := boringCert(t, "L2_I", boringRSAKey(t, 1024), I_R1, boringCertLeaf)
// client verifying server cert
testServerCert := func(t *testing.T, desc string, pool *x509.CertPool, key interface{}, list [][]byte, ok bool) {
clientConfig := testConfig.Clone()
clientConfig.RootCAs = pool
clientConfig.InsecureSkipVerify = false
clientConfig.ServerName = "example.com"
serverConfig := testConfig.Clone()
serverConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}}
serverConfig.BuildNameToCertificate()
clientErr, _ := boringHandshake(t, clientConfig, serverConfig)
if (clientErr == nil) == ok {
if ok {
t.Logf("%s: accept", desc)
} else {
t.Logf("%s: reject", desc)
}
} else {
if ok {
t.Errorf("%s: BAD reject (%v)", desc, clientErr)
} else {
t.Errorf("%s: BAD accept", desc)
}
}
}
// server verifying client cert
testClientCert := func(t *testing.T, desc string, pool *x509.CertPool, key interface{}, list [][]byte, ok bool) {
clientConfig := testConfig.Clone()
clientConfig.ServerName = "example.com"
clientConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}}
serverConfig := testConfig.Clone()
serverConfig.ClientCAs = pool
serverConfig.ClientAuth = RequireAndVerifyClientCert
_, serverErr := boringHandshake(t, clientConfig, serverConfig)
if (serverErr == nil) == ok {
if ok {
t.Logf("%s: accept", desc)
} else {
t.Logf("%s: reject", desc)
}
} else {
if ok {
t.Errorf("%s: BAD reject (%v)", desc, serverErr)
} else {
t.Errorf("%s: BAD accept", desc)
}
}
}
// Run simple basic test with known answers before proceeding to
// exhaustive test with computed answers.
r1pool := x509.NewCertPool()
r1pool.AddCert(R1.cert)
testServerCert(t, "basic", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true)
testClientCert(t, "basic (client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true)
fipstls.Force()
testServerCert(t, "basic (fips)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false)
testClientCert(t, "basic (fips, client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false)
fipstls.Abandon()
if t.Failed() {
t.Fatal("basic test failed, skipping exhaustive test")
}
if testing.Short() {
t.Logf("basic test passed; skipping exhaustive test in -short mode")
return
}
for l := 1; l <= 2; l++ {
leaf := L1_I
if l == 2 {
leaf = L2_I
}
for i := 0; i < 64; i++ {
reachable := map[string]bool{leaf.parentOrg: true}
reachableFIPS := map[string]bool{leaf.parentOrg: leaf.fipsOK}
list := [][]byte{leaf.der}
listName := leaf.name
addList := func(cond int, c *boringCertificate) {
if cond != 0 {
list = append(list, c.der)
listName += "," + c.name
if reachable[c.org] {
reachable[c.parentOrg] = true
}
if reachableFIPS[c.org] && c.fipsOK {
reachableFIPS[c.parentOrg] = true
}
}
}
addList(i&1, I_R1)
addList(i&2, I_R2)
addList(i&4, I_M1)
addList(i&8, I_M2)
addList(i&16, M1_R1)
addList(i&32, M2_R1)
for r := 1; r <= 3; r++ {
pool := x509.NewCertPool()
rootName := ","
shouldVerify := false
shouldVerifyFIPS := false
addRoot := func(cond int, c *boringCertificate) {
if cond != 0 {
rootName += "," + c.name
pool.AddCert(c.cert)
if reachable[c.org] {
shouldVerify = true
}
if reachableFIPS[c.org] && c.fipsOK {
shouldVerifyFIPS = true
}
}
}
addRoot(r&1, R1)
addRoot(r&2, R2)
rootName = rootName[1:] // strip leading comma
testServerCert(t, listName+"->"+rootName[1:], pool, leaf.key, list, shouldVerify)
testClientCert(t, listName+"->"+rootName[1:]+"(client cert)", pool, leaf.key, list, shouldVerify)
fipstls.Force()
testServerCert(t, listName+"->"+rootName[1:]+" (fips)", pool, leaf.key, list, shouldVerifyFIPS)
testClientCert(t, listName+"->"+rootName[1:]+" (fips, client cert)", pool, leaf.key, list, shouldVerifyFIPS)
fipstls.Abandon()
}
}
}
}
const (
boringCertCA = iota
boringCertLeaf
boringCertFIPSOK = 0x80
)
func boringRSAKey(t *testing.T, size int) *rsa.PrivateKey {
k, err := rsa.GenerateKey(rand.Reader, size)
if err != nil {
t.Fatal(err)
}
return k
}
func boringECDSAKey(t *testing.T, curve elliptic.Curve) *ecdsa.PrivateKey {
k, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
t.Fatal(err)
}
return k
}
type boringCertificate struct {
name string
org string
parentOrg string
der []byte
cert *x509.Certificate
key interface{}
fipsOK bool
}
func boringCert(t *testing.T, name string, key interface{}, parent *boringCertificate, mode int) *boringCertificate {
org := name
parentOrg := ""
if i := strings.Index(org, "_"); i >= 0 {
org = org[:i]
parentOrg = name[i+1:]
}
tmpl := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
Organization: []string{org},
},
NotBefore: time.Unix(0, 0),
NotAfter: time.Unix(0, 0),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,
}
if mode&^boringCertFIPSOK == boringCertLeaf {
tmpl.DNSNames = []string{"example.com"}
} else {
tmpl.IsCA = true
tmpl.KeyUsage |= x509.KeyUsageCertSign
}
var pcert *x509.Certificate
var pkey interface{}
if parent != nil {
pcert = parent.cert
pkey = parent.key
} else {
pcert = tmpl
pkey = key
}
var pub interface{}
switch k := key.(type) {
case *rsa.PrivateKey:
pub = &k.PublicKey
case *ecdsa.PrivateKey:
pub = &k.PublicKey
default:
t.Fatalf("invalid key %T", key)
}
der, err := x509.CreateCertificate(rand.Reader, tmpl, pcert, pub, pkey)
if err != nil {
t.Fatal(err)
}
cert, err := x509.ParseCertificate(der)
if err != nil {
t.Fatal(err)
}
fipsOK := mode&boringCertFIPSOK != 0
return &boringCertificate{name, org, parentOrg, der, cert, key, fipsOK}
}
// A self-signed test certificate with an RSA key of size 2048, for testing
// RSA-PSS with SHA512. SAN of example.golang.
var (
testRSA2048Certificate []byte
testRSA2048PrivateKey *rsa.PrivateKey
)
func init() {
block, _ := pem.Decode([]byte(`
-----BEGIN CERTIFICATE-----
MIIC/zCCAeegAwIBAgIRALHHX/kh4+4zMU9DarzBEcQwDQYJKoZIhvcNAQELBQAw
EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xMTAxMDExNTA0MDVaFw0yMDEyMjkxNTA0
MDVaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQCf8fk0N6ieCBX4IOVIfKitt4kGcOQLeimCfsjqqHcysMIVGEtFSM6E
4Ay141f/7IqdW0UtIqNb4PXhROID7yDxR284xL6XbCuv/t5hP3UcehYc3hmLiyVd
MkZQiZWtfUUJf/1qOtM+ohNg59LRWp4d+6iX0la1JL3EwCIckkNjJ9hQbF7Pb2CS
+ES9Yo55KAap8KOblpcR8MBSN38bqnwjfQdCXvOEOjam2HUxKzEFX5MA+fA0me4C
ioCcCRLWKl+GoN9F8fABfoZ+T+2eal4DLuO95rXR8SrOIVBh3XFOr/RVhjtXcNVF
ZKcvDt6d68V6jAKAYKm5nlj9GPpd4v+rAgMBAAGjUDBOMA4GA1UdDwEB/wQEAwIF
oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBkGA1UdEQQSMBCC
DmV4YW1wbGUuZ29sYW5nMA0GCSqGSIb3DQEBCwUAA4IBAQCOoYsVcFCBhboqe3WH
dC6V7XXXECmnjh01r8h80yv0NR379nSD3cw2M+HKvaXysWqrl5hjGVKw0vtwD81r
V4JzDu7IfIog5m8+QNC+7LqDZsz88vDKOrsoySVOmUCgmCKFXew+LA+eO/iQEJTr
7ensddOeXJEp27Ed5vW+kmWW3Qmglc2Gwy8wFrMDIqnrnOzBA4oCnDEgtXJt0zog
nRwbfEMAWi1aQRy5dT9KA3SP9mo5SeTFSzGGHiE4s4gHUe7jvsAFF2qgtD6+wH6s
z9b6shxnC7g5IlBKhI7SVB/Uqt2ydJ+kH1YbjMcIq6NAM5eNMKgZuJr3+zwsSgwh
GNaE
-----END CERTIFICATE-----`))
testRSA2048Certificate = block.Bytes
block, _ = pem.Decode([]byte(`
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAn/H5NDeonggV+CDlSHyorbeJBnDkC3opgn7I6qh3MrDCFRhL
RUjOhOAMteNX/+yKnVtFLSKjW+D14UTiA+8g8UdvOMS+l2wrr/7eYT91HHoWHN4Z
i4slXTJGUImVrX1FCX/9ajrTPqITYOfS0VqeHfuol9JWtSS9xMAiHJJDYyfYUGxe
z29gkvhEvWKOeSgGqfCjm5aXEfDAUjd/G6p8I30HQl7zhDo2pth1MSsxBV+TAPnw
NJnuAoqAnAkS1ipfhqDfRfHwAX6Gfk/tnmpeAy7jvea10fEqziFQYd1xTq/0VYY7
V3DVRWSnLw7enevFeowCgGCpuZ5Y/Rj6XeL/qwIDAQABAoIBAQCNpMZifd/vg42h
HdCvLuZaYS0R7SunFlpoXEsltGdLFsnp0IfoJZ/ugFQBSAIIfLwMumU6oXA1z7Uv
98aIYV61DePrTCDVDFBsHbNmP8JAo8WtbusEbwd5zyoB7LYG2+clkJklWE73KqUq
rmI+UJeyScl2Gin7ZTxBXz1WPBk9VwcnwkeaXpgASIBW23fhECM9gnYEEwaBez5T
6Me8d1tHtYQv7vsKe7ro9w9/HKrRXejqYKK1LxkhfFriyV+m8LZJZn2nXOa6G3gF
Nb8Qk1Uk5PUBENBmyMFJhT4M/uuSq4YtMrrO2gi8Q+fPhuGzc5SshYKRBp0W4P5r
mtVCtEFRAoGBAMENBIFLrV2+HsGj0xYFasKov/QPe6HSTR1Hh2IZONp+oK4oszWE
jBT4VcnITmpl6tC1Wy4GcrxjNgKIFZAj+1x1LUULdorXkuG8yr0tAhG9zNyfWsSy
PrSovC0UVbzr8Jxxla+kQVxEQQqWQxPlEVuL8kXaIDA6Lyt1Hpua2LvPAoGBANQZ
c6Lq2T7+BxLxNdi2m8kZzej5kgzBp/XdVsbFWRlebIX2KrFHsrHzT9PUk3DE1vZK
M6pzTt94nQhWSkDgCaw1SohElJ3HFIFwcusF1SJAc3pQepd8ug6IYdlpDMLtBj/P
/5P6BVUtgo05E4+I/T3iYatmglQxTtlZ0RkSV2llAoGBALOXkKFX7ahPvf0WksDh
uTfuFOTPoowgQG0EpgW0wRdCxeg/JLic3lSD0gsttQV2WsRecryWcxaelRg10RmO
38BbogmhaF4xvgsSvujOfiZTE8oK1T43M+6NKsIlML3YILbpU/9aJxPWy0s2DqDr
cQJhZrlk+pzjBA7Bnf/URdwxAoGAKR/CNw14D+mrL3YLbbiCXiydqxVwxv5pdZdz
8thi3TNcsWC4iGURdcVqbfUinVPdJiXe/Kac3WGCeRJaFVgbKAOxLti1RB5MkIhg
D8eyupBqk4W1L1gkrxqsdj4TFlxkwMywjl2E2S4YyQ8PBt6V04DoVRZsIKzqz+PF
UionPq0CgYBCYXvqioJhPewkOq/Y5wrDBeZW1FQK5QD9W5M8/5zxd4rdvJtjhbJp
oOrtvMdrl6upy9Hz4BJD3FXwVFiPFE7jqeNqi0F21viLxBPMMD3UODF6LL5EyLiR
9V4xVMS8KXxvg7rxsuqzMPscViaWUL6WNVBhsD2+92dHxSXzz5EJKQ==
-----END RSA PRIVATE KEY-----`))
var err error
testRSA2048PrivateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
panic(err)
}
}

View file

@ -4,6 +4,8 @@
package tls
import "crypto/internal/boring"
import (
"crypto"
"crypto/aes"
@ -421,7 +423,13 @@ func cipherAES(key, iv []byte, isRead bool) any {
// macSHA1 returns a SHA-1 based constant time MAC.
func macSHA1(key []byte) hash.Hash {
return hmac.New(newConstantTimeHash(sha1.New), key)
h := sha1.New
// The BoringCrypto SHA1 does not have a constant-time
// checksum function, so don't try to use it.
if !boring.Enabled {
h = newConstantTimeHash(h)
}
return hmac.New(h, key)
}
// macSHA256 returns a SHA-256 based MAC. This is only supported in TLS 1.2 and
@ -509,7 +517,16 @@ func aeadAESGCM(key, noncePrefix []byte) aead {
if err != nil {
panic(err)
}
aead, err := cipher.NewGCM(aes)
type gcmtls interface {
NewGCMTLS() (cipher.AEAD, error)
}
var aead cipher.AEAD
if aesTLS, ok := aes.(gcmtls); ok {
aead, err = aesTLS.NewGCMTLS()
} else {
boring.Unreachable()
aead, err = cipher.NewGCM(aes)
}
if err != nil {
panic(err)
}
@ -569,6 +586,7 @@ func (c *cthWrapper) Write(p []byte) (int, error) { return c.h.Write(p) }
func (c *cthWrapper) Sum(b []byte) []byte { return c.h.ConstantTimeSum(b) }
func newConstantTimeHash(h func() hash.Hash) func() hash.Hash {
boring.Unreachable()
return func() hash.Hash {
return &cthWrapper{h().(constantTimeHash)}
}

View file

@ -171,11 +171,11 @@ const (
// hash function associated with the Ed25519 signature scheme.
var directSigning crypto.Hash = 0
// supportedSignatureAlgorithms contains the signature and hash algorithms that
// defaultSupportedSignatureAlgorithms contains the signature and hash algorithms that
// the code advertises as supported in a TLS 1.2+ ClientHello and in a TLS 1.2+
// CertificateRequest. The two fields are merged to match with TLS 1.3.
// Note that in TLS 1.2, the ECDSA algorithms are not constrained to P-256, etc.
var supportedSignatureAlgorithms = []SignatureScheme{
var defaultSupportedSignatureAlgorithms = []SignatureScheme{
PSSWithSHA256,
ECDSAWithP256AndSHA256,
Ed25519,
@ -960,6 +960,9 @@ func (c *Config) time() time.Time {
}
func (c *Config) cipherSuites() []uint16 {
if needFIPS() {
return fipsCipherSuites(c)
}
if c.CipherSuites != nil {
return c.CipherSuites
}
@ -981,6 +984,9 @@ const roleServer = false
func (c *Config) supportedVersions(isClient bool) []uint16 {
versions := make([]uint16, 0, len(supportedVersions))
for _, v := range supportedVersions {
if needFIPS() && (v < fipsMinVersion(c) || v > fipsMaxVersion(c)) {
continue
}
if (c == nil || c.MinVersion == 0) &&
isClient && v < VersionTLS12 {
continue
@ -1021,6 +1027,9 @@ func supportedVersionsFromMax(maxVersion uint16) []uint16 {
var defaultCurvePreferences = []CurveID{X25519, CurveP256, CurveP384, CurveP521}
func (c *Config) curvePreferences() []CurveID {
if needFIPS() {
return fipsCurvePreferences(c)
}
if c == nil || len(c.CurvePreferences) == 0 {
return defaultCurvePreferences
}

View file

@ -0,0 +1,29 @@
// Copyright 2017 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 boringcrypto
// Package fipsonly restricts all TLS configuration to FIPS-approved settings.
//
// The effect is triggered by importing the package anywhere in a program, as in:
//
// import _ "crypto/tls/fipsonly"
//
// This package only exists when using Go compiled with GOEXPERIMENT=boringcrypto.
package fipsonly
// This functionality is provided as a side effect of an import to make
// it trivial to add to an existing program. It requires only a single line
// added to an existing source file, or it can be done by adding a whole
// new source file and not modifying any existing source files.
import (
"crypto/internal/boring/fipstls"
"crypto/internal/boring/sig"
)
func init() {
fipstls.Force()
sig.FIPSOnly()
}

View file

@ -0,0 +1,18 @@
// Copyright 2017 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 boringcrypto
package fipsonly
import (
"crypto/internal/boring/fipstls"
"testing"
)
func Test(t *testing.T) {
if !fipstls.Required() {
t.Fatal("fipstls.Required() = false, must be true")
}
}

View file

@ -34,6 +34,8 @@ type clientHandshakeState struct {
session *ClientSessionState
}
var testingOnlyForceClientHelloSignatureAlgorithms []SignatureScheme
func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) {
config := c.config
if len(config.ServerName) == 0 && !config.InsecureSkipVerify {
@ -117,7 +119,10 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) {
}
if hello.vers >= VersionTLS12 {
hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms
hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
}
if testingOnlyForceClientHelloSignatureAlgorithms != nil {
hello.supportedSignatureAlgorithms = testingOnlyForceClientHelloSignatureAlgorithms
}
var params ecdheParameters
@ -861,6 +866,7 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
DNSName: c.config.ServerName,
Intermediates: x509.NewCertPool(),
}
for _, cert := range certs[1:] {
opts.Intermediates.AddCert(cert)
}

View file

@ -41,6 +41,10 @@ type clientHandshakeStateTLS13 struct {
func (hs *clientHandshakeStateTLS13) handshake() error {
c := hs.c
if needFIPS() {
return errors.New("tls: internal error: TLS 1.3 reached in FIPS mode")
}
// The server must not select TLS 1.3 in a renegotiation. See RFC 8446,
// sections 4.1.2 and 4.1.3.
if c.handshakes > 0 {
@ -470,7 +474,7 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error {
}
// See RFC 8446, Section 4.4.3.
if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms) {
if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms()) {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: certificate used with invalid signature algorithm")
}

View file

@ -148,10 +148,10 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
}
}
if rand.Intn(10) > 5 {
m.supportedSignatureAlgorithms = supportedSignatureAlgorithms
m.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
}
if rand.Intn(10) > 5 {
m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms
m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms()
}
for i := 0; i < rand.Intn(5); i++ {
m.alpnProtocols = append(m.alpnProtocols, randomString(rand.Intn(20)+1, rand))
@ -370,10 +370,10 @@ func (*certificateRequestMsgTLS13) Generate(rand *rand.Rand, size int) reflect.V
m.scts = true
}
if rand.Intn(10) > 5 {
m.supportedSignatureAlgorithms = supportedSignatureAlgorithms
m.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
}
if rand.Intn(10) > 5 {
m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms
m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms()
}
if rand.Intn(10) > 5 {
m.certificateAuthorities = make([][]byte, 3)

View file

@ -541,7 +541,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
}
if c.vers >= VersionTLS12 {
certReq.hasSignatureAlgorithm = true
certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms
certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
}
// An empty list of certificateAuthorities signals to

Some files were not shown because too many files have changed in this diff Show more