Compare commits

..

31 Commits

Author SHA1 Message Date
Russ Cox
8a5ef1501d [dev.typealias] all: merge go1.8.3 into dev.typealias
352996a381 (tag: go1.8.3) [release-branch.go1.8] go1.8.3
bb5055d6f1 [release-branch.go1.8] doc: document go1.8.3
439c0c8be8 [release-branch.go1.8] cmd/compile: don't move spills to loop exits where the spill is dead
e396667ba3 [release-branch.go1.8] cmd/compile: zero ambiguously live variables at VARKILLs
daf6706f37 [release-branch.go1.8] runtime: use pselect6 for usleep on linux/386
958c64bbab [release-branch.go1.8] runtime: use pselect6 for usleep on linux/amd64 and linux/arm
195e20a976 [release-branch.go1.8] cmd/compile: ignore types when considering tuple select for CSE
f55bc1c4eb [release-branch.go1.8] net/http: update bundled http2 for gracefulShutdownCh lock contention slowdown
51f508bb4a [release-branch.go1.8] cmd/compile: fix s390x unsigned comparison constant merging rules
243dee1737 [release-branch.go1.8] cmd/go: if we get a C compiler dwarf2 warning, try without -g
a43c0d2dc8 [release-branch.go1.8] runtime: don't corrupt arena bounds on low mmap
1054085dcf [release-branch.go1.8] cmd/compile: fix store chain in schedule pass
18a13d373a [release-branch.go1.8] runtime: doubly fix "double wakeup" panic
6efa2f22ac [release-branch.go1.8] database/sql: ensure releaseConn is defined before a possible close
fb9770f09b [release-branch.go1.8] runtime: print debug info on "base out of range"
b6a8fc8d8c [release-branch.go1.8] doc: remove mentions of yacc tool
59870f9e19 (tag: go1.8.2) [release-branch.go1.8] go1.8.2
c9688ddb6b [release-branch.go1.8] doc: document go1.8.2 and go1.7.6
38d35f49e7 [release-branch.go1.8] crypto/elliptic: fix carry bug in x86-64 P-256 implementation.

Change-Id: I2aa0eab7a990d24e25809fb13ce6cb031104f474
2017-06-14 13:53:57 -04:00
Russ Cox
1ba29926f3 [dev.typealias] dev.typealias: merge go1.8.1 into dev.typealias
This also includes fixes since Go 1.8rc3.

a4c18f063b [release-branch.go1.8] go1.8.1
8babce23e3 [release-branch.go1.8] doc: document go1.8.1
853d533ed6 [release-branch.go1.8] cmd/go: add test for test -race -i behavior
166f2159d8 [release-branch.go1.8] cmd/go: do not install broken libraries during 'go test -i -race'
95a5b80e6d [release-branch.go1.8] cmd/compile: added special case for reflect header fields to esc
fe79c75268 [release-branch.go1.8] cmd/compile: add missing WBs for reflect.{Slice,String}Header.Data
d7989b784e [release-branch.go1.8] cmd/link: skip TestDWARF when cgo is disabled
056be9f79c [release-branch.go1.8] cmd/link: skip TestDWARF on Plan 9
02240408a1 [release-branch.go1.8] encoding/xml: disable checking of attribute syntax, like Go 1.7
04017ffadf [release-branch.go1.8] reflect: fix out-of-bounds pointers calling no-result method
2d0043014f [release-branch.go1.8] cmd/link: emit a mach-o dwarf segment that dsymutil will accept
3ca0d34fa1 [release-branch.go1.8] cmd/link: make mach-o dwarf segment properly aligned
84192f2734 [release-branch.go1.8] cmd/link: disable mach-o dwarf munging with -w (in addition to -s)
752b8b773d [release-branch.go1.8] cmd/compile: don't crash when slicing non-slice
ff5695d0fd [release-branch.go1.8] runtime: print user stack on other threads during GOTRACBEACK=crash
517a38c630 [release-branch.go1.8] test/fixedbugs: add test for #19403
dc70a5efd1 [release-branch.go1.8] cmd/compile: mark MOVWF/MOVFW clobbering F15 on ARM
77476e81d9 [release-branch.go1.8] cmd/compile,runtime: fix atomic And8 for mipsle
bf71119d54 [release-branch.go1.8] cmd/compile: repaired loop-finder to handle trickier nesting
11a224bc56 [release-branch.go1.8] cmd/compile: add opcode flag hasSideEffects for do-not-remove
3a8841bcaf [release-branch.go1.8] cmd/link: do not pass -s through to host linker on macOS
6c5abcf21a [release-branch.go1.8] text/template: fix handling of empty blocks
43fa04c23c [release-branch.go1.8] image/png: restore Go 1.7 rejection of transparent gray8 images
e35c01b404 [release-branch.go1.8] net, net/http: adjust time-in-past constant even earlier
c955eb1935 [release-branch.go1.8] cmd/compile/internal/ssa: don't schedule values after select
f8ed4539eb [release-branch.go1.8] os/exec: deflake TestStdinCloseRace
d43130743c [release-branch.go1.8] cmd/link: put plt stubs first in Textp on ppc64x
0a5cec792f [release-branch.go1.8] doc: reorganize the contribution guidelines into a guide
8890527476 [release-branch.go1.8] time: make the ParseInLocation test more robust
ea6781bcd0 [release-branch.go1.8] crypto/tls: make Config.Clone also clone the GetClientCertificate field
2327d696c1 [release-branch.go1.8] cmd/compile: do not fold offset into load/store for args on ARM64
ba48d2002e [release-branch.go1.8] cmd/compile: check both syms when folding address into load/store on ARM64
b43fabfb30 [release-branch.go1.8] cmd/compile: add zero-extension before right shift when lowering Lrot on ARM
6a712dfac1 [release-branch.go1.8] cmd/compile: fix merging of s390x conditional moves into branch conditions
865536b197 [release-branch.go1.8] cmd/compile: remove unnecessary type conversions on s390x
bae53daa72 [release-branch.go1.8] runtime: avoid O(n) semaphore list walk in contention profiling
d4ee1f4a40 [release-branch.go1.8] website: mention go1.8 in project page
991ee8f4ac [release-branch.go1.8] doc: fix broken link in go1.8.html
cd6b6202dd [release-branch.go1.8] go1.8
606eb9b0c1 [release-branch.go1.8] doc: document go1.8
bcda91c18d [release-branch.go1.8] runtime: do not call wakep from enlistWorker, to avoid possible deadlock
7d7a0a9d64 [release-branch.go1.8] doc: update Code of Conduct wording and scope
cedc511a6e [release-branch.go1.8] encoding/xml: fix incorrect indirect code in chardata, comment, innerxml fields
ae13ccfd6d [release-branch.go1.8] database/sql: convert test timeouts to explicit waits with checks
7cec9a583d [release-branch.go1.8] reflect: clear ptrToThis in Ptr when allocating result on heap
d84dee069a [release-branch.go1.8] database/sql: ensure driverConns are closed if not returned to pool
f1e44a4b74 [release-branch.go1.8] database/sql: do not exhaust connection pool on conn request timeout
3ade54063e [release-branch.go1.8] database/sql: record the context error in Rows if canceled
0545006bdb [release-branch.go1.8] crypto/x509: check for new tls-ca-bundle.pem last
1363eeba65 [release-branch.go1.8] cmd/go, go/build: better defenses against GOPATH=GOROOT
1edfd64761 [release-branch.go1.8] cmd/compile: do not use "oaslit" for global
6eb0f5440e [release-branch.go1.8] cmd/compile/internal/syntax: avoid follow-up error for incorrect if statement
c543cc353d [release-branch.go1.8] cmd/compile/internal/syntax: make a parser error "1.7 compliant"
f0749fe163 [release-branch.go1.8] cmd/link: use external linking for PIE by default
ba878ac0c8 [release-branch.go1.8] doc: remove inactive members of the CoC working group
6177f6d448 [release-branch.go1.8] vendor/golang.org/x/crypto/curve25519: avoid loss of R15 in -dynlink mode
67cd1fa780 [release-branch.go1.8] cmd/compile: do not fold large offset on ARM64

Change-Id: I907afba886429c4feb36c9895f16046eeab4ad5f
2017-04-10 08:48:35 -04:00
Chris Broadfoot
a4c18f063b [release-branch.go1.8] go1.8.1
Change-Id: Ieb4552841bbf488acdbde805958a1e2ae0bd8aa3
Reviewed-on: https://go-review.googlesource.com/39920
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2017-04-07 16:48:41 +00:00
Russ Cox
0954fdd51e [dev.typealias] set version to go1.8.typealias, including new build tag
This will keep toolchains built on this branch from pretending
to support whatever new things are coming in Go 1.9.

Change-Id: I3e0b623be57c3ad7e01f32abf148d181e3dc1fec
Reviewed-on: https://go-review.googlesource.com/37510
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2017-02-27 15:41:51 +00:00
Russ Cox
3b4fc5d1c6 [dev.typealias] all: merge go1.8 into dev.typealias
This should provide a way for people who want to try
"Go 1.8 with type aliases" to do so.

Removed go1.8 VERSION file as part of merge.

Change-Id: I60d79439677d9980de7b5575e2e6cb9c23be02b6
2017-02-16 19:45:42 -05:00
Robert Griesemer
f8b4123613 [dev.typealias] spec: use term 'embedded field' rather than 'anonymous field'
First steps towards defining type aliases in the spec.
This is a nomenclature clarification, not a language change.

The spec used all three terms 'embedded type', 'anonymous field',
and 'embedded field'. Users where using the terms inconsistently.

The notion of an 'anonymous' field was always misleading since they
always had a de-facto name. With type aliases that name becomes even
more important because we may have different names for the same type.

Use the term 'embedded field' consistently and remove competing
terminology.

For #18130.

Change-Id: I2083bbc85788cab0b2e2cb1ff58b2f979491f001
Reviewed-on: https://go-review.googlesource.com/35108
Reviewed-by: Alan Donovan <adonovan@google.com>
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
2017-01-31 17:12:17 +00:00
Matthew Dempsky
9ecc3ee252 [dev.typealias] cmd/compile: avoid false positive cycles from type aliases
For #18130.
Fixes #18640.

Change-Id: I26cf1d1b78cca6ef207cc4333f30a9011ef347c9
Reviewed-on: https://go-review.googlesource.com/35831
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2017-01-26 18:35:13 +00:00
Russ Cox
49b7af8a30 [dev.typealias] reflect: add test for type aliases
For #18130.

Change-Id: Idd77cb391178c185227cfd779c70fec16351f825
Reviewed-on: https://go-review.googlesource.com/35733
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2017-01-25 18:57:29 +00:00
Russ Cox
9bbb07ddec [dev.typealias] cmd/compile, reflect: fix struct field names for embedded byte, rune
Will also fix type aliases.

Fixes #17766.
For #18130.

Change-Id: I9e1584d47128782152e06abd0a30ef423d5c30d2
Reviewed-on: https://go-review.googlesource.com/35732
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2017-01-25 18:57:20 +00:00
Russ Cox
43c7094386 [dev.typealias] reflect: fix StructOf use of StructField to match StructField docs
The runtime internal structField interprets name=="" as meaning anonymous,
but the exported reflect.StructField has always set Name, even for anonymous
fields, and also set Anonymous=true.

The initial implementation of StructOf confused the internal and public
meanings of the StructField, expecting the runtime representation of
anonymous fields instead of the exported reflect API representation.
It also did not document this fact, so that users had no way to know how
to create an anonymous field.

This CL changes StructOf to use the previously documented interpretation
of reflect.StructField instead of an undocumented one.

The implementation of StructOf also, in some cases, allowed creating
structs with unexported fields (if you knew how to ask) but set the
PkgPath incorrectly on those fields. Rather than try to fix that, this CL
changes StructOf to reject attempts to create unexported fields.
(I think that may be the right design choice, not just a temporary limitation.
In any event, it's not the topic for today's work.)

For #17766.
Fixes #18780.

Change-Id: I585a4e324dc5a90551f49d21ae04d2de9ea04b6c
Reviewed-on: https://go-review.googlesource.com/35731
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2017-01-25 18:56:51 +00:00
Russ Cox
9657e0b077 [dev.typealias] cmd/doc: update for type alias
For #18130.

Change-Id: I06b05a2b45a2aa6764053fc51e05883063572dad
Reviewed-on: https://go-review.googlesource.com/35670
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2017-01-25 17:27:07 +00:00
Matthew Dempsky
de2e5459ae [dev.typealias] cmd/compile: declare methods after resolving receiver type
For #18130.
Fixes #18655.

Change-Id: I58e2f076b9d8273f128cc033bba9edcd06c81567
Reviewed-on: https://go-review.googlesource.com/35575
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2017-01-25 08:04:17 +00:00
Ian Lance Taylor
9259f3073a [dev.typealias] test: match gccgo error messages on alias2.go
For #18130.

Change-Id: I9561ee2b8a9f7b11f0851f281a899f78b9e9703e
Reviewed-on: https://go-review.googlesource.com/35640
Reviewed-by: Robert Griesemer <gri@golang.org>
2017-01-24 22:51:50 +00:00
Matthew Dempsky
5d92916770 [dev.typealias] cmd/compile: change Func.Shortname to *Sym
A Func's Shortname is just an identifier. No need for an entire ONAME
Node.

Change-Id: Ie4d397e8d694c907fdf924ce57bd96bdb4aaabca
Reviewed-on: https://go-review.googlesource.com/35574
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2017-01-24 01:34:14 +00:00
Robert Griesemer
a7c884efc1 [dev.typealias] go/internal/gccgoimporter: support for type aliases
For #18130.

Change-Id: Iac182a6c5bc62633eb02191d9da6166d3b254c4c
Reviewed-on: https://go-review.googlesource.com/35268
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
2017-01-20 05:57:33 +00:00
Robert Griesemer
5802cfd900 [dev.typealias] cmd/compile: export/import test cases for type aliases
Plus a few minor changes.

For #18130.

Change-Id: Ica6503fe9c888cc05c15b46178423f620c087491
Reviewed-on: https://go-review.googlesource.com/35233
Reviewed-by: Alan Donovan <adonovan@google.com>
2017-01-20 05:55:53 +00:00
Robert Griesemer
d7cabd40dd [dev.typealias] go/types: clarified doc string
Also: removed internal TODO and added better comment

Fixes #18644.

Change-Id: I3e3763d3afdad6937173cdd32fc661618fb60820
Reviewed-on: https://go-review.googlesource.com/35245
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
2017-01-17 20:31:39 +00:00
Robert Griesemer
cc2dcce3d7 [dev.typealias] cmd/compile: a few better comments related to alias types
For #18130.

Change-Id: I50bded3af0db673fc92b20c41a86b9cae614acd9
Reviewed-on: https://go-review.googlesource.com/35191
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-01-12 23:25:54 +00:00
Robert Griesemer
5c160b28ba [dev.typealias] cmd/compile: improved error message for cyles involving type aliases
Known issue: #18640 (requires a bit more work, I believe).

For #18130.

Change-Id: I53dc26012070e0c79f63b7c76266732190a83d47
Reviewed-on: https://go-review.googlesource.com/35129
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-01-12 23:25:20 +00:00
Robert Griesemer
b2386dffa1 [dev.typealias] cmd/compile: type-check type alias declarations
Known issues:
- needs many more tests
- duplicate method declarations via type alias names are not detected
- type alias cycle error messages need to be improved
- need to review setup of byte/rune type aliases

For #18130.

Change-Id: Icc2fefad6214e5e56539a9dcb3fe537bf58029f8
Reviewed-on: https://go-review.googlesource.com/35121
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-01-12 21:58:33 +00:00
Robert Griesemer
ac8421f9a5 [dev.typealias] cmd/compile: various minor cleanups
Also: Don't allow type pragmas with type alias declarations.

For #18130.

Change-Id: Ie54ea5fefcd677ad87ced03466bbfd783771e974
Reviewed-on: https://go-review.googlesource.com/35102
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-01-10 22:01:14 +00:00
Robert Griesemer
f011e0c6c3 [dev.typealias] cmd/compile, go/types, go/importer: various alias related fixes
cmd/compile:
- remove crud from prior alias implementation
- better comments in places

go/types:
- fix TypeName.IsAlias predicate
- more tests

go/importer (go/internal/gcimporter15):
- handle "@" format for anonymous fields using aliases
  (currently tested indirectly via x/tools/gcimporter15 tests)

For #18130.

Change-Id: I23a6d4e3a4c2a5c1ae589513da73fde7cad5f386
Reviewed-on: https://go-review.googlesource.com/35101
Reviewed-by: Alan Donovan <adonovan@google.com>
2017-01-10 21:57:59 +00:00
Robert Griesemer
49de5f0351 [dev.typealias] cmd/compile, go/importer: define export format and implement importing of type aliases
This defines the (tentative) export/import format for type aliases.

The compiler doesn't support type aliases yet, so while the code is present
it is guarded with a flag.

The export format for embedded (anonymous) fields now has three modes (mode 3 is new):
1) The original type name and the anonymous field name are the same, and the name is exported:
   we don't need the field name and write "" instead
2) The original type name and the anonymous field name are the same, and the name is not exported:
   we don't need the field name and write "?" instead, indicating that there is package info
3) The original type name and the anonymous field name are different:
   we do need the field name and write "@" followed by the field name (and possible package info)

For #18130.

Change-Id: I790dad826757233fa71396a210f966c6256b75d3
Reviewed-on: https://go-review.googlesource.com/35100
Reviewed-by: Alan Donovan <adonovan@google.com>
2017-01-10 21:33:32 +00:00
Robert Griesemer
5ceec42dc0 [dev.typealias] go/types: export TypeName.IsAlias so clients can use it
For #18130.

Change-Id: I634eaaeaa11e92fc31219d70419fdb4a7aa6e0b4
Reviewed-on: https://go-review.googlesource.com/35099
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-01-10 20:47:12 +00:00
Robert Griesemer
aa1f0681bc [dev.typealias] go/types: improved Object printing
- added internal isAlias predicated and test
- use it for improved Object printing
- when printing a basic type object, don't repeat type name
  (i.e., print "type int" rather than "type int int")
- added another test to testdata/decls4.src

For #18130.

Change-Id: Ice9517c0065a2cc465c6d12f87cd27c01ef801e6
Reviewed-on: https://go-review.googlesource.com/35093
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
2017-01-10 20:30:39 +00:00
Robert Griesemer
c80748e389 [dev.typealias] go/types: remove some more vestiges of prior alias implementation
For #18130.

Change-Id: Ibec8efd158d32746978242910dc71e5ed23e9d91
Reviewed-on: https://go-review.googlesource.com/35092
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
2017-01-10 20:30:21 +00:00
Robert Griesemer
80d8b69e95 [dev.typealias] go/types: implement type aliases
Now a TypeName is just that: a name for a type (not just Named and Basic types
as before). If it happens to be an alias, its type won't be a Named or Basic type,
or it won't have the same name. We can determine this externally.

It may be useful to provide a helper predicate to make that test easily accessible,
but we can get to that if there's an actual need.

The field/method lookup code has become more general an simpler, which is a good sign.
The changes in methodset.go are symmetric to the changes in lookup.go.

Known issue: Cycles created via alias types are not properly detected at the moment.

For #18130.

Change-Id: I90a3206be13116f89c221b5ab4d0f577eec6c78a
Reviewed-on: https://go-review.googlesource.com/35091
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
2017-01-10 20:29:54 +00:00
Russ Cox
a917097b5e [dev.typealias] go/build: add go1.9 build tag
It's earlier than usual but this will help us put the type alias-aware
code into x/tools without breaking clients on go1.6, go1.7,
or (eventually) go1.8.

Change-Id: I43e7ea804922de07d153c7e356cf95e2a11fc592
Reviewed-on: https://go-review.googlesource.com/35050
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2017-01-10 00:56:18 +00:00
Robert Griesemer
3e11940437 [dev.typealias] cmd/compile: recognize type aliases but complain for now (not yet supported)
Added test file.

For #18130.

Change-Id: Ifcfd7cd1acf9dd6a2f4f3d85979d232bb6b8c6b1
Reviewed-on: https://go-review.googlesource.com/34988
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-01-10 00:10:11 +00:00
Robert Griesemer
e0a05c274a [dev.typealias] cmd/gofmt: added test cases for alias type declarations
For #18130.

Change-Id: I95e84130df40db5241e0cc25c36873c3281199ff
Reviewed-on: https://go-review.googlesource.com/34987
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-01-10 00:09:48 +00:00
Robert Griesemer
2e5116bd99 [dev.typealias] go/ast, go/parser, go/printer, go/types: initial type alias support
Parsing and printing support for type aliases complete.
go/types recognizes them an issues an "unimplemented" error for now.

For #18130.

Change-Id: I9f2f7b1971b527276b698d9347bcd094ef0012ee
Reviewed-on: https://go-review.googlesource.com/34986
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-01-09 23:43:12 +00:00
140 changed files with 1377 additions and 5284 deletions

View File

@@ -1,18 +0,0 @@
# dev.boringcrypto branch
We have been working inside Google on a fork of Go that uses
BoringCrypto (the core of [BoringSSL](https://boringssl.googlesource.com/boringssl/)) for various crypto primitives, in
furtherance of some [work related to FIPS 140-2](http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp2964.pdf). We have heard that
some external users of Go would be interested in this code as well, so
I intend to create a new branch dev.boringcrypto that will hold
patches to make Go use BoringCrypto.
Unlike typical dev branches, we do not intend any eventual merge of
this code into the master branch. Instead we intend to maintain in
that branch the latest release plus BoringCrypto patches. In this
sense it is a bit like dev.typealias holding go1.8+type alias patches.
To be clear, we are not making any statements or representations about
the suitability of this code in relation to the FIPS 140-2 standard.
Interested users will have to evaluate for themselves whether the code
is useful for their own purposes.

1
VERSION Normal file
View File

@@ -0,0 +1 @@
go1.8.3.typealias

View File

@@ -57,7 +57,6 @@ pkg crypto/x509, const SHA384WithRSAPSS SignatureAlgorithm
pkg crypto/x509, const SHA512WithRSAPSS = 15
pkg crypto/x509, const SHA512WithRSAPSS SignatureAlgorithm
pkg crypto/x509, type UnknownAuthorityError struct, Cert *Certificate
pkg crypto/x509, type VerifyOptions struct, IsBoring func(*Certificate) bool
pkg database/sql, const LevelDefault = 0
pkg database/sql, const LevelDefault IsolationLevel
pkg database/sql, const LevelLinearizable = 7

View File

@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Version of November 18, 2016",
"Subtitle": "Version of January 31, 2017",
"Path": "/ref/spec"
}-->
@@ -738,7 +738,7 @@ The method set of any other type <code>T</code> consists of all
The method set of the corresponding <a href="#Pointer_types">pointer type</a> <code>*T</code>
is the set of all methods declared with receiver <code>*T</code> or <code>T</code>
(that is, it also contains the method set of <code>T</code>).
Further rules apply to structs containing anonymous fields, as described
Further rules apply to structs containing embedded fields, as described
in the section on <a href="#Struct_types">struct types</a>.
Any other type has an empty method set.
In a method set, each method must have a
@@ -947,16 +947,16 @@ Moreover, the inner slices must be initialized individually.
<p>
A struct is a sequence of named elements, called fields, each of which has a
name and a type. Field names may be specified explicitly (IdentifierList) or
implicitly (AnonymousField).
implicitly (EmbeddedField).
Within a struct, non-<a href="#Blank_identifier">blank</a> field names must
be <a href="#Uniqueness_of_identifiers">unique</a>.
</p>
<pre class="ebnf">
StructType = "struct" "{" { FieldDecl ";" } "}" .
FieldDecl = (IdentifierList Type | AnonymousField) [ Tag ] .
AnonymousField = [ "*" ] TypeName .
Tag = string_lit .
StructType = "struct" "{" { FieldDecl ";" } "}" .
FieldDecl = (IdentifierList Type | EmbeddedField) [ Tag ] .
EmbeddedField = [ "*" ] TypeName .
Tag = string_lit .
</pre>
<pre>
@@ -974,16 +974,15 @@ struct {
</pre>
<p>
A field declared with a type but no explicit field name is an <i>anonymous field</i>,
also called an <i>embedded</i> field or an embedding of the type in the struct.
An embedded type must be specified as
A field declared with a type but no explicit field name is called an <i>embedded field</i>.
An embedded field must be specified as
a type name <code>T</code> or as a pointer to a non-interface type name <code>*T</code>,
and <code>T</code> itself may not be
a pointer type. The unqualified type name acts as the field name.
</p>
<pre>
// A struct with four anonymous fields of type T1, *T2, P.T3 and *P.T4
// A struct with four embedded fields of types T1, *T2, P.T3 and *P.T4
struct {
T1 // field name is T1
*T2 // field name is T2
@@ -1000,15 +999,15 @@ in a struct type:
<pre>
struct {
T // conflicts with anonymous field *T and *P.T
*T // conflicts with anonymous field T and *P.T
*P.T // conflicts with anonymous field T and *T
T // conflicts with embedded field *T and *P.T
*T // conflicts with embedded field T and *P.T
*P.T // conflicts with embedded field T and *T
}
</pre>
<p>
A field or <a href="#Method_declarations">method</a> <code>f</code> of an
anonymous field in a struct <code>x</code> is called <i>promoted</i> if
embedded field in a struct <code>x</code> is called <i>promoted</i> if
<code>x.f</code> is a legal <a href="#Selectors">selector</a> that denotes
that field or method <code>f</code>.
</p>
@@ -1025,7 +1024,7 @@ promoted methods are included in the method set of the struct as follows:
</p>
<ul>
<li>
If <code>S</code> contains an anonymous field <code>T</code>,
If <code>S</code> contains an embedded field <code>T</code>,
the <a href="#Method_sets">method sets</a> of <code>S</code>
and <code>*S</code> both include promoted methods with receiver
<code>T</code>. The method set of <code>*S</code> also
@@ -1033,7 +1032,7 @@ promoted methods are included in the method set of the struct as follows:
</li>
<li>
If <code>S</code> contains an anonymous field <code>*T</code>,
If <code>S</code> contains an embedded field <code>*T</code>,
the method sets of <code>S</code> and <code>*S</code> both
include promoted methods with receiver <code>T</code> or
<code>*T</code>.
@@ -1434,8 +1433,8 @@ literal structure and corresponding components have identical types. In detail:
<li>Two struct types are identical if they have the same sequence of fields,
and if corresponding fields have the same names, and identical types,
and identical tags.
Two anonymous fields are considered to have the same name. Lower-case field
names from different packages are always different.</li>
<a href="#Exported_identifiers">Non-exported</a> field names from different
packages are always different.</li>
<li>Two pointer types are identical if they have identical base types.</li>
@@ -1445,8 +1444,9 @@ literal structure and corresponding components have identical types. In detail:
Parameter and result names are not required to match.</li>
<li>Two interface types are identical if they have the same set of methods
with the same names and identical function types. Lower-case method names from
different packages are always different. The order of the methods is irrelevant.</li>
with the same names and identical function types.
<a href="#Exported_identifiers">Non-exported</a> method names from different
packages are always different. The order of the methods is irrelevant.</li>
<li>Two map types are identical if they have identical key and value types.</li>
@@ -1891,7 +1891,7 @@ type NewMutex Mutex
type PtrMutex *Mutex
// The method set of *PrintableMutex contains the methods
// Lock and Unlock bound to its anonymous field Mutex.
// Lock and Unlock bound to its embedded field Mutex.
type PrintableMutex struct {
Mutex
}
@@ -2492,13 +2492,13 @@ If <code>x</code> is a package name, see the section on
A selector <code>f</code> may denote a field or method <code>f</code> of
a type <code>T</code>, or it may refer
to a field or method <code>f</code> of a nested
<a href="#Struct_types">anonymous field</a> of <code>T</code>.
The number of anonymous fields traversed
<a href="#Struct_types">embedded field</a> of <code>T</code>.
The number of embedded fields traversed
to reach <code>f</code> is called its <i>depth</i> in <code>T</code>.
The depth of a field or method <code>f</code>
declared in <code>T</code> is zero.
The depth of a field or method <code>f</code> declared in
an anonymous field <code>A</code> in <code>T</code> is the
an embedded field <code>A</code> in <code>T</code> is the
depth of <code>f</code> in <code>A</code> plus one.
</p>

View File

@@ -143,7 +143,7 @@ packaged Go distribution.
<p>
To build a bootstrap tool chain from source, use
either the git branch <code>release-branch.go1.4</code> or
<a href="https://storage.googleapis.com/golang/go1.4-bootstrap-20170531.tar.gz">go1.4-bootstrap-20170531.tar.gz</a>,
<a href="https://storage.googleapis.com/golang/go1.4-bootstrap-20161024.tar.gz">go1.4-bootstrap-20161024.tar.gz</a>,
which contains the Go 1.4 source code plus accumulated fixes
to keep the tools running on newer operating systems.
(Go 1.4 was the last distribution in which the tool chain was written in C.)

View File

@@ -1 +0,0 @@
4

View File

@@ -74,7 +74,13 @@ func widstruct(errtype *Type, t *Type, o int64, flag int) int64 {
lastzero = o
}
o += w
if o >= Thearch.MAXWIDTH {
maxwidth := Thearch.MAXWIDTH
// On 32-bit systems, reflect tables impose an additional constraint
// that each field start offset must fit in 31 bits.
if maxwidth < 1<<32 {
maxwidth = 1<<31 - 1
}
if o >= maxwidth {
yyerror("type %L too large", errtype)
o = 8 // small but nonzero
}

View File

@@ -140,11 +140,12 @@ const debugFormat = false // default: false
const forceObjFileStability = true
// Current export format version. Increase with each format change.
// 3: added aliasTag and export of aliases
// 2: removed unused bool in ODCL export
// 4: type name objects support type aliases, uses aliasTag
// 3: Go1.8 encoding (same as version 2, aliasTag defined but never used)
// 2: removed unused bool in ODCL export (compiler only)
// 1: header format change (more regular), export package for _ struct fields
// 0: Go1.7 encoding
const exportVersion = 3
const exportVersion = 4
// exportInlined enables the export of inlined function bodies and related
// dependencies. The compiler should work w/o any loss of functionality with
@@ -351,8 +352,8 @@ func export(out *bufio.Writer, trace bool) int {
p.tracef("\n")
}
if sym.Flags&SymAlias != 0 {
Fatalf("exporter: unexpected alias %v in inlined function body", sym)
if sym.isAlias() {
Fatalf("exporter: unexpected type alias %v in inlined function body", sym)
}
p.obj(sym)
@@ -446,30 +447,6 @@ func unidealType(typ *Type, val Val) *Type {
}
func (p *exporter) obj(sym *Sym) {
if sym.Flags&SymAlias != 0 {
p.tag(aliasTag)
p.pos(nil) // TODO(gri) fix position information
// Aliases can only be exported from the package that
// declares them (aliases to aliases are resolved to the
// original object, and so are uses of aliases in inlined
// exported function bodies). Thus, we only need the alias
// name without package qualification.
if sym.Pkg != localpkg {
Fatalf("exporter: export of non-local alias: %v", sym)
}
p.string(sym.Name)
orig := sym.Def.Sym
if orig.Flags&SymAlias != 0 {
Fatalf("exporter: original object %v marked as alias", sym)
}
p.qualifiedName(orig)
return
}
if sym != sym.Def.Sym {
Fatalf("exporter: exported object %v is not original %v", sym, sym.Def.Sym)
}
// Exported objects may be from different packages because they
// may be re-exported via an exported alias or as dependencies in
// exported inlined function bodies. Thus, exported object names
@@ -509,7 +486,13 @@ func (p *exporter) obj(sym *Sym) {
Fatalf("exporter: export of incomplete type %v", sym)
}
p.tag(typeTag)
if sym.isAlias() {
p.tag(aliasTag)
p.pos(n)
p.qualifiedName(sym)
} else {
p.tag(typeTag)
}
p.typ(t)
case ONAME:
@@ -868,19 +851,29 @@ func (p *exporter) methodList(t *Type) {
func (p *exporter) method(m *Field) {
p.pos(m.Nname)
p.fieldName(m)
p.methodName(m.Sym)
p.paramList(m.Type.Params(), false)
p.paramList(m.Type.Results(), false)
}
// fieldName is like qualifiedName but it doesn't record the package for exported names.
func (p *exporter) fieldName(t *Field) {
name := t.Sym.Name
if t.Embedded != 0 {
name = "" // anonymous field
if bname := basetypeName(t.Type); bname != "" && !exportname(bname) {
// anonymous field with unexported base type name
name = "?" // unexported name to force export of package
// anonymous field - we distinguish between 3 cases:
// 1) field name matches base type name and is exported
// 2) field name matches base type name and is not exported
// 3) field name doesn't match base type name (alias name)
bname := basetypeName(t.Type)
if name == bname {
if exportname(name) {
name = "" // 1) we don't need to know the field name or package
} else {
name = "?" // 2) use unexported name "?" to force package export
}
} else {
// 3) indicate alias and export name as is
// (this requires an extra "@" but this is a rare case)
p.string("@")
}
}
p.string(name)
@@ -889,16 +882,23 @@ func (p *exporter) fieldName(t *Field) {
}
}
// methodName is like qualifiedName but it doesn't record the package for exported names.
func (p *exporter) methodName(sym *Sym) {
p.string(sym.Name)
if !exportname(sym.Name) {
p.pkg(sym.Pkg)
}
}
func basetypeName(t *Type) string {
s := t.Sym
if s == nil && t.IsPtr() {
s = t.Elem().Sym // deref
}
// s should exist, but be conservative
if s != nil {
return s.Name
}
return ""
return "" // unnamed type
}
func (p *exporter) paramList(params *Type, numbered bool) {
@@ -1797,7 +1797,7 @@ const (
nilTag
unknownTag // not used by gc (only appears in packages with errors)
// Aliases
// Type aliases
aliasTag
)
@@ -1835,7 +1835,7 @@ var tagString = [...]string{
-nilTag: "nil",
-unknownTag: "unknown",
// Aliases
// Type aliases
-aliasTag: "alias",
}
@@ -1889,7 +1889,7 @@ func predeclared() []*Type {
Types[TCOMPLEX128],
Types[TSTRING],
// aliases
// basic type aliases
bytetype,
runetype,

View File

@@ -86,10 +86,10 @@ func Import(in *bufio.Reader) {
// read version specific flags - extend as necessary
switch p.version {
// case 4:
// case 5:
// ...
// fallthrough
case 3, 2, 1:
case 4, 3, 2, 1:
p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
p.trackAllTypes = p.bool()
p.posInfoFormat = p.bool()
@@ -317,6 +317,12 @@ func (p *importer) obj(tag int) {
val := p.value(typ)
importconst(sym, idealType(typ), nodlit(val))
case aliasTag:
p.pos()
sym := p.qualifiedName()
typ := p.typ()
importalias(sym, typ)
case typeTag:
p.typ()
@@ -356,17 +362,6 @@ func (p *importer) obj(tag int) {
}
}
case aliasTag:
p.pos()
alias := importpkg.Lookup(p.string())
orig := p.qualifiedName()
// Although the protocol allows the alias to precede the original,
// this never happens in files produced by gc.
alias.Flags |= SymAlias
alias.Def = orig.Def
importsym(alias, orig.Def.Op)
default:
formatErrorf("unexpected object (tag = %d)", tag)
}
@@ -473,14 +468,7 @@ func (p *importer) typ() *Type {
result := p.paramList()
nointerface := p.bool()
base := recv[0].Type
star := false
if base.IsPtr() {
base = base.Elem()
star = true
}
n := methodname0(sym, star, base.Sym)
n := newfuncname(methodname(sym, recv[0].Type))
n.Type = functypefield(recv[0], params, result)
checkwidth(n.Type)
addmethod(sym, n.Type, false, nointerface)
@@ -583,19 +571,22 @@ func (p *importer) fieldList() (fields []*Field) {
func (p *importer) field() *Field {
p.pos()
sym := p.fieldName()
sym, alias := p.fieldName()
typ := p.typ()
note := p.string()
f := newField()
if sym.Name == "" {
// anonymous field - typ must be T or *T and T must be a type name
// anonymous field: typ must be T or *T and T must be a type name
s := typ.Sym
if s == nil && typ.IsPtr() {
s = typ.Elem().Sym // deref
}
sym = sym.Pkg.Lookup(s.Name)
f.Embedded = 1
} else if alias {
// anonymous field: we have an explicit name because it's a type alias
f.Embedded = 1
}
f.Sym = sym
@@ -618,7 +609,7 @@ func (p *importer) methodList() (methods []*Field) {
func (p *importer) method() *Field {
p.pos()
sym := p.fieldName()
sym := p.methodName()
params := p.paramList()
result := p.paramList()
@@ -629,18 +620,44 @@ func (p *importer) method() *Field {
return f
}
func (p *importer) fieldName() *Sym {
func (p *importer) fieldName() (*Sym, bool) {
name := p.string()
if p.version == 0 && name == "_" {
// version 0 didn't export a package for _ fields
// version 0 didn't export a package for _ field names
// but used the builtin package instead
return builtinpkg.Lookup(name), false
}
pkg := localpkg
alias := false
switch name {
case "":
// 1) field name matches base type name and is exported: nothing to do
case "?":
// 2) field name matches base type name and is not exported: need package
name = ""
pkg = p.pkg()
case "@":
// 3) field name doesn't match base type name (alias name): need name and possibly package
name = p.string()
alias = true
fallthrough
default:
if !exportname(name) {
pkg = p.pkg()
}
}
return pkg.Lookup(name), alias
}
func (p *importer) methodName() *Sym {
name := p.string()
if p.version == 0 && name == "_" {
// version 0 didn't export a package for _ method names
// but used the builtin package instead
return builtinpkg.Lookup(name)
}
pkg := localpkg
if name != "" && !exportname(name) {
if name == "?" {
name = ""
}
if !exportname(name) {
pkg = p.pkg()
}
return pkg.Lookup(name)

View File

@@ -519,10 +519,6 @@ func funchdr(n *Node) {
Fatalf("funchdr: dclcontext = %d", dclcontext)
}
if Ctxt.Flag_dynlink && importpkg == nil && n.Func.Nname != nil {
makefuncsym(n.Func.Nname.Sym)
}
dclcontext = PAUTO
funcstart(n)
@@ -695,10 +691,20 @@ func typedcl0(s *Sym) *Node {
// node n, which was returned by typedcl0
// is being declared to have uncompiled type t.
// return the ODCLTYPE node to use.
func typedcl1(n *Node, t *Node, local bool) *Node {
n.Name.Param.Ntype = t
n.Local = local
// returns the ODCLTYPE node to use.
func typedcl1(n *Node, t *Node, pragma Pragma, alias bool) *Node {
if pragma != 0 && alias {
yyerror("cannot specify directive with type alias")
pragma = 0
}
n.Local = true
p := n.Name.Param
p.Ntype = t
p.Pragma = pragma
p.Alias = alias
return nod(ODCLTYPE, n, nil)
}
@@ -1153,19 +1159,19 @@ bad:
return nil
}
func methodname(n *Node, t *Node) *Node {
// methodname is a misnomer because this now returns a Sym, rather
// than an ONAME.
// TODO(mdempsky): Reconcile with methodsym.
func methodname(s *Sym, recv *Type) *Sym {
star := false
if t.Op == OIND {
if recv.IsPtr() {
star = true
t = t.Left
recv = recv.Elem()
}
return methodname0(n.Sym, star, t.Sym)
}
func methodname0(s *Sym, star bool, tsym *Sym) *Node {
tsym := recv.Sym
if tsym == nil || isblanksym(s) {
return newfuncname(s)
return s
}
var p string
@@ -1181,14 +1187,13 @@ func methodname0(s *Sym, star bool, tsym *Sym) *Node {
s = Pkglookup(p, tsym.Pkg)
}
return newfuncname(s)
return s
}
// Add a method, declared as a function.
// - msym is the method symbol
// - t is function type (with receiver)
func addmethod(msym *Sym, t *Type, local, nointerface bool) {
// get field sym
if msym == nil {
Fatalf("no method symbol")
}
@@ -1309,7 +1314,7 @@ func funcsym(s *Sym) *Sym {
s1 := Pkglookup(s.Name+"·f", s.Pkg)
if !Ctxt.Flag_dynlink && s1.Def == nil {
s1.Def = newfuncname(s1)
s1.Def.Func.Shortname = newname(s)
s1.Def.Func.Shortname = s
funcsyms = append(funcsyms, s1.Def)
}
s.Fsym = s1
@@ -1326,8 +1331,11 @@ func makefuncsym(s *Sym) {
return
}
s1 := funcsym(s)
if s1.Def != nil {
return
}
s1.Def = newfuncname(s1)
s1.Def.Func.Shortname = newname(s)
s1.Def.Func.Shortname = s
funcsyms = append(funcsyms, s1.Def)
}

View File

@@ -45,8 +45,8 @@ func exportsym(n *Node) {
fmt.Printf("export symbol %v\n", n.Sym)
}
// Ensure original object is on exportlist before aliases.
if n.Sym.Flags&SymAlias != 0 {
// Ensure original types are on exportlist before type aliases.
if n.Sym.isAlias() {
exportlist = append(exportlist, n.Sym.Def)
}
@@ -83,7 +83,7 @@ func autoexport(n *Node, ctxt Class) {
if (ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN {
return
}
if n.Name.Param != nil && n.Name.Param.Ntype != nil && n.Name.Param.Ntype.Op == OTFUNC && n.Name.Param.Ntype.Left != nil { // method
if n.Type != nil && n.Type.IsKind(TFUNC) && n.Type.Recv() != nil { // method
return
}
@@ -348,6 +348,27 @@ func importvar(s *Sym, t *Type) {
}
}
// importalias declares symbol s as an imported type alias with type t.
func importalias(s *Sym, t *Type) {
importsym(s, OTYPE)
if s.Def != nil && s.Def.Op == OTYPE {
if eqtype(t, s.Def.Type) {
return
}
yyerror("inconsistent definition for type alias %v during import\n\t%v (in %q)\n\t%v (in %q)", s, s.Def.Type, s.Importdef.Path, t, importpkg.Path)
}
n := newname(s)
n.Op = OTYPE
s.Importdef = importpkg
n.Type = t
declare(n, PEXTERN)
if Debug['E'] != 0 {
fmt.Printf("import type %v = %L\n", s, t)
}
}
func dumpasmhdr() {
b, err := bio.Create(asmhdr)
if err != nil {

View File

@@ -1077,6 +1077,7 @@ var opprec = []int{
OSEND: 3,
OANDAND: 2,
OOROR: 1,
// Statements handled by stmtfmt
OAS: -1,
OAS2: -1,
@@ -1104,7 +1105,8 @@ var opprec = []int{
OSWITCH: -1,
OXCASE: -1,
OXFALL: -1,
OEND: 0,
OEND: 0,
}
func (n *Node) exprfmt(s fmt.State, prec int) {

View File

@@ -63,9 +63,12 @@ const (
SymSiggen
SymAsm
SymAlgGen
SymAlias // alias, original is Sym.Def.Sym
)
func (sym *Sym) isAlias() bool {
return sym.Def != nil && sym.Def.Sym != sym
}
// The Class of a variable/function describes the "storage class"
// of a variable or function. During parsing, storage classes are
// called declaration contexts.
@@ -87,7 +90,7 @@ const (
// of the compilers arrays.
//
// typedef struct
// { // must not move anything
// { // must not move anything
// uchar array[8]; // pointer to data
// uchar nel[4]; // number of elements
// uchar cap[4]; // allocated number of elements
@@ -104,7 +107,7 @@ var sizeof_Array int // runtime sizeof(Array)
// of the compilers strings.
//
// typedef struct
// { // must not move anything
// { // must not move anything
// uchar array[8]; // pointer to data
// uchar nel[4]; // number of elements
// } String;

View File

@@ -340,13 +340,16 @@ func Main() {
// Phase 1: const, type, and names and types of funcs.
// This will gather all the information about types
// and methods but doesn't depend on any of it.
// We also defer type alias declarations until phase 2
// to avoid cycles like #18640.
defercheckwidth()
// Don't use range--typecheck can add closures to xtop.
timings.Start("fe", "typecheck", "top1")
for i := 0; i < len(xtop); i++ {
if xtop[i].Op != ODCL && xtop[i].Op != OAS && xtop[i].Op != OAS2 {
xtop[i] = typecheck(xtop[i], Etop)
n := xtop[i]
if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) {
xtop[i] = typecheck(n, Etop)
}
}
@@ -356,8 +359,9 @@ func Main() {
// Don't use range--typecheck can add closures to xtop.
timings.Start("fe", "typecheck", "top2")
for i := 0; i < len(xtop); i++ {
if xtop[i].Op == ODCL || xtop[i].Op == OAS || xtop[i].Op == OAS2 {
xtop[i] = typecheck(xtop[i], Etop)
n := xtop[i]
if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias {
xtop[i] = typecheck(n, Etop)
}
}
resumecheckwidth()
@@ -367,8 +371,9 @@ func Main() {
timings.Start("fe", "typecheck", "func")
var fcount int64
for i := 0; i < len(xtop); i++ {
if xtop[i].Op == ODCLFUNC || xtop[i].Op == OCLOSURE {
Curfn = xtop[i]
n := xtop[i]
if op := n.Op; op == ODCLFUNC || op == OCLOSURE {
Curfn = n
decldepth = 1
saveerrors()
typecheckslice(Curfn.Nbody.Slice(), Etop)
@@ -460,8 +465,9 @@ func Main() {
timings.Start("be", "compilefuncs")
fcount = 0
for i := 0; i < len(xtop); i++ {
if xtop[i].Op == ODCLFUNC {
funccompile(xtop[i])
n := xtop[i]
if n.Op == ODCLFUNC {
funccompile(n)
fcount++
}
}
@@ -924,7 +930,7 @@ func mkpackage(pkgname string) {
continue
}
if s.Def.Sym != s && s.Flags&SymAlias == 0 {
if s.isAlias() {
// throw away top-level name left over
// from previous import . "x"
if s.Def.Name != nil && s.Def.Name.Pack != nil && !s.Def.Name.Pack.Used && nsyntaxerrors == 0 {

View File

@@ -154,11 +154,7 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) {
func (p *noder) varDecl(decl *syntax.VarDecl) []*Node {
names := p.declNames(decl.NameList)
var typ *Node
if decl.Type != nil {
typ = p.typeExpr(decl.Type)
}
typ := p.typeExprOrNil(decl.Type)
var exprs []*Node
if decl.Values != nil {
@@ -171,11 +167,7 @@ func (p *noder) varDecl(decl *syntax.VarDecl) []*Node {
func (p *noder) constDecl(decl *syntax.ConstDecl) []*Node {
names := p.declNames(decl.NameList)
var typ *Node
if decl.Type != nil {
typ = p.typeExpr(decl.Type)
}
typ := p.typeExprOrNil(decl.Type)
var exprs []*Node
if decl.Values != nil {
@@ -187,14 +179,11 @@ func (p *noder) constDecl(decl *syntax.ConstDecl) []*Node {
func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
name := typedcl0(p.name(decl.Name))
name.Name.Param.Pragma = Pragma(decl.Pragma)
var typ *Node
if decl.Type != nil {
typ = p.typeExpr(decl.Type)
}
// decl.Type may be nil but in that case we got a syntax error during parsing
typ := p.typeExprOrNil(decl.Type)
return typedcl1(name, typ, true)
return typedcl1(name, typ, Pragma(decl.Pragma), decl.Alias)
}
func (p *noder) declNames(names []*syntax.Name) []*Node {
@@ -259,19 +248,19 @@ func (p *noder) funcHeader(fun *syntax.FuncDecl) *Node {
yyerror("func main must have no arguments and no return values")
}
}
f.Func.Nname = newfuncname(name)
} else {
// Receiver MethodName Signature
f.Func.Shortname = newfuncname(name)
f.Func.Nname = methodname(f.Func.Shortname, t.Left.Right)
f.Func.Shortname = name
name = nblank.Sym // filled in by typecheckfunc
}
f.Func.Nname = newfuncname(name)
f.Func.Nname.Name.Defn = f
f.Func.Nname.Name.Param.Ntype = t // TODO: check if nname already has an ntype
declare(f.Func.Nname, PFUNC)
if fun.Recv == nil {
declare(f.Func.Nname, PFUNC)
}
funchdr(f)
return f
}
@@ -467,6 +456,13 @@ func (p *noder) typeExpr(typ syntax.Expr) *Node {
return p.expr(typ)
}
func (p *noder) typeExprOrNil(typ syntax.Expr) *Node {
if typ != nil {
return p.expr(typ)
}
return nil
}
func (p *noder) chanDir(dir syntax.ChanDir) ChanDir {
switch dir {
case 0:

View File

@@ -213,7 +213,7 @@ func dumpglobls() {
}
for _, n := range funcsyms {
dsymptr(n.Sym, 0, n.Sym.Def.Func.Shortname.Sym, 0)
dsymptr(n.Sym, 0, n.Sym.Def.Func.Shortname, 0)
ggloblsym(n.Sym, int32(Widthptr), obj.DUPOK|obj.RODATA)
}

View File

@@ -511,7 +511,7 @@ func isExportedField(ft *Field) (bool, *Pkg) {
// dnameField dumps a reflect.name for a struct field.
func dnameField(s *Sym, ot int, spkg *Pkg, ft *Field) int {
var name string
if ft.Sym != nil && ft.Embedded == 0 {
if ft.Sym != nil {
name = ft.Sym.Name
}
isExported, fpkg := isExportedField(ft)
@@ -1312,32 +1312,9 @@ ok:
// ../../../../runtime/type.go:/structType
// for security, only the exported fields.
case TSTRUCT:
// omitFieldForAwfulBoringCryptoKludge reports whether
// the field t should be omitted from the reflect data.
// In the crypto/... packages we omit an unexported field
// named "boring", to keep from breaking client code that
// expects rsa.PublicKey etc to have only public fields.
// As the name suggests, this is an awful kludge, but it is
// limited to the dev.boringcrypto branch and avoids
// much more invasive effects elsewhere.
omitFieldForAwfulBoringCryptoKludge := func(t *Field) bool {
if t.Sym == nil || t.Sym.Name != "boring" || t.Sym.Pkg == nil {
return false
}
path := t.Sym.Pkg.Path
if t.Sym.Pkg == localpkg {
path = myimportpath
}
return strings.HasPrefix(path, "crypto/")
}
n := 0
for _, t1 := range t.Fields().Slice() {
if omitFieldForAwfulBoringCryptoKludge(t1) {
continue
}
dtypesym(t1.Type)
n++
}
@@ -1365,13 +1342,17 @@ ok:
ot = dextratype(s, ot, t, dataAdd)
for _, f := range t.Fields().Slice() {
if omitFieldForAwfulBoringCryptoKludge(f) {
continue
}
// ../../../../runtime/type.go:/structField
ot = dnameField(s, ot, pkg, f)
ot = dsymptr(s, ot, dtypesym(f.Type), 0)
ot = duintptr(s, ot, uint64(f.Offset))
offsetAnon := uint64(f.Offset) << 1
if offsetAnon>>1 != uint64(f.Offset) {
Fatalf("%v: bad field offset for %s", t, f.Sym.Name)
}
if f.Embedded != 0 {
offsetAnon |= 1
}
ot = duintptr(s, ot, offsetAnon)
}
}

View File

@@ -27,7 +27,7 @@ type Node struct {
// func
Func *Func
// ONAME
// ONAME, OTYPE, OPACK, OLABEL, some OLITERAL
Name *Name
Sym *Sym // various
@@ -59,8 +59,8 @@ type Node struct {
Noescape bool // func arguments do not escape; TODO(rsc): move Noescape to Func struct (see CL 7360)
Walkdef uint8 // tracks state during typecheckdef; 2 == loop detected
Typecheck uint8 // tracks state during typechecking; 2 == loop detected
Local bool
IsStatic bool // whether this Node will be converted to purely static data
Local bool // type created in this file (see also Type.Local); TODO(gri): move this into flags
IsStatic bool // whether this Node will be converted to purely static data
Initorder uint8
Used bool // for variable/label declared and not used error
Isddd bool // is the argument variadic
@@ -180,14 +180,14 @@ func (n *Node) SetIota(x int64) {
n.Xoffset = x
}
// Name holds Node fields used only by named nodes (ONAME, OPACK, OLABEL, some OLITERAL).
// Name holds Node fields used only by named nodes (ONAME, OTYPE, OPACK, OLABEL, some OLITERAL).
type Name struct {
Pack *Node // real package for import . names
Pkg *Pkg // pkg for OPACK nodes
Heapaddr *Node // temp holding heap address of param (could move to Param?)
Defn *Node // initializing assignment
Curfn *Node // function for local variables
Param *Param // additional fields for ONAME
Param *Param // additional fields for ONAME, OTYPE
Decldepth int32 // declaration loop depth, increased for every loop or label
Vargen int32 // unique name for ONAME within a function. Function outputs are numbered starting at one.
Funcdepth int32
@@ -280,15 +280,16 @@ type Param struct {
Innermost *Node
Outer *Node
// OTYPE pragmas
// OTYPE
//
// TODO: Should Func pragmas also be stored on the Name?
Pragma Pragma
Alias bool // node is alias for Ntype (only used when type-checking ODCLTYPE)
}
// Func holds Node fields used only with function-like nodes.
type Func struct {
Shortname *Node
Shortname *Sym
Enter Nodes // for example, allocate and initialize memory for escaping parameters
Exit Nodes
Cvars Nodes // closure params
@@ -382,7 +383,7 @@ const (
ODCLFUNC // func f() or func (r) f()
ODCLFIELD // struct field, interface field, or func/method argument/return value.
ODCLCONST // const pi = 3.14
ODCLTYPE // type Int int
ODCLTYPE // type Int int or type Int = int
ODELETE // delete(Left, Right)
ODOT // Left.Sym (Left is of struct type)

View File

@@ -96,16 +96,16 @@ func typekind(t *Type) string {
return fmt.Sprintf("etype=%d", et)
}
// sprint_depchain prints a dependency chain of nodes into fmt.
// sprint_depchain prints a dependency chain of nodes into trace.
// It is used by typecheck in the case of OLITERAL nodes
// to print constant definition loops.
func sprint_depchain(fmt_ *string, stack []*Node, cur *Node, first *Node) {
func sprint_depchain(trace *string, stack []*Node, cur *Node, first *Node) {
for i := len(stack) - 1; i >= 0; i-- {
if n := stack[i]; n.Op == cur.Op {
if n != first {
sprint_depchain(fmt_, stack[:i], n, first)
sprint_depchain(trace, stack[:i], n, first)
}
*fmt_ += fmt.Sprintf("\n\t%v: %v uses %v", n.Line(), n, cur)
*trace += fmt.Sprintf("\n\t%v: %v uses %v", n.Line(), n, cur)
return
}
}
@@ -152,7 +152,6 @@ func typecheck(n *Node, top int) *Node {
if n.Typecheck == 2 {
// Typechecking loop. Trying printing a meaningful message,
// otherwise a stack trace of typechecking.
var fmt_ string
switch n.Op {
// We can already diagnose variables used as types.
case ONAME:
@@ -160,22 +159,30 @@ func typecheck(n *Node, top int) *Node {
yyerror("%v is not a type", n)
}
case OTYPE:
if top&Etype == Etype {
var trace string
sprint_depchain(&trace, typecheck_tcstack, n, n)
yyerrorl(n.Lineno, "invalid recursive type alias %v%s", n, trace)
}
case OLITERAL:
if top&(Erv|Etype) == Etype {
yyerror("%v is not a type", n)
break
}
sprint_depchain(&fmt_, typecheck_tcstack, n, n)
yyerrorl(n.Lineno, "constant definition loop%s", fmt_)
var trace string
sprint_depchain(&trace, typecheck_tcstack, n, n)
yyerrorl(n.Lineno, "constant definition loop%s", trace)
}
if nsavederrors+nerrors == 0 {
fmt_ = ""
var trace string
for i := len(typecheck_tcstack) - 1; i >= 0; i-- {
x := typecheck_tcstack[i]
fmt_ += fmt.Sprintf("\n\t%v %v", x.Line(), x)
trace += fmt.Sprintf("\n\t%v %v", x.Line(), x)
}
yyerror("typechecking loop involving %v%s", n, fmt_)
yyerror("typechecking loop involving %v%s", n, trace)
}
lineno = lno
@@ -3428,7 +3435,14 @@ func typecheckfunc(n *Node) {
t.SetNname(n.Func.Nname)
rcvr := t.Recv()
if rcvr != nil && n.Func.Shortname != nil {
addmethod(n.Func.Shortname.Sym, t, true, n.Func.Pragma&Nointerface != 0)
n.Func.Nname.Sym = methodname(n.Func.Shortname, rcvr.Type)
declare(n.Func.Nname, PFUNC)
addmethod(n.Func.Shortname, t, true, n.Func.Pragma&Nointerface != 0)
}
if Ctxt.Flag_dynlink && importpkg == nil && n.Func.Nname != nil {
makefuncsym(n.Func.Nname.Sym)
}
}
@@ -3577,8 +3591,6 @@ func typecheckdeftype(n *Node) {
// copy new type and clear fields
// that don't come along.
// anything zeroed here must be zeroed in
// typedcl2 too.
copytype(n, t)
ret:
@@ -3757,12 +3769,29 @@ func typecheckdef(n *Node) *Node {
n.Name.Defn = typecheck(n.Name.Defn, Etop) // fills in n->type
case OTYPE:
if p := n.Name.Param; p.Alias {
// Type alias declaration: Simply use the rhs type - no need
// to create a new type.
// If we have a syntax error, p.Ntype may be nil.
if p.Ntype != nil {
p.Ntype = typecheck(p.Ntype, Etype)
n.Type = p.Ntype.Type
if n.Type == nil {
n.Diag = true
goto ret
}
n.Sym.Def = p.Ntype
}
break
}
// regular type declaration
if Curfn != nil {
defercheckwidth()
}
n.Walkdef = 1
n.Type = typ(TFORW)
n.Type.Sym = n.Sym
n.Type.Sym = n.Sym // TODO(gri) this also happens in typecheckdeftype(n) - where should it happen?
nerrors0 := nerrors
typecheckdeftype(n)
if n.Type.Etype == TFORW && nerrors > nerrors0 {
@@ -3770,7 +3799,6 @@ func typecheckdef(n *Node) *Node {
// but it was reported. Silence future errors.
n.Type.Broke = true
}
if Curfn != nil {
resumecheckwidth()
}

View File

@@ -398,6 +398,14 @@ func lexinit1() {
// errortype.Orig = makeErrorInterface()
s.Def = typenod(errortype)
// We create separate byte and rune types for better error messages
// rather than just creating type alias *Sym's for the uint8 and
// int32 types. Hence, (bytetype|runtype).Sym.isAlias() is false.
// TODO(gri) Should we get rid of this special case (at the cost
// of less informative error messages involving bytes and runes)?
// (Alternatively, we could introduce an OTALIAS node representing
// type aliases, albeit at the cost of having to deal with it everywhere).
// byte alias
s = Pkglookup("byte", builtinpkg)
bytetype = typ(TUINT8)

View File

@@ -74,6 +74,7 @@ type (
// Name Type
TypeDecl struct {
Name *Name
Alias bool
Type Expr
Group *Group // nil means not part of a group
Pragma Pragma

View File

@@ -325,7 +325,7 @@ func (p *parser) constDecl(group *Group) Decl {
return d
}
// TypeSpec = identifier Type .
// TypeSpec = identifier [ "=" ] Type .
func (p *parser) typeDecl(group *Group) Decl {
if trace {
defer p.trace("typeDecl")()
@@ -335,6 +335,7 @@ func (p *parser) typeDecl(group *Group) Decl {
d.init(p)
d.Name = p.name()
d.Alias = p.got(_Assign)
d.Type = p.tryType()
if d.Type == nil {
p.syntax_error("in type declaration")

View File

@@ -619,7 +619,11 @@ func (p *printer) printRawNode(n Node) {
if n.Group == nil {
p.print(_Type, blank)
}
p.print(n.Name, blank, n.Type)
p.print(n.Name, blank)
if n.Alias {
p.print(_Assign, blank)
}
p.print(n.Type)
case *VarDecl:
if n.Group == nil {

View File

@@ -22,3 +22,20 @@ func TestPrint(t *testing.T) {
Fprint(os.Stdout, ast, true)
fmt.Println()
}
func TestPrintString(t *testing.T) {
for _, want := range []string{
"package p",
"package p; type _ = int; type T1 = struct{}; type ( _ = *struct{}; T2 = float32 )",
// TODO(gri) expand
} {
ast, err := ParseBytes([]byte(want), nil, nil, 0)
if err != nil {
t.Error(err)
continue
}
if got := String(ast); got != want {
t.Errorf("%q: got %q", want, got)
}
}
}

View File

@@ -600,6 +600,7 @@ func (t *tester) registerTests() {
})
}
}
return // skip API check on go1.8.typealias branch
if t.goos != "nacl" && t.goos != "android" && !t.iOS() {
t.tests = append(t.tests, distTest{
name: "api",

View File

@@ -71,6 +71,7 @@ var tests = []test{
`const MultiLineConst = ...`, // Multi line constant.
`var MultiLineVar = map\[struct{ ... }\]struct{ ... }{ ... }`, // Multi line variable.
`func MultiLineFunc\(x interface{ ... }\) \(r struct{ ... }\)`, // Multi line function.
`type T1 = T2`, // Type alias
},
[]string{
`const internalConstant = 2`, // No internal constants.
@@ -89,6 +90,7 @@ var tests = []test{
`unexportedTypedConstant`, // No unexported typed constant.
`Field`, // No fields.
`Method`, // No methods.
`type T1 T2`, // Type alias does not display as type declaration.
},
},
// Package dump -u
@@ -265,6 +267,18 @@ var tests = []test{
`error`, // No embedded error.
},
},
// Type T1 dump (alias).
{
"type T1",
[]string{p+".T1"},
[]string{
`type T1 = T2`,
},
[]string{
`type T1 T2`,
`type ExportedType`,
},
},
// Type -u with unexported fields.
{
"type with unexported fields and -u",

View File

@@ -258,7 +258,11 @@ func (pkg *Package) oneLineNodeDepth(node ast.Node, depth int) string {
return fmt.Sprintf("func %s%s%s", recv, name, fnc)
case *ast.TypeSpec:
return fmt.Sprintf("type %s %s", n.Name.Name, pkg.oneLineNodeDepth(n.Type, depth))
sep := " "
if n.Assign.IsValid() {
sep = " = "
}
return fmt.Sprintf("type %s%s%s", n.Name.Name, sep, pkg.oneLineNodeDepth(n.Type, depth))
case *ast.FuncType:
var params []string

View File

@@ -172,3 +172,7 @@ const (
)
const ConstGroup4 ExportedType = ExportedType{}
type T2 int
type T1 = T2

View File

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

@@ -3497,8 +3497,8 @@ func TestBinaryOnlyPackages(t *testing.T) {
tg.grepStdout("false", "did not see BinaryOnly=false for p4")
}
// Issue 16050 and 21884.
func TestLinkSysoFiles(t *testing.T) {
// Issue 16050.
func TestAlwaysLinkSysoFiles(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
@@ -3517,10 +3517,6 @@ func TestLinkSysoFiles(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

@@ -173,12 +173,6 @@ func (p *Package) copyBuild(pp *build.Package) {
p.SwigFiles = pp.SwigFiles
p.SwigCXXFiles = pp.SwigCXXFiles
p.SysoFiles = pp.SysoFiles
if 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

24
src/cmd/gofmt/testdata/typealias.golden vendored Normal file
View File

@@ -0,0 +1,24 @@
package q
import "p"
type _ = int
type a = struct{ x int }
type b = p.B
type (
_ = chan<- int
aa = interface{}
bb = p.BB
)
// TODO(gri) We may want to put the '=' into a separate column if
// we have mixed (regular and alias) type declarations in a group.
type (
_ chan<- int
_ = chan<- int
aa0 interface{}
aaa = interface{}
bb0 p.BB
bbb = p.BB
)

24
src/cmd/gofmt/testdata/typealias.input vendored Normal file
View File

@@ -0,0 +1,24 @@
package q
import "p"
type _ = int
type a = struct{ x int }
type b = p.B
type (
_ = chan<- int
aa = interface{}
bb = p.BB
)
// TODO(gri) We may want to put the '=' into a separate column if
// we have mixed (regular and alias) type declarations in a group.
type (
_ chan<- int
_ = chan<- int
aa0 interface{}
aaa = interface{}
bb0 p.BB
bbb = p.BB
)

View File

@@ -118,17 +118,6 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
r.Add += 4
return true
case 256 + ld.R_X86_64_PC64:
if targ.Type == obj.SDYNIMPORT {
ld.Errorf(s, "unexpected R_X86_64_PC64 relocation for dynamic symbol %s", targ.Name)
}
if targ.Type == 0 || targ.Type == obj.SXREF {
ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
}
r.Type = obj.R_PCREL
r.Add += 8
return true
case 256 + ld.R_X86_64_PLT32:
r.Type = obj.R_PCREL
r.Add += 4

View File

@@ -1836,11 +1836,6 @@ func (ctxt *Link) dodata() {
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
for _, s := range dwarfp[i:] {
// Syms can (incorrectly) appear twice on the list. Ignore repeats.
// See golang.org/issue/21566.
if s.Type == obj.SRODATA {
continue
}
if s.Type != obj.SDWARFINFO {
break
}

View File

@@ -255,7 +255,7 @@ func decodetypeStructFieldType(s *Symbol, i int) *Symbol {
func decodetypeStructFieldOffs(arch *sys.Arch, s *Symbol, i int) int64 {
off := decodetypeStructFieldArrayOff(s, i)
return int64(decodeInuxi(arch, s.P[off+2*SysArch.PtrSize:], SysArch.IntSize))
return int64(decodeInuxi(arch, s.P[off+2*SysArch.PtrSize:], SysArch.IntSize) >> 1)
}
// InterfaceType.methods.length

View File

@@ -1201,7 +1201,6 @@ func relSize(ctxt *Link, pn string, elftype uint32) uint8 {
return 4
case AMD64 | R_X86_64_64<<24,
AMD64 | R_X86_64_PC64<<24,
PPC64 | R_PPC64_ADDR64<<24,
S390X | R_390_GLOB_DAT<<24,
S390X | R_390_RELATIVE<<24,

View File

@@ -808,7 +808,6 @@ var hostobj []Hostobj
// These packages can use internal linking mode.
// Others trigger external mode.
var internalpkg = []string{
"crypto/internal/boring",
"crypto/x509",
"net",
"os/user",

View File

@@ -6,7 +6,6 @@ package aes
import (
"crypto/cipher"
"crypto/internal/boring"
"strconv"
)
@@ -37,9 +36,6 @@ func NewCipher(key []byte) (cipher.Block, error) {
case 16, 24, 32:
break
}
if boring.Enabled {
return boring.NewAESCipher(key)
}
return newCipher(key)
}

View File

@@ -6,7 +6,6 @@ package aes
import (
"crypto/cipher"
"crypto/internal/boring"
"crypto/internal/cipherhw"
)
@@ -47,7 +46,6 @@ 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")
}
@@ -58,7 +56,6 @@ 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

@@ -1,100 +0,0 @@
// 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 ecdsa
import (
"crypto/internal/boring"
"math/big"
"sync/atomic"
"unsafe"
)
// Cached conversions from Go PublicKey/PrivateKey to BoringCrypto.
//
// A new 'boring atomic.Value' field in both PublicKey and PrivateKey
// serves as a cache for the most recent conversion. The cache is an
// atomic.Value because code might reasonably set up a key and then
// (thinking it immutable) use it from multiple goroutines simultaneously.
// The first operation initializes the cache; if there are multiple simultaneous
// first operations, they will do redundant work but not step on each other.
//
// 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.
type boringPub struct {
key *boring.PublicKeyECDSA
orig PublicKey
}
func boringPublicKey(pub *PublicKey) (*boring.PublicKeyECDSA, error) {
b := (*boringPub)(atomic.LoadPointer(&pub.boring))
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, b.orig.X, b.orig.Y)
if err != nil {
return nil, err
}
b.key = key
atomic.StorePointer(&pub.boring, unsafe.Pointer(b))
return key, nil
}
type boringPriv struct {
key *boring.PrivateKeyECDSA
orig PrivateKey
}
func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyECDSA, error) {
b := (*boringPriv)(atomic.LoadPointer(&priv.boring))
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, b.orig.X, b.orig.Y, b.orig.D)
if err != nil {
return nil, err
}
b.key = key
atomic.StorePointer(&priv.boring, 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

@@ -21,13 +21,11 @@ import (
"crypto/aes"
"crypto/cipher"
"crypto/elliptic"
"crypto/internal/boring"
"crypto/sha512"
"encoding/asn1"
"errors"
"io"
"math/big"
"unsafe"
)
// A invertible implements fast inverse mod Curve.Params().N
@@ -49,16 +47,12 @@ const (
type PublicKey struct {
elliptic.Curve
X, Y *big.Int
boring unsafe.Pointer
}
// PrivateKey represents a ECDSA private key.
type PrivateKey struct {
PublicKey
D *big.Int
boring unsafe.Pointer
}
type ecdsaSignature struct {
@@ -75,15 +69,6 @@ func (priv *PrivateKey) Public() crypto.PublicKey {
// hardware module. Common uses should use the Sign function in this package
// directly.
func (priv *PrivateKey) Sign(rand io.Reader, msg []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, msg)
}
boring.UnreachableExceptTests()
r, s, err := Sign(rand, priv, msg)
if err != nil {
return nil, err
@@ -113,15 +98,6 @@ 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: x, Y: y}, D: d}, nil
}
boring.UnreachableExceptTests()
k, err := randFieldElement(c, rand)
if err != nil {
return nil, err
@@ -173,15 +149,6 @@ var errZeroParam = errors.New("zero parameter")
// returns the signature as a pair of integers. The security of the private key
// depends on the entropy of rand.
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
if boring.Enabled && rand == boring.RandReader {
b, err := boringPrivateKey(priv)
if err != nil {
return nil, nil, err
}
return boring.SignECDSA(b, hash)
}
boring.UnreachableExceptTests()
// Get min(log2(q) / 2, 256) bits of entropy from rand.
entropylen := (priv.Curve.Params().BitSize + 7) / 16
if entropylen > 32 {
@@ -258,15 +225,6 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
// Verify verifies the signature in r, s of hash using the public key, pub. Its
// return value records whether the signature is valid.
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
if boring.Enabled {
b, err := boringPublicKey(pub)
if err != nil {
return false
}
return boring.VerifyECDSA(b, hash, r, s)
}
boring.UnreachableExceptTests()
// See [NSA] 3.4.2
c := pub.Curve
N := c.Params().N

View File

@@ -22,7 +22,6 @@ timing side-channels:
package hmac
import (
"crypto/internal/boring"
"crypto/subtle"
"hash"
)
@@ -66,13 +65,6 @@ func (h *hmac) Reset() {
// New returns a new HMAC hash using the given hash.Hash type and key.
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,7 +5,6 @@
package hmac
import (
"bytes"
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
@@ -519,31 +518,6 @@ 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) {
@@ -595,42 +569,6 @@ 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

@@ -1,200 +0,0 @@
The Go source code and supporting files in this directory
are covered by the usual Go license (see ../../../../LICENSE).
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-20170615/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

@@ -1,357 +0,0 @@
// 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.
// +build linux,amd64
// +build !android
// +build !cmd_go_bootstrap
// +build !msan
package boring
// #include "goboringcrypto.h"
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 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 int) (cipher.AEAD, error) {
return c.newGCM(nonceSize, false)
}
func (c *aesCipher) NewGCMTLS() (cipher.AEAD, error) {
return c.newGCM(gcmStandardNonceSize, true)
}
func (c *aesCipher) newGCM(nonceSize int, tls bool) (cipher.AEAD, error) {
if nonceSize != gcmStandardNonceSize {
// Fall back to standard library for GCM with non-standard nonce size.
return cipher.NewGCMWithNonceSize(&noGCM{c}, nonceSize)
}
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}, nonceSize)
}
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() != nonceSize {
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")
}
var outLen C.size_t
ok := C._goboringcrypto_EVP_AEAD_CTX_seal(
&g.ctx,
(*C.uint8_t)(unsafe.Pointer(&dst[n])), &outLen, C.size_t(len(plaintext)+gcmTagSize),
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"))
}
if outLen != C.size_t(len(plaintext)+gcmTagSize) {
panic("boringcrypto: internal confusion about GCM tag size")
}
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")
}
var outLen C.size_t
ok := C._goboringcrypto_EVP_AEAD_CTX_open(
&g.ctx,
base(dst[n:]), &outLen, C.size_t(len(ciphertext)-gcmTagSize),
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
}
if outLen != C.size_t(len(ciphertext)-gcmTagSize) {
panic("boringcrypto: internal confusion about GCM tag size")
}
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

@@ -1,83 +0,0 @@
// 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.
// +build linux,amd64
// +build !android
// +build !cmd_go_bootstrap
// +build !msan
package boring
// #include "goboringcrypto.h"
import "C"
import (
"crypto/internal/boring/sig"
"math/big"
)
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 bigToBN(x *big.Int) *C.GO_BIGNUM {
raw := x.Bytes()
return C._goboringcrypto_BN_bin2bn(base(raw), C.size_t(len(raw)), nil)
}
func bnToBig(bn *C.GO_BIGNUM) *big.Int {
raw := make([]byte, C._goboringcrypto_BN_num_bytes(bn))
n := C._goboringcrypto_BN_bn2bin(bn, base(raw))
return new(big.Int).SetBytes(raw[:n])
}
func bigToBn(bnp **C.GO_BIGNUM, b *big.Int) bool {
if *bnp != nil {
C._goboringcrypto_BN_free(*bnp)
*bnp = nil
}
if b == nil {
return true
}
raw := b.Bytes()
bn := C._goboringcrypto_BN_bin2bn(base(raw), C.size_t(len(raw)), nil)
if bn == nil {
return false
}
*bnp = bn
return true
}

View File

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

@@ -1 +0,0 @@
boringssl-24e5886c0edfc409c8083d10f9f1120111efd6f5.tar.xz

View File

@@ -1,6 +0,0 @@
This is not a Go package. The directory must not contain Go sources,
to prevent it from being considered a Go package.
This directory holds the script for building ../goboringcrypto_*.syso.
Run build.sh on an Ubuntu system.
See the comment at the top of build.sh for details.

View File

@@ -1,63 +0,0 @@
#!/bin/bash
# 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.
# Run on Ubuntu system set up with:
# sudo apt-get install debootstrap
# sudo apt-get install squid-deb-proxy
#
# The script sets up an Ubuntu chroot and then runs the build
# in that chroot, to make sure we know exactly what software
# is being used for the build. To repeat the script reusing the
# chroot installation, run build.sh -quick. This mode is useful
# if all you've modified is goboringcrypto.c and ../goboringcrypto.h
# (or some of the setup scripts in this directory).
# Comment this setting out if not using squid-deb-proxy,
# but it will be much slower to repeat the script.
http_proxy=http://127.0.0.1:8000
chroot=/var/tmp/boringssl
sudo umount -f $chroot/proc
sudo umount -f $chroot/sys
sudo umount -f $chroot/dev/pts
sudo umount -f $chroot/dev
set -e
if [ "$1" != "-quick" ]; then
sudo rm -rf $chroot
sudo http_proxy=$http_proxy debootstrap --variant=minbase zesty $chroot
fi
sudo chown $USER $chroot
sudo chmod u+w $chroot
sudo mount -t proc proc $chroot/proc
sudo mount -t sysfs sys $chroot/sys
sudo mount -o bind /dev $chroot/dev
sudo mount -t devpts devpts $chroot/dev/pts
sudo cp sources.list $chroot/etc/apt/sources.list
cp *chroot.sh $chroot
# Following http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp2964.pdf page 18.
if [ ! -e $chroot/boringssl-24e5886c0edfc409c8083d10f9f1120111efd6f5.tar.xz ]; then
wget -O $chroot/boringssl-24e5886c0edfc409c8083d10f9f1120111efd6f5.tar.xz https://commondatastorage.googleapis.com/chromium-boringssl-docs/fips/boringssl-24e5886c0edfc409c8083d10f9f1120111efd6f5.tar.xz
fi
if [ "$(sha256sum $chroot/boringssl-24e5886c0edfc409c8083d10f9f1120111efd6f5.tar.xz | awk '{print $1}')" != 15a65d676eeae27618e231183a1ce9804fc9c91bcc3abf5f6ca35216c02bf4da ]; then
echo WRONG SHA256SUM
exit 2
fi
rm -rf $chroot/godriver
mkdir $chroot/godriver
cp ../goboringcrypto.h $chroot/godriver
sudo http_proxy=$http_proxy chroot $chroot /root_setup_in_chroot.sh
sudo chroot --userspec=$(id -u):$(id -g) $chroot /build_in_chroot.sh
cp $chroot/godriver/goboringcrypto_linux_amd64.syso ..
sha256sum ../goboringcrypto_linux_amd64.syso
echo DONE

View File

@@ -1,198 +0,0 @@
#!/bin/bash
# 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.
set -e
echo running build_in_chroot.sh
id
date
export LANG=C
unset LANGUAGE
# Build BoringCrypto libcrypto.a.
# Following http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp2964.pdf page 18.
if ! [ -e ./boringssl/build/tool/bssl ]; then
export PATH=$PATH:/usr/lib/go-1.8/bin:/clangbin
# 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.
mkdir /clangbin
echo '#!/bin/bash
exec clang-4.0 -fPIC "$@"
' >/clangbin/clang
echo '#!/bin/bash
exec clang++-4.0 -fPIC "$@"
' >/clangbin/clang++
chmod +x /clangbin/clang /clangbin/clang++
rm -rf boringssl
tar xJf ../boringssl-*z
cd boringssl
# Verbatim instructions from BoringCrypto build docs.
printf "set(CMAKE_C_COMPILER \"clang\")\nset(CMAKE_CXX_COMPILER \"clang++\")\n" >/toolchain
mkdir build && cd build && cmake -GNinja -DCMAKE_TOOLCHAIN_FILE=/toolchain -DFIPS=1 -DCMAKE_BUILD_TYPE=Release ..
ninja -v
ninja run_tests
cd ../..
fi
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++-4.0 -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-4.0 -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 --redefine-syms=renames.txt goboringcrypto.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

@@ -1,13 +0,0 @@
#!/bin/bash
# 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.
set -e
id
date
echo http_proxy=$http_proxy
export LANG=C
unset LANGUAGE
apt-get update
apt-get install --no-install-recommends -y cmake clang-4.0 golang-1.8-go ninja-build xz-utils

View File

@@ -1,10 +0,0 @@
deb http://archive.ubuntu.com/ubuntu/ zesty main restricted
deb http://archive.ubuntu.com/ubuntu/ zesty-updates main restricted
deb http://archive.ubuntu.com/ubuntu/ zesty universe
deb http://archive.ubuntu.com/ubuntu/ zesty-updates universe
deb http://archive.ubuntu.com/ubuntu/ zesty multiverse
deb http://archive.ubuntu.com/ubuntu/ zesty-updates multiverse
deb http://archive.ubuntu.com/ubuntu/ zesty-backports main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu zesty-security main restricted
deb http://security.ubuntu.com/ubuntu zesty-security universe
deb http://security.ubuntu.com/ubuntu zesty-security multiverse

View File

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

View File

@@ -1,201 +0,0 @@
// 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.
// +build linux,amd64
// +build !android
// +build !cmd_go_bootstrap
// +build !msan
package boring
// #include "goboringcrypto.h"
import "C"
import (
"encoding/asn1"
"errors"
"math/big"
"runtime"
"unsafe"
)
type ecdsaSignature struct {
R, S *big.Int
}
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 *big.Int) (*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 *big.Int) (*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 *big.Int, D *big.Int) (*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 SignECDSA(priv *PrivateKeyECDSA, hash []byte) (r, s *big.Int, err error) {
// We could use ECDSA_do_sign instead but would need to convert
// the resulting BIGNUMs to *big.Int form. If we're going to do a
// conversion, converting the ASN.1 form is more convenient and
// likely not much more expensive.
sig, err := SignMarshalECDSA(priv, hash)
if err != nil {
return nil, nil, err
}
var esig ecdsaSignature
if _, err := asn1.Unmarshal(sig, &esig); err != nil {
return nil, nil, err
}
return esig.R, esig.S, 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, r, s *big.Int) bool {
// We could use ECDSA_do_verify instead but would need to convert
// r and s to BIGNUM form. If we're going to do a conversion, marshaling
// to ASN.1 is more convenient and likely not much more expensive.
sig, err := asn1.Marshal(ecdsaSignature{r, s})
if err != nil {
return false
}
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 *big.Int, 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

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

@@ -1,49 +0,0 @@
// 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 fipstls allows control over whether crypto/tls requires FIPS-approved settings.
// This package's effects are independent of the use of the BoringCrypto implementation.
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

@@ -1,236 +0,0 @@
// 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);
// #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[24]; } 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*);
size_t _goboringcrypto_BN_bn2bin(const GO_BIGNUM*, uint8_t*);
// #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[120]; } 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, 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

@@ -1,156 +0,0 @@
// 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.
// +build linux,amd64
// +build !android
// +build !cmd_go_bootstrap
// +build !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

@@ -1,109 +0,0 @@
// 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.
// +build !linux !amd64 !cgo android cmd_go_bootstrap msan
package boring
import (
"crypto"
"crypto/cipher"
"crypto/internal/boring/sig"
"hash"
"math/big"
)
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 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 *big.Int, err error) {
panic("boringcrypto: not available")
}
func NewPrivateKeyECDSA(curve string, X, Y, D *big.Int) (*PrivateKeyECDSA, error) {
panic("boringcrypto: not available")
}
func NewPublicKeyECDSA(curve string, X, Y *big.Int) (*PublicKeyECDSA, error) {
panic("boringcrypto: not available")
}
func SignECDSA(priv *PrivateKeyECDSA, hash []byte) (r, s *big.Int, err error) {
panic("boringcrypto: not available")
}
func SignMarshalECDSA(priv *PrivateKeyECDSA, hash []byte) ([]byte, error) {
panic("boringcrypto: not available")
}
func VerifyECDSA(pub *PublicKeyECDSA, hash []byte, r, s *big.Int) 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 *big.Int, err error) {
panic("boringcrypto: not available")
}
func NewPrivateKeyRSA(N, E, D, P, Q, Dp, Dq, Qinv *big.Int) (*PrivateKeyRSA, error) {
panic("boringcrypto: not available")
}
func NewPublicKeyRSA(N, E *big.Int) (*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

@@ -1,27 +0,0 @@
// 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.
// +build linux,amd64
// +build !android
// +build !cmd_go_bootstrap
// +build !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

@@ -1,329 +0,0 @@
// 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.
// +build linux,amd64
// +build !android
// +build !cmd_go_bootstrap
// +build !msan
package boring
// #include "goboringcrypto.h"
import "C"
import (
"crypto"
"crypto/subtle"
"errors"
"hash"
"math/big"
"runtime"
"strconv"
"unsafe"
)
func GenerateKeyRSA(bits int) (N, E, D, P, Q, Dp, Dq, Qinv *big.Int, err error) {
bad := func(e error) (N, E, D, P, Q, Dp, Dq, Qinv *big.Int, 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 *C.GO_RSA
}
func NewPublicKeyRSA(N, E *big.Int) (*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}
// 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, (*PublicKeyRSA).finalize)
return k, nil
}
func (k *PublicKeyRSA) finalize() {
C._goboringcrypto_RSA_free(k.key)
}
type PrivateKeyRSA struct {
key *C.GO_RSA
}
func NewPrivateKeyRSA(N, E, D, P, Q, Dp, Dq, Qinv *big.Int) (*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}
// 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, (*PrivateKeyRSA).finalize)
return k, nil
}
func (k *PrivateKeyRSA) finalize() {
C._goboringcrypto_RSA_free(k.key)
}
func setupRSA(key *C.GO_RSA,
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 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.malloc(C.size_t(len(label))))
if clabel == nil {
return nil, nil, fail("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(gokey interface{}, key *C.GO_RSA,
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(key, 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")
}
runtime.KeepAlive(gokey) // keep key from being freed before now
return out[:outLen], nil
}
func DecryptRSAOAEP(h hash.Hash, priv *PrivateKeyRSA, ciphertext, label []byte) ([]byte, error) {
return cryptRSA(priv, priv.key, 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, pub.key, C.GO_RSA_PKCS1_OAEP_PADDING, h, label, 0, 0, encryptInit, encrypt, msg)
}
func DecryptRSAPKCS1(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) {
return cryptRSA(priv, priv.key, C.GO_RSA_PKCS1_PADDING, nil, nil, 0, 0, decryptInit, decrypt, ciphertext)
}
func EncryptRSAPKCS1(pub *PublicKeyRSA, msg []byte) ([]byte, error) {
return cryptRSA(pub, pub.key, C.GO_RSA_PKCS1_PADDING, nil, nil, 0, 0, encryptInit, encrypt, msg)
}
func DecryptRSANoPadding(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) {
return cryptRSA(priv, priv.key, C.GO_RSA_NO_PADDING, nil, nil, 0, 0, decryptInit, decrypt, ciphertext)
}
func EncryptRSANoPadding(pub *PublicKeyRSA, msg []byte) ([]byte, error) {
return cryptRSA(pub, pub.key, 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
}
out := make([]byte, C._goboringcrypto_RSA_size(priv.key))
var outLen C.size_t
if C._goboringcrypto_RSA_sign_pss_mgf1(priv.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")
}
runtime.KeepAlive(priv)
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 C._goboringcrypto_RSA_verify_pss_mgf1(pub.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")
}
runtime.KeepAlive(pub)
return nil
}
func SignRSAPKCS1v15(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte) ([]byte, error) {
out := make([]byte, C._goboringcrypto_RSA_size(priv.key))
if h == 0 {
// No hashing.
var outLen C.size_t
if C._goboringcrypto_RSA_sign_raw(priv.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")
}
runtime.KeepAlive(priv)
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 outLen C.uint
if C._goboringcrypto_RSA_sign(nid, base(hashed), C.uint(len(hashed)), base(out), &outLen, priv.key) == 0 {
return nil, fail("RSA_sign")
}
runtime.KeepAlive(priv)
return out[:outLen], nil
}
func VerifyRSAPKCS1v15(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte) error {
size := int(C._goboringcrypto_RSA_size(pub.key))
if len(sig) < size {
// BoringCrypto requires sig to be same size as RSA key, so pad with leading zeros.
zsig := make([]byte, size)
copy(zsig[len(zsig)-len(sig):], sig)
sig = zsig
}
if h == 0 {
var outLen C.size_t
out := make([]byte, size)
if C._goboringcrypto_RSA_verify_raw(pub.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")
}
runtime.KeepAlive(pub)
return nil
}
md := cryptoHashToMD(h)
if md == nil {
return errors.New("crypto/rsa: unsupported hash function")
}
nid := C._goboringcrypto_EVP_MD_type(md)
if C._goboringcrypto_RSA_verify(nid, base(hashed), C.size_t(len(hashed)), base(sig), C.size_t(len(sig)), pub.key) == 0 {
return fail("RSA_verify")
}
runtime.KeepAlive(pub)
return nil
}

View File

@@ -1,177 +0,0 @@
// 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.
// +build linux,amd64
// +build !android
// +build !cmd_go_bootstrap
// +build !msan
package boring
// #include "goboringcrypto.h"
import "C"
import (
"hash"
"unsafe"
)
// 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
}
func (h *sha1Hash) Reset() { C._goboringcrypto_SHA1_Init(&h.ctx) }
func (h *sha1Hash) Size() int { return 20 }
func (h *sha1Hash) BlockSize() int { return 64 }
func (h *sha1Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }
func (h *sha1Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA1_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA1_Update failed")
}
return len(p), nil
}
func (h0 *sha1Hash) sum() []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA1_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
panic("boringcrypto: SHA1_Final failed")
}
return h.out[:]
}
// 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) Reset() { C._goboringcrypto_SHA224_Init(&h.ctx) }
func (h *sha224Hash) Size() int { return 224 / 8 }
func (h *sha224Hash) BlockSize() int { return 64 }
func (h *sha224Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }
func (h *sha224Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA224_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA224_Update failed")
}
return len(p), nil
}
func (h0 *sha224Hash) sum() []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA224_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
panic("boringcrypto: SHA224_Final failed")
}
return 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) Reset() { C._goboringcrypto_SHA256_Init(&h.ctx) }
func (h *sha256Hash) Size() int { return 256 / 8 }
func (h *sha256Hash) BlockSize() int { return 64 }
func (h *sha256Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }
func (h *sha256Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA256_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA256_Update failed")
}
return len(p), nil
}
func (h0 *sha256Hash) sum() []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA256_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
panic("boringcrypto: SHA256_Final failed")
}
return h.out[:]
}
// 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) Reset() { C._goboringcrypto_SHA384_Init(&h.ctx) }
func (h *sha384Hash) Size() int { return 384 / 8 }
func (h *sha384Hash) BlockSize() int { return 128 }
func (h *sha384Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }
func (h *sha384Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA384_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA384_Update failed")
}
return len(p), nil
}
func (h0 *sha384Hash) sum() []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA384_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
panic("boringcrypto: SHA384_Final failed")
}
return 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) Reset() { C._goboringcrypto_SHA512_Init(&h.ctx) }
func (h *sha512Hash) Size() int { return 512 / 8 }
func (h *sha512Hash) BlockSize() int { return 128 }
func (h *sha512Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }
func (h *sha512Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA512_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA512_Update failed")
}
return len(p), nil
}
func (h0 *sha512Hash) sum() []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA512_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
panic("boringcrypto: SHA512_Final failed")
}
return h.out[:]
}

View File

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

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

@@ -1,19 +0,0 @@
// 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.
// +build !amd64
TEXT ·BoringCrypto(SB),$0
RET
TEXT ·FIPSOnly(SB),$0
RET
TEXT ·StandardCrypto(SB),$0
RET

View File

@@ -6,19 +6,11 @@
package cipherhw
import "crypto/internal/boring"
// defined in asm_amd64.s
func hasAESNI() bool
// AESGCMSupport returns true if the Go standard library supports AES-GCM in
// hardware.
func AESGCMSupport() bool {
// If BoringCrypto is enabled, we report having
// AES-GCM support, so that crypto/tls will
// prioritize AES-GCM usage.
if boring.Enabled {
return true
}
return hasAESNI()
}

View File

@@ -13,7 +13,6 @@ import (
"bufio"
"crypto/aes"
"crypto/cipher"
"crypto/internal/boring"
"io"
"os"
"runtime"
@@ -27,10 +26,6 @@ const urandomDevice = "/dev/urandom"
// This is sufficient on Linux, OS X, and FreeBSD.
func init() {
if boring.Enabled {
Reader = boring.RandReader
return
}
if runtime.GOOS == "plan9" {
Reader = newReader(nil)
} else {
@@ -50,7 +45,6 @@ type devReader struct {
var altGetRandom func([]byte) (ok bool)
func (r *devReader) Read(b []byte) (n int, err error) {
boring.Unreachable()
if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) {
return len(b), nil
}
@@ -114,7 +108,6 @@ type reader struct {
}
func (r *reader) Read(b []byte) (n int, err error) {
boring.Unreachable()
r.mu.Lock()
defer r.mu.Unlock()
n = len(b)

View File

@@ -1,163 +0,0 @@
// 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 rsa
import (
"crypto/internal/boring"
"crypto/rand"
"io"
"math/big"
"sync/atomic"
"unsafe"
)
// Cached conversions from Go PublicKey/PrivateKey to BoringCrypto.
//
// A new 'boring atomic.Value' field in both PublicKey and PrivateKey
// serves as a cache for the most recent conversion. The cache is an
// atomic.Value because code might reasonably set up a key and then
// (thinking it immutable) use it from multiple goroutines simultaneously.
// The first operation initializes the cache; if there are multiple simultaneous
// first operations, they will do redundant work but not step on each other.
//
// 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
}
func boringPublicKey(pub *PublicKey) (*boring.PublicKeyRSA, error) {
b := (*boringPub)(atomic.LoadPointer(&pub.boring))
if b != nil && publicKeyEqual(&b.orig, pub) {
return b.key, nil
}
b = new(boringPub)
b.orig = copyPublicKey(pub)
key, err := boring.NewPublicKeyRSA(b.orig.N, big.NewInt(int64(b.orig.E)))
if err != nil {
return nil, err
}
b.key = key
atomic.StorePointer(&pub.boring, unsafe.Pointer(b))
return key, nil
}
type boringPriv struct {
key *boring.PrivateKeyRSA
orig PrivateKey
}
func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyRSA, error) {
b := (*boringPriv)(atomic.LoadPointer(&priv.boring))
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(N, E, D, P, Q, Dp, Dq, Qinv)
if err != nil {
return nil, err
}
b.key = key
atomic.StorePointer(&priv.boring, 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
}
// boringFakeRandomBlind consumes from random to mimic the
// blinding operation done in the standard Go func decrypt.
// When we are using BoringCrypto, we always let it handle decrypt
// regardless of random source, because the blind doesn't affect
// the visible output of decryption, but if the random source is not
// true randomness then the caller might still observe the side effect
// of consuming from the source. We consume from the source
// to give the same side effect. This should only happen during tests
// (verified by the UnreachableExceptTests call below).
//
// We go to the trouble of doing this so that we can verify that
// func decrypt (standard RSA decryption) is dropped from
// BoringCrypto-linked binaries entirely; otherwise we'd have to
// keep it in the binary just in case a call happened with a
// non-standard randomness source.
func boringFakeRandomBlind(random io.Reader, priv *PrivateKey) {
if random == nil || random == boring.RandReader {
return
}
boring.UnreachableExceptTests()
// Copied from func decrypt.
for {
r, err := rand.Int(random, priv.N)
if err != nil {
return
}
if r.Cmp(bigZero) == 0 {
r = bigOne
}
_, ok := modInverse(r, priv.N)
if ok {
break
}
}
}

View File

@@ -1,332 +0,0 @@
// 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.
// Note: Can run these tests against the non-BoringCrypto
// version of the code by using "CGO_ENABLED=0 go test".
package rsa
import (
"bytes"
"crypto"
"crypto/rand"
"crypto/sha1"
"crypto/sha256"
"encoding/asn1"
"encoding/hex"
"reflect"
"runtime"
"runtime/debug"
"sync"
"sync/atomic"
"testing"
"unsafe"
)
func TestBoringASN1Marshal(t *testing.T) {
k, err := GenerateKey(rand.Reader, 128)
if err != nil {
t.Fatal(err)
}
// This used to fail, because of the unexported 'boring' field.
// Now the compiler hides it [sic].
_, err = asn1.Marshal(k.PublicKey)
if err != nil {
t.Fatal(err)
}
}
func TestBoringDeepEqual(t *testing.T) {
k, err := GenerateKey(rand.Reader, 128)
if err != nil {
t.Fatal(err)
}
k.boring = nil // probably nil already but just in case
k2 := *k
k2.boring = unsafe.Pointer(k) // anything not nil, for this test
if !reflect.DeepEqual(k, &k2) {
// compiler should be hiding the boring field from reflection
t.Fatalf("DeepEqual compared boring fields")
}
}
func TestBoringVerify(t *testing.T) {
// This changed behavior and broke golang.org/x/crypto/openpgp.
// Go accepts signatures without leading 0 padding, while BoringCrypto does not.
// So the Go wrappers must adapt.
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: %v", err)
}
err = VerifyPKCS1v15(key, crypto.SHA1, hash, sig)
if err != nil {
t.Errorf("sha1: %v", err)
}
}
// The goal for BoringCrypto is to be indistinguishable from standard Go crypto.
// Test that when routines are passed a not-actually-random reader, they
// consume and potentially expose the expected bits from that reader.
// This is awful but it makes sure that golden tests based on deterministic
// "randomness" sources are unchanged by BoringCrypto.
//
// For decryption and signing, r is only used for blinding,
// so we can and do still use BoringCrypto with its own true
// randomness source, but we must be careful to consume
// from r as if we'd used it for blinding.
type testRandReader struct {
t *testing.T
offset int64
seq [8]byte
data []byte
buf [32]byte
}
func (r *testRandReader) Read(b []byte) (int, error) {
if len(r.data) == 0 && len(b) > 0 {
for i := range r.seq {
r.seq[i]++
if r.seq[i] != 0 {
break
}
}
r.buf = sha256.Sum256(r.seq[:])
r.data = r.buf[:]
}
n := copy(b, r.data)
r.data = r.data[n:]
r.offset += int64(n)
return n, nil
}
func (r *testRandReader) checkOffset(offset int64) {
if r.offset != offset {
r.t.Fatalf("r.offset = %d, expected %d", r.offset, offset)
}
}
func testRand(t *testing.T) *testRandReader {
return &testRandReader{t: t}
}
var testKeyCache struct {
once sync.Once
k *PrivateKey
}
func testKey(t *testing.T) *PrivateKey {
testKeyCache.once.Do(func() {
// Note: Key must be 2048 bits in order to trigger
// BoringCrypto code paths.
k, err := GenerateKey(testRand(t), 2048)
if err != nil {
t.Fatal(err)
}
testKeyCache.k = k
})
return testKeyCache.k
}
func bytesFromHex(t *testing.T, x string) []byte {
b, err := hex.DecodeString(x)
if err != nil {
t.Fatal(err)
}
return b
}
func TestBoringRandGenerateKey(t *testing.T) {
r := testRand(t)
k, err := GenerateKey(r, 2048) // 2048 is smallest size BoringCrypto might kick in for
if err != nil {
t.Fatal(err)
}
n := bigFromHex("b2e9c4c8b1c0f03ba6994fe1e715a3e598f0571f4676da420615b7b997d431ea7535ceb98e6b52172fe0d2fccfc5f696d1b34144f7d19d85633fcbf56daff805a66457b360b1b0f40ec18fb83f4c9b86f1b5fe26b209cdfff26911a95047df797210969693226423915c9be53ff1c06f86fe2d228273ef25970b90a3c70979f9d68458d5dd38f6700436f7cd5939c04be3e1f2ff52272513171540a685c9e8c8e20694e529cc3e0cc13d2fb91ac499d44b920a03e42be89a15e7ca73c29f2e2a1a8a7d9be57516ccb95e878db6ce6096e386a793cccc19eba15a37cc0f1234b7a25ee7c87569bc74c7ef3d6ad8d84a5ddb1e8901ae593f945523fe5e0ed451a5")
if k.N.Cmp(n) != 0 {
t.Fatalf("GenerateKey: wrong N\nhave %x\nwant %x", k.N, n)
}
r.checkOffset(35200)
// 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 TestBoringRandGenerateMultiPrimeKey(t *testing.T) {
r := testRand(t)
k, err := GenerateMultiPrimeKey(r, 2, 2048)
if err != nil {
t.Fatal(err)
}
n := bigFromHex("b2e9c4c8b1c0f03ba6994fe1e715a3e598f0571f4676da420615b7b997d431ea7535ceb98e6b52172fe0d2fccfc5f696d1b34144f7d19d85633fcbf56daff805a66457b360b1b0f40ec18fb83f4c9b86f1b5fe26b209cdfff26911a95047df797210969693226423915c9be53ff1c06f86fe2d228273ef25970b90a3c70979f9d68458d5dd38f6700436f7cd5939c04be3e1f2ff52272513171540a685c9e8c8e20694e529cc3e0cc13d2fb91ac499d44b920a03e42be89a15e7ca73c29f2e2a1a8a7d9be57516ccb95e878db6ce6096e386a793cccc19eba15a37cc0f1234b7a25ee7c87569bc74c7ef3d6ad8d84a5ddb1e8901ae593f945523fe5e0ed451a5")
if k.N.Cmp(n) != 0 {
t.Fatalf("GenerateKey: wrong N\nhave %x\nwant %x", k.N, n)
}
r.checkOffset(35200)
}
func TestBoringRandEncryptPKCS1v15(t *testing.T) {
r := testRand(t)
k := testKey(t)
enc, err := EncryptPKCS1v15(r, &k.PublicKey, []byte("hello world"))
if err != nil {
t.Fatal(err)
}
want := bytesFromHex(t, "a8c8c0d248e669942a140c1184e1112afbf794b7427d9ac966bd2dbb4c05a2fee76f311f7feec743b8a8715e34bf741b0d0c4226559daf4de258ff712178e3f25fecb7d3eee90251e8ae4b4b7b907cd2763948cc9da34ce83c69934b523830545a536c1ba4d3740f4687e877acee9c768bcd8e88d472ba5d905493121f4830d95dcea36ef0f1223ffb0a9008eddfc53aca36877328924a2c631dce4b67e745564301fe51ab2c768b39e525bda1e1a08e029b58c53a0b92285f734592d2deebda957bcfd29c697aee263fce5c5023c7d3495b6a9114a8ac691aa661721cf45973b68678bb1e15d6605b9040951163d5b6df0d7f0b20dcefa251a7a8947a090f4b")
if !bytes.Equal(enc, want) {
t.Fatalf("EncryptPKCS1v15: wrong enc\nhave %x\nwant %x", enc, want)
}
r.checkOffset(242)
}
func TestBoringRandDecryptPKCS1v15(t *testing.T) {
r := testRand(t)
k := testKey(t)
enc := bytesFromHex(t, "a8c8c0d248e669942a140c1184e1112afbf794b7427d9ac966bd2dbb4c05a2fee76f311f7feec743b8a8715e34bf741b0d0c4226559daf4de258ff712178e3f25fecb7d3eee90251e8ae4b4b7b907cd2763948cc9da34ce83c69934b523830545a536c1ba4d3740f4687e877acee9c768bcd8e88d472ba5d905493121f4830d95dcea36ef0f1223ffb0a9008eddfc53aca36877328924a2c631dce4b67e745564301fe51ab2c768b39e525bda1e1a08e029b58c53a0b92285f734592d2deebda957bcfd29c697aee263fce5c5023c7d3495b6a9114a8ac691aa661721cf45973b68678bb1e15d6605b9040951163d5b6df0d7f0b20dcefa251a7a8947a090f4b")
dec, err := DecryptPKCS1v15(r, k, enc)
if err != nil {
t.Fatal(err)
}
want := []byte("hello world")
if !bytes.Equal(dec, want) {
t.Fatalf("DecryptPKCS1v15: wrong dec\nhave %x\nwant %x", dec, want)
}
r.checkOffset(256)
}
func TestBoringRandDecryptPKCS1v15SessionKey(t *testing.T) {
r := testRand(t)
k := testKey(t)
enc := bytesFromHex(t, "a8c8c0d248e669942a140c1184e1112afbf794b7427d9ac966bd2dbb4c05a2fee76f311f7feec743b8a8715e34bf741b0d0c4226559daf4de258ff712178e3f25fecb7d3eee90251e8ae4b4b7b907cd2763948cc9da34ce83c69934b523830545a536c1ba4d3740f4687e877acee9c768bcd8e88d472ba5d905493121f4830d95dcea36ef0f1223ffb0a9008eddfc53aca36877328924a2c631dce4b67e745564301fe51ab2c768b39e525bda1e1a08e029b58c53a0b92285f734592d2deebda957bcfd29c697aee263fce5c5023c7d3495b6a9114a8ac691aa661721cf45973b68678bb1e15d6605b9040951163d5b6df0d7f0b20dcefa251a7a8947a090f4b")
dec := make([]byte, 11)
err := DecryptPKCS1v15SessionKey(r, k, enc, dec)
if err != nil {
t.Fatal(err)
}
want := []byte("hello world")
if !bytes.Equal(dec, want) {
t.Fatalf("DecryptPKCS1v15SessionKey: wrong dec\nhave %x\nwant %x", dec, want)
}
r.checkOffset(256)
}
func TestBoringRandSignPKCS1v15(t *testing.T) {
r := testRand(t)
k := testKey(t)
sum := sha1.Sum([]byte("hello"))
sig, err := SignPKCS1v15(r, k, crypto.SHA1, sum[:])
if err != nil {
t.Fatal(err)
}
want := bytesFromHex(t, "4a8da3c0c41af2b8a93d011d4e11f4da9b2d52641c6c3d78d863987e857295adcedfae0e0d3ec00352bd134dc3fbb93b23a1fbe3718775762d78165bbbd37c6ef8e07bfa44e16ed2f1b05ebc04ba7bd60162d8689edb8709349e06bc281d34c2a3ee75d3454bfd95053cbb27c10515fb9132290a6ecc858e0c003201a9e100aac7f66af967364a1176e4ed9ef672d41481c59580f98bb82f205f712153fd5e3035a811da9d6e56e50609d1d604857f6d8e958bb84f354cfa28e0b8bcbb1261f929382d431454f07cbf60c18ff1243b11c6b552f3a0aa7e936f45cded40688ee53b1b630f944139f4f51baae49cd039b57b2b82f58f5589335137f4b09bd315f5")
if !bytes.Equal(sig, want) {
t.Fatalf("SignPKCS1v15(hash=SHA1): wrong sig\nhave %x\nwant %x", sig, want)
}
sig, err = SignPKCS1v15(r, k, 0, sum[:])
if err != nil {
t.Fatal(err)
}
want = bytesFromHex(t, "5d3d34495ffade926adab2de0545aaf1f22a03def949b69e1c91d34a2f0c7f2d682af46034151a1b67aa22cb9c1a8cc24c1358fce9ac6a2141879bbe107371b14faa97b12494260d9602ed1355f22ab3495b0bb7c137bc6801c1113fc2bdc00d4c250bbd8fa17e4ff86f71544b30a78e9d62c0b949afd1159760282c2700ec8be24cd884efd585ec55b45506d90e66cc3c5911baaea961e6c4e8018c4b4feb04afdd71880e3d8eff120288e53289a1bfb9fe7a3b9aca1d4549f133063647bfd4c6f4c0f4038f1bbcb4d112aa601f1b15402595076adfdbefb1bb64d3193bafb0305145bb536cd949a03ebe0470c6a155369f784afab2e25e9d5c03d8e13dcf1a")
if !bytes.Equal(sig, want) {
t.Fatalf("SignPKCS1v15(hash=0): wrong sig\nhave %x\nwant %x", sig, want)
}
r.checkOffset(768)
}
func TestBoringRandSignPSS(t *testing.T) {
r := testRand(t)
k := testKey(t)
sum := sha1.Sum([]byte("hello"))
sig, err := SignPSS(r, k, crypto.SHA1, sum[:], nil)
if err != nil {
t.Fatal(err)
}
want := bytesFromHex(t, "a0de84c9654c2e78e33c899090f8dc0590046fda4ee29d133340800596401ae0df61bf8aa5689df3f873ad13cf55df5209c3a8c6450918b74c2017f87c2d588809740622c7752e3153a26d04bd3e9d9f6daa676e8e5e65a8a11d4fbd271d4693ab6a303652328dc1c923b484fa179fd6d9e8b523da74f3a307531c0dd75f243a041f7df22414dfdb83b3a241fe73e7af0f95cb6b60831bdd46dc05618e5cb3653476eb7d5405fa5ca98dad8f787ca86179055f305daa87eb424671878a93965e47d3002e2774be311d696b42e5691eddb2f788cd35246b408eb5d045c891ba1d57ce4c6fc935ceec90f7999406252f6266957cce4e7f12cf0ec94af358aeefa7")
if !bytes.Equal(sig, want) {
t.Fatalf("SignPSS: wrong sig\nhave %x\nwant %x", sig, want)
}
r.checkOffset(490)
}
func TestBoringRandEncryptOAEP(t *testing.T) {
r := testRand(t)
k := testKey(t)
enc, err := EncryptOAEP(sha256.New(), r, &k.PublicKey, []byte("hello"), []byte("label"))
if err != nil {
t.Fatal(err)
}
want := bytesFromHex(t, "55dc7b590a511c2d249232ecbb70040e8e0ec03206caae5ec0a401a0ad8013209ef546870f93d0946b9845ace092d456d092403f76f12ee65c2b8759731a25589d8a7e857407d09cfbe36ae36fc4daeb514ac597b1de2f7dc8450ab78a9e420c9b5dbbae3e402c8f378bd35505a47d556b705ab8985707a22e3583c172ef5730f05fd0845880d67c1ddd3c1525aa4c2c4e162bd6435a485609f6bd76c8ff73a7b5d043e4724458594703245fabdb479ef2786c757b35932a645399f2703647785b59b971970e6bccef3e6cd6fae39f9f135203eb104f0db20cf48e461cb7d824889c0d5d6a47cd0bf213c2f7acb3ddbd3effefebb4f60458ffc8b6ff1e4cc447")
if !bytes.Equal(enc, want) {
t.Fatalf("EncryptOAEP: wrong enc\nhave %x\nwant %x", enc, want)
}
r.checkOffset(32)
}
func TestBoringRandDecryptOAEP(t *testing.T) {
r := testRand(t)
k := testKey(t)
enc := bytesFromHex(t, "55dc7b590a511c2d249232ecbb70040e8e0ec03206caae5ec0a401a0ad8013209ef546870f93d0946b9845ace092d456d092403f76f12ee65c2b8759731a25589d8a7e857407d09cfbe36ae36fc4daeb514ac597b1de2f7dc8450ab78a9e420c9b5dbbae3e402c8f378bd35505a47d556b705ab8985707a22e3583c172ef5730f05fd0845880d67c1ddd3c1525aa4c2c4e162bd6435a485609f6bd76c8ff73a7b5d043e4724458594703245fabdb479ef2786c757b35932a645399f2703647785b59b971970e6bccef3e6cd6fae39f9f135203eb104f0db20cf48e461cb7d824889c0d5d6a47cd0bf213c2f7acb3ddbd3effefebb4f60458ffc8b6ff1e4cc447")
dec, err := DecryptOAEP(sha256.New(), r, k, enc, []byte("label"))
if err != nil {
t.Fatal(err)
}
want := []byte("hello")
if !bytes.Equal(dec, want) {
t.Fatalf("DecryptOAEP: wrong dec\nhave %x\nwant %x", dec, want)
}
r.checkOffset(256)
}
func TestBoringFinalizers(t *testing.T) {
if runtime.GOOS == "nacl" {
// Times out on nacl (without BoringCrypto)
// but not clear why - probably consuming rand.Reader too quickly
// and being throttled. Also doesn't really matter.
t.Skip("skipping on nacl")
}
k := testKey(t)
// 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.
atomic.StorePointer(&k.boring, nil)
// 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

@@ -6,7 +6,6 @@ package rsa
import (
"crypto"
"crypto/internal/boring"
"crypto/subtle"
"errors"
"io"
@@ -35,7 +34,7 @@ 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(random io.Reader, pub *PublicKey, msg []byte) ([]byte, error) {
func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error) {
if err := checkPub(pub); err != nil {
return nil, err
}
@@ -44,37 +43,20 @@ func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, erro
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, random)
err := nonZeroRandomBytes(ps, rand)
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)
copyWithLeftPad(em, c.Bytes())
return em, nil
}
@@ -91,20 +73,6 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byt
if err := checkPub(&priv.PublicKey); err != nil {
return nil, err
}
if boring.Enabled {
boringFakeRandomBlind(rand, priv)
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
@@ -172,27 +140,13 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid
return
}
if boring.Enabled {
boringFakeRandomBlind(rand, priv)
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 = leftPad(m.Bytes(), k)
c := new(big.Int).SetBytes(ciphertext)
m, err := decrypt(rand, priv, c)
if err != nil {
return
}
em = leftPad(m.Bytes(), k)
firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2)
@@ -271,7 +225,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(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
if err != nil {
return nil, err
@@ -283,15 +237,6 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [
return nil, ErrMessageTooLong
}
if boring.Enabled {
boringFakeRandomBlind(random, priv)
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
@@ -302,7 +247,7 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [
copy(em[k-hashLen:k], hashed)
m := new(big.Int).SetBytes(em)
c, err := decryptAndCheck(random, priv, m)
c, err := decryptAndCheck(rand, priv, m)
if err != nil {
return nil, err
}
@@ -317,17 +262,6 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [
// 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

@@ -64,7 +64,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: %v", i, err)
t.Errorf("#%d error decrypting", i)
}
want := []byte(test.out)
if !bytes.Equal(out, want) {

View File

@@ -11,7 +11,6 @@ package rsa
import (
"bytes"
"crypto"
"crypto/internal/boring"
"errors"
"hash"
"io"
@@ -198,22 +197,6 @@ func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed,
if err != nil {
return
}
if boring.Enabled {
boringFakeRandomBlind(rand, priv)
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 {
@@ -276,14 +259,6 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte,
hash = opts.Hash
}
if boring.Enabled && rand == boring.RandReader {
bkey, err := boringPrivateKey(priv)
if err != nil {
return nil, err
}
return boring.SignRSAPSS(bkey, hash, hashed, saltLength)
}
salt := make([]byte, saltLength)
if _, err := io.ReadFull(rand, salt); err != nil {
return nil, err
@@ -302,16 +277,6 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, opts
// verifyPSS verifies a PSS signature with the given salt length.
func verifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, saltLen int) error {
if boring.Enabled {
bkey, err := boringPublicKey(pub)
if err != nil {
return err
}
if err := boring.VerifyRSAPSS(bkey, hash, hashed, sig, saltLen); err != nil {
return ErrVerification
}
return nil
}
nBits := pub.N.BitLen()
if len(sig) != (nBits+7)/8 {
return ErrVerification

View File

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

View File

@@ -24,7 +24,6 @@ package rsa
import (
"crypto"
"crypto/internal/boring"
"crypto/rand"
"crypto/subtle"
"errors"
@@ -32,7 +31,6 @@ import (
"io"
"math"
"math/big"
"unsafe"
)
var bigZero = big.NewInt(0)
@@ -42,8 +40,6 @@ var bigOne = big.NewInt(1)
type PublicKey struct {
N *big.Int // modulus
E int // public exponent
boring unsafe.Pointer
}
// OAEPOptions is an interface for passing options to OAEP decryption using the
@@ -89,8 +85,6 @@ type PrivateKey struct {
// Precomputed contains precomputed values that speed up private
// operations, if available.
Precomputed PrecomputedValues
boring unsafe.Pointer
}
// Public returns the public key corresponding to priv.
@@ -216,32 +210,6 @@ func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) {
// [1] US patent 4405829 (1972, expired)
// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error) {
if boring.Enabled && random == boring.RandReader && nprimes == 2 && (bits == 2048 || bits == 3072) {
N, E, D, P, Q, Dp, Dq, Qinv, err := boring.GenerateKeyRSA(bits)
if err != nil {
return nil, err
}
e64 := E.Int64()
if E.Cmp(big.NewInt(e64)) != 0 || 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
@@ -376,7 +344,6 @@ 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
@@ -409,15 +376,6 @@ 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()
@@ -438,24 +396,10 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
mgf1XOR(db, hash, seed)
mgf1XOR(seed, hash, db)
var out []byte
if boring.Enabled {
var bkey *boring.PublicKeyRSA
bkey, err = boringPublicKey(pub)
if err != nil {
return nil, err
}
c, err := boring.EncryptRSANoPadding(bkey, em)
if err != nil {
return nil, err
}
out = c
} else {
m := new(big.Int)
m.SetBytes(em)
c := encrypt(new(big.Int), pub, m)
out = c.Bytes()
}
m := new(big.Int)
m.SetBytes(em)
c := encrypt(new(big.Int), pub, m)
out := c.Bytes()
if len(out) < k {
// If the output is too small, we need to left-pad with zeros.
@@ -533,9 +477,6 @@ 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
@@ -651,18 +592,6 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
return nil, ErrDecryption
}
if boring.Enabled {
boringFakeRandomBlind(random, priv)
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

@@ -7,29 +7,26 @@ package rsa
import (
"bytes"
"crypto"
"crypto/internal/boring"
"crypto/rand"
"crypto/sha1"
"crypto/sha256"
"fmt"
"math/big"
"testing"
)
func TestKeyGeneration(t *testing.T) {
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
}
size := 1024
if testing.Short() {
size = 128
}
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) {
@@ -113,25 +110,6 @@ 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)
@@ -180,10 +158,6 @@ func init() {
}
func BenchmarkRSA2048Decrypt(b *testing.B) {
if boring.Enabled {
b.Skip("no raw decrypt in BoringCrypto")
}
b.StopTimer()
c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313")
@@ -206,10 +180,6 @@ 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{
@@ -252,7 +222,7 @@ func TestEncryptOAEP(t *testing.T) {
n := new(big.Int)
for i, test := range testEncryptOAEPData {
n.SetString(test.modulus, 16)
public := PublicKey{N: n, E: test.e}
public := PublicKey{n, test.e}
for j, message := range test.msgs {
randomSource := bytes.NewReader(message.seed)
@@ -277,7 +247,7 @@ func TestDecryptOAEP(t *testing.T) {
n.SetString(test.modulus, 16)
d.SetString(test.d, 16)
private := new(PrivateKey)
private.PublicKey = PublicKey{N: n, E: test.e}
private.PublicKey = PublicKey{n, test.e}
private.D = d
for j, message := range test.msgs {
@@ -302,36 +272,6 @@ 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

View File

@@ -1,22 +0,0 @@
// 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.
// +build !cmd_go_bootstrap
package sha1
import (
"crypto/internal/boring"
"hash"
)
const boringEnabled = boring.Enabled
func boringNewSHA1() hash.Hash { return boring.NewSHA1() }
func boringUnreachable() { boring.Unreachable() }

View File

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

View File

@@ -49,9 +49,6 @@ func (d *digest) Reset() {
// New returns a new hash.Hash computing the SHA1 checksum.
func New() hash.Hash {
if boringEnabled {
return boringNewSHA1()
}
d := new(digest)
d.Reset()
return d
@@ -62,7 +59,6 @@ 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 {
@@ -86,7 +82,6 @@ func (d *digest) Write(p []byte) (nn int, err error) {
}
func (d0 *digest) Sum(in []byte) []byte {
boringUnreachable()
// Make a copy of d0 so that caller can keep writing and summing.
d := *d0
hash := d.checkSum()
@@ -196,13 +191,6 @@ func (d *digest) constSum() [Size]byte {
// Sum returns the SHA1 checksum of the data.
func Sum(data []byte) [Size]byte {
if boringEnabled {
h := New()
h.Write(data)
var ret [Size]byte
h.Sum(ret[:0])
return ret
}
var d digest
d.Reset()
d.Write(data)

View File

@@ -7,7 +7,6 @@
package sha1
import (
"crypto/internal/boring"
"crypto/rand"
"fmt"
"io"
@@ -74,9 +73,6 @@ 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:])
@@ -107,9 +103,6 @@ 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)

View File

@@ -8,7 +8,6 @@ package sha256
import (
"crypto"
"crypto/internal/boring"
"hash"
)
@@ -81,9 +80,6 @@ func (d *digest) Reset() {
// New returns a new hash.Hash computing the SHA256 checksum.
func New() hash.Hash {
if boring.Enabled {
return boring.NewSHA256()
}
d := new(digest)
d.Reset()
return d
@@ -91,9 +87,6 @@ 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()
@@ -110,7 +103,6 @@ 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 {
@@ -134,7 +126,6 @@ func (d *digest) Write(p []byte) (nn int, err error) {
}
func (d0 *digest) Sum(in []byte) []byte {
boring.Unreachable()
// Make a copy of d0 so that caller can keep writing and summing.
d := *d0
hash := d.checkSum()
@@ -184,13 +175,6 @@ func (d *digest) checkSum() [Size]byte {
// Sum256 returns the SHA256 checksum of the data.
func Sum256(data []byte) [Size]byte {
if boring.Enabled {
h := New()
h.Write(data)
var ret [Size]byte
h.Sum(ret[:0])
return ret
}
var d digest
d.Reset()
d.Write(data)
@@ -199,13 +183,6 @@ func Sum256(data []byte) [Size]byte {
// Sum224 returns the SHA224 checksum of the data.
func Sum224(data []byte) (sum224 [Size224]byte) {
if boring.Enabled {
h := New224()
h.Write(data)
var ret [Size224]byte
h.Sum(ret[:0])
return ret
}
var d digest
d.is224 = true
d.Reset()

View File

@@ -7,7 +7,6 @@
package sha256
import (
"crypto/internal/boring"
"crypto/rand"
"fmt"
"io"
@@ -154,9 +153,6 @@ 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)

View File

@@ -8,7 +8,6 @@ package sha512
import (
"crypto"
"crypto/internal/boring"
"hash"
)
@@ -127,9 +126,6 @@ func (d *digest) Reset() {
// 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
@@ -151,9 +147,6 @@ 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
@@ -175,9 +168,6 @@ 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 {
@@ -201,9 +191,6 @@ func (d *digest) Write(p []byte) (nn int, err error) {
}
func (d0 *digest) Sum(in []byte) []byte {
if d0.function != crypto.SHA512_224 && d0.function != crypto.SHA512_256 {
boring.Unreachable()
}
// Make a copy of d0 so that caller can keep writing and summing.
d := new(digest)
*d = *d0
@@ -264,13 +251,6 @@ func (d *digest) checkSum() [Size]byte {
// Sum512 returns the SHA512 checksum of the data.
func Sum512(data []byte) [Size]byte {
if boring.Enabled {
h := New()
h.Write(data)
var ret [Size]byte
h.Sum(ret[:0])
return ret
}
d := digest{function: crypto.SHA512}
d.Reset()
d.Write(data)
@@ -279,13 +259,6 @@ func Sum512(data []byte) [Size]byte {
// Sum384 returns the SHA384 checksum of the data.
func Sum384(data []byte) (sum384 [Size384]byte) {
if boring.Enabled {
h := New384()
h.Write(data)
var ret [Size384]byte
h.Sum(ret[:0])
return ret
}
d := digest{function: crypto.SHA384}
d.Reset()
d.Write(data)

View File

@@ -7,7 +7,6 @@
package sha512
import (
"crypto/internal/boring"
"crypto/rand"
"encoding/hex"
"hash"
@@ -308,9 +307,6 @@ 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)

View File

@@ -1,121 +0,0 @@
// 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 tls
import (
"crypto/ecdsa"
"crypto/internal/boring/fipstls"
"crypto/rsa"
"crypto/x509"
)
// 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
}
// default FIPSCipherSuites is the FIPS-allowed cipher suites,
// in preference order (most preferable first).
var defaultFIPSCipherSuites = []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 defaultFIPSCipherSuites
}
var list []uint16
for _, id := range c.CipherSuites {
for _, allowed := range defaultFIPSCipherSuites {
if id == allowed {
list = append(list, id)
break
}
}
}
return list
}
// isBoringCertificate reports whether a certificate may be used
// when constructing a verified chain.
// It is called for each leaf, intermediate, and root certificate.
func isBoringCertificate(c *x509.Certificate) bool {
if !needFIPS() {
// Everything is OK if we haven't forced FIPS-only mode.
return true
}
// Otherwise the key must be RSA 2048, RSA 3072, or ECDSA P-256.
switch k := c.PublicKey.(type) {
default:
return false
case *rsa.PublicKey:
if size := k.N.BitLen(); size != 2048 && size != 3072 {
return false
}
case *ecdsa.PublicKey:
if name := k.Curve.Params().Name; name != "P-256" && name != "P-384" {
return false
}
}
return true
}
// supportedSignatureAlgorithms returns the supported signature algorithms.
// It knows that the FIPS-allowed ones are all at the beginning of
// defaultSupportedSignatureAlgorithms.
func supportedSignatureAlgorithms() []signatureAndHash {
all := defaultSupportedSignatureAlgorithms
if !needFIPS() {
return all
}
i := 0
for i < len(all) && all[i].hash != hashSHA1 {
i++
}
return all[:i]
}
var testingOnlyForceClientHelloSignatureAndHashes []signatureAndHash

View File

@@ -1,579 +0,0 @@
// 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 tls
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/internal/boring/fipstls"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"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,
cipherSuites: allCipherSuites(),
compressionMethods: []uint8{compressionNone},
}
testClientHelloFailure(t, serverConfig, clientHello, msg)
})
}
test("VersionSSL30", VersionSSL30, "")
test("VersionTLS10", VersionTLS10, "")
test("VersionTLS11", VersionTLS11, "")
test("VersionTLS12", VersionTLS12, "")
fipstls.Force()
defer fipstls.Abandon()
test("VersionSSL30", VersionSSL30, "unsupported, maximum protocol version")
test("VersionTLS10", VersionTLS10, "unsupported, maximum protocol version")
test("VersionTLS11", VersionTLS11, "unsupported, maximum protocol version")
test("VersionTLS12", 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&suiteECDSA == suiteECDSA
}
}
panic(fmt.Sprintf("unknown cipher suite %#x", id))
}
func isBoringSignatureAndHash(sigHash signatureAndHash) bool {
switch sigHash.signature {
default:
return false
case signatureRSA,
signatureECDSA:
// ok
}
switch sigHash.hash {
default:
return false
case hashSHA256,
hashSHA384:
// 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,
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,
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 := realNetPipe(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) {
serverConfig := testConfig.Clone()
serverConfig.Certificates = make([]Certificate, 1)
defer func() {
testingOnlyForceClientHelloSignatureAndHashes = nil
}()
for _, sigHash := range defaultSupportedSignatureAlgorithms {
testingOnlyForceClientHelloSignatureAndHashes = []signatureAndHash{sigHash}
t.Run(fmt.Sprintf("%v", sigHash), func(t *testing.T) {
if sigHash.signature == signatureRSA {
serverConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
serverConfig.Certificates[0].Certificate = [][]byte{testRSACertificate}
serverConfig.Certificates[0].PrivateKey = testRSAPrivateKey
} else {
serverConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}
serverConfig.Certificates = make([]Certificate, 1)
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
}
serverConfig.BuildNameToCertificate()
clientErr, _ := boringHandshake(t, testConfig, serverConfig)
if clientErr != nil {
t.Fatalf("expected handshake with %v to succeed; err=%v", sigHash, clientErr)
}
// 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 isBoringSignatureAndHash(sigHash) {
if clientErr != nil {
t.Fatalf("expected handshake with %v to succeed; err=%v", sigHash, clientErr)
}
} else {
if clientErr == nil {
t.Fatalf("expected handshake with %v 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.CipherSuites = allCipherSuites()
clientConfig.CurvePreferences = defaultCurvePreferences
go Client(c, testConfig).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 hello.vers != VersionTLS12 {
t.Errorf("client vers=%#x, want %#x (TLS 1.2)", hello.vers, VersionTLS12)
}
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.signatureAndHashes {
if !isBoringSignatureAndHash(sigHash) {
t.Errorf("client offered disallowed signature-and-hash %v", sigHash)
}
}
}
func TestBoringCertAlgs(t *testing.T) {
// NaCl and arm 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" {
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)
// boringCert checked that isBoringCertificate matches the caller's boringCertFIPSOK bit.
// If not, no point in building bigger end-to-end tests.
if t.Failed() {
t.Fatalf("isBoringCertificate failures; not continuing")
}
// 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{}
var desc string
switch k := key.(type) {
case *rsa.PrivateKey:
pub = &k.PublicKey
desc = fmt.Sprintf("RSA-%d", k.N.BitLen())
case *ecdsa.PrivateKey:
pub = &k.PublicKey
desc = "ECDSA-" + k.Curve.Params().Name
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)
}
// Tell isBoringCertificate to enforce FIPS restrictions for this check.
fipstls.Force()
defer fipstls.Abandon()
fipsOK := mode&boringCertFIPSOK != 0
if isBoringCertificate(cert) != fipsOK {
t.Errorf("isBoringCertificate(cert with %s key) = %v, want %v", desc, !fipsOK, fipsOK)
}
return &boringCertificate{name, org, parentOrg, der, cert, key, fipsOK}
}
func boringPool(t *testing.T, list ...*boringCertificate) *x509.CertPool {
pool := x509.NewCertPool()
for _, c := range list {
cert, err := x509.ParseCertificate(c.der)
if err != nil {
t.Fatal(err)
}
pool.AddCert(cert)
}
return pool
}
func boringList(t *testing.T, list ...*boringCertificate) [][]byte {
var all [][]byte
for _, c := range list {
all = append(all, c.der)
}
return all
}
// realNetPipe is like net.Pipe but returns an actual network socket pair,
// which has buffering that avoids various deadlocks if both sides
// try to speak at the same time.
func realNetPipe(t *testing.T) (net.Conn, net.Conn) {
l := newLocalListener(t)
defer l.Close()
c, err := net.Dial("tcp", l.Addr().String())
if err != nil {
t.Fatal(err)
}
s, err := l.Accept()
if err != nil {
c.Close()
t.Fatal(err)
}
return c, s
}

View File

@@ -9,7 +9,6 @@ import (
"crypto/cipher"
"crypto/des"
"crypto/hmac"
"crypto/internal/boring"
"crypto/rc4"
"crypto/sha1"
"crypto/sha256"
@@ -136,11 +135,7 @@ func macSHA1(version uint16, key []byte) macFunction {
copy(mac.key, key)
return mac
}
h := sha1.New
if !boring.Enabled {
h = newConstantTimeHash(h)
}
return tls10MAC{hmac.New(h, key)}
return tls10MAC{hmac.New(newConstantTimeHash(sha1.New), key)}
}
// macSHA256 returns a SHA-256 based MAC. These are only supported in TLS 1.2
@@ -220,22 +215,12 @@ func (f *xorNonceAEAD) Open(out, nonce, plaintext, additionalData []byte) ([]byt
return result, err
}
type gcmtls interface {
NewGCMTLS() (cipher.AEAD, error)
}
func aeadAESGCM(key, fixedNonce []byte) cipher.AEAD {
aes, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
var aead cipher.AEAD
if aesTLS, ok := aes.(gcmtls); ok {
aead, err = aesTLS.NewGCMTLS()
} else {
boring.Unreachable()
aead, err = cipher.NewGCM(aes)
}
aead, err := cipher.NewGCM(aes)
if err != nil {
panic(err)
}
@@ -313,11 +298,6 @@ 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 {
if boring.Enabled {
// The BoringCrypto SHA1 does not have a constant-time
// checksum function, so don't try to use it.
return h
}
return func() hash.Hash {
return &cthWrapper{h().(constantTimeHash)}
}

View File

@@ -145,10 +145,10 @@ type signatureAndHash struct {
hash, signature uint8
}
// defaultSupportedSignatureAlgorithms contains the signature and hash algorithms that
// supportedSignatureAlgorithms 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.
var defaultSupportedSignatureAlgorithms = []signatureAndHash{
var supportedSignatureAlgorithms = []signatureAndHash{
{hashSHA256, signatureRSA},
{hashSHA256, signatureECDSA},
{hashSHA384, signatureRSA},
@@ -670,9 +670,6 @@ func (c *Config) time() time.Time {
}
func (c *Config) cipherSuites() []uint16 {
if needFIPS() {
return fipsCipherSuites(c)
}
s := c.CipherSuites
if s == nil {
s = defaultCipherSuites()
@@ -681,9 +678,6 @@ func (c *Config) cipherSuites() []uint16 {
}
func (c *Config) minVersion() uint16 {
if needFIPS() {
return fipsMinVersion(c)
}
if c == nil || c.MinVersion == 0 {
return minVersion
}
@@ -691,9 +685,6 @@ func (c *Config) minVersion() uint16 {
}
func (c *Config) maxVersion() uint16 {
if needFIPS() {
return fipsMaxVersion(c)
}
if c == nil || c.MaxVersion == 0 {
return maxVersion
}
@@ -703,9 +694,6 @@ func (c *Config) maxVersion() 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

@@ -1,27 +0,0 @@
// 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 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 in the dev.boringcrypto branch of Go.
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

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

@@ -99,11 +99,7 @@ NextCipherSuite:
}
if hello.vers >= VersionTLS12 {
hello.signatureAndHashes = supportedSignatureAlgorithms()
}
if testingOnlyForceClientHelloSignatureAndHashes != nil {
hello.signatureAndHashes = testingOnlyForceClientHelloSignatureAndHashes
hello.signatureAndHashes = supportedSignatureAlgorithms
}
var session *ClientSessionState
@@ -289,8 +285,6 @@ func (hs *clientHandshakeState) doFullHandshake() error {
if !c.config.InsecureSkipVerify {
opts := x509.VerifyOptions{
IsBoring: isBoringCertificate,
Roots: c.config.RootCAs,
CurrentTime: c.config.time(),
DNSName: c.config.ServerName,

View File

@@ -137,7 +137,7 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
}
}
if rand.Intn(10) > 5 {
m.signatureAndHashes = supportedSignatureAlgorithms()
m.signatureAndHashes = supportedSignatureAlgorithms
}
m.alpnProtocols = make([]string, rand.Intn(5))
for i := range m.alpnProtocols {

View File

@@ -422,7 +422,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
}
if c.vers >= VersionTLS12 {
certReq.hasSignatureAndHash = true
certReq.signatureAndHashes = supportedSignatureAlgorithms()
certReq.signatureAndHashes = supportedSignatureAlgorithms
}
// An empty list of certificateAuthorities signals to
@@ -526,7 +526,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
var signatureAndHash signatureAndHash
if certVerify.hasSignatureAndHash {
signatureAndHash = certVerify.signatureAndHash
if !isSupportedSignatureAndHash(signatureAndHash, supportedSignatureAlgorithms()) {
if !isSupportedSignatureAndHash(signatureAndHash, supportedSignatureAlgorithms) {
return errors.New("tls: unsupported hash function for client certificate")
}
} else {
@@ -722,8 +722,6 @@ func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (c
if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
opts := x509.VerifyOptions{
IsBoring: isBoringCertificate,
Roots: c.config.ClientCAs,
CurrentTime: c.config.time(),
Intermediates: x509.NewCertPool(),

View File

@@ -114,7 +114,7 @@ func md5SHA1Hash(slices [][]byte) []byte {
// only used for >= TLS 1.2 and precisely identifies the hash function to use.
func hashForServerKeyExchange(sigAndHash signatureAndHash, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
if version >= VersionTLS12 {
if !isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms()) {
if !isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms) {
return nil, crypto.Hash(0), errors.New("tls: unsupported hash function used by peer")
}
hashFunc, err := lookupTLSHash(sigAndHash.hash)
@@ -149,7 +149,7 @@ func pickTLS12HashForSignature(sigType uint8, clientList []signatureAndHash) (ui
if sigAndHash.signature != sigType {
continue
}
if isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms()) {
if isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms) {
return sigAndHash.hash, nil
}
}

View File

@@ -319,7 +319,7 @@ func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureA
}
for _, v := range serverList {
if v.signature == sigType && isSupportedSignatureAndHash(v, supportedSignatureAlgorithms()) {
if v.signature == sigType && isSupportedSignatureAndHash(v, supportedSignatureAlgorithms) {
return v, nil
}
}

View File

@@ -156,11 +156,6 @@ type VerifyOptions struct {
// constraint down the chain which mirrors Windows CryptoAPI behavior,
// but not the spec. To accept any key usage, include ExtKeyUsageAny.
KeyUsages []ExtKeyUsage
// IsBoring is a validity check for BoringCrypto.
// If not nil, it will be called to check whether a given certificate
// can be used for constructing verification chains.
IsBoring func(*Certificate) bool
}
const (
@@ -253,13 +248,6 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
}
}
if opts.IsBoring != nil && !opts.IsBoring(c) {
// IncompatibleUsage is not quite right here,
// but it's also the "no chains found" error
// and is close enough.
return CertificateInvalidError{c, IncompatibleUsage}
}
return nil
}

View File

@@ -848,6 +848,7 @@ type (
TypeSpec struct {
Doc *CommentGroup // associated documentation; or nil
Name *Ident // type name
Assign token.Pos // position of '=', if any
Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes
Comment *CommentGroup // line comments; or nil
}

View File

@@ -290,7 +290,8 @@ func defaultContext() Context {
// in all releases >= Go 1.x. Code that requires Go 1.x or later should
// say "+build go1.x", and code that should only be built before Go 1.x
// (perhaps it is the stub to use in that case) should say "+build !go1.x".
c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7", "go1.8"}
// NOTE: If you add to this list, also update the doc comment in doc.go.
c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7", "go1.8", "go1.8.typealias"}
env := os.Getenv("CGO_ENABLED")
if env == "" {

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