[dev.boringcrypto.go1.11] all: merge go1.11.11 into dev.boringcrypto.go1.11

Change-Id: Ib34dd423b6d83a7e5d0c1f9d7be638aa892fa28c
diff --git a/README.boringcrypto.md b/README.boringcrypto.md
new file mode 100644
index 0000000..b6f5805
--- /dev/null
+++ b/README.boringcrypto.md
@@ -0,0 +1,18 @@
+# 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.
diff --git a/VERSION b/VERSION
deleted file mode 100644
index bff546b..0000000
--- a/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-go1.11.11
\ No newline at end of file
diff --git a/api/go1.9.txt b/api/go1.9.txt
index c23a17e..c7a4968 100644
--- a/api/go1.9.txt
+++ b/api/go1.9.txt
@@ -7,6 +7,7 @@
 pkg crypto, const BLAKE2s_256 = 16
 pkg crypto, const BLAKE2s_256 Hash
 pkg crypto/x509, type Certificate struct, ExcludedDNSDomains []string
+pkg crypto/x509, type VerifyOptions struct, IsBoring func(*Certificate) bool
 pkg database/sql, method (*Conn) BeginTx(context.Context, *TxOptions) (*Tx, error)
 pkg database/sql, method (*Conn) Close() error
 pkg database/sql, method (*Conn) ExecContext(context.Context, string, ...interface{}) (Result, error)
diff --git a/misc/boring/README.md b/misc/boring/README.md
new file mode 100644
index 0000000..405e36c
--- /dev/null
+++ b/misc/boring/README.md
@@ -0,0 +1,114 @@
+# README.md
+
+This directory holds build scripts for unofficial, unsupported
+distributions of Go+BoringCrypto.
+
+## Version strings
+
+The distribution name for a Go+BoringCrypto release has the form `<GoVersion>b<BoringCryptoVersion>`,
+where `<GoVersion>` is the Go version the release is based on, and `<BoringCryptoVersion>` is
+an integer that increments each time there is a new release with different BoringCrypto bits.
+The `<BoringCryptoVersion>` is stored in the `VERSION` file in this directory.
+
+For example, the first release is based on Go 1.8.3 is `go1.8.3b1`.
+If the BoringCrypto bits are updated, the next would be `go1.8.3b2`.
+If, after that, Go 1.9 is released and the same BoringCrypto code added to it,
+that would result in `go1.9b2`. There would likely not be a `go1.9b1`,
+since that would indicate Go 1.9 with the older BoringCrypto code.
+
+## Releases
+
+The `build.release` script prepares a binary release and publishes it in Google Cloud Storage
+at `gs://go-boringcrypto/`, making it available for download at
+`https://go-boringcrypto.storage.googleapis.com/<FILE>`.
+The script records each published release in the `RELEASES` file in this directory.
+
+The `build.docker` script, which must be run after `build.release`, prepares a Docker image
+and publishes it on hub.docker.com in the goboring organization.
+`go1.8.3b1` is published as `goboring/golang:1.8.3b1`.
+
+## Release process
+
+1. If the BoringCrypto bits have been updated, increment the number in `VERSION`,
+send that change out as a CL for review, get it committed, and run `git sync`.
+
+2. Run `build.release`, which will determine the base Go version and the BoringCrypto
+version, build a release, and upload it.
+
+3. Run `build.docker`, which will build and upload a Docker image from the latest release.
+
+4. Send out a CL with the updated `RELEASES` file and get it committed.
+
+## Release process for dev.boringcrypto.go1.8.
+
+In addition to the dev.boringcrypto branch, we have a dev.boringcrypto.go1.8 branch,
+which is BoringCrypto backported to the Go 1.8 release branch.
+To issue new BoringCrypto releases based on Go 1.8:
+
+1. Do a regular release on the (not Go 1.8) dev.boringcrypto branch.
+
+2. Change to the dev.boringcrypto.go1.8 branch and cherry-pick all
+BoringCrypto updates, including the update of the `VERSION` file.
+Mail them out and get them committed.
+
+3. **Back on the (not Go 1.8) dev.boringcrypto branch**,
+run `make.bash` and then `build.release <commit>`,
+where `<commit>` is the latest commit on the dev.boringcrypto.go1.8 branch.
+The script will build a release and upload it.
+
+4. Run `build.docker`.
+
+5. Send out a CL with the updated `RELEASES` file and get it committed.
+
+## Building from Docker
+
+A Dockerfile that starts with `FROM golang:1.8.3` can switch
+to `FROM goboring/golang:1.8.3b2` (see [goboring/golang on Docker Hub](https://hub.docker.com/r/goboring/golang/))
+and should need no other modifications.
+
+## Building from Bazel
+
+Starting from [bazelbuild/rules_go](https://github.com/bazelbuild/rules_go)
+tag 0.7.1, simply download the BoringCrypto-enabled Go SDK using
+`go_download_sdk()` before calling `go_register_toolchains()`.
+
+For example, to use Go 1.9.3 with BoringCrypto on Linux, use the following lines
+in `WORKSPACE`:
+```python
+load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_download_sdk", "go_register_toolchains")
+
+go_rules_dependencies()
+
+go_download_sdk(
+    name = "go_sdk",
+    sdks = {
+       "linux_amd64": ("go1.9.3b4.linux-amd64.tar.gz", "db1997b2454a2f27669b849d2d2cafb247a55128d53da678f06cb409310d6660"),
+    },
+    urls = ["https://storage.googleapis.com/go-boringcrypto/{}"],
+)
+
+go_register_toolchains()
+```
+
+**Note**: you must *not* enable `pure` mode, since cgo must be enabled. To
+ensure that binaries are linked with BoringCrypto, you can set `pure = "off"` on
+all relevant `go_binary` rules.
+
+## Caveat
+
+BoringCrypto is used for a given build only in limited circumstances:
+
+  - The build must be GOOS=linux, GOARCH=amd64.
+  - The build must have cgo enabled.
+  - The android build tag must not be specified.
+  - The cmd_go_bootstrap build tag must not be specified.
+
+The version string reported by `runtime.Version` does not indicate that BoringCrypto
+was actually used for the build. For example, linux/386 and non-cgo linux/amd64 binaries
+will report a version of `go1.8.3b2` but not be using BoringCrypto.
+
+To check whether a given binary is using BoringCrypto, run `go tool nm` on it and check
+that it has symbols named `*_Cfunc__goboringcrypto_*`.
+
+The program [rsc.io/goversion](https://godoc.org/rsc.io/goversion) will report the
+crypto implementation used by a given binary when invoked with the `-crypto` flag.
diff --git a/misc/boring/RELEASES b/misc/boring/RELEASES
new file mode 100644
index 0000000..b271985
--- /dev/null
+++ b/misc/boring/RELEASES
@@ -0,0 +1,17 @@
+# This file lists published Go+BoringCrypto releases.
+# Each line describes a single release: <version> <git commit> <target> <URL> <sha256sum>
+go1.9rc2b2 91753387bdf7 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.9rc2b2.linux-amd64.tar.gz 59355a45e6970e8013060851ddb3f079afe8db52e90db520a0826a13f1b5ae5b
+go1.8.3b3 f6ff81bac156 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.8.3b3.linux-amd64.tar.gz 6287ad971cd268bb2684fb8b1275dea928ad527823062bc057e73036c419e7af
+go1.9rc2b4 c339bc4e07a6 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.9rc2b4.linux-amd64.tar.gz a8f677d48dc93920065fca4dca1a55bf7110aba132489c47e25d26d55c67eb32
+go1.9b4 e6ad24cde71e linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.9b4.linux-amd64.tar.gz 6592e36a05df8e7c59812328a3a4bfa6c4eed72132fc31245951c3ade3ef2a8a
+go1.9b4 e6ad24cde71e src https://go-boringcrypto.storage.googleapis.com/go1.9b4.src.tar.gz c85f31dc743fee0e8ce0c6ffc286e27c1f51b66c9b923afafb43cdc378a41091
+go1.8.3b4 42cb4dcdb59a linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.8.3b4.linux-amd64.tar.gz 4011c86e6175925e1c63dc7c19a51f825be53bbe7b08260918e5107b0fbd4f85
+go1.8.3b4 42cb4dcdb59a src https://go-boringcrypto.storage.googleapis.com/go1.8.3b4.src.tar.gz 2531ca8918aa024aed8f4a6c9e5c3b25bc8777623f1efa66aec7214601d474e4
+go1.9.2b4 cda3c6f91d7c linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.9.2b4.linux-amd64.tar.gz 7c5e9a033ddc3ab36646e3bac7fd16962742710c70c18122e44a9ab56cdd3cf7
+go1.9.2b4 cda3c6f91d7c src https://go-boringcrypto.storage.googleapis.com/go1.9.2b4.src.tar.gz 38a2260b64a6a5ab20f8972d08b4765bad116721356433f39aebd29c7598218c
+go1.9.3b4 f4e5ebdf35c8 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.9.3b4.linux-amd64.tar.gz db1997b2454a2f27669b849d2d2cafb247a55128d53da678f06cb409310d6660
+go1.9.3b4 f4e5ebdf35c8 src https://go-boringcrypto.storage.googleapis.com/go1.9.3b4.src.tar.gz 7485e1fc53a9fab9cf34f71de74d69f4c50f9d11a449647de40ee04b59bf8a5b
+go1.9.7b4 0bad1bef406e linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.9.7b4.linux-amd64.tar.gz 9e33a0deb8fed3bd7fa3d122bb5143be9e0a974a422ab4ddac5e765fa1310a6f
+go1.9.7b4 0bad1bef406e src https://go-boringcrypto.storage.googleapis.com/go1.9.7b4.src.tar.gz ad9fb6e22a27382c468467ecade4937f725b33818852f1c1da0d09b471e7486c
+go1.10.3b4 35ba5284935c linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.10.3b4.linux-amd64.tar.gz 6754729d78a375bd1debd980b1e3e7fd49198a980d0bbd8f39e89569aa001942
+go1.10.3b4 35ba5284935c src https://go-boringcrypto.storage.googleapis.com/go1.10.3b4.src.tar.gz f3e75c60a835c11b97e30429b63917ceb31f799b2ba7e2001d99db908fb8e28f
diff --git a/misc/boring/VERSION b/misc/boring/VERSION
new file mode 100644
index 0000000..b8626c4
--- /dev/null
+++ b/misc/boring/VERSION
@@ -0,0 +1 @@
+4
diff --git a/misc/boring/build.docker b/misc/boring/build.docker
new file mode 100755
index 0000000..992c859
--- /dev/null
+++ b/misc/boring/build.docker
@@ -0,0 +1,57 @@
+#!/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.
+
+# build.docker builds and publishes a Docker image for
+# a given Go+BoringCrypto release.
+
+set -e
+
+# With no arguments, use the most recent linux-amd64 release in the RELEASES file.
+case "$#" in
+0)
+	version=$(grep linux-amd64 RELEASES | tail -1 | awk '{print $1}');;
+1)
+	version="$1";;
+*)
+	echo 'usage: build.docker [version]' >&2
+	exit 2
+esac
+
+url="$(grep "^$version .* linux-amd64 " RELEASES | awk '{print $4}')"
+sha256="$(grep "^$version .* linux-amd64 " RELEASES | awk '{print $5}')"
+if [ "$sha256" = "" ]; then
+	echo "cannot find $version in RELEASES file" >&2
+	exit 2
+fi
+
+# Build a temporary directory with a Dockerfile.
+dir=$(mktemp -d)
+trap "rm -rf $dir" EXIT
+
+if echo "$url" | grep '!' >/dev/null; then
+	# ! is sed delimiter below. Should never happen.
+	echo "URL contains an exclamation mark!" >&2
+	exit 2
+fi
+
+sed "s!UUU!$url!; s/SSS/$sha256/" dockerfile.in >$dir/Dockerfile
+cp go-wrapper $dir/go-wrapper
+
+dversion=$(echo "$version" | sed 's/^go//')
+docker build -t goboring/golang:$dversion $dir
+docker run goboring/golang:$dversion go version
+docker run goboring/golang:$dversion go tool nm /usr/local/go/bin/go >$dir/nm
+if ! grep crypto/sha1.boringNewSHA1 $dir/nm >/dev/null; then
+	echo 'built docker image but did NOT find sha1.boringNewSHA1 in go command!' >&2
+	exit 2
+fi
+if egrep 'crypto/sha1\.\(\*digest\)' $dir/nm >/dev/null; then
+	echo 'built docker image but DID find sha1.(*digest) in go command unexpectedly!' >&2
+	exit 2
+fi
+docker push goboring/golang:$dversion
+
+echo
+echo published as goboring/golang:$dversion
diff --git a/misc/boring/build.release b/misc/boring/build.release
new file mode 100755
index 0000000..b78bfe3
--- /dev/null
+++ b/misc/boring/build.release
@@ -0,0 +1,104 @@
+#!/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.
+
+# build.release builds and publishes a new Go+BoringCrypto release.
+# After running this script, the change to the RELEASES file should be
+# sent out for review and committed to the repository (but the release
+# is already done, so there's not much to review).
+
+set -e
+
+case "$#" in
+0)
+	rev=HEAD;;
+1)
+	rev="$1";;
+*)
+	echo 'usage: build.release [git-rev]' >&2
+	exit 2
+esac
+
+# Determine commit to use.
+commit=$(git rev-parse "$rev" | awk '{print substr($1, 1, 12)}')
+if [ "$commit" = "" ]; then
+	echo 'cannot find commit in git history' >&2
+	exit 2
+fi
+
+# Determine base Go release from tags.
+base=$(git log --decorate=short --oneline "$rev" | grep 'tag: go' | sed 1q | sed 's/[),].*//; s/.*tag: //')
+if [ "$base" = "" ]; then
+	echo "cannot find go release tag in git history for $rev" >&2
+	exit 2
+fi
+
+# Determine boring crypto version from file.
+boring=$(git show "$commit:misc/boring/VERSION")
+if [ "$boring" = "" ]; then
+	echo "missing BORINGVERSION file in $commit" >&2
+	exit 2
+fi
+
+# Make sure we're not redefining a published release.
+version="${base}b${boring}"
+if grep "^$version " RELEASES >/dev/null; then
+	echo "found $version in RELEASES - not rereleasing" >&2
+	exit 2
+fi
+
+# Show what's going on, while the release builds.
+# Good time for user to type ^C if something is wrong.
+echo >&2
+echo "building $version from $commit" >&2
+echo >&2
+git log -n1 "$commit" >&2
+echo >&2
+
+# Build the release tool in a temporary GOPATH.
+dir=$(mktemp -d)
+trap "rm -rf $dir" EXIT
+export GOPATH="$dir"
+export GOBIN="$dir"
+go get -u golang.org/x/build/cmd/release
+
+# Build the release.
+sha() {
+    if hash sha256sum 2>/dev/null; then
+        sha256sum "$@"
+    else
+        shasum -a 256 "$@"
+    fi
+}
+shortgo=$(echo "$base" | perl -pe 's/(go\d+\.\d+)(\.\d+|rc\d+)/$1/')
+$dir/release -target linux-amd64 -rev "$commit" -version "$version" -tools "release-branch.$shortgo"
+$dir/release -target src -rev "$commit" -version "$version" -tools "release-branch.$shortgo"
+output="$version.linux-amd64.tar.gz"
+ls -l "$output"
+sha256=$(sha "$output" | awk '{print $1}')
+outputsrc="$version.src.tar.gz"
+ls -l "$outputsrc"
+sha256src=$(sha "$outputsrc" | awk '{print $1}')
+
+trap "rm -f /tmp/go.release.$$ /tmp/go.nm.$$" EXIT
+tar -xzf "$output" -O go/bin/go >/tmp/go.release.$$
+go tool nm /tmp/go.release.$$ >/tmp/go.nm.$$
+if ! grep crypto/sha1.boringNewSHA1 /tmp/go.nm.$$ >/dev/null; then
+	echo 'built release but did NOT find sha1.boringNewSHA1 in go command!' >&2
+	exit 2
+fi
+if egrep 'crypto/sha1\.\(\*digest\)' /tmp/go.nm.$$ >/dev/null; then
+	echo 'built release but DID find sha1.(*digest) in go command unexpectedly!' >&2
+	exit 2
+fi
+
+# Publish the release.
+gsutil cp "$output" gs://go-boringcrypto/
+url="https://go-boringcrypto.storage.googleapis.com/$output"
+gsutil cp "$outputsrc" gs://go-boringcrypto/
+urlsrc="https://go-boringcrypto.storage.googleapis.com/$outputsrc"
+
+# Record that it was published.
+echo "$version $commit linux-amd64 $url $sha256" >>RELEASES
+echo "$version $commit src $urlsrc $sha256src" >>RELEASES
diff --git a/misc/boring/dockerfile.in b/misc/boring/dockerfile.in
new file mode 100644
index 0000000..dc03cd6
--- /dev/null
+++ b/misc/boring/dockerfile.in
@@ -0,0 +1,29 @@
+# Template for Dockerfile, used in build.docker script.
+# Based on https://github.com/docker-library/golang/blob/master/1.9-rc/stretch/Dockerfile
+FROM buildpack-deps:stretch-scm
+
+# gcc for cgo
+RUN apt-get update && apt-get install -y --no-install-recommends \
+		g++ \
+		gcc \
+		libc6-dev \
+		make \
+		pkg-config \
+	&& rm -rf /var/lib/apt/lists/*
+
+ADD UUU /go.tgz
+
+RUN set -eux; \
+	\
+	echo "SSS /go.tgz" | sha256sum -c -; \
+	tar -C /usr/local -xzf /go.tgz; \
+	rm /go.tgz; \
+	export PATH="/usr/local/go/bin:$PATH"; \
+	go version
+
+ENV GOPATH /go
+ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
+RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
+WORKDIR $GOPATH
+
+COPY go-wrapper /usr/local/bin/
diff --git a/misc/boring/go-wrapper b/misc/boring/go-wrapper
new file mode 100755
index 0000000..eacd6cc
--- /dev/null
+++ b/misc/boring/go-wrapper
@@ -0,0 +1,100 @@
+#!/bin/sh
+# Copied from https://raw.githubusercontent.com/docker-library/golang/master/1.9-rc/stretch/go-wrapper
+# Copied into Docker images.
+
+set -e
+
+usage() {
+	base="$(basename "$0")"
+	cat <<EOUSAGE
+
+usage: $base command [args]
+
+This script assumes that is is run from the root of your Go package (for
+example, "/go/src/app" if your GOPATH is set to "/go").
+
+In Go 1.4, a feature was introduced to supply the canonical "import path" for a
+given package in a comment attached to a package statement
+(https://golang.org/s/go14customimport).
+
+This script allows us to take a generic directory of Go source files such as
+"/go/src/app" and determine that the canonical "import path" of where that code
+expects to live and reference itself is "github.com/jsmith/my-cool-app".  It
+will then ensure that "/go/src/github.com/jsmith/my-cool-app" is a symlink to
+"/go/src/app", which allows us to build and run it under the proper package
+name.
+
+For compatibility with versions of Go older than 1.4, the "import path" may also
+be placed in a file named ".godir".
+
+Available Commands:
+
+  $base download
+  $base download -u
+    (equivalent to "go get -d [args] [godir]")
+
+  $base install
+  $base install -race
+    (equivalent to "go install [args] [godir]")
+
+  $base run
+  $base run -app -specific -arguments
+    (assumes "GOPATH/bin" is in "PATH")
+
+EOUSAGE
+}
+
+# make sure there is a subcommand specified
+if [ "$#" -eq 0 ]; then
+	usage >&2
+	exit 1
+fi
+# "shift" so that "$@" becomes the remaining arguments and can be passed along to other "go" subcommands easily
+cmd="$1"
+shift
+
+goDir="$(go list -e -f '{{.ImportComment}}' 2>/dev/null || true)"
+
+if [ -z "$goDir" -a -s .godir ]; then
+	goDir="$(cat .godir)"
+fi
+
+dir="$(pwd -P)"
+if [ "$goDir" ]; then
+	goPath="${GOPATH%%:*}" # this just grabs the first path listed in GOPATH, if there are multiple (which is the detection logic "go get" itself uses, too)
+	goDirPath="$goPath/src/$goDir"
+	mkdir -p "$(dirname "$goDirPath")"
+	if [ ! -e "$goDirPath" ]; then
+		ln -sfv "$dir" "$goDirPath"
+	elif [ ! -L "$goDirPath" ]; then
+		echo >&2 "error: $goDirPath already exists but is unexpectedly not a symlink!"
+		exit 1
+	fi
+	goBin="$goPath/bin/$(basename "$goDir")"
+else
+	goBin="$(basename "$dir")" # likely "app"
+fi
+
+case "$cmd" in
+	download)
+		set -- go get -v -d "$@"
+		if [ "$goDir" ]; then set -- "$@" "$goDir"; fi
+		set -x; exec "$@"
+		;;
+		
+	install)
+		set -- go install -v "$@"
+		if [ "$goDir" ]; then set -- "$@" "$goDir"; fi
+		set -x; exec "$@"
+		;;
+		
+	run)
+		set -x; exec "$goBin" "$@"
+		;;
+		
+	*)
+		echo >&2 'error: unknown command:' "$cmd"
+		usage >&2
+		exit 1
+		;;
+esac
diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go
index 935c3b0..ffaaae4 100644
--- a/src/cmd/compile/internal/gc/reflect.go
+++ b/src/cmd/compile/internal/gc/reflect.go
@@ -1299,6 +1299,33 @@
 	// for security, only the exported fields.
 	case TSTRUCT:
 		fields := t.Fields().Slice()
+
+		// 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 *types.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/")
+		}
+		newFields := fields[:0:0]
+		for _, t1 := range fields {
+			if !omitFieldForAwfulBoringCryptoKludge(t1) {
+				newFields = append(newFields, t1)
+			}
+		}
+		fields = newFields
+
 		for _, t1 := range fields {
 			dtypesym(t1.Type)
 		}
diff --git a/src/cmd/go/go_boring_test.go b/src/cmd/go/go_boring_test.go
new file mode 100644
index 0000000..0000497
--- /dev/null
+++ b/src/cmd/go/go_boring_test.go
@@ -0,0 +1,20 @@
+// 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"))
+}
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index 85cae90..ae81ff1 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -4154,8 +4154,12 @@
 	tg.grepStdout("false", "did not see BinaryOnly=false for p4")
 }
 
-// Issue 16050.
-func TestAlwaysLinkSysoFiles(t *testing.T) {
+// Issue 16050 and 21884.
+func TestLinkSysoFiles(t *testing.T) {
+	if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
+		t.Skip("not linux/amd64")
+	}
+
 	tg := testgo(t)
 	defer tg.cleanup()
 	tg.parallel()
@@ -4174,6 +4178,10 @@
 	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.
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index ec2fa73..d969678 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -275,6 +275,12 @@
 	p.SwigFiles = pp.SwigFiles
 	p.SwigCXXFiles = pp.SwigCXXFiles
 	p.SysoFiles = pp.SysoFiles
+	if cfg.BuildMSan {
+		// There's no way for .syso files to be built both with and without
+		// support for memory sanitizer. Assume they are built without,
+		// and drop them.
+		p.SysoFiles = nil
+	}
 	p.CgoCFLAGS = pp.CgoCFLAGS
 	p.CgoCPPFLAGS = pp.CgoCPPFLAGS
 	p.CgoCXXFLAGS = pp.CgoCXXFLAGS
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 54ce150..eeb1f00 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -861,6 +861,7 @@
 // These packages can use internal linking mode.
 // Others trigger external mode.
 var internalpkg = []string{
+	"crypto/internal/boring",
 	"crypto/x509",
 	"net",
 	"os/user",
diff --git a/src/crypto/aes/cipher.go b/src/crypto/aes/cipher.go
index bb93fbb..db0ee38 100644
--- a/src/crypto/aes/cipher.go
+++ b/src/crypto/aes/cipher.go
@@ -6,6 +6,7 @@
 
 import (
 	"crypto/cipher"
+	"crypto/internal/boring"
 	"crypto/internal/subtle"
 	"strconv"
 )
@@ -37,6 +38,9 @@
 	case 16, 24, 32:
 		break
 	}
+	if boring.Enabled {
+		return boring.NewAESCipher(key)
+	}
 	return newCipher(key)
 }
 
diff --git a/src/crypto/aes/cipher_asm.go b/src/crypto/aes/cipher_asm.go
index 646bdfa..93b963b 100644
--- a/src/crypto/aes/cipher_asm.go
+++ b/src/crypto/aes/cipher_asm.go
@@ -8,6 +8,7 @@
 
 import (
 	"crypto/cipher"
+	"crypto/internal/boring"
 	"crypto/internal/subtle"
 	"internal/cpu"
 )
@@ -56,6 +57,7 @@
 func (c *aesCipherAsm) BlockSize() int { return BlockSize }
 
 func (c *aesCipherAsm) Encrypt(dst, src []byte) {
+	boring.Unreachable()
 	if len(src) < BlockSize {
 		panic("crypto/aes: input not full block")
 	}
@@ -69,6 +71,7 @@
 }
 
 func (c *aesCipherAsm) Decrypt(dst, src []byte) {
+	boring.Unreachable()
 	if len(src) < BlockSize {
 		panic("crypto/aes: input not full block")
 	}
diff --git a/src/crypto/ecdsa/boring.go b/src/crypto/ecdsa/boring.go
new file mode 100644
index 0000000..fa15ecb
--- /dev/null
+++ b/src/crypto/ecdsa/boring.go
@@ -0,0 +1,100 @@
+// 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),
+	}
+}
diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go
index 2bab14c..bae3f03 100644
--- a/src/crypto/ecdsa/ecdsa.go
+++ b/src/crypto/ecdsa/ecdsa.go
@@ -21,11 +21,13 @@
 	"crypto/aes"
 	"crypto/cipher"
 	"crypto/elliptic"
+	"crypto/internal/boring"
 	"crypto/sha512"
 	"encoding/asn1"
 	"errors"
 	"io"
 	"math/big"
+	"unsafe"
 
 	"crypto/internal/randutil"
 )
@@ -49,12 +51,16 @@
 type PublicKey struct {
 	elliptic.Curve
 	X, Y *big.Int
+
+	boring unsafe.Pointer
 }
 
 // PrivateKey represents an ECDSA private key.
 type PrivateKey struct {
 	PublicKey
 	D *big.Int
+
+	boring unsafe.Pointer
 }
 
 type ecdsaSignature struct {
@@ -74,6 +80,15 @@
 // where the private part is kept in, for example, a hardware module. Common
 // uses should use the Sign function in this package directly.
 func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
+	if boring.Enabled && rand == boring.RandReader {
+		b, err := boringPrivateKey(priv)
+		if err != nil {
+			return nil, err
+		}
+		return boring.SignMarshalECDSA(b, digest)
+	}
+	boring.UnreachableExceptTests()
+
 	r, s, err := Sign(rand, priv, digest)
 	if err != nil {
 		return nil, err
@@ -103,6 +118,15 @@
 
 // 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
@@ -156,6 +180,15 @@
 func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
 	randutil.MaybeReadByte(rand)
 
+	if boring.Enabled && rand == boring.RandReader {
+		b, err := boringPrivateKey(priv)
+		if err != nil {
+			return nil, nil, err
+		}
+		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 {
@@ -232,6 +265,15 @@
 // 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
diff --git a/src/crypto/hmac/hmac.go b/src/crypto/hmac/hmac.go
index c8c0617..1f70abb 100644
--- a/src/crypto/hmac/hmac.go
+++ b/src/crypto/hmac/hmac.go
@@ -22,6 +22,7 @@
 package hmac
 
 import (
+	"crypto/internal/boring"
 	"crypto/subtle"
 	"hash"
 )
@@ -68,6 +69,13 @@
 // the returned Hash does not implement encoding.BinaryMarshaler
 // or encoding.BinaryUnmarshaler.
 func New(h func() hash.Hash, key []byte) hash.Hash {
+	if boring.Enabled {
+		hm := boring.NewHMAC(h, key)
+		if hm != nil {
+			return hm
+		}
+		// BoringCrypto did not recognize h, so fall through to standard Go code.
+	}
 	hm := new(hmac)
 	hm.outer = h()
 	hm.inner = h()
diff --git a/src/crypto/hmac/hmac_test.go b/src/crypto/hmac/hmac_test.go
index eea345e..96e84f7 100644
--- a/src/crypto/hmac/hmac_test.go
+++ b/src/crypto/hmac/hmac_test.go
@@ -5,6 +5,7 @@
 package hmac
 
 import (
+	"bytes"
 	"crypto/md5"
 	"crypto/sha1"
 	"crypto/sha256"
@@ -518,6 +519,31 @@
 		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) {
@@ -569,6 +595,42 @@
 	}
 }
 
+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)
diff --git a/src/crypto/internal/boring/LICENSE b/src/crypto/internal/boring/LICENSE
new file mode 100644
index 0000000..4a618c3
--- /dev/null
+++ b/src/crypto/internal/boring/LICENSE
@@ -0,0 +1,200 @@
+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.
diff --git a/src/crypto/internal/boring/aes.go b/src/crypto/internal/boring/aes.go
new file mode 100644
index 0000000..504a841
--- /dev/null
+++ b/src/crypto/internal/boring/aes.go
@@ -0,0 +1,391 @@
+// 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"
+
+// These wrappers allocate out_len on the C stack, and check that it matches the expected
+// value, to avoid having to pass a pointer from Go, which would escape to the heap.
+
+int EVP_AEAD_CTX_seal_wrapper(const GO_EVP_AEAD_CTX *ctx, uint8_t *out,
+							  size_t exp_out_len,
+							  const uint8_t *nonce, size_t nonce_len,
+							  const uint8_t *in, size_t in_len,
+							  const uint8_t *ad, size_t ad_len) {
+	size_t out_len;
+	int ok = _goboringcrypto_EVP_AEAD_CTX_seal(ctx, out, &out_len, exp_out_len,
+		nonce, nonce_len, in, in_len, ad, ad_len);
+	if (out_len != exp_out_len) {
+		return 0;
+	}
+	return ok;
+};
+
+int EVP_AEAD_CTX_open_wrapper(const GO_EVP_AEAD_CTX *ctx, uint8_t *out,
+							  size_t exp_out_len,
+							  const uint8_t *nonce, size_t nonce_len,
+							  const uint8_t *in, size_t in_len,
+							  const uint8_t *ad, size_t ad_len) {
+	size_t out_len;
+	int ok = _goboringcrypto_EVP_AEAD_CTX_open(ctx, out, &out_len, exp_out_len,
+		nonce, nonce_len, in, in_len, ad, ad_len);
+	if (out_len != exp_out_len) {
+		return 0;
+	}
+	return ok;
+};
+
+*/
+import "C"
+import (
+	"crypto/cipher"
+	"errors"
+	"runtime"
+	"strconv"
+	"unsafe"
+)
+
+type aesKeySizeError int
+
+func (k aesKeySizeError) Error() string {
+	return "crypto/aes: invalid key size " + strconv.Itoa(int(k))
+}
+
+const aesBlockSize = 16
+
+type aesCipher struct {
+	key []byte
+	enc C.GO_AES_KEY
+	dec C.GO_AES_KEY
+}
+
+type extraModes interface {
+	// Copied out of crypto/aes/modes.go.
+	NewCBCEncrypter(iv []byte) cipher.BlockMode
+	NewCBCDecrypter(iv []byte) cipher.BlockMode
+	NewCTR(iv []byte) cipher.Stream
+	NewGCM(nonceSize, tagSize int) (cipher.AEAD, error)
+
+	// Invented for BoringCrypto.
+	NewGCMTLS() (cipher.AEAD, error)
+}
+
+var _ extraModes = (*aesCipher)(nil)
+
+func NewAESCipher(key []byte) (cipher.Block, error) {
+	c := &aesCipher{key: make([]byte, len(key))}
+	copy(c.key, key)
+	// Note: 0 is success, contradicting the usual BoringCrypto convention.
+	if C._goboringcrypto_AES_set_decrypt_key((*C.uint8_t)(unsafe.Pointer(&c.key[0])), C.uint(8*len(c.key)), &c.dec) != 0 ||
+		C._goboringcrypto_AES_set_encrypt_key((*C.uint8_t)(unsafe.Pointer(&c.key[0])), C.uint(8*len(c.key)), &c.enc) != 0 {
+		return nil, aesKeySizeError(len(key))
+	}
+	return c, nil
+}
+
+func (c *aesCipher) BlockSize() int { return aesBlockSize }
+
+func (c *aesCipher) Encrypt(dst, src []byte) {
+	if inexactOverlap(dst, src) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
+	if len(src) < aesBlockSize {
+		panic("crypto/aes: input not full block")
+	}
+	if len(dst) < aesBlockSize {
+		panic("crypto/aes: output not full block")
+	}
+	C._goboringcrypto_AES_encrypt(
+		(*C.uint8_t)(unsafe.Pointer(&src[0])),
+		(*C.uint8_t)(unsafe.Pointer(&dst[0])),
+		&c.enc)
+}
+
+func (c *aesCipher) Decrypt(dst, src []byte) {
+	if inexactOverlap(dst, src) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
+	if len(src) < aesBlockSize {
+		panic("crypto/aes: input not full block")
+	}
+	if len(dst) < aesBlockSize {
+		panic("crypto/aes: output not full block")
+	}
+	C._goboringcrypto_AES_decrypt(
+		(*C.uint8_t)(unsafe.Pointer(&src[0])),
+		(*C.uint8_t)(unsafe.Pointer(&dst[0])),
+		&c.dec)
+}
+
+type aesCBC struct {
+	key  *C.GO_AES_KEY
+	mode C.int
+	iv   [aesBlockSize]byte
+}
+
+func (x *aesCBC) BlockSize() int { return aesBlockSize }
+
+func (x *aesCBC) CryptBlocks(dst, src []byte) {
+	if inexactOverlap(dst, src) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
+	if len(src)%aesBlockSize != 0 {
+		panic("crypto/cipher: input not full blocks")
+	}
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
+	if len(src) > 0 {
+		C._goboringcrypto_AES_cbc_encrypt(
+			(*C.uint8_t)(unsafe.Pointer(&src[0])),
+			(*C.uint8_t)(unsafe.Pointer(&dst[0])),
+			C.size_t(len(src)), x.key,
+			(*C.uint8_t)(unsafe.Pointer(&x.iv[0])), x.mode)
+	}
+}
+
+func (x *aesCBC) SetIV(iv []byte) {
+	if len(iv) != aesBlockSize {
+		panic("cipher: incorrect length IV")
+	}
+	copy(x.iv[:], iv)
+}
+
+func (c *aesCipher) NewCBCEncrypter(iv []byte) cipher.BlockMode {
+	x := &aesCBC{key: &c.enc, mode: C.GO_AES_ENCRYPT}
+	copy(x.iv[:], iv)
+	return x
+}
+
+func (c *aesCipher) NewCBCDecrypter(iv []byte) cipher.BlockMode {
+	x := &aesCBC{key: &c.dec, mode: C.GO_AES_DECRYPT}
+	copy(x.iv[:], iv)
+	return x
+}
+
+type aesCTR struct {
+	key        *C.GO_AES_KEY
+	iv         [aesBlockSize]byte
+	num        C.uint
+	ecount_buf [16]C.uint8_t
+}
+
+func (x *aesCTR) XORKeyStream(dst, src []byte) {
+	if inexactOverlap(dst, src) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
+	if len(src) == 0 {
+		return
+	}
+	C._goboringcrypto_AES_ctr128_encrypt(
+		(*C.uint8_t)(unsafe.Pointer(&src[0])),
+		(*C.uint8_t)(unsafe.Pointer(&dst[0])),
+		C.size_t(len(src)), x.key, (*C.uint8_t)(unsafe.Pointer(&x.iv[0])),
+		&x.ecount_buf[0], &x.num)
+}
+
+func (c *aesCipher) NewCTR(iv []byte) cipher.Stream {
+	x := &aesCTR{key: &c.enc}
+	copy(x.iv[:], iv)
+	return x
+}
+
+type aesGCM struct {
+	ctx  C.GO_EVP_AEAD_CTX
+	aead *C.GO_EVP_AEAD
+}
+
+const (
+	gcmBlockSize         = 16
+	gcmTagSize           = 16
+	gcmStandardNonceSize = 12
+)
+
+type aesNonceSizeError int
+
+func (n aesNonceSizeError) Error() string {
+	return "crypto/aes: invalid GCM nonce size " + strconv.Itoa(int(n))
+}
+
+type noGCM struct {
+	cipher.Block
+}
+
+func (c *aesCipher) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) {
+	if nonceSize != gcmStandardNonceSize && tagSize != gcmTagSize {
+		return nil, errors.New("crypto/aes: GCM tag and nonce sizes can't be non-standard at the same time")
+	}
+	// Fall back to standard library for GCM with non-standard nonce or tag size.
+	if nonceSize != gcmStandardNonceSize {
+		return cipher.NewGCMWithNonceSize(&noGCM{c}, nonceSize)
+	}
+	if tagSize != gcmTagSize {
+		return cipher.NewGCMWithTagSize(&noGCM{c}, tagSize)
+	}
+	return c.newGCM(false)
+}
+
+func (c *aesCipher) NewGCMTLS() (cipher.AEAD, error) {
+	return c.newGCM(true)
+}
+
+func (c *aesCipher) newGCM(tls bool) (cipher.AEAD, error) {
+	var aead *C.GO_EVP_AEAD
+	switch len(c.key) * 8 {
+	case 128:
+		if tls {
+			aead = C._goboringcrypto_EVP_aead_aes_128_gcm_tls12()
+		} else {
+			aead = C._goboringcrypto_EVP_aead_aes_128_gcm()
+		}
+	case 256:
+		if tls {
+			aead = C._goboringcrypto_EVP_aead_aes_256_gcm_tls12()
+		} else {
+			aead = C._goboringcrypto_EVP_aead_aes_256_gcm()
+		}
+	default:
+		// Fall back to standard library for GCM with non-standard key size.
+		return cipher.NewGCMWithNonceSize(&noGCM{c}, gcmStandardNonceSize)
+	}
+
+	g := &aesGCM{aead: aead}
+	if C._goboringcrypto_EVP_AEAD_CTX_init(&g.ctx, aead, (*C.uint8_t)(unsafe.Pointer(&c.key[0])), C.size_t(len(c.key)), C.GO_EVP_AEAD_DEFAULT_TAG_LENGTH, nil) == 0 {
+		return nil, fail("EVP_AEAD_CTX_init")
+	}
+	// Note: Because of the finalizer, any time g.ctx is passed to cgo,
+	// that call must be followed by a call to runtime.KeepAlive(g),
+	// to make sure g is not collected (and finalized) before the cgo
+	// call returns.
+	runtime.SetFinalizer(g, (*aesGCM).finalize)
+	if g.NonceSize() != gcmStandardNonceSize {
+		panic("boringcrypto: internal confusion about nonce size")
+	}
+	if g.Overhead() != gcmTagSize {
+		panic("boringcrypto: internal confusion about tag size")
+	}
+
+	return g, nil
+}
+
+func (g *aesGCM) finalize() {
+	C._goboringcrypto_EVP_AEAD_CTX_cleanup(&g.ctx)
+}
+
+func (g *aesGCM) NonceSize() int {
+	return int(C._goboringcrypto_EVP_AEAD_nonce_length(g.aead))
+}
+
+func (g *aesGCM) Overhead() int {
+	return int(C._goboringcrypto_EVP_AEAD_max_overhead(g.aead))
+}
+
+// base returns the address of the underlying array in b,
+// being careful not to panic when b has zero length.
+func base(b []byte) *C.uint8_t {
+	if len(b) == 0 {
+		return nil
+	}
+	return (*C.uint8_t)(unsafe.Pointer(&b[0]))
+}
+
+func (g *aesGCM) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
+	if len(nonce) != gcmStandardNonceSize {
+		panic("cipher: incorrect nonce length given to GCM")
+	}
+	if uint64(len(plaintext)) > ((1<<32)-2)*aesBlockSize || len(plaintext)+gcmTagSize < len(plaintext) {
+		panic("cipher: message too large for GCM")
+	}
+	if len(dst)+len(plaintext)+gcmTagSize < len(dst) {
+		panic("cipher: message too large for buffer")
+	}
+
+	// Make room in dst to append plaintext+overhead.
+	n := len(dst)
+	for cap(dst) < n+len(plaintext)+gcmTagSize {
+		dst = append(dst[:cap(dst)], 0)
+	}
+	dst = dst[:n+len(plaintext)+gcmTagSize]
+
+	// Check delayed until now to make sure len(dst) is accurate.
+	if inexactOverlap(dst[n:], plaintext) {
+		panic("cipher: invalid buffer overlap")
+	}
+
+	outLen := C.size_t(len(plaintext) + gcmTagSize)
+	ok := C.EVP_AEAD_CTX_seal_wrapper(
+		&g.ctx,
+		(*C.uint8_t)(unsafe.Pointer(&dst[n])), outLen,
+		base(nonce), C.size_t(len(nonce)),
+		base(plaintext), C.size_t(len(plaintext)),
+		base(additionalData), C.size_t(len(additionalData)))
+	runtime.KeepAlive(g)
+	if ok == 0 {
+		panic(fail("EVP_AEAD_CTX_seal"))
+	}
+	return dst[:n+int(outLen)]
+}
+
+var errOpen = errors.New("cipher: message authentication failed")
+
+func (g *aesGCM) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+	if len(nonce) != gcmStandardNonceSize {
+		panic("cipher: incorrect nonce length given to GCM")
+	}
+	if len(ciphertext) < gcmTagSize {
+		return nil, errOpen
+	}
+	if uint64(len(ciphertext)) > ((1<<32)-2)*aesBlockSize+gcmTagSize {
+		return nil, errOpen
+	}
+
+	// Make room in dst to append ciphertext without tag.
+	n := len(dst)
+	for cap(dst) < n+len(ciphertext)-gcmTagSize {
+		dst = append(dst[:cap(dst)], 0)
+	}
+	dst = dst[:n+len(ciphertext)-gcmTagSize]
+
+	// Check delayed until now to make sure len(dst) is accurate.
+	if inexactOverlap(dst[n:], ciphertext) {
+		panic("cipher: invalid buffer overlap")
+	}
+
+	outLen := C.size_t(len(ciphertext) - gcmTagSize)
+	ok := C.EVP_AEAD_CTX_open_wrapper(
+		&g.ctx,
+		base(dst[n:]), outLen,
+		base(nonce), C.size_t(len(nonce)),
+		base(ciphertext), C.size_t(len(ciphertext)),
+		base(additionalData), C.size_t(len(additionalData)))
+	runtime.KeepAlive(g)
+	if ok == 0 {
+		return nil, errOpen
+	}
+	return dst[:n+int(outLen)], nil
+}
+
+func anyOverlap(x, y []byte) bool {
+	return len(x) > 0 && len(y) > 0 &&
+		uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) &&
+		uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1]))
+}
+
+func inexactOverlap(x, y []byte) bool {
+	if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] {
+		return false
+	}
+	return anyOverlap(x, y)
+}
diff --git a/src/crypto/internal/boring/boring.go b/src/crypto/internal/boring/boring.go
new file mode 100644
index 0000000..9ccad7e
--- /dev/null
+++ b/src/crypto/internal/boring/boring.go
@@ -0,0 +1,83 @@
+// 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
+}
diff --git a/src/crypto/internal/boring/boring_test.go b/src/crypto/internal/boring/boring_test.go
new file mode 100644
index 0000000..83bbbd3
--- /dev/null
+++ b/src/crypto/internal/boring/boring_test.go
@@ -0,0 +1,34 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Most functionality in this package is tested by replacing existing code
+// and inheriting that code's tests.
+
+package boring
+
+import "testing"
+
+// Test that func init does not panic.
+func TestInit(t *testing.T) {}
+
+// Test that Unreachable panics.
+func TestUnreachable(t *testing.T) {
+	defer func() {
+		if Enabled {
+			if err := recover(); err == nil {
+				t.Fatal("expected Unreachable to panic")
+			}
+		} else {
+			if err := recover(); err != nil {
+				t.Fatalf("expected Unreachable to be a no-op")
+			}
+		}
+	}()
+	Unreachable()
+}
+
+// Test that UnreachableExceptTests does not panic (this is a test).
+func TestUnreachableExceptTests(t *testing.T) {
+	UnreachableExceptTests()
+}
diff --git a/src/crypto/internal/boring/build/.gitignore b/src/crypto/internal/boring/build/.gitignore
new file mode 100644
index 0000000..a19e8a9
--- /dev/null
+++ b/src/crypto/internal/boring/build/.gitignore
@@ -0,0 +1 @@
+boringssl-24e5886c0edfc409c8083d10f9f1120111efd6f5.tar.xz
diff --git a/src/crypto/internal/boring/build/README b/src/crypto/internal/boring/build/README
new file mode 100644
index 0000000..22ce944
--- /dev/null
+++ b/src/crypto/internal/boring/build/README
@@ -0,0 +1,6 @@
+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.
diff --git a/src/crypto/internal/boring/build/build.sh b/src/crypto/internal/boring/build/build.sh
new file mode 100755
index 0000000..7c50327
--- /dev/null
+++ b/src/crypto/internal/boring/build/build.sh
@@ -0,0 +1,63 @@
+#!/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
diff --git a/src/crypto/internal/boring/build/build_in_chroot.sh b/src/crypto/internal/boring/build/build_in_chroot.sh
new file mode 100755
index 0000000..b5e5a77
--- /dev/null
+++ b/src/crypto/internal/boring/build/build_in_chroot.sh
@@ -0,0 +1,198 @@
+#!/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
diff --git a/src/crypto/internal/boring/build/root_setup_in_chroot.sh b/src/crypto/internal/boring/build/root_setup_in_chroot.sh
new file mode 100755
index 0000000..fef91f5
--- /dev/null
+++ b/src/crypto/internal/boring/build/root_setup_in_chroot.sh
@@ -0,0 +1,13 @@
+#!/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
diff --git a/src/crypto/internal/boring/build/sources.list b/src/crypto/internal/boring/build/sources.list
new file mode 100644
index 0000000..35df0f2
--- /dev/null
+++ b/src/crypto/internal/boring/build/sources.list
@@ -0,0 +1,10 @@
+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
diff --git a/src/crypto/internal/boring/doc.go b/src/crypto/internal/boring/doc.go
new file mode 100644
index 0000000..64f41e3
--- /dev/null
+++ b/src/crypto/internal/boring/doc.go
@@ -0,0 +1,14 @@
+// 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
diff --git a/src/crypto/internal/boring/ecdsa.go b/src/crypto/internal/boring/ecdsa.go
new file mode 100644
index 0000000..4fcba4b
--- /dev/null
+++ b/src/crypto/internal/boring/ecdsa.go
@@ -0,0 +1,201 @@
+// 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
+}
diff --git a/src/crypto/internal/boring/fipstls/dummy.s b/src/crypto/internal/boring/fipstls/dummy.s
new file mode 100644
index 0000000..53bb7d9
--- /dev/null
+++ b/src/crypto/internal/boring/fipstls/dummy.s
@@ -0,0 +1,10 @@
+// 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).
diff --git a/src/crypto/internal/boring/fipstls/tls.go b/src/crypto/internal/boring/fipstls/tls.go
new file mode 100644
index 0000000..4127533
--- /dev/null
+++ b/src/crypto/internal/boring/fipstls/tls.go
@@ -0,0 +1,49 @@
+// 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
+}
diff --git a/src/crypto/internal/boring/goboringcrypto.h b/src/crypto/internal/boring/goboringcrypto.h
new file mode 100644
index 0000000..f982ce8
--- /dev/null
+++ b/src/crypto/internal/boring/goboringcrypto.h
@@ -0,0 +1,236 @@
+// 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);
diff --git a/src/crypto/internal/boring/goboringcrypto_linux_amd64.syso b/src/crypto/internal/boring/goboringcrypto_linux_amd64.syso
new file mode 100644
index 0000000..e439dc3
--- /dev/null
+++ b/src/crypto/internal/boring/goboringcrypto_linux_amd64.syso
Binary files differ
diff --git a/src/crypto/internal/boring/hmac.go b/src/crypto/internal/boring/hmac.go
new file mode 100644
index 0000000..01b5844
--- /dev/null
+++ b/src/crypto/internal/boring/hmac.go
@@ -0,0 +1,156 @@
+// 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...)
+}
diff --git a/src/crypto/internal/boring/notboring.go b/src/crypto/internal/boring/notboring.go
new file mode 100644
index 0000000..c21cb3c
--- /dev/null
+++ b/src/crypto/internal/boring/notboring.go
@@ -0,0 +1,109 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +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")
+}
diff --git a/src/crypto/internal/boring/rand.go b/src/crypto/internal/boring/rand.go
new file mode 100644
index 0000000..c3fc27c
--- /dev/null
+++ b/src/crypto/internal/boring/rand.go
@@ -0,0 +1,27 @@
+// 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)
diff --git a/src/crypto/internal/boring/rsa.go b/src/crypto/internal/boring/rsa.go
new file mode 100644
index 0000000..8cb5526
--- /dev/null
+++ b/src/crypto/internal/boring/rsa.go
@@ -0,0 +1,329 @@
+// 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
+}
diff --git a/src/crypto/internal/boring/sha.go b/src/crypto/internal/boring/sha.go
new file mode 100644
index 0000000..5ca158c
--- /dev/null
+++ b/src/crypto/internal/boring/sha.go
@@ -0,0 +1,480 @@
+// 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 (
+	"errors"
+	"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
+}
+
+type sha1Ctx struct {
+	h      [5]uint32
+	nl, nh uint32
+	x      [64]byte
+	nx     uint32
+}
+
+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[:]
+}
+
+const (
+	sha1Magic         = "sha\x01"
+	sha1MarshaledSize = len(sha1Magic) + 5*4 + 64 + 8
+)
+
+func (h *sha1Hash) MarshalBinary() ([]byte, error) {
+	d := (*sha1Ctx)(unsafe.Pointer(&h.ctx))
+	b := make([]byte, 0, sha1MarshaledSize)
+	b = append(b, sha1Magic...)
+	b = appendUint32(b, d.h[0])
+	b = appendUint32(b, d.h[1])
+	b = appendUint32(b, d.h[2])
+	b = appendUint32(b, d.h[3])
+	b = appendUint32(b, d.h[4])
+	b = append(b, d.x[:d.nx]...)
+	b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
+	b = appendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29)
+	return b, nil
+}
+
+func (h *sha1Hash) UnmarshalBinary(b []byte) error {
+	if len(b) < len(sha1Magic) || string(b[:len(sha1Magic)]) != sha1Magic {
+		return errors.New("crypto/sha1: invalid hash state identifier")
+	}
+	if len(b) != sha1MarshaledSize {
+		return errors.New("crypto/sha1: invalid hash state size")
+	}
+	d := (*sha1Ctx)(unsafe.Pointer(&h.ctx))
+	b = b[len(sha1Magic):]
+	b, d.h[0] = consumeUint32(b)
+	b, d.h[1] = consumeUint32(b)
+	b, d.h[2] = consumeUint32(b)
+	b, d.h[3] = consumeUint32(b)
+	b, d.h[4] = consumeUint32(b)
+	b = b[copy(d.x[:], b):]
+	b, n := consumeUint64(b)
+	d.nl = uint32(n << 3)
+	d.nh = uint32(n >> 29)
+	d.nx = uint32(n) % 64
+	return nil
+}
+
+// NewSHA224 returns a new SHA224 hash.
+func NewSHA224() hash.Hash {
+	h := new(sha224Hash)
+	h.Reset()
+	return h
+}
+
+type sha224Hash struct {
+	ctx C.GO_SHA256_CTX
+	out [224 / 8]byte
+}
+
+func (h *sha224Hash) 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[:]
+}
+
+const (
+	magic224         = "sha\x02"
+	magic256         = "sha\x03"
+	marshaledSize256 = len(magic256) + 8*4 + 64 + 8
+)
+
+type sha256Ctx struct {
+	h      [8]uint32
+	nl, nh uint32
+	x      [64]byte
+	nx     uint32
+}
+
+func (h *sha224Hash) MarshalBinary() ([]byte, error) {
+	d := (*sha256Ctx)(unsafe.Pointer(&h.ctx))
+	b := make([]byte, 0, marshaledSize256)
+	b = append(b, magic224...)
+	b = appendUint32(b, d.h[0])
+	b = appendUint32(b, d.h[1])
+	b = appendUint32(b, d.h[2])
+	b = appendUint32(b, d.h[3])
+	b = appendUint32(b, d.h[4])
+	b = appendUint32(b, d.h[5])
+	b = appendUint32(b, d.h[6])
+	b = appendUint32(b, d.h[7])
+	b = append(b, d.x[:d.nx]...)
+	b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
+	b = appendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29)
+	return b, nil
+}
+
+func (h *sha256Hash) MarshalBinary() ([]byte, error) {
+	d := (*sha256Ctx)(unsafe.Pointer(&h.ctx))
+	b := make([]byte, 0, marshaledSize256)
+	b = append(b, magic256...)
+	b = appendUint32(b, d.h[0])
+	b = appendUint32(b, d.h[1])
+	b = appendUint32(b, d.h[2])
+	b = appendUint32(b, d.h[3])
+	b = appendUint32(b, d.h[4])
+	b = appendUint32(b, d.h[5])
+	b = appendUint32(b, d.h[6])
+	b = appendUint32(b, d.h[7])
+	b = append(b, d.x[:d.nx]...)
+	b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
+	b = appendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29)
+	return b, nil
+}
+
+func (h *sha224Hash) UnmarshalBinary(b []byte) error {
+	if len(b) < len(magic224) || string(b[:len(magic224)]) != magic224 {
+		return errors.New("crypto/sha256: invalid hash state identifier")
+	}
+	if len(b) != marshaledSize256 {
+		return errors.New("crypto/sha256: invalid hash state size")
+	}
+	d := (*sha256Ctx)(unsafe.Pointer(&h.ctx))
+	b = b[len(magic224):]
+	b, d.h[0] = consumeUint32(b)
+	b, d.h[1] = consumeUint32(b)
+	b, d.h[2] = consumeUint32(b)
+	b, d.h[3] = consumeUint32(b)
+	b, d.h[4] = consumeUint32(b)
+	b, d.h[5] = consumeUint32(b)
+	b, d.h[6] = consumeUint32(b)
+	b, d.h[7] = consumeUint32(b)
+	b = b[copy(d.x[:], b):]
+	b, n := consumeUint64(b)
+	d.nl = uint32(n << 3)
+	d.nh = uint32(n >> 29)
+	d.nx = uint32(n) % 64
+	return nil
+}
+
+func (h *sha256Hash) UnmarshalBinary(b []byte) error {
+	if len(b) < len(magic256) || string(b[:len(magic256)]) != magic256 {
+		return errors.New("crypto/sha256: invalid hash state identifier")
+	}
+	if len(b) != marshaledSize256 {
+		return errors.New("crypto/sha256: invalid hash state size")
+	}
+	d := (*sha256Ctx)(unsafe.Pointer(&h.ctx))
+	b = b[len(magic256):]
+	b, d.h[0] = consumeUint32(b)
+	b, d.h[1] = consumeUint32(b)
+	b, d.h[2] = consumeUint32(b)
+	b, d.h[3] = consumeUint32(b)
+	b, d.h[4] = consumeUint32(b)
+	b, d.h[5] = consumeUint32(b)
+	b, d.h[6] = consumeUint32(b)
+	b, d.h[7] = consumeUint32(b)
+	b = b[copy(d.x[:], b):]
+	b, n := consumeUint64(b)
+	d.nl = uint32(n << 3)
+	d.nh = uint32(n >> 29)
+	d.nx = uint32(n) % 64
+	return nil
+}
+
+// NewSHA384 returns a new SHA384 hash.
+func NewSHA384() hash.Hash {
+	h := new(sha384Hash)
+	h.Reset()
+	return h
+}
+
+type sha384Hash struct {
+	ctx C.GO_SHA512_CTX
+	out [384 / 8]byte
+}
+
+func (h *sha384Hash) 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[:]
+}
+
+type sha512Ctx struct {
+	h      [8]uint64
+	nl, nh uint64
+	x      [128]byte
+	nx     uint32
+}
+
+const (
+	magic384         = "sha\x04"
+	magic512_224     = "sha\x05"
+	magic512_256     = "sha\x06"
+	magic512         = "sha\x07"
+	marshaledSize512 = len(magic512) + 8*8 + 128 + 8
+)
+
+var zero [128]byte
+
+func (h *sha384Hash) MarshalBinary() ([]byte, error) {
+	d := (*sha512Ctx)(unsafe.Pointer(&h.ctx))
+	b := make([]byte, 0, marshaledSize512)
+	b = append(b, magic384...)
+	b = appendUint64(b, d.h[0])
+	b = appendUint64(b, d.h[1])
+	b = appendUint64(b, d.h[2])
+	b = appendUint64(b, d.h[3])
+	b = appendUint64(b, d.h[4])
+	b = appendUint64(b, d.h[5])
+	b = appendUint64(b, d.h[6])
+	b = appendUint64(b, d.h[7])
+	b = append(b, d.x[:d.nx]...)
+	b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
+	b = appendUint64(b, d.nl>>3|d.nh<<61)
+	return b, nil
+}
+
+func (h *sha512Hash) MarshalBinary() ([]byte, error) {
+	d := (*sha512Ctx)(unsafe.Pointer(&h.ctx))
+	b := make([]byte, 0, marshaledSize512)
+	b = append(b, magic512...)
+	b = appendUint64(b, d.h[0])
+	b = appendUint64(b, d.h[1])
+	b = appendUint64(b, d.h[2])
+	b = appendUint64(b, d.h[3])
+	b = appendUint64(b, d.h[4])
+	b = appendUint64(b, d.h[5])
+	b = appendUint64(b, d.h[6])
+	b = appendUint64(b, d.h[7])
+	b = append(b, d.x[:d.nx]...)
+	b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
+	b = appendUint64(b, d.nl>>3|d.nh<<61)
+	return b, nil
+}
+
+func (h *sha384Hash) UnmarshalBinary(b []byte) error {
+	if len(b) < len(magic512) {
+		return errors.New("crypto/sha512: invalid hash state identifier")
+	}
+	if string(b[:len(magic384)]) != magic384 {
+		return errors.New("crypto/sha512: invalid hash state identifier")
+	}
+	if len(b) != marshaledSize512 {
+		return errors.New("crypto/sha512: invalid hash state size")
+	}
+	d := (*sha512Ctx)(unsafe.Pointer(&h.ctx))
+	b = b[len(magic512):]
+	b, d.h[0] = consumeUint64(b)
+	b, d.h[1] = consumeUint64(b)
+	b, d.h[2] = consumeUint64(b)
+	b, d.h[3] = consumeUint64(b)
+	b, d.h[4] = consumeUint64(b)
+	b, d.h[5] = consumeUint64(b)
+	b, d.h[6] = consumeUint64(b)
+	b, d.h[7] = consumeUint64(b)
+	b = b[copy(d.x[:], b):]
+	b, n := consumeUint64(b)
+	d.nl = n << 3
+	d.nh = n >> 61
+	d.nx = uint32(n) % 128
+	return nil
+}
+
+func (h *sha512Hash) UnmarshalBinary(b []byte) error {
+	if len(b) < len(magic512) {
+		return errors.New("crypto/sha512: invalid hash state identifier")
+	}
+	if string(b[:len(magic512)]) != magic512 {
+		return errors.New("crypto/sha512: invalid hash state identifier")
+	}
+	if len(b) != marshaledSize512 {
+		return errors.New("crypto/sha512: invalid hash state size")
+	}
+	d := (*sha512Ctx)(unsafe.Pointer(&h.ctx))
+	b = b[len(magic512):]
+	b, d.h[0] = consumeUint64(b)
+	b, d.h[1] = consumeUint64(b)
+	b, d.h[2] = consumeUint64(b)
+	b, d.h[3] = consumeUint64(b)
+	b, d.h[4] = consumeUint64(b)
+	b, d.h[5] = consumeUint64(b)
+	b, d.h[6] = consumeUint64(b)
+	b, d.h[7] = consumeUint64(b)
+	b = b[copy(d.x[:], b):]
+	b, n := consumeUint64(b)
+	d.nl = n << 3
+	d.nh = n >> 61
+	d.nx = uint32(n) % 128
+	return nil
+}
+
+func appendUint64(b []byte, x uint64) []byte {
+	var a [8]byte
+	putUint64(a[:], x)
+	return append(b, a[:]...)
+}
+
+func appendUint32(b []byte, x uint32) []byte {
+	var a [4]byte
+	putUint32(a[:], x)
+	return append(b, a[:]...)
+}
+
+func consumeUint64(b []byte) ([]byte, uint64) {
+	_ = b[7]
+	x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
+		uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
+	return b[8:], x
+}
+
+func consumeUint32(b []byte) ([]byte, uint32) {
+	_ = b[3]
+	x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
+	return b[4:], x
+}
+
+func putUint64(x []byte, s uint64) {
+	_ = x[7]
+	x[0] = byte(s >> 56)
+	x[1] = byte(s >> 48)
+	x[2] = byte(s >> 40)
+	x[3] = byte(s >> 32)
+	x[4] = byte(s >> 24)
+	x[5] = byte(s >> 16)
+	x[6] = byte(s >> 8)
+	x[7] = byte(s)
+}
+
+func putUint32(x []byte, s uint32) {
+	_ = x[3]
+	x[0] = byte(s >> 24)
+	x[1] = byte(s >> 16)
+	x[2] = byte(s >> 8)
+	x[3] = byte(s)
+}
diff --git a/src/crypto/internal/boring/sig/sig.go b/src/crypto/internal/boring/sig/sig.go
new file mode 100644
index 0000000..716c03c
--- /dev/null
+++ b/src/crypto/internal/boring/sig/sig.go
@@ -0,0 +1,17 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package sig holds “code signatures” that can be called
+// and will result in certain code sequences being linked into
+// the final binary. The functions themselves are no-ops.
+package sig
+
+// BoringCrypto indicates that the BoringCrypto module is present.
+func BoringCrypto()
+
+// FIPSOnly indicates that package crypto/tls/fipsonly is present.
+func FIPSOnly()
+
+// StandardCrypto indicates that standard Go crypto is present.
+func StandardCrypto()
diff --git a/src/crypto/internal/boring/sig/sig_amd64.s b/src/crypto/internal/boring/sig/sig_amd64.s
new file mode 100644
index 0000000..64e3462
--- /dev/null
+++ b/src/crypto/internal/boring/sig/sig_amd64.s
@@ -0,0 +1,54 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// These functions are no-ops, but you can search for their implementations
+// to find out whether they are linked into a particular binary.
+//
+// Each function consists of a two-byte jump over the next 29-bytes,
+// then a 5-byte indicator sequence unlikely to occur in real x86 instructions,
+// then a randomly-chosen 24-byte sequence, and finally a return instruction
+// (the target of the jump).
+//
+// These sequences are known to rsc.io/goversion.
+
+#define START \
+	BYTE $0xEB; BYTE $0x1D; BYTE $0xF4; BYTE $0x48; BYTE $0xF4; BYTE $0x4B; BYTE $0xF4
+
+#define END \
+	BYTE $0xC3
+
+// BoringCrypto indicates that BoringCrypto (in particular, its func init) is present.
+TEXT ·BoringCrypto(SB),NOSPLIT,$0
+	START
+	BYTE $0xB3; BYTE $0x32; BYTE $0xF5; BYTE $0x28;
+	BYTE $0x13; BYTE $0xA3; BYTE $0xB4; BYTE $0x50;
+	BYTE $0xD4; BYTE $0x41; BYTE $0xCC; BYTE $0x24;
+	BYTE $0x85; BYTE $0xF0; BYTE $0x01; BYTE $0x45;
+	BYTE $0x4E; BYTE $0x92; BYTE $0x10; BYTE $0x1B;
+	BYTE $0x1D; BYTE $0x2F; BYTE $0x19; BYTE $0x50;
+	END
+
+// StandardCrypto indicates that standard Go crypto is present.
+TEXT ·StandardCrypto(SB),NOSPLIT,$0
+	START
+	BYTE $0xba; BYTE $0xee; BYTE $0x4d; BYTE $0xfa;
+	BYTE $0x98; BYTE $0x51; BYTE $0xca; BYTE $0x56;
+	BYTE $0xa9; BYTE $0x11; BYTE $0x45; BYTE $0xe8;
+	BYTE $0x3e; BYTE $0x99; BYTE $0xc5; BYTE $0x9c;
+	BYTE $0xf9; BYTE $0x11; BYTE $0xcb; BYTE $0x8e;
+	BYTE $0x80; BYTE $0xda;  BYTE $0xf1; BYTE $0x2f;
+	END
+
+// FIPSOnly indicates that crypto/tls/fipsonly is present.
+TEXT ·FIPSOnly(SB),NOSPLIT,$0
+	START
+	BYTE $0x36; BYTE $0x3C; BYTE $0xB9; BYTE $0xCE;
+	BYTE $0x9D; BYTE $0x68; BYTE $0x04; BYTE $0x7D;
+	BYTE $0x31; BYTE $0xF2; BYTE $0x8D; BYTE $0x32;
+	BYTE $0x5D; BYTE $0x5C; BYTE $0xA5; BYTE $0x87;
+	BYTE $0x3F; BYTE $0x5D; BYTE $0x80; BYTE $0xCA;
+	BYTE $0xF6; BYTE $0xD6; BYTE $0x15; BYTE $0x1B;
+	END
diff --git a/src/crypto/internal/boring/sig/sig_other.s b/src/crypto/internal/boring/sig/sig_other.s
new file mode 100644
index 0000000..2eb3173
--- /dev/null
+++ b/src/crypto/internal/boring/sig/sig_other.s
@@ -0,0 +1,19 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// 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
diff --git a/src/crypto/issue21104_test.go b/src/crypto/issue21104_test.go
index b4276df..4662088 100644
--- a/src/crypto/issue21104_test.go
+++ b/src/crypto/issue21104_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package crypto
+package crypto_test
 
 import (
 	"crypto/aes"
diff --git a/src/crypto/rand/rand_unix.go b/src/crypto/rand/rand_unix.go
index 631972b..f7cd746 100644
--- a/src/crypto/rand/rand_unix.go
+++ b/src/crypto/rand/rand_unix.go
@@ -13,6 +13,7 @@
 	"bufio"
 	"crypto/aes"
 	"crypto/cipher"
+	"crypto/internal/boring"
 	"io"
 	"os"
 	"runtime"
@@ -26,6 +27,10 @@
 // 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 {
@@ -45,6 +50,7 @@
 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
 	}
@@ -108,6 +114,7 @@
 }
 
 func (r *reader) Read(b []byte) (n int, err error) {
+	boring.Unreachable()
 	r.mu.Lock()
 	defer r.mu.Unlock()
 	n = len(b)
diff --git a/src/crypto/rsa/boring.go b/src/crypto/rsa/boring.go
new file mode 100644
index 0000000..0f362a2
--- /dev/null
+++ b/src/crypto/rsa/boring.go
@@ -0,0 +1,124 @@
+// 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"
+	"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
+}
diff --git a/src/crypto/rsa/boring_test.go b/src/crypto/rsa/boring_test.go
new file mode 100644
index 0000000..26fdabb
--- /dev/null
+++ b/src/crypto/rsa/boring_test.go
@@ -0,0 +1,127 @@
+// 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 (
+	"crypto"
+	"crypto/rand"
+	"encoding/asn1"
+	"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)
+	}
+}
+
+func TestBoringGenerateKey(t *testing.T) {
+	k, err := GenerateKey(rand.Reader, 2048) // 2048 is smallest size BoringCrypto might kick in for
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Non-Boring GenerateKey always sets CRTValues to a non-nil (possibly empty) slice.
+	if k.Precomputed.CRTValues == nil {
+		t.Fatalf("GenerateKey: Precomputed.CRTValues = nil")
+	}
+}
+
+func TestBoringFinalizers(t *testing.T) {
+	if runtime.GOOS == "nacl" || runtime.GOOS == "js" {
+		// Times out on nacl and js/wasm (without BoringCrypto)
+		// but not clear why - probably consuming rand.Reader too quickly
+		// and being throttled. Also doesn't really matter.
+		t.Skipf("skipping on %s/%s", runtime.GOOS, runtime.GOARCH)
+	}
+
+	k, err := GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Run test with GOGC=10, to make bug more likely.
+	// Without the KeepAlives, the loop usually dies after
+	// about 30 iterations.
+	defer debug.SetGCPercent(debug.SetGCPercent(10))
+	for n := 0; n < 200; n++ {
+		// Clear the underlying BoringCrypto object.
+		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()
+	}
+}
diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go
index 37790ac..5a0e9e2 100644
--- a/src/crypto/rsa/pkcs1v15.go
+++ b/src/crypto/rsa/pkcs1v15.go
@@ -6,6 +6,7 @@
 
 import (
 	"crypto"
+	"crypto/internal/boring"
 	"crypto/subtle"
 	"errors"
 	"io"
@@ -36,8 +37,8 @@
 //
 // WARNING: use of this function to encrypt plaintexts other than
 // session keys is dangerous. Use RSA OAEP in new protocols.
-func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error) {
-	randutil.MaybeReadByte(rand)
+func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, error) {
+	randutil.MaybeReadByte(random)
 
 	if err := checkPub(pub); err != nil {
 		return nil, err
@@ -47,20 +48,37 @@
 		return nil, ErrMessageTooLong
 	}
 
+	if boring.Enabled && random == boring.RandReader {
+		bkey, err := boringPublicKey(pub)
+		if err != nil {
+			return nil, err
+		}
+		return boring.EncryptRSAPKCS1(bkey, msg)
+	}
+	boring.UnreachableExceptTests()
+
 	// EM = 0x00 || 0x02 || PS || 0x00 || M
 	em := make([]byte, k)
 	em[1] = 2
 	ps, mm := em[2:len(em)-len(msg)-1], em[len(em)-len(msg):]
-	err := nonZeroRandomBytes(ps, rand)
+	err := nonZeroRandomBytes(ps, random)
 	if err != nil {
 		return nil, err
 	}
 	em[len(em)-len(msg)-1] = 0
 	copy(mm, msg)
 
+	if boring.Enabled {
+		var bkey *boring.PublicKeyRSA
+		bkey, err = boringPublicKey(pub)
+		if err != nil {
+			return nil, err
+		}
+		return boring.EncryptRSANoPadding(bkey, em)
+	}
+
 	m := new(big.Int).SetBytes(em)
 	c := encrypt(new(big.Int), pub, m)
-
 	copyWithLeftPad(em, c.Bytes())
 	return em, nil
 }
@@ -77,6 +95,19 @@
 	if err := checkPub(&priv.PublicKey); err != nil {
 		return nil, err
 	}
+
+	if boring.Enabled {
+		bkey, err := boringPrivateKey(priv)
+		if err != nil {
+			return nil, err
+		}
+		out, err := boring.DecryptRSAPKCS1(bkey, ciphertext)
+		if err != nil {
+			return nil, ErrDecryption
+		}
+		return out, nil
+	}
+
 	valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext)
 	if err != nil {
 		return nil, err
@@ -144,13 +175,26 @@
 		return
 	}
 
-	c := new(big.Int).SetBytes(ciphertext)
-	m, err := decrypt(rand, priv, c)
-	if err != nil {
-		return
+	if boring.Enabled {
+		var bkey *boring.PrivateKeyRSA
+		bkey, err = boringPrivateKey(priv)
+		if err != nil {
+			return
+		}
+		em, err = boring.DecryptRSANoPadding(bkey, ciphertext)
+		if err != nil {
+			return
+		}
+	} else {
+		c := new(big.Int).SetBytes(ciphertext)
+		var m *big.Int
+		m, err = decrypt(rand, priv, c)
+		if err != nil {
+			return
+		}
+		em = leftPad(m.Bytes(), k)
 	}
 
-	em = leftPad(m.Bytes(), k)
 	firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
 	secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2)
 
@@ -229,7 +273,7 @@
 // messages is small, an attacker may be able to build a map from
 // messages to signatures and identify the signed messages. As ever,
 // signatures provide authenticity, not confidentiality.
-func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
+func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
 	hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
 	if err != nil {
 		return nil, err
@@ -241,6 +285,14 @@
 		return nil, ErrMessageTooLong
 	}
 
+	if boring.Enabled {
+		bkey, err := boringPrivateKey(priv)
+		if err != nil {
+			return nil, err
+		}
+		return boring.SignRSAPKCS1v15(bkey, hash, hashed)
+	}
+
 	// EM = 0x00 || 0x01 || PS || 0x00 || T
 	em := make([]byte, k)
 	em[1] = 1
@@ -251,7 +303,7 @@
 	copy(em[k-hashLen:k], hashed)
 
 	m := new(big.Int).SetBytes(em)
-	c, err := decryptAndCheck(rand, priv, m)
+	c, err := decryptAndCheck(random, priv, m)
 	if err != nil {
 		return nil, err
 	}
@@ -266,6 +318,17 @@
 // 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
diff --git a/src/crypto/rsa/pkcs1v15_test.go b/src/crypto/rsa/pkcs1v15_test.go
index 47444f3..7f380b6 100644
--- a/src/crypto/rsa/pkcs1v15_test.go
+++ b/src/crypto/rsa/pkcs1v15_test.go
@@ -64,7 +64,7 @@
 		for i, test := range decryptPKCS1v15Tests {
 			out, err := decryptFunc(decodeBase64(test.in))
 			if err != nil {
-				t.Errorf("#%d error decrypting", i)
+				t.Errorf("#%d error decrypting: %v", i, err)
 			}
 			want := []byte(test.out)
 			if !bytes.Equal(out, want) {
diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
index 3ff0c2f..89f850e 100644
--- a/src/crypto/rsa/pss.go
+++ b/src/crypto/rsa/pss.go
@@ -11,6 +11,7 @@
 import (
 	"bytes"
 	"crypto"
+	"crypto/internal/boring"
 	"errors"
 	"hash"
 	"io"
@@ -197,6 +198,21 @@
 	if err != nil {
 		return
 	}
+
+	if boring.Enabled {
+		bkey, err := boringPrivateKey(priv)
+		if err != nil {
+			return nil, err
+		}
+		// Note: BoringCrypto takes care of the "AndCheck" part of "decryptAndCheck".
+		// (It's not just decrypt.)
+		s, err := boring.DecryptRSANoPadding(bkey, em)
+		if err != nil {
+			return nil, err
+		}
+		return s, nil
+	}
+
 	m := new(big.Int).SetBytes(em)
 	c, err := decryptAndCheck(rand, priv, m)
 	if err != nil {
@@ -259,6 +275,14 @@
 		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
@@ -277,6 +301,16 @@
 
 // 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
diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go
index cae24e5..4ce5ad8 100644
--- a/src/crypto/rsa/pss_test.go
+++ b/src/crypto/rsa/pss_test.go
@@ -9,7 +9,6 @@
 	"bytes"
 	"compress/bzip2"
 	"crypto"
-	_ "crypto/md5"
 	"crypto/rand"
 	"crypto/sha1"
 	_ "crypto/sha256"
@@ -211,7 +210,7 @@
 		{8, 8, true},
 	}
 
-	hash := crypto.MD5
+	hash := crypto.SHA1
 	h := hash.New()
 	h.Write([]byte("testing"))
 	hashed := h.Sum(nil)
diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go
index ad32d3e..755bd6d 100644
--- a/src/crypto/rsa/rsa.go
+++ b/src/crypto/rsa/rsa.go
@@ -24,6 +24,7 @@
 
 import (
 	"crypto"
+	"crypto/internal/boring"
 	"crypto/rand"
 	"crypto/subtle"
 	"errors"
@@ -31,6 +32,7 @@
 	"io"
 	"math"
 	"math/big"
+	"unsafe"
 
 	"crypto/internal/randutil"
 )
@@ -42,6 +44,8 @@
 type PublicKey struct {
 	N *big.Int // modulus
 	E int      // public exponent
+
+	boring unsafe.Pointer
 }
 
 // Size returns the modulus size in bytes. Raw signatures and ciphertexts
@@ -93,6 +97,8 @@
 	// Precomputed contains precomputed values that speed up private
 	// operations, if available.
 	Precomputed PrecomputedValues
+
+	boring unsafe.Pointer
 }
 
 // Public returns the public key corresponding to priv.
@@ -222,6 +228,32 @@
 func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error) {
 	randutil.MaybeReadByte(random)
 
+	if boring.Enabled && random == boring.RandReader && nprimes == 2 && (bits == 2048 || bits == 3072) {
+		N, E, D, P, Q, Dp, Dq, Qinv, err := boring.GenerateKeyRSA(bits)
+		if err != nil {
+			return nil, err
+		}
+		e64 := E.Int64()
+		if !E.IsInt64() || int64(int(e64)) != e64 {
+			return nil, errors.New("crypto/rsa: generated key exponent too large")
+		}
+		key := &PrivateKey{
+			PublicKey: PublicKey{
+				N: N,
+				E: int(e64),
+			},
+			D:      D,
+			Primes: []*big.Int{P, Q},
+			Precomputed: PrecomputedValues{
+				Dp:        Dp,
+				Dq:        Dq,
+				Qinv:      Qinv,
+				CRTValues: make([]CRTValue, 0), // non-nil, to match Precompute
+			},
+		}
+		return key, nil
+	}
+
 	priv := new(PrivateKey)
 	priv.E = 65537
 
@@ -351,6 +383,7 @@
 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
@@ -383,6 +416,15 @@
 		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()
@@ -403,10 +445,24 @@
 	mgf1XOR(db, hash, seed)
 	mgf1XOR(seed, hash, db)
 
-	m := new(big.Int)
-	m.SetBytes(em)
-	c := encrypt(new(big.Int), pub, m)
-	out := c.Bytes()
+	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()
+	}
 
 	if len(out) < k {
 		// If the output is too small, we need to left-pad with zeros.
@@ -460,6 +516,9 @@
 // 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
@@ -576,6 +635,17 @@
 		return nil, ErrDecryption
 	}
 
+	if boring.Enabled {
+		bkey, err := boringPrivateKey(priv)
+		if err != nil {
+			return nil, err
+		}
+		out, err := boring.DecryptRSAOAEP(hash, bkey, ciphertext, label)
+		if err != nil {
+			return nil, ErrDecryption
+		}
+		return out, nil
+	}
 	c := new(big.Int).SetBytes(ciphertext)
 
 	m, err := decrypt(random, priv, c)
diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go
index 84b1674..3abe88a 100644
--- a/src/crypto/rsa/rsa_test.go
+++ b/src/crypto/rsa/rsa_test.go
@@ -7,26 +7,29 @@
 import (
 	"bytes"
 	"crypto"
+	"crypto/internal/boring"
 	"crypto/rand"
 	"crypto/sha1"
 	"crypto/sha256"
+	"fmt"
 	"math/big"
 	"testing"
 )
 
 func TestKeyGeneration(t *testing.T) {
-	size := 1024
-	if testing.Short() {
-		size = 128
+	for _, size := range []int{128, 1024, 2048, 3072} {
+		priv, err := GenerateKey(rand.Reader, size)
+		if err != nil {
+			t.Errorf("GenerateKey(%d): %v", size, err)
+		}
+		if bits := priv.N.BitLen(); bits != size {
+			t.Errorf("key too short (%d vs %d)", bits, size)
+		}
+		testKeyBasics(t, priv)
+		if testing.Short() {
+			break
+		}
 	}
-	priv, err := GenerateKey(rand.Reader, size)
-	if err != nil {
-		t.Errorf("failed to generate key")
-	}
-	if bits := priv.N.BitLen(); bits != size {
-		t.Errorf("key too short (%d vs %d)", bits, size)
-	}
-	testKeyBasics(t, priv)
 }
 
 func Test3PrimeKeyGeneration(t *testing.T) {
@@ -110,6 +113,25 @@
 		t.Errorf("private exponent too large")
 	}
 
+	if boring.Enabled {
+		// Cannot call encrypt/decrypt directly. Test via PKCS1v15.
+		msg := []byte("hi!")
+		enc, err := EncryptPKCS1v15(rand.Reader, &priv.PublicKey, msg)
+		if err != nil {
+			t.Errorf("EncryptPKCS1v15: %v", err)
+			return
+		}
+		dec, err := DecryptPKCS1v15(rand.Reader, priv, enc)
+		if err != nil {
+			t.Errorf("DecryptPKCS1v15: %v", err)
+			return
+		}
+		if !bytes.Equal(dec, msg) {
+			t.Errorf("got:%x want:%x (%+v)", dec, msg, priv)
+		}
+		return
+	}
+
 	pub := &priv.PublicKey
 	m := big.NewInt(42)
 	c := encrypt(new(big.Int), pub, m)
@@ -158,6 +180,10 @@
 }
 
 func BenchmarkRSA2048Decrypt(b *testing.B) {
+	if boring.Enabled {
+		b.Skip("no raw decrypt in BoringCrypto")
+	}
+
 	b.StopTimer()
 
 	c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313")
@@ -180,6 +206,10 @@
 }
 
 func Benchmark3PrimeRSA2048Decrypt(b *testing.B) {
+	if boring.Enabled {
+		b.Skip("no raw decrypt in BoringCrypto")
+	}
+
 	b.StopTimer()
 	priv := &PrivateKey{
 		PublicKey: PublicKey{
@@ -222,7 +252,7 @@
 	n := new(big.Int)
 	for i, test := range testEncryptOAEPData {
 		n.SetString(test.modulus, 16)
-		public := PublicKey{n, test.e}
+		public := PublicKey{N: n, E: test.e}
 
 		for j, message := range test.msgs {
 			randomSource := bytes.NewReader(message.seed)
@@ -247,7 +277,7 @@
 		n.SetString(test.modulus, 16)
 		d.SetString(test.d, 16)
 		private := new(PrivateKey)
-		private.PublicKey = PublicKey{n, test.e}
+		private.PublicKey = PublicKey{N: n, E: test.e}
 		private.D = d
 
 		for j, message := range test.msgs {
@@ -272,6 +302,36 @@
 	}
 }
 
+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
diff --git a/src/crypto/sha1/boring.go b/src/crypto/sha1/boring.go
new file mode 100644
index 0000000..44c2609
--- /dev/null
+++ b/src/crypto/sha1/boring.go
@@ -0,0 +1,22 @@
+// 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() }
diff --git a/src/crypto/sha1/notboring.go b/src/crypto/sha1/notboring.go
new file mode 100644
index 0000000..9726fcd
--- /dev/null
+++ b/src/crypto/sha1/notboring.go
@@ -0,0 +1,17 @@
+// 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() {}
diff --git a/src/crypto/sha1/sha1.go b/src/crypto/sha1/sha1.go
index db70b7d..a9546bb 100644
--- a/src/crypto/sha1/sha1.go
+++ b/src/crypto/sha1/sha1.go
@@ -118,6 +118,9 @@
 // implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to
 // marshal and unmarshal the internal state of the hash.
 func New() hash.Hash {
+	if boringEnabled {
+		return boringNewSHA1()
+	}
 	d := new(digest)
 	d.Reset()
 	return d
@@ -128,6 +131,7 @@
 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 {
@@ -151,6 +155,7 @@
 }
 
 func (d *digest) Sum(in []byte) []byte {
+	boringUnreachable()
 	// Make a copy of d so that caller can keep writing and summing.
 	d0 := *d
 	hash := d0.checkSum()
@@ -258,6 +263,13 @@
 
 // Sum returns the SHA-1 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)
diff --git a/src/crypto/sha1/sha1_test.go b/src/crypto/sha1/sha1_test.go
index 4f22926..6ce39de 100644
--- a/src/crypto/sha1/sha1_test.go
+++ b/src/crypto/sha1/sha1_test.go
@@ -8,6 +8,7 @@
 
 import (
 	"bytes"
+	"crypto/internal/boring"
 	"crypto/rand"
 	"encoding"
 	"fmt"
@@ -76,6 +77,9 @@
 				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:])
@@ -140,6 +144,9 @@
 
 // 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)
diff --git a/src/crypto/sha256/sha256.go b/src/crypto/sha256/sha256.go
index 1389de2..6ac585f 100644
--- a/src/crypto/sha256/sha256.go
+++ b/src/crypto/sha256/sha256.go
@@ -8,6 +8,7 @@
 
 import (
 	"crypto"
+	"crypto/internal/boring"
 	"errors"
 	"hash"
 )
@@ -178,6 +179,9 @@
 // encoding.BinaryUnmarshaler to marshal and unmarshal the internal
 // state of the hash.
 func New() hash.Hash {
+	if boring.Enabled {
+		return boring.NewSHA256()
+	}
 	d := new(digest)
 	d.Reset()
 	return d
@@ -185,6 +189,9 @@
 
 // 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()
@@ -201,6 +208,7 @@
 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 {
@@ -224,6 +232,7 @@
 }
 
 func (d *digest) Sum(in []byte) []byte {
+	boring.Unreachable()
 	// Make a copy of d so that caller can keep writing and summing.
 	d0 := *d
 	hash := d0.checkSum()
@@ -271,6 +280,13 @@
 
 // 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)
@@ -279,6 +295,13 @@
 
 // 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()
diff --git a/src/crypto/sha256/sha256_test.go b/src/crypto/sha256/sha256_test.go
index cd40286..a188a64 100644
--- a/src/crypto/sha256/sha256_test.go
+++ b/src/crypto/sha256/sha256_test.go
@@ -8,6 +8,7 @@
 
 import (
 	"bytes"
+	"crypto/internal/boring"
 	"crypto/rand"
 	"encoding"
 	"fmt"
@@ -216,6 +217,9 @@
 
 // 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)
diff --git a/src/crypto/sha512/sha512.go b/src/crypto/sha512/sha512.go
index 24fde7d..355d7bb 100644
--- a/src/crypto/sha512/sha512.go
+++ b/src/crypto/sha512/sha512.go
@@ -12,6 +12,7 @@
 
 import (
 	"crypto"
+	"crypto/internal/boring"
 	"errors"
 	"hash"
 )
@@ -222,6 +223,9 @@
 
 // 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
@@ -243,6 +247,9 @@
 
 // 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
@@ -264,6 +271,9 @@
 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 {
@@ -287,6 +297,9 @@
 }
 
 func (d *digest) Sum(in []byte) []byte {
+	if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 {
+		boring.Unreachable()
+	}
 	// Make a copy of d so that caller can keep writing and summing.
 	d0 := new(digest)
 	*d0 = *d
@@ -341,6 +354,13 @@
 
 // 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)
@@ -349,6 +369,13 @@
 
 // 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)
diff --git a/src/crypto/sha512/sha512_test.go b/src/crypto/sha512/sha512_test.go
index 4423cf5..93c4591 100644
--- a/src/crypto/sha512/sha512_test.go
+++ b/src/crypto/sha512/sha512_test.go
@@ -8,6 +8,7 @@
 
 import (
 	"bytes"
+	"crypto/internal/boring"
 	"crypto/rand"
 	"encoding"
 	"encoding/hex"
@@ -821,6 +822,9 @@
 
 // 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)
diff --git a/src/crypto/tls/boring.go b/src/crypto/tls/boring.go
new file mode 100644
index 0000000..f6d922c
--- /dev/null
+++ b/src/crypto/tls/boring.go
@@ -0,0 +1,121 @@
+// 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() []SignatureScheme {
+	all := defaultSupportedSignatureAlgorithms
+	if !needFIPS() {
+		return all
+	}
+	i := 0
+	for i < len(all) && all[i] != PKCS1WithSHA1 {
+		i++
+	}
+	return all[:i]
+}
+
+var testingOnlyForceClientHelloSignatureAlgorithms []SignatureScheme
diff --git a/src/crypto/tls/boring_test.go b/src/crypto/tls/boring_test.go
new file mode 100644
index 0000000..2ac62a5
--- /dev/null
+++ b/src/crypto/tls/boring_test.go
@@ -0,0 +1,576 @@
+// 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 isBoringSignatureScheme(alg SignatureScheme) bool {
+	switch alg {
+	default:
+		return false
+	case PKCS1WithSHA256,
+		ECDSAWithP256AndSHA256,
+		PKCS1WithSHA384,
+		ECDSAWithP384AndSHA384,
+		PKCS1WithSHA512,
+		ECDSAWithP521AndSHA512:
+		// 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() {
+		testingOnlyForceClientHelloSignatureAlgorithms = nil
+	}()
+
+	for _, sigHash := range defaultSupportedSignatureAlgorithms {
+		testingOnlyForceClientHelloSignatureAlgorithms = []SignatureScheme{sigHash}
+
+		t.Run(fmt.Sprintf("%v", sigHash), func(t *testing.T) {
+			if sigHash == PKCS1WithSHA1 || sigHash == PKCS1WithSHA256 || sigHash == PKCS1WithSHA384 || sigHash == PKCS1WithSHA512 {
+				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 isBoringSignatureScheme(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.supportedSignatureAlgorithms {
+		if !isBoringSignatureScheme(sigHash) {
+			t.Errorf("client offered disallowed signature-and-hash %v", sigHash)
+		}
+	}
+}
+
+func TestBoringCertAlgs(t *testing.T) {
+	// NaCl, arm and wasm time out generating keys. Nothing in this test is architecture-specific, so just don't bother on those.
+	if runtime.GOOS == "nacl" || runtime.GOARCH == "arm" || runtime.GOOS == "js" {
+		t.Skipf("skipping on %s/%s because key generation takes too long", runtime.GOOS, runtime.GOARCH)
+	}
+
+	// Set up some roots, intermediate CAs, and leaf certs with various algorithms.
+	// X_Y is X signed by Y.
+	R1 := boringCert(t, "R1", boringRSAKey(t, 2048), nil, boringCertCA|boringCertFIPSOK)
+	R2 := boringCert(t, "R2", boringRSAKey(t, 4096), nil, boringCertCA)
+
+	M1_R1 := boringCert(t, "M1_R1", boringECDSAKey(t, elliptic.P256()), R1, boringCertCA|boringCertFIPSOK)
+	M2_R1 := boringCert(t, "M2_R1", boringECDSAKey(t, elliptic.P224()), R1, boringCertCA)
+
+	I_R1 := boringCert(t, "I_R1", boringRSAKey(t, 3072), R1, boringCertCA|boringCertFIPSOK)
+	I_R2 := boringCert(t, "I_R2", I_R1.key, R2, boringCertCA|boringCertFIPSOK)
+	I_M1 := boringCert(t, "I_M1", I_R1.key, M1_R1, boringCertCA|boringCertFIPSOK)
+	I_M2 := boringCert(t, "I_M2", I_R1.key, M2_R1, boringCertCA|boringCertFIPSOK)
+
+	L1_I := boringCert(t, "L1_I", boringECDSAKey(t, elliptic.P384()), I_R1, boringCertLeaf|boringCertFIPSOK)
+	L2_I := boringCert(t, "L2_I", boringRSAKey(t, 1024), I_R1, boringCertLeaf)
+
+	// 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
+}
diff --git a/src/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go
index 3c8dc4b..e4027e8 100644
--- a/src/crypto/tls/cipher_suites.go
+++ b/src/crypto/tls/cipher_suites.go
@@ -9,6 +9,7 @@
 	"crypto/cipher"
 	"crypto/des"
 	"crypto/hmac"
+	"crypto/internal/boring"
 	"crypto/rc4"
 	"crypto/sha1"
 	"crypto/sha256"
@@ -135,7 +136,11 @@
 		copy(mac.key, key)
 		return mac
 	}
-	return tls10MAC{hmac.New(newConstantTimeHash(sha1.New), key)}
+	h := sha1.New
+	if !boring.Enabled {
+		h = newConstantTimeHash(h)
+	}
+	return tls10MAC{hmac.New(h, key)}
 }
 
 // macSHA256 returns a SHA-256 based MAC. These are only supported in TLS 1.2
@@ -215,12 +220,22 @@
 	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)
 	}
-	aead, err := cipher.NewGCM(aes)
+	var aead cipher.AEAD
+	if aesTLS, ok := aes.(gcmtls); ok {
+		aead, err = aesTLS.NewGCMTLS()
+	} else {
+		boring.Unreachable()
+		aead, err = cipher.NewGCM(aes)
+	}
 	if err != nil {
 		panic(err)
 	}
@@ -298,6 +313,11 @@
 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)}
 	}
diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go
index 7b627fc..5a27be2 100644
--- a/src/crypto/tls/common.go
+++ b/src/crypto/tls/common.go
@@ -7,6 +7,7 @@
 import (
 	"container/list"
 	"crypto"
+	"crypto/internal/boring"
 	"crypto/rand"
 	"crypto/sha512"
 	"crypto/x509"
@@ -135,11 +136,11 @@
 	signatureRSAPSS
 )
 
-// supportedSignatureAlgorithms contains the signature and hash algorithms that
+// defaultSupportedSignatureAlgorithms contains the signature and hash algorithms that
 // the code advertises as supported in a TLS 1.2 ClientHello and in a TLS 1.2
 // CertificateRequest. The two fields are merged to match with TLS 1.3.
 // Note that in TLS 1.2, the ECDSA algorithms are not constrained to P-256, etc.
-var supportedSignatureAlgorithms = []SignatureScheme{
+var defaultSupportedSignatureAlgorithms = []SignatureScheme{
 	PKCS1WithSHA256,
 	ECDSAWithP256AndSHA256,
 	PKCS1WithSHA384,
@@ -673,6 +674,9 @@
 }
 
 func (c *Config) cipherSuites() []uint16 {
+	if needFIPS() {
+		return fipsCipherSuites(c)
+	}
 	s := c.CipherSuites
 	if s == nil {
 		s = defaultCipherSuites()
@@ -681,6 +685,9 @@
 }
 
 func (c *Config) minVersion() uint16 {
+	if needFIPS() {
+		return fipsMinVersion(c)
+	}
 	if c == nil || c.MinVersion == 0 {
 		return minVersion
 	}
@@ -688,6 +695,9 @@
 }
 
 func (c *Config) maxVersion() uint16 {
+	if needFIPS() {
+		return fipsMaxVersion(c)
+	}
 	if c == nil || c.MaxVersion == 0 {
 		return maxVersion
 	}
@@ -697,6 +707,9 @@
 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
 	}
@@ -937,7 +950,8 @@
 
 	hasGCMAsm := hasGCMAsmAMD64 || hasGCMAsmARM64 || hasGCMAsmS390X
 
-	if hasGCMAsm {
+	if hasGCMAsm || boring.Enabled {
+		// If BoringCrypto is enabled, always prioritize AES-GCM.
 		// If AES-GCM hardware is provided then prioritise AES-GCM
 		// cipher suites.
 		topCipherSuites = []uint16{
diff --git a/src/crypto/tls/fipsonly/fipsonly.go b/src/crypto/tls/fipsonly/fipsonly.go
new file mode 100644
index 0000000..85b3532
--- /dev/null
+++ b/src/crypto/tls/fipsonly/fipsonly.go
@@ -0,0 +1,27 @@
+// 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()
+}
diff --git a/src/crypto/tls/fipsonly/fipsonly_test.go b/src/crypto/tls/fipsonly/fipsonly_test.go
new file mode 100644
index 0000000..facd248
--- /dev/null
+++ b/src/crypto/tls/fipsonly/fipsonly_test.go
@@ -0,0 +1,16 @@
+// 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")
+	}
+}
diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go
index 32fdc6d..9f5731b 100644
--- a/src/crypto/tls/handshake_client.go
+++ b/src/crypto/tls/handshake_client.go
@@ -86,7 +86,10 @@
 	}
 
 	if hello.vers >= VersionTLS12 {
-		hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms
+		hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
+	}
+	if testingOnlyForceClientHelloSignatureAlgorithms != nil {
+		hello.supportedSignatureAlgorithms = testingOnlyForceClientHelloSignatureAlgorithms
 	}
 
 	return hello, nil
@@ -325,6 +328,8 @@
 
 		if !c.config.InsecureSkipVerify {
 			opts := x509.VerifyOptions{
+				IsBoring: isBoringCertificate,
+
 				Roots:         c.config.RootCAs,
 				CurrentTime:   c.config.time(),
 				DNSName:       c.config.ServerName,
diff --git a/src/crypto/tls/handshake_messages_test.go b/src/crypto/tls/handshake_messages_test.go
index 37eb748..1bf12c9 100644
--- a/src/crypto/tls/handshake_messages_test.go
+++ b/src/crypto/tls/handshake_messages_test.go
@@ -145,7 +145,7 @@
 		}
 	}
 	if rand.Intn(10) > 5 {
-		m.supportedSignatureAlgorithms = supportedSignatureAlgorithms
+		m.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
 	}
 	m.alpnProtocols = make([]string, rand.Intn(5))
 	for i := range m.alpnProtocols {
diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go
index ac491ba..f2ad226 100644
--- a/src/crypto/tls/handshake_server.go
+++ b/src/crypto/tls/handshake_server.go
@@ -419,7 +419,7 @@
 		}
 		if c.vers >= VersionTLS12 {
 			certReq.hasSignatureAndHash = true
-			certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms
+			certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
 		}
 
 		// An empty list of certificateAuthorities signals to
@@ -520,7 +520,7 @@
 		}
 
 		// Determine the signature type.
-		_, sigType, hashFunc, err := pickSignatureAlgorithm(pub, []SignatureScheme{certVerify.signatureAlgorithm}, supportedSignatureAlgorithms, c.vers)
+		_, sigType, hashFunc, err := pickSignatureAlgorithm(pub, []SignatureScheme{certVerify.signatureAlgorithm}, supportedSignatureAlgorithms(), c.vers)
 		if err != nil {
 			c.sendAlert(alertIllegalParameter)
 			return err
@@ -678,6 +678,8 @@
 
 	if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
 		opts := x509.VerifyOptions{
+			IsBoring: isBoringCertificate,
+
 			Roots:         c.config.ClientCAs,
 			CurrentTime:   c.config.time(),
 			Intermediates: x509.NewCertPool(),
diff --git a/src/crypto/tls/key_agreement.go b/src/crypto/tls/key_agreement.go
index 1e77fac..0754d1b 100644
--- a/src/crypto/tls/key_agreement.go
+++ b/src/crypto/tls/key_agreement.go
@@ -213,7 +213,7 @@
 		return nil, errors.New("tls: certificate private key does not implement crypto.Signer")
 	}
 
-	signatureAlgorithm, sigType, hashFunc, err := pickSignatureAlgorithm(priv.Public(), clientHello.supportedSignatureAlgorithms, supportedSignatureAlgorithms, ka.version)
+	signatureAlgorithm, sigType, hashFunc, err := pickSignatureAlgorithm(priv.Public(), clientHello.supportedSignatureAlgorithms, supportedSignatureAlgorithms(), ka.version)
 	if err != nil {
 		return nil, err
 	}
diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go
index d84272e..122a7c6 100644
--- a/src/crypto/x509/verify.go
+++ b/src/crypto/x509/verify.go
@@ -188,6 +188,11 @@
 // VerifyOptions contains parameters for Certificate.Verify. It's a structure
 // because other PKIX verification APIs have ended up needing many options.
 type VerifyOptions struct {
+	// 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
+
 	DNSName       string
 	Intermediates *CertPool
 	Roots         *CertPool // if nil, the system roots are used
@@ -701,6 +706,13 @@
 		}
 	}
 
+	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
 }
 
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index 29dbe47..08ab218 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -117,10 +117,17 @@
 	"reflect":                {"L2"},
 	"sort":                   {"reflect"},
 
+	"crypto/internal/boring":         {"L2", "C", "crypto", "crypto/cipher", "crypto/internal/boring/sig", "crypto/subtle", "encoding/asn1", "hash", "math/big"},
+	"crypto/internal/boring/fipstls": {"sync/atomic"},
+	"crypto/internal/cipherhw":       {"crypto/internal/boring"},
+	"crypto/tls/fipsonly":            {"crypto/internal/boring/fipstls", "crypto/internal/boring/sig"},
+
 	"L3": {
 		"L2",
 		"crypto",
 		"crypto/cipher",
+		"crypto/internal/boring",
+		"crypto/internal/boring/fipstls",
 		"crypto/internal/subtle",
 		"crypto/subtle",
 		"encoding/base32",
@@ -231,49 +238,49 @@
 	"go/types":                  {"L4", "GOPARSER", "container/heap", "go/constant"},
 
 	// One of a kind.
-	"archive/tar":              {"L4", "OS", "syscall", "os/user"},
-	"archive/zip":              {"L4", "OS", "compress/flate"},
-	"container/heap":           {"sort"},
-	"compress/bzip2":           {"L4"},
-	"compress/flate":           {"L4"},
-	"compress/gzip":            {"L4", "compress/flate"},
-	"compress/lzw":             {"L4"},
-	"compress/zlib":            {"L4", "compress/flate"},
-	"context":                  {"errors", "fmt", "reflect", "sync", "time"},
-	"database/sql":             {"L4", "container/list", "context", "database/sql/driver", "database/sql/internal"},
-	"database/sql/driver":      {"L4", "context", "time", "database/sql/internal"},
-	"debug/dwarf":              {"L4"},
-	"debug/elf":                {"L4", "OS", "debug/dwarf", "compress/zlib"},
-	"debug/gosym":              {"L4"},
-	"debug/macho":              {"L4", "OS", "debug/dwarf", "compress/zlib"},
-	"debug/pe":                 {"L4", "OS", "debug/dwarf", "compress/zlib"},
-	"debug/plan9obj":           {"L4", "OS"},
-	"encoding":                 {"L4"},
-	"encoding/ascii85":         {"L4"},
-	"encoding/asn1":            {"L4", "math/big"},
-	"encoding/csv":             {"L4"},
-	"encoding/gob":             {"L4", "OS", "encoding"},
-	"encoding/hex":             {"L4"},
-	"encoding/json":            {"L4", "encoding"},
-	"encoding/pem":             {"L4"},
-	"encoding/xml":             {"L4", "encoding"},
-	"flag":                     {"L4", "OS"},
-	"go/build":                 {"L4", "OS", "GOPARSER"},
-	"html":                     {"L4"},
-	"image/draw":               {"L4", "image/internal/imageutil"},
-	"image/gif":                {"L4", "compress/lzw", "image/color/palette", "image/draw"},
-	"image/internal/imageutil": {"L4"},
-	"image/jpeg":               {"L4", "image/internal/imageutil"},
-	"image/png":                {"L4", "compress/zlib"},
-	"index/suffixarray":        {"L4", "regexp"},
-	"internal/singleflight":    {"sync"},
-	"internal/trace":           {"L4", "OS"},
-	"math/big":                 {"L4"},
-	"mime":                     {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
-	"mime/quotedprintable":     {"L4"},
-	"net/internal/socktest":    {"L4", "OS", "syscall", "internal/syscall/windows"},
-	"net/url":                  {"L4"},
-	"plugin":                   {"L0", "OS", "CGO"},
+	"archive/tar":                    {"L4", "OS", "syscall", "os/user"},
+	"archive/zip":                    {"L4", "OS", "compress/flate"},
+	"container/heap":                 {"sort"},
+	"compress/bzip2":                 {"L4"},
+	"compress/flate":                 {"L4"},
+	"compress/gzip":                  {"L4", "compress/flate"},
+	"compress/lzw":                   {"L4"},
+	"compress/zlib":                  {"L4", "compress/flate"},
+	"context":                        {"errors", "fmt", "reflect", "sync", "time"},
+	"database/sql":                   {"L4", "container/list", "context", "database/sql/driver", "database/sql/internal"},
+	"database/sql/driver":            {"L4", "context", "time", "database/sql/internal"},
+	"debug/dwarf":                    {"L4"},
+	"debug/elf":                      {"L4", "OS", "debug/dwarf", "compress/zlib"},
+	"debug/gosym":                    {"L4"},
+	"debug/macho":                    {"L4", "OS", "debug/dwarf", "compress/zlib"},
+	"debug/pe":                       {"L4", "OS", "debug/dwarf", "compress/zlib"},
+	"debug/plan9obj":                 {"L4", "OS"},
+	"encoding":                       {"L4"},
+	"encoding/ascii85":               {"L4"},
+	"encoding/asn1":                  {"L4", "math/big"},
+	"encoding/csv":                   {"L4"},
+	"encoding/gob":                   {"L4", "OS", "encoding"},
+	"encoding/hex":                   {"L4"},
+	"encoding/json":                  {"L4", "encoding"},
+	"encoding/pem":                   {"L4"},
+	"encoding/xml":                   {"L4", "encoding"},
+	"flag":                           {"L4", "OS"},
+	"go/build":                       {"L4", "OS", "GOPARSER"},
+	"html":                           {"L4"},
+	"image/draw":                     {"L4", "image/internal/imageutil"},
+	"image/gif":                      {"L4", "compress/lzw", "image/color/palette", "image/draw"},
+	"image/internal/imageutil":       {"L4"},
+	"image/jpeg":                     {"L4", "image/internal/imageutil"},
+	"image/png":                      {"L4", "compress/zlib"},
+	"index/suffixarray":              {"L4", "regexp"},
+	"internal/singleflight":          {"sync"},
+	"internal/trace":                 {"L4", "OS"},
+	"math/big":                       {"L4"},
+	"mime":                           {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
+	"mime/quotedprintable":           {"L4"},
+	"net/internal/socktest":          {"L4", "OS", "syscall", "internal/syscall/windows"},
+	"net/url":                        {"L4"},
+	"plugin":                         {"L0", "OS", "CGO"},
 	"runtime/pprof/internal/profile": {"L4", "OS", "compress/gzip", "regexp"},
 	"testing/internal/testdeps":      {"L4", "internal/testlog", "runtime/pprof", "regexp"},
 	"text/scanner":                   {"L4", "OS"},
diff --git a/src/internal/boringtest/boring.go b/src/internal/boringtest/boring.go
new file mode 100644
index 0000000..bea1276
--- /dev/null
+++ b/src/internal/boringtest/boring.go
@@ -0,0 +1,8 @@
+// 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.
+
+// Nothing to see here but the tests.
+// This file keeps 'go install internal/...' working.
+
+package boring
diff --git a/src/internal/boringtest/boring_test.go b/src/internal/boringtest/boring_test.go
new file mode 100644
index 0000000..a6b07ed
--- /dev/null
+++ b/src/internal/boringtest/boring_test.go
@@ -0,0 +1,47 @@
+// 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.
+
+// Like crypto/rsa/boring_test.go but outside the crypto/ tree.
+// Tests what happens if a package outside the crypto/ tree
+// "adopts" a struct definition. This happens in golang.org/x/crypto/ssh.
+
+package boring
+
+import (
+	"crypto/rand"
+	"crypto/rsa"
+	"encoding/asn1"
+	"reflect"
+	"testing"
+)
+
+type publicKey rsa.PublicKey
+
+func TestBoringASN1Marshal(t *testing.T) {
+	k, err := rsa.GenerateKey(rand.Reader, 128)
+	if err != nil {
+		t.Fatal(err)
+	}
+	pk := (*publicKey)(&k.PublicKey)
+	// This used to fail, because of the unexported 'boring' field.
+	// Now the compiler hides it [sic].
+	_, err = asn1.Marshal(*pk)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestBoringDeepEqual(t *testing.T) {
+	k0, err := rsa.GenerateKey(rand.Reader, 128)
+	if err != nil {
+		t.Fatal(err)
+	}
+	k := (*publicKey)(&k0.PublicKey)
+	k2 := *k
+	rsa.EncryptPKCS1v15(rand.Reader, (*rsa.PublicKey)(&k2), []byte("hello")) // initialize hidden boring field
+	if !reflect.DeepEqual(k, &k2) {
+		// compiler should be hiding the boring field from reflection
+		t.Fatalf("DeepEqual compared boring fields")
+	}
+}
diff --git a/src/runtime/race/testdata/mop_test.go b/src/runtime/race/testdata/mop_test.go
index 5d25ed4..b60cabf 100644
--- a/src/runtime/race/testdata/mop_test.go
+++ b/src/runtime/race/testdata/mop_test.go
@@ -6,9 +6,9 @@
 
 import (
 	"bytes"
-	"crypto/sha1"
 	"errors"
 	"fmt"
+	"hash/crc32"
 	"io"
 	"os"
 	"runtime"
@@ -1924,7 +1924,7 @@
 			err = nil
 		}
 	}()
-	h := sha1.New()
+	h := crc32.New(crc32.MakeTable(0x12345678))
 	for b := range in {
 		h.Write(b)
 	}
diff --git a/src/runtime/runtime_boring.go b/src/runtime/runtime_boring.go
new file mode 100644
index 0000000..5a98b20
--- /dev/null
+++ b/src/runtime/runtime_boring.go
@@ -0,0 +1,19 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import _ "unsafe" // for go:linkname
+
+//go:linkname boring_runtime_arg0 crypto/internal/boring.runtime_arg0
+func boring_runtime_arg0() string {
+	// On Windows, argslice is not set, and it's too much work to find argv0.
+	if len(argslice) == 0 {
+		return ""
+	}
+	return argslice[0]
+}
+
+//go:linkname fipstls_runtime_arg0 crypto/internal/boring/fipstls.runtime_arg0
+func fipstls_runtime_arg0() string { return boring_runtime_arg0() }