Bump cfssl to 56268a6

pull/8/head
Christoph Blecker 2018-08-08 21:22:01 -07:00
parent 952fc9f6f8
commit ed7304b30c
No known key found for this signature in database
GPG Key ID: B34A59A9D39F838B
45 changed files with 7832 additions and 241 deletions

258
Godeps/Godeps.json generated
View File

@ -26,12 +26,12 @@
},
{
"ImportPath": "cloud.google.com/go/compute/metadata",
"Comment": "v0.1.0-115-g3b1ae45",
"Comment": "v0.1.0-115-g3b1ae453",
"Rev": "3b1ae45394a234c385be014e9a488f2bb6eef821"
},
{
"ImportPath": "cloud.google.com/go/internal",
"Comment": "v0.1.0-115-g3b1ae45",
"Comment": "v0.1.0-115-g3b1ae453",
"Rev": "3b1ae45394a234c385be014e9a488f2bb6eef821"
},
{
@ -436,308 +436,318 @@
},
{
"ImportPath": "github.com/cloudflare/cfssl/api",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/api/bundle",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/api/certinfo",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/api/client",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/api/crl",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/api/gencrl",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/api/generator",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/api/health",
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/api/info",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/api/initca",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/api/ocsp",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/api/revoke",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/api/scan",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/api/signhandler",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/auth",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/bundler",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/certdb",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/certdb/dbconf",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/certdb/sql",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/certinfo",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/bundle",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/certinfo",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/crl",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/gencert",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/gencrl",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/gencsr",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/genkey",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/info",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/ocspdump",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/ocsprefresh",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/ocspserve",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/ocspsign",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/printdefault",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/revoke",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/scan",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/selfsign",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/serve",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/sign",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli/version",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cmd/cfssl",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cmd/cfssljson",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/config",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/crl",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs7",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/csr",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/errors",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/helpers",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/helpers/derhelpers",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/info",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/initca",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/log",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/ocsp",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/ocsp/config",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/revoke",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/scan",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/scan/crypto/tls",
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/selfsign",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/signer",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/signer/local",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/signer/remote",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/signer/universal",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/cloudflare/cfssl/ubiquity",
"Comment": "1.3.1",
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
"Comment": "1.3.2-21-g56268a6",
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
},
{
"ImportPath": "github.com/clusterhq/flocker-go",

64
Godeps/LICENSES generated
View File

@ -13681,6 +13681,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
================================================================================
= vendor/github.com/cloudflare/cfssl/api/health licensed under: =
Copyright (c) 2014 CloudFlare Inc.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"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 COPYRIGHT
HOLDER 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.
= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0
================================================================================
================================================================================
= vendor/github.com/cloudflare/cfssl/api/info licensed under: =
@ -15217,6 +15249,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
================================================================================
= vendor/github.com/cloudflare/cfssl/scan/crypto/tls licensed under: =
Copyright (c) 2014 CloudFlare Inc.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"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 COPYRIGHT
HOLDER 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.
= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0
================================================================================
================================================================================
= vendor/github.com/cloudflare/cfssl/selfsign licensed under: =

View File

@ -29,6 +29,7 @@ filegroup(
"//vendor/github.com/cloudflare/cfssl/api/crl:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/gencrl:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/generator:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/health:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/info:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/initca:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/ocsp:all-srcs",

View File

@ -105,14 +105,28 @@ func (srv *server) getURL(endpoint string) string {
return fmt.Sprintf("%s/api/v1/cfssl/%s", srv.URL, endpoint)
}
func (srv *server) createTransport() (transport *http.Transport) {
transport = new(http.Transport)
func (srv *server) createTransport() *http.Transport {
// Start with defaults from http.DefaultTransport
transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
// Setup HTTPS client
tlsConfig := srv.TLSConfig
tlsConfig.BuildNameToCertificate()
transport.TLSClientConfig = tlsConfig
// Setup Proxy
if srv.proxy != nil {
transport.Proxy = srv.proxy
}
return transport
}

24
vendor/github.com/cloudflare/cfssl/api/health/BUILD generated vendored Normal file
View File

@ -0,0 +1,24 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["health.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api/health",
importpath = "github.com/cloudflare/cfssl/api/health",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/cloudflare/cfssl/api:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,26 @@
package health
import (
"encoding/json"
"net/http"
"github.com/cloudflare/cfssl/api"
)
// Response contains the response to the /health API
type Response struct {
Healthy bool `json:"healthy"`
}
func healthHandler(w http.ResponseWriter, r *http.Request) error {
response := api.NewSuccessResponse(&Response{Healthy: true})
return json.NewEncoder(w).Encode(response)
}
// NewHealthCheck creates a new handler to serve health checks.
func NewHealthCheck() http.Handler {
return api.HTTPHandler{
Handler: api.HandlerFunc(healthHandler),
Methods: []string{"GET"},
}
}

View File

@ -113,7 +113,7 @@ func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
return err
}
// We parse the OCSP repsonse in order to get the next
// We parse the OCSP response in order to get the next
// update time/expiry time
ocspParsed, err := stdocsp.ParseResponse(ocspResponse, nil)
if err != nil {

View File

@ -30,6 +30,7 @@ type Config struct {
IntBundleFile string
Address string
Port int
MinTLSVersion string
Password string
ConfigFile string
CFG *config.Config
@ -68,6 +69,7 @@ type Config struct {
AKI string
DBConfigFile string
CRLExpiration time.Duration
Disable string
}
// registerFlags defines all cfssl command flags and associates their values with variables.
@ -90,6 +92,7 @@ func registerFlags(c *Config, f *flag.FlagSet) {
f.StringVar(&c.IntBundleFile, "int-bundle", "", "path to intermediate certificate store")
f.StringVar(&c.Address, "address", "127.0.0.1", "Address to bind")
f.IntVar(&c.Port, "port", 8888, "Port to bind")
f.StringVar(&c.MinTLSVersion, "min-tls-version", "", "Minimum version of TLS to use, defaults to 1.0")
f.StringVar(&c.ConfigFile, "config", "", "path to configuration file")
f.StringVar(&c.Profile, "profile", "", "signing profile to use")
f.BoolVar(&c.IsCA, "initca", false, "initialise new CA")
@ -128,6 +131,7 @@ func registerFlags(c *Config, f *flag.FlagSet) {
f.StringVar(&c.DBConfigFile, "db-config", "", "certificate db configuration file")
f.DurationVar(&c.CRLExpiration, "expiry", 7*helpers.OneDay, "time from now after which the CRL will expire (default: one week)")
f.IntVar(&log.Level, "loglevel", log.LevelInfo, "Log level (0 = DEBUG, 5 = FATAL)")
f.StringVar(&c.Disable, "disable", "", "endpoints to disable")
}
// RootFromConfig returns a universal signer Root structure that can

View File

@ -14,6 +14,7 @@ go_library(
"//vendor/github.com/cloudflare/cfssl/api/crl:go_default_library",
"//vendor/github.com/cloudflare/cfssl/api/gencrl:go_default_library",
"//vendor/github.com/cloudflare/cfssl/api/generator:go_default_library",
"//vendor/github.com/cloudflare/cfssl/api/health:go_default_library",
"//vendor/github.com/cloudflare/cfssl/api/info:go_default_library",
"//vendor/github.com/cloudflare/cfssl/api/initca:go_default_library",
"//vendor/github.com/cloudflare/cfssl/api/ocsp:go_default_library",

View File

@ -20,6 +20,7 @@ import (
"github.com/cloudflare/cfssl/api/crl"
"github.com/cloudflare/cfssl/api/gencrl"
"github.com/cloudflare/cfssl/api/generator"
"github.com/cloudflare/cfssl/api/health"
"github.com/cloudflare/cfssl/api/info"
"github.com/cloudflare/cfssl/api/initca"
apiocsp "github.com/cloudflare/cfssl/api/ocsp"
@ -45,21 +46,21 @@ import (
var serverUsageText = `cfssl serve -- set up a HTTP server handles CF SSL requests
Usage of serve:
cfssl serve [-address address] [-ca cert] [-ca-bundle bundle] \
cfssl serve [-address address] [-min-tls-version version] [-ca cert] [-ca-bundle bundle] \
[-ca-key key] [-int-bundle bundle] [-int-dir dir] [-port port] \
[-metadata file] [-remote remote_host] [-config config] \
[-responder cert] [-responder-key key] [-tls-cert cert] [-tls-key key] \
[-mutual-tls-ca ca] [-mutual-tls-cn regex] \
[-responder cert] [-responder-key key] \
[-tls-cert cert] [-tls-key key] [-mutual-tls-ca ca] [-mutual-tls-cn regex] \
[-tls-remote-ca ca] [-mutual-tls-client-cert cert] [-mutual-tls-client-key key] \
[-db-config db-config]
[-db-config db-config] [-disable endpoint[,endpoint]]
Flags:
`
// Flags used by 'cfssl serve'
var serverFlags = []string{"address", "port", "ca", "ca-key", "ca-bundle", "int-bundle", "int-dir", "metadata",
"remote", "config", "responder", "responder-key", "tls-key", "tls-cert", "mutual-tls-ca", "mutual-tls-cn",
"tls-remote-ca", "mutual-tls-client-cert", "mutual-tls-client-key", "db-config"}
var serverFlags = []string{"address", "port", "min-tls-version", "ca", "ca-key", "ca-bundle", "int-bundle", "int-dir",
"metadata", "remote", "config", "responder", "responder-key", "tls-key", "tls-cert", "mutual-tls-ca",
"mutual-tls-cn", "tls-remote-ca", "mutual-tls-client-cert", "mutual-tls-client-key", "db-config", "disable"}
var (
conf cli.Config
@ -80,7 +81,7 @@ func v1APIPath(path string) string {
}
// httpBox implements http.FileSystem which allows the use of Box with a http.FileServer.
// Atempting to Open an API endpoint will result in an error.
// Attempting to Open an API endpoint will result in an error.
type httpBox struct {
*rice.Box
redirects map[string]string
@ -241,13 +242,27 @@ var endpoints = map[string]func() (http.Handler, error){
return http.FileServer(staticBox), nil
},
"health": func() (http.Handler, error) {
return health.NewHealthCheck(), nil
},
}
// registerHandlers instantiates various handlers and associate them to corresponding endpoints.
func registerHandlers() {
disabled := make(map[string]bool)
if conf.Disable != "" {
for _, endpoint := range strings.Split(conf.Disable, ",") {
disabled[endpoint] = true
}
}
for path, getHandler := range endpoints {
log.Debugf("getHandler for %s", path)
if handler, err := getHandler(); err != nil {
if _, ok := disabled[path]; ok {
log.Infof("endpoint '%s' is explicitly disabled", path)
} else if handler, err := getHandler(); err != nil {
log.Warningf("endpoint '%s' is disabled: %v", path, err)
} else {
if path, handler, err = wrapHandler(path, handler, err); err != nil {
@ -298,6 +313,11 @@ func serverMain(args []string, c cli.Config) error {
addr := net.JoinHostPort(conf.Address, strconv.Itoa(conf.Port))
tlscfg := tls.Config{}
if conf.MinTLSVersion != "" {
tlscfg.MinVersion = helpers.StringTLSVersion(conf.MinTLSVersion)
}
if conf.TLSCertFile == "" || conf.TLSKeyFile == "" {
log.Info("Now listening on ", addr)
return http.ListenAndServe(addr, nil)
@ -308,12 +328,12 @@ func serverMain(args []string, c cli.Config) error {
return fmt.Errorf("failed to load mutual TLS CA file: %s", err)
}
tlscfg.ClientAuth = tls.RequireAndVerifyClientCert
tlscfg.ClientCAs = clientPool
server := http.Server{
Addr: addr,
TLSConfig: &tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: clientPool,
},
TLSConfig: &tlscfg,
}
if conf.MutualTLSCNRegex != "" {
@ -338,7 +358,11 @@ func serverMain(args []string, c cli.Config) error {
return server.ListenAndServeTLS(conf.TLSCertFile, conf.TLSKeyFile)
}
log.Info("Now listening on https://", addr)
return http.ListenAndServeTLS(addr, conf.TLSCertFile, conf.TLSKeyFile, nil)
server := http.Server{
Addr: addr,
TLSConfig: &tlscfg,
}
return server.ListenAndServeTLS(conf.TLSCertFile, conf.TLSKeyFile)
}

View File

@ -14,7 +14,7 @@ var version = struct {
Minor int
Patch int
Revision string
}{1, 3, 0, "release"}
}{1, 3, 2, "release"}
func versionString() string {
return fmt.Sprintf("%d.%d.%d", version.Major, version.Minor, version.Patch)

View File

@ -553,7 +553,7 @@ func (p *Signing) Valid() bool {
var KeyUsage = map[string]x509.KeyUsage{
"signing": x509.KeyUsageDigitalSignature,
"digital signature": x509.KeyUsageDigitalSignature,
"content committment": x509.KeyUsageContentCommitment,
"content commitment": x509.KeyUsageContentCommitment,
"key encipherment": x509.KeyUsageKeyEncipherment,
"key agreement": x509.KeyUsageKeyAgreement,
"data encipherment": x509.KeyUsageDataEncipherment,

View File

@ -194,6 +194,13 @@ const (
// CTClientConstructionFailed occurs when the construction of a new
// github.com/google/certificate-transparency client fails.
CTClientConstructionFailed
// PrecertMissingPoison occurs when a precert is passed to SignFromPrecert
// and is missing the CT poison extension.
PrecertMissingPoison
// PrecertInvalidPoison occurs when a precert is passed to SignFromPrecert
// and has a invalid CT poison extension value or the extension is not
// critical.
PrecertInvalidPoison
)
// Certificate persistence related errors specified with CertStoreError
@ -369,6 +376,10 @@ func New(category Category, reason Reason) *Error {
msg = "Certificate transparency parsing failed due to unknown error"
case PrecertSubmissionFailed:
msg = "Certificate transparency precertificate submission failed"
case PrecertMissingPoison:
msg = "Precertificate is missing CT poison extension"
case PrecertInvalidPoison:
msg = "Precertificate contains an invalid CT poison extension"
default:
panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category CTError.", reason))
}
@ -415,7 +426,7 @@ func Wrap(category Category, reason Reason, err error) *Error {
}
}
case PrivateKeyError, IntermediatesError, RootError, PolicyError, DialError,
APIClientError, CSRError, CTError, CertStoreError:
APIClientError, CSRError, CTError, CertStoreError, OCSPError:
// no-op, just use the error
default:
panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",

View File

@ -13,6 +13,7 @@ go_library(
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/google/certificate-transparency-go:go_default_library",
"//vendor/github.com/google/certificate-transparency-go/tls:go_default_library",
"//vendor/github.com/google/certificate-transparency-go/x509:go_default_library",
"//vendor/golang.org/x/crypto/ocsp:go_default_library",
"//vendor/golang.org/x/crypto/pkcs12:go_default_library",
],

View File

@ -2,11 +2,17 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["derhelpers.go"],
srcs = [
"derhelpers.go",
"ed25519.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/helpers/derhelpers",
importpath = "github.com/cloudflare/cfssl/helpers/derhelpers",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/cloudflare/cfssl/errors:go_default_library"],
deps = [
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/golang.org/x/crypto/ed25519:go_default_library",
],
)
filegroup(

View File

@ -9,16 +9,19 @@ import (
"crypto/x509"
cferr "github.com/cloudflare/cfssl/errors"
"golang.org/x/crypto/ed25519"
)
// ParsePrivateKeyDER parses a PKCS #1, PKCS #8, or elliptic curve
// DER-encoded private key. The key must not be in PEM format.
// ParsePrivateKeyDER parses a PKCS #1, PKCS #8, ECDSA, or Ed25519 DER-encoded
// private key. The key must not be in PEM format.
func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) {
generalKey, err := x509.ParsePKCS8PrivateKey(keyDER)
if err != nil {
generalKey, err = x509.ParsePKCS1PrivateKey(keyDER)
if err != nil {
generalKey, err = x509.ParseECPrivateKey(keyDER)
if err != nil {
generalKey, err = ParseEd25519PrivateKey(keyDER)
if err != nil {
// We don't include the actual error into
// the final error. The reason might be
@ -29,12 +32,15 @@ func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) {
}
}
}
}
switch generalKey.(type) {
case *rsa.PrivateKey:
return generalKey.(*rsa.PrivateKey), nil
case *ecdsa.PrivateKey:
return generalKey.(*ecdsa.PrivateKey), nil
case ed25519.PrivateKey:
return generalKey.(ed25519.PrivateKey), nil
}
// should never reach here

View File

@ -0,0 +1,133 @@
package derhelpers
import (
"crypto"
"crypto/x509/pkix"
"encoding/asn1"
"errors"
"golang.org/x/crypto/ed25519"
)
var errEd25519WrongID = errors.New("incorrect object identifier")
var errEd25519WrongKeyType = errors.New("incorrect key type")
// ed25519OID is the OID for the Ed25519 signature scheme: see
// https://datatracker.ietf.org/doc/draft-ietf-curdle-pkix-04.
var ed25519OID = asn1.ObjectIdentifier{1, 3, 101, 112}
// subjectPublicKeyInfo reflects the ASN.1 object defined in the X.509 standard.
//
// This is defined in crypto/x509 as "publicKeyInfo".
type subjectPublicKeyInfo struct {
Algorithm pkix.AlgorithmIdentifier
PublicKey asn1.BitString
}
// MarshalEd25519PublicKey creates a DER-encoded SubjectPublicKeyInfo for an
// ed25519 public key, as defined in
// https://tools.ietf.org/html/draft-ietf-curdle-pkix-04. This is analagous to
// MarshalPKIXPublicKey in crypto/x509, which doesn't currently support Ed25519.
func MarshalEd25519PublicKey(pk crypto.PublicKey) ([]byte, error) {
pub, ok := pk.(ed25519.PublicKey)
if !ok {
return nil, errEd25519WrongKeyType
}
spki := subjectPublicKeyInfo{
Algorithm: pkix.AlgorithmIdentifier{
Algorithm: ed25519OID,
},
PublicKey: asn1.BitString{
BitLength: len(pub) * 8,
Bytes: pub,
},
}
return asn1.Marshal(spki)
}
// ParseEd25519PublicKey returns the Ed25519 public key encoded by the input.
func ParseEd25519PublicKey(der []byte) (crypto.PublicKey, error) {
var spki subjectPublicKeyInfo
if rest, err := asn1.Unmarshal(der, &spki); err != nil {
return nil, err
} else if len(rest) > 0 {
return nil, errors.New("SubjectPublicKeyInfo too long")
}
if !spki.Algorithm.Algorithm.Equal(ed25519OID) {
return nil, errEd25519WrongID
}
if spki.PublicKey.BitLength != ed25519.PublicKeySize*8 {
return nil, errors.New("SubjectPublicKeyInfo PublicKey length mismatch")
}
return ed25519.PublicKey(spki.PublicKey.Bytes), nil
}
// oneAsymmetricKey reflects the ASN.1 structure for storing private keys in
// https://tools.ietf.org/html/draft-ietf-curdle-pkix-04, excluding the optional
// fields, which we don't use here.
//
// This is identical to pkcs8 in crypto/x509.
type oneAsymmetricKey struct {
Version int
Algorithm pkix.AlgorithmIdentifier
PrivateKey []byte
}
// curvePrivateKey is the innter type of the PrivateKey field of
// oneAsymmetricKey.
type curvePrivateKey []byte
// MarshalEd25519PrivateKey returns a DER encdoing of the input private key as
// specified in https://tools.ietf.org/html/draft-ietf-curdle-pkix-04.
func MarshalEd25519PrivateKey(sk crypto.PrivateKey) ([]byte, error) {
priv, ok := sk.(ed25519.PrivateKey)
if !ok {
return nil, errEd25519WrongKeyType
}
// Marshal the innter CurvePrivateKey.
curvePrivateKey, err := asn1.Marshal(priv.Seed())
if err != nil {
return nil, err
}
// Marshal the OneAsymmetricKey.
asym := oneAsymmetricKey{
Version: 0,
Algorithm: pkix.AlgorithmIdentifier{
Algorithm: ed25519OID,
},
PrivateKey: curvePrivateKey,
}
return asn1.Marshal(asym)
}
// ParseEd25519PrivateKey returns the Ed25519 private key encoded by the input.
func ParseEd25519PrivateKey(der []byte) (crypto.PrivateKey, error) {
asym := new(oneAsymmetricKey)
if rest, err := asn1.Unmarshal(der, asym); err != nil {
return nil, err
} else if len(rest) > 0 {
return nil, errors.New("OneAsymmetricKey too long")
}
// Check that the key type is correct.
if !asym.Algorithm.Algorithm.Equal(ed25519OID) {
return nil, errEd25519WrongID
}
// Unmarshal the inner CurvePrivateKey.
seed := new(curvePrivateKey)
if rest, err := asn1.Unmarshal(asym.PrivateKey, seed); err != nil {
return nil, err
} else if len(rest) > 0 {
return nil, errors.New("CurvePrivateKey too long")
}
return ed25519.NewKeyFromSeed(*seed), nil
}

View File

@ -12,16 +12,15 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/binary"
"encoding/pem"
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"github.com/google/certificate-transparency-go"
cttls "github.com/google/certificate-transparency-go/tls"
ctx509 "github.com/google/certificate-transparency-go/x509"
"golang.org/x/crypto/ocsp"
"strings"
@ -185,7 +184,20 @@ func HashAlgoString(alg x509.SignatureAlgorithm) string {
}
}
// EncodeCertificatesPEM encodes a number of x509 certficates to PEM
// StringTLSVersion returns underlying enum values from human names for TLS
// versions, defaults to current golang default of TLS 1.0
func StringTLSVersion(version string) uint16 {
switch version {
case "1.2":
return tls.VersionTLS12
case "1.1":
return tls.VersionTLS11
default:
return tls.VersionTLS10
}
}
// EncodeCertificatesPEM encodes a number of x509 certificates to PEM
func EncodeCertificatesPEM(certs []*x509.Certificate) []byte {
var buffer bytes.Buffer
for _, cert := range certs {
@ -198,7 +210,7 @@ func EncodeCertificatesPEM(certs []*x509.Certificate) []byte {
return buffer.Bytes()
}
// EncodeCertificatePEM encodes a single x509 certficates to PEM
// EncodeCertificatePEM encodes a single x509 certificates to PEM
func EncodeCertificatePEM(cert *x509.Certificate) []byte {
return EncodeCertificatesPEM([]*x509.Certificate{cert})
}
@ -408,7 +420,7 @@ func ParseCSR(in []byte) (csr *x509.CertificateRequest, rest []byte, err error)
return csr, rest, nil
}
// ParseCSRPEM parses a PEM-encoded certificiate signing request.
// ParseCSRPEM parses a PEM-encoded certificate signing request.
// It does not check the signature. This is useful for dumping data from a CSR
// locally.
func ParseCSRPEM(csrPEM []byte) (*x509.CertificateRequest, error) {
@ -484,64 +496,40 @@ func CreateTLSConfig(remoteCAs *x509.CertPool, cert *tls.Certificate) *tls.Confi
// SerializeSCTList serializes a list of SCTs.
func SerializeSCTList(sctList []ct.SignedCertificateTimestamp) ([]byte, error) {
var buf bytes.Buffer
list := ctx509.SignedCertificateTimestampList{}
for _, sct := range sctList {
sct, err := cttls.Marshal(sct)
sctBytes, err := cttls.Marshal(sct)
if err != nil {
return nil, err
}
binary.Write(&buf, binary.BigEndian, uint16(len(sct)))
buf.Write(sct)
list.SCTList = append(list.SCTList, ctx509.SerializedSCT{Val: sctBytes})
}
var sctListLengthField = make([]byte, 2)
binary.BigEndian.PutUint16(sctListLengthField, uint16(buf.Len()))
return bytes.Join([][]byte{sctListLengthField, buf.Bytes()}, nil), nil
return cttls.Marshal(list)
}
// DeserializeSCTList deserializes a list of SCTs.
func DeserializeSCTList(serializedSCTList []byte) (*[]ct.SignedCertificateTimestamp, error) {
sctList := new([]ct.SignedCertificateTimestamp)
sctReader := bytes.NewBuffer(serializedSCTList)
var sctListLen uint16
err := binary.Read(sctReader, binary.BigEndian, &sctListLen)
func DeserializeSCTList(serializedSCTList []byte) ([]ct.SignedCertificateTimestamp, error) {
var sctList ctx509.SignedCertificateTimestampList
rest, err := cttls.Unmarshal(serializedSCTList, &sctList)
if err != nil {
if err == io.EOF {
return sctList, cferr.Wrap(cferr.CTError, cferr.Unknown,
errors.New("serialized SCT list could not be read"))
return nil, err
}
return sctList, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
if len(rest) != 0 {
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, errors.New("serialized SCT list contained trailing garbage"))
}
if sctReader.Len() != int(sctListLen) {
return sctList, errors.New("SCT length field and SCT length don't match")
}
for err != io.EOF {
var sctLen uint16
err = binary.Read(sctReader, binary.BigEndian, &sctLen)
if err != nil {
if err == io.EOF {
return sctList, nil
}
return sctList, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
}
if sctReader.Len() < int(sctLen) {
return sctList, errors.New("SCT length field and SCT length don't match")
}
serializedSCT := sctReader.Next(int(sctLen))
list := make([]ct.SignedCertificateTimestamp, len(sctList.SCTList))
for i, serializedSCT := range sctList.SCTList {
var sct ct.SignedCertificateTimestamp
if _, err := cttls.Unmarshal(serializedSCT, &sct); err != nil {
return sctList, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
rest, err := cttls.Unmarshal(serializedSCT.Val, &sct)
if err != nil {
return nil, err
}
temp := append(*sctList, sct)
sctList = &temp
if len(rest) != 0 {
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, errors.New("serialized SCT contained trailing garbage"))
}
return sctList, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
list[i] = sct
}
return list, nil
}
// SCTListFromOCSPResponse extracts the SCTList from an ocsp.Response,
@ -560,22 +548,21 @@ func SCTListFromOCSPResponse(response *ocsp.Response) ([]ct.SignedCertificateTim
}
// This code block extracts the sctList from the SCT extension.
var emptySCTList []ct.SignedCertificateTimestamp
sctList := &emptySCTList
var sctList []ct.SignedCertificateTimestamp
var err error
if numBytes := len(SCTListExtension.Value); numBytes != 0 {
serializedSCTList := new([]byte)
var serializedSCTList []byte
rest := make([]byte, numBytes)
copy(rest, SCTListExtension.Value)
for len(rest) != 0 {
rest, err = asn1.Unmarshal(rest, serializedSCTList)
rest, err = asn1.Unmarshal(rest, &serializedSCTList)
if err != nil {
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
}
}
sctList, err = DeserializeSCTList(*serializedSCTList)
sctList, err = DeserializeSCTList(serializedSCTList)
}
return *sctList, err
return sctList, err
}
// ReadBytes reads a []byte either from a file or an environment variable.

View File

@ -113,7 +113,7 @@ func NewFromPEM(req *csr.CertificateRequest, keyFile string) (cert, csrPEM []byt
// RenewFromPEM re-creates a root certificate from the CA cert and key
// files. The resulting root certificate will have the input CA certificate
// as the template and have the same expiry length. E.g. the exsiting CA
// as the template and have the same expiry length. E.g. the existing CA
// is valid for a year from Jan 01 2015 to Jan 01 2016, the renewed certificate
// will be valid from now and expire in one year as well.
func RenewFromPEM(caFile, keyFile string) ([]byte, error) {
@ -178,7 +178,7 @@ func NewFromSigner(req *csr.CertificateRequest, priv crypto.Signer) (cert, csrPE
// RenewFromSigner re-creates a root certificate from the CA cert and crypto.Signer.
// The resulting root certificate will have ca certificate
// as the template and have the same expiry length. E.g. the exsiting CA
// as the template and have the same expiry length. E.g. the existing CA
// is valid for a year from Jan 01 2015 to Jan 01 2016, the renewed certificate
// will be valid from now and expire in one year as well.
func RenewFromSigner(ca *x509.Certificate, priv crypto.Signer) ([]byte, error) {

View File

@ -164,8 +164,10 @@ func (s StandardSigner) Sign(req SignRequest) ([]byte, error) {
if bytes.Compare(req.Certificate.RawIssuer, s.issuer.RawSubject) != 0 {
return nil, cferr.New(cferr.OCSPError, cferr.IssuerMismatch)
}
if req.Certificate.CheckSignatureFrom(s.issuer) != nil {
return nil, cferr.New(cferr.OCSPError, cferr.IssuerMismatch)
err := req.Certificate.CheckSignatureFrom(s.issuer)
if err != nil {
return nil, cferr.Wrap(cferr.OCSPError, cferr.VerifyFailed, err)
}
var thisUpdate, nextUpdate time.Time

View File

@ -18,6 +18,7 @@ go_library(
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/cloudflare/cfssl/revoke:go_default_library",
"//vendor/github.com/cloudflare/cfssl/scan/crypto/tls:go_default_library",
],
)
@ -30,7 +31,10 @@ filegroup(
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
srcs = [
":package-srcs",
"//vendor/github.com/cloudflare/cfssl/scan/crypto/tls:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -2,11 +2,12 @@ package scan
import (
"bufio"
"crypto/tls"
"errors"
"fmt"
"io"
"net"
"github.com/cloudflare/cfssl/scan/crypto/tls"
)
// Connectivity contains scanners testing basic connectivity to the host
@ -53,7 +54,7 @@ var (
)
func initOnCloudFlareScan() ([]*net.IPNet, error) {
// Propogate previous errors and don't attempt to re-download.
// Propagate previous errors and don't attempt to re-download.
if cfNetsErr != nil {
return nil, cfNetsErr
}

View File

@ -0,0 +1,37 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"alert.go",
"cfsslscan_common.go",
"cfsslscan_handshake.go",
"cipher_suites.go",
"common.go",
"conn.go",
"handshake_client.go",
"handshake_messages.go",
"handshake_server.go",
"key_agreement.go",
"prf.go",
"ticket.go",
"tls.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/scan/crypto/tls",
importpath = "github.com/cloudflare/cfssl/scan/crypto/tls",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,79 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package tls
import "strconv"
type alert uint8
const (
// alert level
alertLevelWarning = 1
alertLevelError = 2
)
const (
alertCloseNotify alert = 0
alertUnexpectedMessage alert = 10
alertBadRecordMAC alert = 20
alertDecryptionFailed alert = 21
alertRecordOverflow alert = 22
alertDecompressionFailure alert = 30
alertHandshakeFailure alert = 40
alertBadCertificate alert = 42
alertUnsupportedCertificate alert = 43
alertCertificateRevoked alert = 44
alertCertificateExpired alert = 45
alertCertificateUnknown alert = 46
alertIllegalParameter alert = 47
alertUnknownCA alert = 48
alertAccessDenied alert = 49
alertDecodeError alert = 50
alertDecryptError alert = 51
alertProtocolVersion alert = 70
alertInsufficientSecurity alert = 71
alertInternalError alert = 80
alertInappropriateFallback alert = 86
alertUserCanceled alert = 90
alertNoRenegotiation alert = 100
)
var alertText = map[alert]string{
alertCloseNotify: "close notify",
alertUnexpectedMessage: "unexpected message",
alertBadRecordMAC: "bad record MAC",
alertDecryptionFailed: "decryption failed",
alertRecordOverflow: "record overflow",
alertDecompressionFailure: "decompression failure",
alertHandshakeFailure: "handshake failure",
alertBadCertificate: "bad certificate",
alertUnsupportedCertificate: "unsupported certificate",
alertCertificateRevoked: "revoked certificate",
alertCertificateExpired: "expired certificate",
alertCertificateUnknown: "unknown certificate",
alertIllegalParameter: "illegal parameter",
alertUnknownCA: "unknown certificate authority",
alertAccessDenied: "access denied",
alertDecodeError: "error decoding message",
alertDecryptError: "error decrypting message",
alertProtocolVersion: "protocol version not supported",
alertInsufficientSecurity: "insufficient security level",
alertInternalError: "internal error",
alertInappropriateFallback: "inappropriate fallback",
alertUserCanceled: "user canceled",
alertNoRenegotiation: "no renegotiation",
}
func (e alert) String() string {
s, ok := alertText[e]
if ok {
return s
}
return "alert(" + strconv.Itoa(int(e)) + ")"
}
func (e alert) Error() string {
return e.String()
}

View File

@ -0,0 +1,486 @@
package tls
import (
"fmt"
)
type hashAlgID uint8
const (
HashNone hashAlgID = iota
HashMD5
HashSHA1
HashSHA224
HashSHA256
HashSHA384
HashSHA512
)
func (h hashAlgID) String() string {
switch h {
case HashNone:
return "None"
case HashMD5:
return "MD5"
case HashSHA1:
return "SHA1"
case HashSHA224:
return "SHA224"
case HashSHA256:
return "SHA256"
case HashSHA384:
return "SHA384"
case HashSHA512:
return "SHA512"
default:
return "Unknown"
}
}
type sigAlgID uint8
// Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1)
const (
SigAnon sigAlgID = iota
SigRSA
SigDSA
SigECDSA
)
func (sig sigAlgID) String() string {
switch sig {
case SigAnon:
return "Anon"
case SigRSA:
return "RSA"
case SigDSA:
return "DSA"
case SigECDSA:
return "ECDSA"
default:
return "Unknown"
}
}
// SignatureAndHash mirrors the TLS 1.2, SignatureAndHashAlgorithm struct. See
// RFC 5246, section A.4.1.
type SignatureAndHash struct {
h hashAlgID
s sigAlgID
}
func (sigAlg SignatureAndHash) String() string {
return fmt.Sprintf("{%s,%s}", sigAlg.s, sigAlg.h)
}
func (sigAlg SignatureAndHash) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`{"signature":"%s","hash":"%s"}`, sigAlg.s, sigAlg.h)), nil
}
func (sigAlg SignatureAndHash) internal() signatureAndHash {
return signatureAndHash{uint8(sigAlg.h), uint8(sigAlg.s)}
}
// defaultSignatureAndHashAlgorithms contains the default signature and hash
// algorithm paris supported by `crypto/tls`
var defaultSignatureAndHashAlgorithms []signatureAndHash
// AllSignatureAndHashAlgorithms contains all possible signature and
// hash algorithm pairs that the can be advertised in a TLS 1.2 ClientHello.
var AllSignatureAndHashAlgorithms []SignatureAndHash
func init() {
defaultSignatureAndHashAlgorithms = supportedSignatureAlgorithms
for _, sighash := range supportedSignatureAlgorithms {
AllSignatureAndHashAlgorithms = append(AllSignatureAndHashAlgorithms,
SignatureAndHash{hashAlgID(sighash.hash), sigAlgID(sighash.signature)})
}
}
// TLSVersions is a list of the current SSL/TLS Versions implemented by Go
var Versions = map[uint16]string{
VersionSSL30: "SSL 3.0",
VersionTLS10: "TLS 1.0",
VersionTLS11: "TLS 1.1",
VersionTLS12: "TLS 1.2",
}
// CipherSuite describes an individual cipher suite, with long and short names
// and security properties.
type CipherSuite struct {
Name, ShortName string
// ForwardSecret cipher suites negotiate ephemeral keys, allowing forward secrecy.
ForwardSecret bool
EllipticCurve bool
}
// Returns the (short) name of the cipher suite.
func (c CipherSuite) String() string {
if c.ShortName != "" {
return c.ShortName
}
return c.Name
}
// CipherSuites contains all values in the TLS Cipher Suite Registry
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
var CipherSuites = map[uint16]CipherSuite{
0X0000: {Name: "TLS_NULL_WITH_NULL_NULL"},
0X0001: {Name: "TLS_RSA_WITH_NULL_MD5"},
0X0002: {Name: "TLS_RSA_WITH_NULL_SHA"},
0X0003: {Name: "TLS_RSA_EXPORT_WITH_RC4_40_MD5", ShortName: "EXP-RC4-MD5"},
0X0004: {Name: "TLS_RSA_WITH_RC4_128_MD5", ShortName: "RC4-MD5"},
0X0005: {Name: "TLS_RSA_WITH_RC4_128_SHA", ShortName: "RC4-SHA"},
0X0006: {Name: "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", ShortName: "EXP-RC2-CBC-MD5"},
0X0007: {Name: "TLS_RSA_WITH_IDEA_CBC_SHA", ShortName: "IDEA-CBC-SHA"},
0X0008: {Name: "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", ShortName: "EXP-DES-CBC-SHA"},
0X0009: {Name: "TLS_RSA_WITH_DES_CBC_SHA", ShortName: "DES-CBC-SHA"},
0X000A: {Name: "TLS_RSA_WITH_3DES_EDE_CBC_SHA", ShortName: "DES-CBC3-SHA"},
0X000B: {Name: "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", ShortName: "EXP-DH-DSS-DES-CBC-SHA"},
0X000C: {Name: "TLS_DH_DSS_WITH_DES_CBC_SHA", ShortName: "DH-DSS-DES-CBC-SHA"},
0X000D: {Name: "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", ShortName: "DH-DSS-DES-CBC3-SHA"},
0X000E: {Name: "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", ShortName: "EXP-DH-RSA-DES-CBC-SHA"},
0X000F: {Name: "TLS_DH_RSA_WITH_DES_CBC_SHA", ShortName: "DH-RSA-DES-CBC-SHA"},
0X0010: {Name: "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", ShortName: "DH-RSA-DES-CBC3-SHA"},
0X0011: {Name: "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", ShortName: "EXP-EDH-DSS-DES-CBC-SHA", ForwardSecret: true},
0X0012: {Name: "TLS_DHE_DSS_WITH_DES_CBC_SHA", ShortName: "EDH-DSS-DES-CBC-SHA", ForwardSecret: true},
0X0013: {Name: "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", ShortName: "EDH-DSS-DES-CBC3-SHA", ForwardSecret: true},
0X0014: {Name: "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", ShortName: "EXP-EDH-RSA-DES-CBC-SHA", ForwardSecret: true},
0X0015: {Name: "TLS_DHE_RSA_WITH_DES_CBC_SHA", ShortName: "EDH-RSA-DES-CBC-SHA", ForwardSecret: true},
0X0016: {Name: "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", ShortName: "EDH-RSA-DES-CBC3-SHA", ForwardSecret: true},
0X0017: {Name: "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"},
0X0018: {Name: "TLS_DH_anon_WITH_RC4_128_MD5"},
0X0019: {Name: "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"},
0X001A: {Name: "TLS_DH_anon_WITH_DES_CBC_SHA"},
0X001B: {Name: "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"},
0X001E: {Name: "TLS_KRB5_WITH_DES_CBC_SHA"},
0X001F: {Name: "TLS_KRB5_WITH_3DES_EDE_CBC_SHA"},
0X0020: {Name: "TLS_KRB5_WITH_RC4_128_SHA"},
0X0021: {Name: "TLS_KRB5_WITH_IDEA_CBC_SHA"},
0X0022: {Name: "TLS_KRB5_WITH_DES_CBC_MD5"},
0X0023: {Name: "TLS_KRB5_WITH_3DES_EDE_CBC_MD5"},
0X0024: {Name: "TLS_KRB5_WITH_RC4_128_MD5"},
0X0025: {Name: "TLS_KRB5_WITH_IDEA_CBC_MD5"},
0X0026: {Name: "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA"},
0X0027: {Name: "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA"},
0X0028: {Name: "TLS_KRB5_EXPORT_WITH_RC4_40_SHA"},
0X0029: {Name: "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5"},
0X002A: {Name: "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5"},
0X002B: {Name: "TLS_KRB5_EXPORT_WITH_RC4_40_MD5"},
0X002C: {Name: "TLS_PSK_WITH_NULL_SHA"},
0X002D: {Name: "TLS_DHE_PSK_WITH_NULL_SHA", ForwardSecret: true},
0X002E: {Name: "TLS_RSA_PSK_WITH_NULL_SHA"},
0X002F: {Name: "TLS_RSA_WITH_AES_128_CBC_SHA", ShortName: "AES128-SHA"},
0X0030: {Name: "TLS_DH_DSS_WITH_AES_128_CBC_SHA", ShortName: "DH-DSS-AES128-SHA"},
0X0031: {Name: "TLS_DH_RSA_WITH_AES_128_CBC_SHA", ShortName: "DH-RSA-AES128-SHA"},
0X0032: {Name: "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", ShortName: "DHE-DSS-AES128-SHA", ForwardSecret: true},
0X0033: {Name: "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", ShortName: "DHE-RSA-AES128-SHA", ForwardSecret: true},
0X0034: {Name: "TLS_DH_anon_WITH_AES_128_CBC_SHA"},
0X0035: {Name: "TLS_RSA_WITH_AES_256_CBC_SHA", ShortName: "AES256-SHA"},
0X0036: {Name: "TLS_DH_DSS_WITH_AES_256_CBC_SHA", ShortName: "DH-DSS-AES256-SHA"},
0X0037: {Name: "TLS_DH_RSA_WITH_AES_256_CBC_SHA", ShortName: "DH-RSA-AES256-SHA"},
0X0038: {Name: "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", ShortName: "DHE-DSS-AES256-SHA", ForwardSecret: true},
0X0039: {Name: "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", ShortName: "DHE-RSA-AES256-SHA", ForwardSecret: true},
0X003A: {Name: "TLS_DH_anon_WITH_AES_256_CBC_SHA"},
0X003B: {Name: "TLS_RSA_WITH_NULL_SHA256"},
0X003C: {Name: "TLS_RSA_WITH_AES_128_CBC_SHA256", ShortName: "AES128-SHA256"},
0X003D: {Name: "TLS_RSA_WITH_AES_256_CBC_SHA256", ShortName: "AES256-SHA256"},
0X003E: {Name: "TLS_DH_DSS_WITH_AES_128_CBC_SHA256", ShortName: "DH-DSS-AES128-SHA256"},
0X003F: {Name: "TLS_DH_RSA_WITH_AES_128_CBC_SHA256", ShortName: "DH-RSA-AES128-SHA256"},
0X0040: {Name: "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", ShortName: "DHE-DSS-AES128-SHA256", ForwardSecret: true},
0X0041: {Name: "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA", ShortName: "CAMELLIA128-SHA"},
0X0042: {Name: "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA", ShortName: "DH-DSS-CAMELLIA128-SHA"},
0X0043: {Name: "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA", ShortName: "DH-RSA-CAMELLIA128-SHA"},
0X0044: {Name: "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA", ShortName: "DHE-DSS-CAMELLIA128-SHA", ForwardSecret: true},
0X0045: {Name: "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA", ShortName: "DHE-RSA-CAMELLIA128-SHA", ForwardSecret: true},
0X0046: {Name: "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA"},
0X0067: {Name: "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", ShortName: "DHE-RSA-AES128-SHA256", ForwardSecret: true},
0X0068: {Name: "TLS_DH_DSS_WITH_AES_256_CBC_SHA256", ShortName: "DH-DSS-AES256-SHA256"},
0X0069: {Name: "TLS_DH_RSA_WITH_AES_256_CBC_SHA256", ShortName: "DH-RSA-AES256-SHA256"},
0X006A: {Name: "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", ShortName: "DHE-DSS-AES256-SHA256", ForwardSecret: true},
0X006B: {Name: "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", ShortName: "DHE-RSA-AES256-SHA256", ForwardSecret: true},
0X006C: {Name: "TLS_DH_anon_WITH_AES_128_CBC_SHA256"},
0X006D: {Name: "TLS_DH_anon_WITH_AES_256_CBC_SHA256"},
0X0084: {Name: "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA", ShortName: "CAMELLIA256-SHA"},
0X0085: {Name: "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA", ShortName: "DH-DSS-CAMELLIA256-SHA"},
0X0086: {Name: "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA", ShortName: "DH-RSA-CAMELLIA256-SHA"},
0X0087: {Name: "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA", ShortName: "DHE-DSS-CAMELLIA256-SHA", ForwardSecret: true},
0X0088: {Name: "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA", ShortName: "DHE-RSA-CAMELLIA256-SHA", ForwardSecret: true},
0X0089: {Name: "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA"},
0X008A: {Name: "TLS_PSK_WITH_RC4_128_SHA", ShortName: "PSK-RC4-SHA"},
0X008B: {Name: "TLS_PSK_WITH_3DES_EDE_CBC_SHA", ShortName: "PSK-3DES-EDE-CBC-SHA"},
0X008C: {Name: "TLS_PSK_WITH_AES_128_CBC_SHA", ShortName: "PSK-AES128-CBC-SHA"},
0X008D: {Name: "TLS_PSK_WITH_AES_256_CBC_SHA", ShortName: "PSK-AES256-CBC-SHA"},
0X008E: {Name: "TLS_DHE_PSK_WITH_RC4_128_SHA", ForwardSecret: true},
0X008F: {Name: "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA", ForwardSecret: true},
0X0090: {Name: "TLS_DHE_PSK_WITH_AES_128_CBC_SHA", ForwardSecret: true},
0X0091: {Name: "TLS_DHE_PSK_WITH_AES_256_CBC_SHA", ForwardSecret: true},
0X0092: {Name: "TLS_RSA_PSK_WITH_RC4_128_SHA"},
0X0093: {Name: "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"},
0X0094: {Name: "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"},
0X0095: {Name: "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"},
0X0096: {Name: "TLS_RSA_WITH_SEED_CBC_SHA", ShortName: "SEED-SHA"},
0X0097: {Name: "TLS_DH_DSS_WITH_SEED_CBC_SHA", ShortName: "DH-DSS-SEED-SHA"},
0X0098: {Name: "TLS_DH_RSA_WITH_SEED_CBC_SHA", ShortName: "DH-RSA-SEED-SHA"},
0X0099: {Name: "TLS_DHE_DSS_WITH_SEED_CBC_SHA", ShortName: "DHE-DSS-SEED-SHA", ForwardSecret: true},
0X009A: {Name: "TLS_DHE_RSA_WITH_SEED_CBC_SHA", ShortName: "DHE-RSA-SEED-SHA", ForwardSecret: true},
0X009B: {Name: "TLS_DH_anon_WITH_SEED_CBC_SHA"},
0X009C: {Name: "TLS_RSA_WITH_AES_128_GCM_SHA256", ShortName: "AES128-GCM-SHA256"},
0X009D: {Name: "TLS_RSA_WITH_AES_256_GCM_SHA384", ShortName: "AES256-GCM-SHA384"},
0X009E: {Name: "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", ShortName: "DHE-RSA-AES128-GCM-SHA256", ForwardSecret: true},
0X009F: {Name: "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", ShortName: "DHE-RSA-AES256-GCM-SHA384", ForwardSecret: true},
0X00A0: {Name: "TLS_DH_RSA_WITH_AES_128_GCM_SHA256", ShortName: "DH-RSA-AES128-GCM-SHA256"},
0X00A1: {Name: "TLS_DH_RSA_WITH_AES_256_GCM_SHA384", ShortName: "DH-RSA-AES256-GCM-SHA384"},
0X00A2: {Name: "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", ShortName: "DHE-DSS-AES128-GCM-SHA256", ForwardSecret: true},
0X00A3: {Name: "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", ShortName: "DHE-DSS-AES256-GCM-SHA384", ForwardSecret: true},
0X00A4: {Name: "TLS_DH_DSS_WITH_AES_128_GCM_SHA256", ShortName: "DH-DSS-AES128-GCM-SHA256"},
0X00A5: {Name: "TLS_DH_DSS_WITH_AES_256_GCM_SHA384", ShortName: "DH-DSS-AES256-GCM-SHA384"},
0X00A6: {Name: "TLS_DH_anon_WITH_AES_128_GCM_SHA256"},
0X00A7: {Name: "TLS_DH_anon_WITH_AES_256_GCM_SHA384"},
0X00A8: {Name: "TLS_PSK_WITH_AES_128_GCM_SHA256"},
0X00A9: {Name: "TLS_PSK_WITH_AES_256_GCM_SHA384"},
0X00AA: {Name: "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256", ForwardSecret: true},
0X00AB: {Name: "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384", ForwardSecret: true},
0X00AC: {Name: "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"},
0X00AD: {Name: "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384"},
0X00AE: {Name: "TLS_PSK_WITH_AES_128_CBC_SHA256"},
0X00AF: {Name: "TLS_PSK_WITH_AES_256_CBC_SHA384"},
0X00B0: {Name: "TLS_PSK_WITH_NULL_SHA256"},
0X00B1: {Name: "TLS_PSK_WITH_NULL_SHA384"},
0X00B2: {Name: "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256", ForwardSecret: true},
0X00B3: {Name: "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384", ForwardSecret: true},
0X00B4: {Name: "TLS_DHE_PSK_WITH_NULL_SHA256", ForwardSecret: true},
0X00B5: {Name: "TLS_DHE_PSK_WITH_NULL_SHA384", ForwardSecret: true},
0X00B6: {Name: "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"},
0X00B7: {Name: "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"},
0X00B8: {Name: "TLS_RSA_PSK_WITH_NULL_SHA256"},
0X00B9: {Name: "TLS_RSA_PSK_WITH_NULL_SHA384"},
0X00BA: {Name: "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256"},
0X00BB: {Name: "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256"},
0X00BC: {Name: "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256"},
0X00BD: {Name: "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256", ForwardSecret: true},
0X00BE: {Name: "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", ForwardSecret: true},
0X00BF: {Name: "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256"},
0X00C0: {Name: "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256"},
0X00C1: {Name: "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256"},
0X00C2: {Name: "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256"},
0X00C3: {Name: "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256", ForwardSecret: true},
0X00C4: {Name: "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256", ForwardSecret: true},
0X00C5: {Name: "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256"},
0X00FF: {Name: "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"},
0XC001: {Name: "TLS_ECDH_ECDSA_WITH_NULL_SHA", EllipticCurve: true},
0XC002: {Name: "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", ShortName: "ECDH-ECDSA-RC4-SHA", EllipticCurve: true},
0XC003: {Name: "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", ShortName: "ECDH-ECDSA-DES-CBC3-SHA", EllipticCurve: true},
0XC004: {Name: "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", ShortName: "ECDH-ECDSA-AES128-SHA", EllipticCurve: true},
0XC005: {Name: "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", ShortName: "ECDH-ECDSA-AES256-SHA", EllipticCurve: true},
0XC006: {Name: "TLS_ECDHE_ECDSA_WITH_NULL_SHA", ForwardSecret: true, EllipticCurve: true},
0XC007: {Name: "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", ShortName: "ECDHE-ECDSA-RC4-SHA", ForwardSecret: true, EllipticCurve: true},
0XC008: {Name: "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", ShortName: "ECDHE-ECDSA-DES-CBC3-SHA", ForwardSecret: true, EllipticCurve: true},
0XC009: {Name: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", ShortName: "ECDHE-ECDSA-AES128-SHA", ForwardSecret: true, EllipticCurve: true},
0XC00A: {Name: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", ShortName: "ECDHE-ECDSA-AES256-SHA", ForwardSecret: true, EllipticCurve: true},
0XC00B: {Name: "TLS_ECDH_RSA_WITH_NULL_SHA", EllipticCurve: true},
0XC00C: {Name: "TLS_ECDH_RSA_WITH_RC4_128_SHA", ShortName: "ECDH-RSA-RC4-SHA", EllipticCurve: true},
0XC00D: {Name: "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", ShortName: "ECDH-RSA-DES-CBC3-SHA", EllipticCurve: true},
0XC00E: {Name: "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", ShortName: "ECDH-RSA-AES128-SHA", EllipticCurve: true},
0XC00F: {Name: "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", ShortName: "ECDH-RSA-AES256-SHA", EllipticCurve: true},
0XC010: {Name: "TLS_ECDHE_RSA_WITH_NULL_SHA", ForwardSecret: true, EllipticCurve: true},
0XC011: {Name: "TLS_ECDHE_RSA_WITH_RC4_128_SHA", ShortName: "ECDHE-RSA-RC4-SHA", ForwardSecret: true, EllipticCurve: true},
0XC012: {Name: "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", ShortName: "ECDHE-RSA-DES-CBC3-SHA", ForwardSecret: true, EllipticCurve: true},
0XC013: {Name: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", ShortName: "ECDHE-RSA-AES128-SHA", ForwardSecret: true, EllipticCurve: true},
0XC014: {Name: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", ShortName: "ECDHE-RSA-AES256-SHA", ForwardSecret: true, EllipticCurve: true},
0XC015: {Name: "TLS_ECDH_anon_WITH_NULL_SHA", EllipticCurve: true},
0XC016: {Name: "TLS_ECDH_anon_WITH_RC4_128_SHA", EllipticCurve: true},
0XC017: {Name: "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", EllipticCurve: true},
0XC018: {Name: "TLS_ECDH_anon_WITH_AES_128_CBC_SHA", EllipticCurve: true},
0XC019: {Name: "TLS_ECDH_anon_WITH_AES_256_CBC_SHA", EllipticCurve: true},
0XC01A: {Name: "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA", ShortName: "SRP-3DES-EDE-CBC-SHA"},
0XC01B: {Name: "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA", ShortName: "SRP-RSA-3DES-EDE-CBC-SHA"},
0XC01C: {Name: "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA", ShortName: "SRP-DSS-3DES-EDE-CBC-SHA"},
0XC01D: {Name: "TLS_SRP_SHA_WITH_AES_128_CBC_SHA", ShortName: "SRP-AES-128-CBC-SHA"},
0XC01E: {Name: "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA", ShortName: "SRP-RSA-AES-128-CBC-SHA"},
0XC01F: {Name: "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA", ShortName: "SRP-DSS-AES-128-CBC-SHA"},
0XC020: {Name: "TLS_SRP_SHA_WITH_AES_256_CBC_SHA", ShortName: "SRP-AES-256-CBC-SHA"},
0XC021: {Name: "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", ShortName: "SRP-RSA-AES-256-CBC-SHA"},
0XC022: {Name: "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", ShortName: "SRP-DSS-AES-256-CBC-SHA"},
0XC023: {Name: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", ShortName: "ECDHE-ECDSA-AES128-SHA256", ForwardSecret: true, EllipticCurve: true},
0XC024: {Name: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", ShortName: "ECDHE-ECDSA-AES256-SHA384", ForwardSecret: true, EllipticCurve: true},
0XC025: {Name: "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", ShortName: "ECDH-ECDSA-AES128-SHA256", EllipticCurve: true},
0XC026: {Name: "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", ShortName: "ECDH-ECDSA-AES256-SHA384", EllipticCurve: true},
0XC027: {Name: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", ShortName: "ECDHE-RSA-AES128-SHA256", ForwardSecret: true, EllipticCurve: true},
0XC028: {Name: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", ShortName: "ECDHE-RSA-AES256-SHA384", ForwardSecret: true, EllipticCurve: true},
0XC029: {Name: "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", ShortName: "ECDH-RSA-AES128-SHA256", EllipticCurve: true},
0XC02A: {Name: "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", ShortName: "ECDH-RSA-AES256-SHA384", EllipticCurve: true},
0XC02B: {Name: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", ShortName: "ECDHE-ECDSA-AES128-GCM-SHA256", ForwardSecret: true, EllipticCurve: true},
0XC02C: {Name: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", ShortName: "ECDHE-ECDSA-AES256-GCM-SHA384", ForwardSecret: true, EllipticCurve: true},
0XC02D: {Name: "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", ShortName: "ECDH-ECDSA-AES128-GCM-SHA256", EllipticCurve: true},
0XC02E: {Name: "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", ShortName: "ECDH-ECDSA-AES256-GCM-SHA384", EllipticCurve: true},
0XC02F: {Name: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", ShortName: "ECDHE-RSA-AES128-GCM-SHA256", ForwardSecret: true, EllipticCurve: true},
0XC030: {Name: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", ShortName: "ECDHE-RSA-AES256-GCM-SHA384", ForwardSecret: true, EllipticCurve: true},
0XC031: {Name: "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", ShortName: "ECDH-RSA-AES128-GCM-SHA256", EllipticCurve: true},
0XC032: {Name: "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", ShortName: "ECDH-RSA-AES256-GCM-SHA384", EllipticCurve: true},
0XC033: {Name: "TLS_ECDHE_PSK_WITH_RC4_128_SHA", ForwardSecret: true, EllipticCurve: true},
0XC034: {Name: "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", ForwardSecret: true, EllipticCurve: true},
0XC035: {Name: "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", ForwardSecret: true, EllipticCurve: true},
0XC036: {Name: "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA", ForwardSecret: true, EllipticCurve: true},
0XC037: {Name: "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256", ForwardSecret: true, EllipticCurve: true},
0XC038: {Name: "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384", ForwardSecret: true, EllipticCurve: true},
0XC039: {Name: "TLS_ECDHE_PSK_WITH_NULL_SHA", ForwardSecret: true, EllipticCurve: true},
0XC03A: {Name: "TLS_ECDHE_PSK_WITH_NULL_SHA256", ForwardSecret: true, EllipticCurve: true},
0XC03B: {Name: "TLS_ECDHE_PSK_WITH_NULL_SHA384", ForwardSecret: true, EllipticCurve: true},
0XC03C: {Name: "TLS_RSA_WITH_ARIA_128_CBC_SHA256"},
0XC03D: {Name: "TLS_RSA_WITH_ARIA_256_CBC_SHA384"},
0XC03E: {Name: "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256"},
0XC03F: {Name: "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384"},
0XC040: {Name: "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256"},
0XC041: {Name: "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384"},
0XC042: {Name: "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256", ForwardSecret: true},
0XC043: {Name: "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384", ForwardSecret: true},
0XC044: {Name: "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256", ForwardSecret: true},
0XC045: {Name: "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384", ForwardSecret: true},
0XC046: {Name: "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256"},
0XC047: {Name: "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384"},
0XC048: {Name: "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256", ForwardSecret: true, EllipticCurve: true},
0XC049: {Name: "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384", ForwardSecret: true, EllipticCurve: true},
0XC04A: {Name: "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256", EllipticCurve: true},
0XC04B: {Name: "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384", EllipticCurve: true},
0XC04C: {Name: "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256", ForwardSecret: true, EllipticCurve: true},
0XC04D: {Name: "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384", ForwardSecret: true, EllipticCurve: true},
0XC04E: {Name: "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256", EllipticCurve: true},
0XC04F: {Name: "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384", EllipticCurve: true},
0XC050: {Name: "TLS_RSA_WITH_ARIA_128_GCM_SHA256"},
0XC051: {Name: "TLS_RSA_WITH_ARIA_256_GCM_SHA384"},
0XC052: {Name: "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256", ForwardSecret: true},
0XC053: {Name: "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384", ForwardSecret: true},
0XC054: {Name: "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256"},
0XC055: {Name: "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384"},
0XC056: {Name: "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256", ForwardSecret: true},
0XC057: {Name: "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384", ForwardSecret: true},
0XC058: {Name: "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256"},
0XC059: {Name: "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384"},
0XC05A: {Name: "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256"},
0XC05B: {Name: "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384"},
0XC05C: {Name: "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256", ForwardSecret: true, EllipticCurve: true},
0XC05D: {Name: "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384", ForwardSecret: true, EllipticCurve: true},
0XC05E: {Name: "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256", EllipticCurve: true},
0XC05F: {Name: "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384", EllipticCurve: true},
0XC060: {Name: "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256", ForwardSecret: true, EllipticCurve: true},
0XC061: {Name: "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384", ForwardSecret: true, EllipticCurve: true},
0XC062: {Name: "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256", EllipticCurve: true},
0XC063: {Name: "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384", EllipticCurve: true},
0XC064: {Name: "TLS_PSK_WITH_ARIA_128_CBC_SHA256"},
0XC065: {Name: "TLS_PSK_WITH_ARIA_256_CBC_SHA384"},
0XC066: {Name: "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256", ForwardSecret: true},
0XC067: {Name: "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384", ForwardSecret: true},
0XC068: {Name: "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256"},
0XC069: {Name: "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384"},
0XC06A: {Name: "TLS_PSK_WITH_ARIA_128_GCM_SHA256"},
0XC06B: {Name: "TLS_PSK_WITH_ARIA_256_GCM_SHA384"},
0XC06C: {Name: "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256", ForwardSecret: true},
0XC06D: {Name: "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384", ForwardSecret: true},
0XC06E: {Name: "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256"},
0XC06F: {Name: "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384"},
0XC070: {Name: "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256", ForwardSecret: true, EllipticCurve: true},
0XC071: {Name: "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384", ForwardSecret: true, EllipticCurve: true},
0XC072: {Name: "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", ForwardSecret: true, EllipticCurve: true},
0XC073: {Name: "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", ForwardSecret: true, EllipticCurve: true},
0XC074: {Name: "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", EllipticCurve: true},
0XC075: {Name: "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", EllipticCurve: true},
0XC076: {Name: "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", ForwardSecret: true, EllipticCurve: true},
0XC077: {Name: "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384", ForwardSecret: true, EllipticCurve: true},
0XC078: {Name: "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256", EllipticCurve: true},
0XC079: {Name: "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384", EllipticCurve: true},
0XC07A: {Name: "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256"},
0XC07B: {Name: "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384"},
0XC07C: {Name: "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", ForwardSecret: true},
0XC07D: {Name: "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", ForwardSecret: true},
0XC07E: {Name: "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256"},
0XC07F: {Name: "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384"},
0XC080: {Name: "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256", ForwardSecret: true},
0XC081: {Name: "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384", ForwardSecret: true},
0XC082: {Name: "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256"},
0XC083: {Name: "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384"},
0XC084: {Name: "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256"},
0XC085: {Name: "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384"},
0XC086: {Name: "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", ForwardSecret: true, EllipticCurve: true},
0XC087: {Name: "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", ForwardSecret: true, EllipticCurve: true},
0XC088: {Name: "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", EllipticCurve: true},
0XC089: {Name: "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", EllipticCurve: true},
0XC08A: {Name: "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", ForwardSecret: true, EllipticCurve: true},
0XC08B: {Name: "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", ForwardSecret: true, EllipticCurve: true},
0XC08C: {Name: "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256", EllipticCurve: true},
0XC08D: {Name: "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384", EllipticCurve: true},
0XC08E: {Name: "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256"},
0XC08F: {Name: "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384"},
0XC090: {Name: "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256", ForwardSecret: true},
0XC091: {Name: "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384", ForwardSecret: true},
0XC092: {Name: "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256"},
0XC093: {Name: "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384"},
0XC094: {Name: "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256"},
0XC095: {Name: "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384"},
0XC096: {Name: "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", ForwardSecret: true},
0XC097: {Name: "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", ForwardSecret: true},
0XC098: {Name: "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256"},
0XC099: {Name: "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384"},
0XC09A: {Name: "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", ForwardSecret: true, EllipticCurve: true},
0XC09B: {Name: "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", ForwardSecret: true, EllipticCurve: true},
0XC09C: {Name: "TLS_RSA_WITH_AES_128_CCM"},
0XC09D: {Name: "TLS_RSA_WITH_AES_256_CCM"},
0XC09E: {Name: "TLS_DHE_RSA_WITH_AES_128_CCM", ForwardSecret: true},
0XC09F: {Name: "TLS_DHE_RSA_WITH_AES_256_CCM", ForwardSecret: true},
0XC0A0: {Name: "TLS_RSA_WITH_AES_128_CCM_8"},
0XC0A1: {Name: "TLS_RSA_WITH_AES_256_CCM_8"},
0XC0A2: {Name: "TLS_DHE_RSA_WITH_AES_128_CCM_8", ForwardSecret: true},
0XC0A3: {Name: "TLS_DHE_RSA_WITH_AES_256_CCM_8", ForwardSecret: true},
0XC0A4: {Name: "TLS_PSK_WITH_AES_128_CCM"},
0XC0A5: {Name: "TLS_PSK_WITH_AES_256_CCM"},
0XC0A6: {Name: "TLS_DHE_PSK_WITH_AES_128_CCM", ForwardSecret: true},
0XC0A7: {Name: "TLS_DHE_PSK_WITH_AES_256_CCM", ForwardSecret: true},
0XC0A8: {Name: "TLS_PSK_WITH_AES_128_CCM_8"},
0XC0A9: {Name: "TLS_PSK_WITH_AES_256_CCM_8"},
0XC0AA: {Name: "TLS_PSK_DHE_WITH_AES_128_CCM_8", ForwardSecret: true},
0XC0AB: {Name: "TLS_PSK_DHE_WITH_AES_256_CCM_8", ForwardSecret: true},
0XC0AC: {Name: "TLS_ECDHE_ECDSA_WITH_AES_128_CCM", ForwardSecret: true, EllipticCurve: true},
0XC0AD: {Name: "TLS_ECDHE_ECDSA_WITH_AES_256_CCM", ForwardSecret: true, EllipticCurve: true},
0XC0AE: {Name: "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", ForwardSecret: true, EllipticCurve: true},
0XC0AF: {Name: "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8", ForwardSecret: true, EllipticCurve: true},
// Non-IANA standardized cipher suites:
// ChaCha20, Poly1305 cipher suites are defined in
// https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
0XCC13: {Name: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", ForwardSecret: true, EllipticCurve: true},
0XCC14: {Name: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", ForwardSecret: true, EllipticCurve: true},
0XCC15: {Name: "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", ForwardSecret: true, EllipticCurve: true},
}
var Curves = map[CurveID]string{
0: "Unassigned",
1: "sect163k1",
2: "sect163r1",
3: "sect163r2",
4: "sect193r1",
5: "sect193r2",
6: "sect233k1",
7: "sect233r1",
8: "sect239k1",
9: "sect283k1",
10: "sect283r1",
11: "sect409k1",
12: "sect409r1",
13: "sect571k1",
14: "sect571r1",
15: "secp160k1",
16: "secp160r1",
17: "secp160r2",
18: "secp192k1",
19: "secp192r1",
20: "secp224k1",
21: "secp224r1",
22: "secp256k1",
23: "secp256r1",
24: "secp384r1",
25: "secp521r1",
26: "brainpoolP256r1",
27: "brainpoolP384r1",
28: "brainpoolP512r1",
65281: "arbitrary_explicit_prime_curves",
65282: "arbitrary_explicit_char2_curves",
}

View File

@ -0,0 +1,109 @@
package tls
// SayHello constructs a simple Client Hello to a server, parses its serverHelloMsg response
// and returns the negotiated ciphersuite ID, and, if an EC cipher suite, the curve ID
func (c *Conn) SayHello(newSigAls []SignatureAndHash) (cipherID, curveType uint16, curveID CurveID, version uint16, certs [][]byte, err error) {
// Set the supported signatures and hashes to the set `newSigAls`
supportedSignatureAlgorithms := make([]signatureAndHash, len(newSigAls))
for i := range newSigAls {
supportedSignatureAlgorithms[i] = newSigAls[i].internal()
}
hello := &clientHelloMsg{
vers: c.config.maxVersion(),
compressionMethods: []uint8{compressionNone},
random: make([]byte, 32),
ocspStapling: true,
serverName: c.config.ServerName,
supportedCurves: c.config.curvePreferences(),
supportedPoints: []uint8{pointFormatUncompressed},
nextProtoNeg: len(c.config.NextProtos) > 0,
secureRenegotiation: true,
cipherSuites: c.config.cipherSuites(),
signatureAndHashes: supportedSignatureAlgorithms,
}
serverHello, err := c.sayHello(hello)
if err != nil {
return
}
// Prime the connection, if necessary, for key
// exchange messages by reading off the certificate
// message and, if necessary, the OCSP stapling
// message
var msg interface{}
msg, err = c.readHandshake()
if err != nil {
return
}
certMsg, ok := msg.(*certificateMsg)
if !ok || len(certMsg.certificates) == 0 {
err = unexpectedMessageError(certMsg, msg)
return
}
certs = certMsg.certificates
if serverHello.ocspStapling {
msg, err = c.readHandshake()
if err != nil {
return
}
certStatusMsg, ok := msg.(*certificateStatusMsg)
if !ok {
err = unexpectedMessageError(certStatusMsg, msg)
return
}
}
if CipherSuites[serverHello.cipherSuite].EllipticCurve {
var skx *serverKeyExchangeMsg
skx, err = c.exchangeKeys()
if err != nil {
return
}
if skx.raw[0] != typeServerKeyExchange {
err = unexpectedMessageError(skx, msg)
return
}
if len(skx.key) < 4 {
err = unexpectedMessageError(skx, msg)
return
}
curveType = uint16(skx.key[0])
// If we have a named curve, report which one it is.
if curveType == 3 {
curveID = CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
}
}
cipherID, version = serverHello.cipherSuite, serverHello.vers
return
}
// sayHello is the backend to SayHello that returns a full serverHelloMsg for processing.
func (c *Conn) sayHello(hello *clientHelloMsg) (serverHello *serverHelloMsg, err error) {
c.writeRecord(recordTypeHandshake, hello.marshal())
msg, err := c.readHandshake()
if err != nil {
return
}
serverHello, ok := msg.(*serverHelloMsg)
if !ok {
return nil, unexpectedMessageError(serverHello, msg)
}
return
}
// exchangeKeys continues the handshake to receive the serverKeyExchange message,
// from which we can extract elliptic curve parameters
func (c *Conn) exchangeKeys() (serverKeyExchange *serverKeyExchangeMsg, err error) {
msg, err := c.readHandshake()
if err != nil {
return
}
serverKeyExchange, ok := msg.(*serverKeyExchangeMsg)
if !ok {
return nil, unexpectedMessageError(serverKeyExchange, msg)
}
return
}

View File

@ -0,0 +1,289 @@
// Copyright 2010 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/aes"
"crypto/cipher"
"crypto/des"
"crypto/hmac"
"crypto/rc4"
"crypto/sha1"
"crypto/x509"
"hash"
)
// a keyAgreement implements the client and server side of a TLS key agreement
// protocol by generating and processing key exchange messages.
type keyAgreement interface {
// On the server side, the first two methods are called in order.
// In the case that the key agreement protocol doesn't use a
// ServerKeyExchange message, generateServerKeyExchange can return nil,
// nil.
generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)
// On the client side, the next two methods are called in order.
// This method may not be called if the server doesn't send a
// ServerKeyExchange message.
processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error
generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error)
}
const (
// suiteECDH indicates that the cipher suite involves elliptic curve
// Diffie-Hellman. This means that it should only be selected when the
// client indicates that it supports ECC with a curve and point format
// that we're happy with.
suiteECDHE = 1 << iota
// suiteECDSA indicates that the cipher suite involves an ECDSA
// signature and therefore may only be selected when the server's
// certificate is ECDSA. If this is not set then the cipher suite is
// RSA based.
suiteECDSA
// suiteTLS12 indicates that the cipher suite should only be advertised
// and accepted when using TLS 1.2.
suiteTLS12
// suiteSHA384 indicates that the cipher suite uses SHA384 as the
// handshake hash.
suiteSHA384
// suiteDefaultOff indicates that this cipher suite is not included by
// default.
suiteDefaultOff
)
// A cipherSuite is a specific combination of key agreement, cipher and MAC
// function. All cipher suites currently assume RSA key agreement.
type cipherSuite struct {
id uint16
// the lengths, in bytes, of the key material needed for each component.
keyLen int
macLen int
ivLen int
ka func(version uint16) keyAgreement
// flags is a bitmask of the suite* values, above.
flags int
cipher func(key, iv []byte, isRead bool) interface{}
mac func(version uint16, macKey []byte) macFunction
aead func(key, fixedNonce []byte) cipher.AEAD
}
var cipherSuites = []*cipherSuite{
// Ciphersuite order is chosen so that ECDHE comes before plain RSA
// and RC4 comes before AES (because of the Lucky13 attack).
{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM},
{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM},
{TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteDefaultOff, cipherRC4, macSHA1, nil},
{TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteDefaultOff, cipherRC4, macSHA1, nil},
{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
{TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM},
{TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteDefaultOff, cipherRC4, macSHA1, nil},
{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
}
func cipherRC4(key, iv []byte, isRead bool) interface{} {
cipher, _ := rc4.NewCipher(key)
return cipher
}
func cipher3DES(key, iv []byte, isRead bool) interface{} {
block, _ := des.NewTripleDESCipher(key)
if isRead {
return cipher.NewCBCDecrypter(block, iv)
}
return cipher.NewCBCEncrypter(block, iv)
}
func cipherAES(key, iv []byte, isRead bool) interface{} {
block, _ := aes.NewCipher(key)
if isRead {
return cipher.NewCBCDecrypter(block, iv)
}
return cipher.NewCBCEncrypter(block, iv)
}
// macSHA1 returns a macFunction for the given protocol version.
func macSHA1(version uint16, key []byte) macFunction {
if version == VersionSSL30 {
mac := ssl30MAC{
h: sha1.New(),
key: make([]byte, len(key)),
}
copy(mac.key, key)
return mac
}
return tls10MAC{hmac.New(sha1.New, key)}
}
type macFunction interface {
Size() int
MAC(digestBuf, seq, header, data []byte) []byte
}
// fixedNonceAEAD wraps an AEAD and prefixes a fixed portion of the nonce to
// each call.
type fixedNonceAEAD struct {
// sealNonce and openNonce are buffers where the larger nonce will be
// constructed. Since a seal and open operation may be running
// concurrently, there is a separate buffer for each.
sealNonce, openNonce []byte
aead cipher.AEAD
}
func (f *fixedNonceAEAD) NonceSize() int { return 8 }
func (f *fixedNonceAEAD) Overhead() int { return f.aead.Overhead() }
func (f *fixedNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte {
copy(f.sealNonce[len(f.sealNonce)-8:], nonce)
return f.aead.Seal(out, f.sealNonce, plaintext, additionalData)
}
func (f *fixedNonceAEAD) Open(out, nonce, plaintext, additionalData []byte) ([]byte, error) {
copy(f.openNonce[len(f.openNonce)-8:], nonce)
return f.aead.Open(out, f.openNonce, plaintext, additionalData)
}
func aeadAESGCM(key, fixedNonce []byte) cipher.AEAD {
aes, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
aead, err := cipher.NewGCM(aes)
if err != nil {
panic(err)
}
nonce1, nonce2 := make([]byte, 12), make([]byte, 12)
copy(nonce1, fixedNonce)
copy(nonce2, fixedNonce)
return &fixedNonceAEAD{nonce1, nonce2, aead}
}
// ssl30MAC implements the SSLv3 MAC function, as defined in
// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 5.2.3.1
type ssl30MAC struct {
h hash.Hash
key []byte
}
func (s ssl30MAC) Size() int {
return s.h.Size()
}
var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}
var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c}
func (s ssl30MAC) MAC(digestBuf, seq, header, data []byte) []byte {
padLength := 48
if s.h.Size() == 20 {
padLength = 40
}
s.h.Reset()
s.h.Write(s.key)
s.h.Write(ssl30Pad1[:padLength])
s.h.Write(seq)
s.h.Write(header[:1])
s.h.Write(header[3:5])
s.h.Write(data)
digestBuf = s.h.Sum(digestBuf[:0])
s.h.Reset()
s.h.Write(s.key)
s.h.Write(ssl30Pad2[:padLength])
s.h.Write(digestBuf)
return s.h.Sum(digestBuf[:0])
}
// tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3.
type tls10MAC struct {
h hash.Hash
}
func (s tls10MAC) Size() int {
return s.h.Size()
}
func (s tls10MAC) MAC(digestBuf, seq, header, data []byte) []byte {
s.h.Reset()
s.h.Write(seq)
s.h.Write(header)
s.h.Write(data)
return s.h.Sum(digestBuf[:0])
}
func rsaKA(version uint16) keyAgreement {
return rsaKeyAgreement{}
}
func ecdheECDSAKA(version uint16) keyAgreement {
return &ecdheKeyAgreement{
sigType: signatureECDSA,
version: version,
}
}
func ecdheRSAKA(version uint16) keyAgreement {
return &ecdheKeyAgreement{
sigType: signatureRSA,
version: version,
}
}
// mutualCipherSuite returns a cipherSuite given a list of supported
// ciphersuites and the id requested by the peer.
func mutualCipherSuite(have []uint16, want uint16) *cipherSuite {
for _, id := range have {
if id == want {
for _, suite := range cipherSuites {
if suite.id == want {
return suite
}
}
return nil
}
}
return nil
}
// A list of the possible cipher suite ids. Taken from
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
const (
TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a
TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009c
TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009d
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xc007
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xc009
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xc00a
TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc02c
// TLS_FALLBACK_SCSV isn't a standard cipher suite but an indicator
// that the client is doing version fallback. See
// https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00.
TLS_FALLBACK_SCSV uint16 = 0x5600
)

View File

@ -0,0 +1,714 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package tls
import (
"container/list"
"crypto"
"crypto/rand"
"crypto/sha512"
"crypto/x509"
"errors"
"fmt"
"io"
"math/big"
"strings"
"sync"
"time"
)
const (
VersionSSL30 = 0x0300
VersionTLS10 = 0x0301
VersionTLS11 = 0x0302
VersionTLS12 = 0x0303
)
const (
maxPlaintext = 16384 // maximum plaintext payload length
maxCiphertext = 16384 + 2048 // maximum ciphertext payload length
recordHeaderLen = 5 // record header length
maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB)
minVersion = VersionTLS10
maxVersion = VersionTLS12
)
// TLS record types.
type recordType uint8
const (
recordTypeChangeCipherSpec recordType = 20
recordTypeAlert recordType = 21
recordTypeHandshake recordType = 22
recordTypeApplicationData recordType = 23
)
// TLS handshake message types.
const (
typeClientHello uint8 = 1
typeServerHello uint8 = 2
typeNewSessionTicket uint8 = 4
typeCertificate uint8 = 11
typeServerKeyExchange uint8 = 12
typeCertificateRequest uint8 = 13
typeServerHelloDone uint8 = 14
typeCertificateVerify uint8 = 15
typeClientKeyExchange uint8 = 16
typeFinished uint8 = 20
typeCertificateStatus uint8 = 22
typeNextProtocol uint8 = 67 // Not IANA assigned
)
// TLS compression types.
const (
compressionNone uint8 = 0
)
// TLS extension numbers
const (
extensionServerName uint16 = 0
extensionStatusRequest uint16 = 5
extensionSupportedCurves uint16 = 10
extensionSupportedPoints uint16 = 11
extensionSignatureAlgorithms uint16 = 13
extensionALPN uint16 = 16
extensionSCT uint16 = 18 // https://tools.ietf.org/html/rfc6962#section-6
extensionSessionTicket uint16 = 35
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
extensionRenegotiationInfo uint16 = 0xff01
)
// TLS signaling cipher suite values
const (
scsvRenegotiation uint16 = 0x00ff
)
// CurveID is the type of a TLS identifier for an elliptic curve. See
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8
type CurveID uint16
const (
CurveP256 CurveID = 23
CurveP384 CurveID = 24
CurveP521 CurveID = 25
)
// TLS Elliptic Curve Point Formats
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9
const (
pointFormatUncompressed uint8 = 0
)
// TLS CertificateStatusType (RFC 3546)
const (
statusTypeOCSP uint8 = 1
)
// Certificate types (for certificateRequestMsg)
const (
certTypeRSASign = 1 // A certificate containing an RSA key
certTypeDSSSign = 2 // A certificate containing a DSA key
certTypeRSAFixedDH = 3 // A certificate containing a static DH key
certTypeDSSFixedDH = 4 // A certificate containing a static DH key
// See RFC4492 sections 3 and 5.5.
certTypeECDSASign = 64 // A certificate containing an ECDSA-capable public key, signed with ECDSA.
certTypeRSAFixedECDH = 65 // A certificate containing an ECDH-capable public key, signed with RSA.
certTypeECDSAFixedECDH = 66 // A certificate containing an ECDH-capable public key, signed with ECDSA.
// Rest of these are reserved by the TLS spec
)
// Hash functions for TLS 1.2 (See RFC 5246, section A.4.1)
const (
hashSHA1 uint8 = 2
hashSHA256 uint8 = 4
hashSHA384 uint8 = 5
)
// Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1)
const (
signatureRSA uint8 = 1
signatureECDSA uint8 = 3
)
// signatureAndHash mirrors the TLS 1.2, SignatureAndHashAlgorithm struct. See
// RFC 5246, section A.4.1.
type signatureAndHash struct {
hash, signature uint8
}
// supportedSignatureAlgorithms contains the signature and hash algorithms that
// the code advertises as supported in a TLS 1.2 ClientHello and in a TLS 1.2
// CertificateRequest.
var supportedSignatureAlgorithms = []signatureAndHash{
{hashSHA256, signatureRSA},
{hashSHA256, signatureECDSA},
{hashSHA384, signatureRSA},
{hashSHA384, signatureECDSA},
{hashSHA1, signatureRSA},
{hashSHA1, signatureECDSA},
}
// ConnectionState records basic TLS details about the connection.
type ConnectionState struct {
Version uint16 // TLS version used by the connection (e.g. VersionTLS12)
HandshakeComplete bool // TLS handshake is complete
DidResume bool // connection resumes a previous TLS connection
CipherSuite uint16 // cipher suite in use (TLS_RSA_WITH_RC4_128_SHA, ...)
NegotiatedProtocol string // negotiated next protocol (from Config.NextProtos)
NegotiatedProtocolIsMutual bool // negotiated protocol was advertised by server
ServerName string // server name requested by client, if any (server side only)
PeerCertificates []*x509.Certificate // certificate chain presented by remote peer
VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates
SignedCertificateTimestamps [][]byte // SCTs from the server, if any
OCSPResponse []byte // stapled OCSP response from server, if any
// TLSUnique contains the "tls-unique" channel binding value (see RFC
// 5929, section 3). For resumed sessions this value will be nil
// because resumption does not include enough context (see
// https://secure-resumption.com/#channelbindings). This will change in
// future versions of Go once the TLS master-secret fix has been
// standardized and implemented.
TLSUnique []byte
}
// ClientAuthType declares the policy the server will follow for
// TLS Client Authentication.
type ClientAuthType int
const (
NoClientCert ClientAuthType = iota
RequestClientCert
RequireAnyClientCert
VerifyClientCertIfGiven
RequireAndVerifyClientCert
)
// ClientSessionState contains the state needed by clients to resume TLS
// sessions.
type ClientSessionState struct {
sessionTicket []uint8 // Encrypted ticket used for session resumption with server
vers uint16 // SSL/TLS version negotiated for the session
cipherSuite uint16 // Ciphersuite negotiated for the session
masterSecret []byte // MasterSecret generated by client on a full handshake
serverCertificates []*x509.Certificate // Certificate chain presented by the server
verifiedChains [][]*x509.Certificate // Certificate chains we built for verification
}
// ClientSessionCache is a cache of ClientSessionState objects that can be used
// by a client to resume a TLS session with a given server. ClientSessionCache
// implementations should expect to be called concurrently from different
// goroutines.
type ClientSessionCache interface {
// Get searches for a ClientSessionState associated with the given key.
// On return, ok is true if one was found.
Get(sessionKey string) (session *ClientSessionState, ok bool)
// Put adds the ClientSessionState to the cache with the given key.
Put(sessionKey string, cs *ClientSessionState)
}
// ClientHelloInfo contains information from a ClientHello message in order to
// guide certificate selection in the GetCertificate callback.
type ClientHelloInfo struct {
// CipherSuites lists the CipherSuites supported by the client (e.g.
// TLS_RSA_WITH_RC4_128_SHA).
CipherSuites []uint16
// ServerName indicates the name of the server requested by the client
// in order to support virtual hosting. ServerName is only set if the
// client is using SNI (see
// http://tools.ietf.org/html/rfc4366#section-3.1).
ServerName string
// SupportedCurves lists the elliptic curves supported by the client.
// SupportedCurves is set only if the Supported Elliptic Curves
// Extension is being used (see
// http://tools.ietf.org/html/rfc4492#section-5.1.1).
SupportedCurves []CurveID
// SupportedPoints lists the point formats supported by the client.
// SupportedPoints is set only if the Supported Point Formats Extension
// is being used (see
// http://tools.ietf.org/html/rfc4492#section-5.1.2).
SupportedPoints []uint8
}
// A Config structure is used to configure a TLS client or server.
// After one has been passed to a TLS function it must not be
// modified. A Config may be reused; the tls package will also not
// modify it.
type Config struct {
// Rand provides the source of entropy for nonces and RSA blinding.
// If Rand is nil, TLS uses the cryptographic random reader in package
// crypto/rand.
// The Reader must be safe for use by multiple goroutines.
Rand io.Reader
// Time returns the current time as the number of seconds since the epoch.
// If Time is nil, TLS uses time.Now.
Time func() time.Time
// Certificates contains one or more certificate chains
// to present to the other side of the connection.
// Server configurations must include at least one certificate
// or else set GetCertificate.
Certificates []Certificate
// NameToCertificate maps from a certificate name to an element of
// Certificates. Note that a certificate name can be of the form
// '*.example.com' and so doesn't have to be a domain name as such.
// See Config.BuildNameToCertificate
// The nil value causes the first element of Certificates to be used
// for all connections.
NameToCertificate map[string]*Certificate
// GetCertificate returns a Certificate based on the given
// ClientHelloInfo. It will only be called if the client supplies SNI
// information or if Certificates is empty.
//
// If GetCertificate is nil or returns nil, then the certificate is
// retrieved from NameToCertificate. If NameToCertificate is nil, the
// first element of Certificates will be used.
GetCertificate func(clientHello *ClientHelloInfo) (*Certificate, error)
// RootCAs defines the set of root certificate authorities
// that clients use when verifying server certificates.
// If RootCAs is nil, TLS uses the host's root CA set.
RootCAs *x509.CertPool
// NextProtos is a list of supported, application level protocols.
NextProtos []string
// ServerName is used to verify the hostname on the returned
// certificates unless InsecureSkipVerify is given. It is also included
// in the client's handshake to support virtual hosting unless it is
// an IP address.
ServerName string
// ClientAuth determines the server's policy for
// TLS Client Authentication. The default is NoClientCert.
ClientAuth ClientAuthType
// ClientCAs defines the set of root certificate authorities
// that servers use if required to verify a client certificate
// by the policy in ClientAuth.
ClientCAs *x509.CertPool
// InsecureSkipVerify controls whether a client verifies the
// server's certificate chain and host name.
// If InsecureSkipVerify is true, TLS accepts any certificate
// presented by the server and any host name in that certificate.
// In this mode, TLS is susceptible to man-in-the-middle attacks.
// This should be used only for testing.
InsecureSkipVerify bool
// CipherSuites is a list of supported cipher suites. If CipherSuites
// is nil, TLS uses a list of suites supported by the implementation.
CipherSuites []uint16
// PreferServerCipherSuites controls whether the server selects the
// client's most preferred ciphersuite, or the server's most preferred
// ciphersuite. If true then the server's preference, as expressed in
// the order of elements in CipherSuites, is used.
PreferServerCipherSuites bool
// SessionTicketsDisabled may be set to true to disable session ticket
// (resumption) support.
SessionTicketsDisabled bool
// SessionTicketKey is used by TLS servers to provide session
// resumption. See RFC 5077. If zero, it will be filled with
// random data before the first server handshake.
//
// If multiple servers are terminating connections for the same host
// they should all have the same SessionTicketKey. If the
// SessionTicketKey leaks, previously recorded and future TLS
// connections using that key are compromised.
SessionTicketKey [32]byte
// SessionCache is a cache of ClientSessionState entries for TLS session
// resumption.
ClientSessionCache ClientSessionCache
// MinVersion contains the minimum SSL/TLS version that is acceptable.
// If zero, then TLS 1.0 is taken as the minimum.
MinVersion uint16
// MaxVersion contains the maximum SSL/TLS version that is acceptable.
// If zero, then the maximum version supported by this package is used,
// which is currently TLS 1.2.
MaxVersion uint16
// CurvePreferences contains the elliptic curves that will be used in
// an ECDHE handshake, in preference order. If empty, the default will
// be used.
CurvePreferences []CurveID
serverInitOnce sync.Once // guards calling (*Config).serverInit
// mutex protects sessionTicketKeys
mutex sync.RWMutex
// sessionTicketKeys contains zero or more ticket keys. If the length
// is zero, SessionTicketsDisabled must be true. The first key is used
// for new tickets and any subsequent keys can be used to decrypt old
// tickets.
sessionTicketKeys []ticketKey
}
// ticketKeyNameLen is the number of bytes of identifier that is prepended to
// an encrypted session ticket in order to identify the key used to encrypt it.
const ticketKeyNameLen = 16
// ticketKey is the internal representation of a session ticket key.
type ticketKey struct {
// keyName is an opaque byte string that serves to identify the session
// ticket key. It's exposed as plaintext in every session ticket.
keyName [ticketKeyNameLen]byte
aesKey [16]byte
hmacKey [16]byte
}
// ticketKeyFromBytes converts from the external representation of a session
// ticket key to a ticketKey. Externally, session ticket keys are 32 random
// bytes and this function expands that into sufficient name and key material.
func ticketKeyFromBytes(b [32]byte) (key ticketKey) {
hashed := sha512.Sum512(b[:])
copy(key.keyName[:], hashed[:ticketKeyNameLen])
copy(key.aesKey[:], hashed[ticketKeyNameLen:ticketKeyNameLen+16])
copy(key.hmacKey[:], hashed[ticketKeyNameLen+16:ticketKeyNameLen+32])
return key
}
func (c *Config) serverInit() {
if c.SessionTicketsDisabled {
return
}
alreadySet := false
for _, b := range c.SessionTicketKey {
if b != 0 {
alreadySet = true
break
}
}
if !alreadySet {
if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil {
c.SessionTicketsDisabled = true
return
}
}
c.sessionTicketKeys = []ticketKey{ticketKeyFromBytes(c.SessionTicketKey)}
}
func (c *Config) ticketKeys() []ticketKey {
c.mutex.RLock()
// c.sessionTicketKeys is constant once created. SetSessionTicketKeys
// will only update it by replacing it with a new value.
ret := c.sessionTicketKeys
c.mutex.RUnlock()
return ret
}
// SetSessionTicketKeys updates the session ticket keys for a server. The first
// key will be used when creating new tickets, while all keys can be used for
// decrypting tickets. It is safe to call this function while the server is
// running in order to rotate the session ticket keys. The function will panic
// if keys is empty.
func (c *Config) SetSessionTicketKeys(keys [][32]byte) {
if len(keys) == 0 {
panic("tls: keys must have at least one key")
}
newKeys := make([]ticketKey, len(keys))
for i, bytes := range keys {
newKeys[i] = ticketKeyFromBytes(bytes)
}
c.mutex.Lock()
c.sessionTicketKeys = newKeys
c.mutex.Unlock()
}
func (c *Config) rand() io.Reader {
r := c.Rand
if r == nil {
return rand.Reader
}
return r
}
func (c *Config) time() time.Time {
t := c.Time
if t == nil {
t = time.Now
}
return t()
}
func (c *Config) cipherSuites() []uint16 {
s := c.CipherSuites
if s == nil {
s = defaultCipherSuites()
}
return s
}
func (c *Config) minVersion() uint16 {
if c == nil || c.MinVersion == 0 {
return minVersion
}
return c.MinVersion
}
func (c *Config) maxVersion() uint16 {
if c == nil || c.MaxVersion == 0 {
return maxVersion
}
return c.MaxVersion
}
var defaultCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521}
func (c *Config) curvePreferences() []CurveID {
if c == nil || len(c.CurvePreferences) == 0 {
return defaultCurvePreferences
}
return c.CurvePreferences
}
// mutualVersion returns the protocol version to use given the advertised
// version of the peer.
func (c *Config) mutualVersion(vers uint16) (uint16, bool) {
minVersion := c.minVersion()
maxVersion := c.maxVersion()
if vers < minVersion {
return 0, false
}
if vers > maxVersion {
vers = maxVersion
}
return vers, true
}
// getCertificate returns the best certificate for the given ClientHelloInfo,
// defaulting to the first element of c.Certificates.
func (c *Config) getCertificate(clientHello *ClientHelloInfo) (*Certificate, error) {
if c.GetCertificate != nil &&
(len(c.Certificates) == 0 || len(clientHello.ServerName) > 0) {
cert, err := c.GetCertificate(clientHello)
if cert != nil || err != nil {
return cert, err
}
}
if len(c.Certificates) == 0 {
return nil, errors.New("crypto/tls: no certificates configured")
}
if len(c.Certificates) == 1 || c.NameToCertificate == nil {
// There's only one choice, so no point doing any work.
return &c.Certificates[0], nil
}
name := strings.ToLower(clientHello.ServerName)
for len(name) > 0 && name[len(name)-1] == '.' {
name = name[:len(name)-1]
}
if cert, ok := c.NameToCertificate[name]; ok {
return cert, nil
}
// try replacing labels in the name with wildcards until we get a
// match.
labels := strings.Split(name, ".")
for i := range labels {
labels[i] = "*"
candidate := strings.Join(labels, ".")
if cert, ok := c.NameToCertificate[candidate]; ok {
return cert, nil
}
}
// If nothing matches, return the first certificate.
return &c.Certificates[0], nil
}
// BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate
// from the CommonName and SubjectAlternateName fields of each of the leaf
// certificates.
func (c *Config) BuildNameToCertificate() {
c.NameToCertificate = make(map[string]*Certificate)
for i := range c.Certificates {
cert := &c.Certificates[i]
x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
if err != nil {
continue
}
if len(x509Cert.Subject.CommonName) > 0 {
c.NameToCertificate[x509Cert.Subject.CommonName] = cert
}
for _, san := range x509Cert.DNSNames {
c.NameToCertificate[san] = cert
}
}
}
// A Certificate is a chain of one or more certificates, leaf first.
type Certificate struct {
Certificate [][]byte
// PrivateKey contains the private key corresponding to the public key
// in Leaf. For a server, this must implement crypto.Signer and/or
// crypto.Decrypter, with an RSA or ECDSA PublicKey. For a client
// (performing client authentication), this must be a crypto.Signer
// with an RSA or ECDSA PublicKey.
PrivateKey crypto.PrivateKey
// OCSPStaple contains an optional OCSP response which will be served
// to clients that request it.
OCSPStaple []byte
// SignedCertificateTimestamps contains an optional list of Signed
// Certificate Timestamps which will be served to clients that request it.
SignedCertificateTimestamps [][]byte
// Leaf is the parsed form of the leaf certificate, which may be
// initialized using x509.ParseCertificate to reduce per-handshake
// processing for TLS clients doing client authentication. If nil, the
// leaf certificate will be parsed as needed.
Leaf *x509.Certificate
}
// A TLS record.
type record struct {
contentType recordType
major, minor uint8
payload []byte
}
type handshakeMessage interface {
marshal() []byte
unmarshal([]byte) bool
}
// lruSessionCache is a ClientSessionCache implementation that uses an LRU
// caching strategy.
type lruSessionCache struct {
sync.Mutex
m map[string]*list.Element
q *list.List
capacity int
}
type lruSessionCacheEntry struct {
sessionKey string
state *ClientSessionState
}
// NewLRUClientSessionCache returns a ClientSessionCache with the given
// capacity that uses an LRU strategy. If capacity is < 1, a default capacity
// is used instead.
func NewLRUClientSessionCache(capacity int) ClientSessionCache {
const defaultSessionCacheCapacity = 64
if capacity < 1 {
capacity = defaultSessionCacheCapacity
}
return &lruSessionCache{
m: make(map[string]*list.Element),
q: list.New(),
capacity: capacity,
}
}
// Put adds the provided (sessionKey, cs) pair to the cache.
func (c *lruSessionCache) Put(sessionKey string, cs *ClientSessionState) {
c.Lock()
defer c.Unlock()
if elem, ok := c.m[sessionKey]; ok {
entry := elem.Value.(*lruSessionCacheEntry)
entry.state = cs
c.q.MoveToFront(elem)
return
}
if c.q.Len() < c.capacity {
entry := &lruSessionCacheEntry{sessionKey, cs}
c.m[sessionKey] = c.q.PushFront(entry)
return
}
elem := c.q.Back()
entry := elem.Value.(*lruSessionCacheEntry)
delete(c.m, entry.sessionKey)
entry.sessionKey = sessionKey
entry.state = cs
c.q.MoveToFront(elem)
c.m[sessionKey] = elem
}
// Get returns the ClientSessionState value associated with a given key. It
// returns (nil, false) if no value is found.
func (c *lruSessionCache) Get(sessionKey string) (*ClientSessionState, bool) {
c.Lock()
defer c.Unlock()
if elem, ok := c.m[sessionKey]; ok {
c.q.MoveToFront(elem)
return elem.Value.(*lruSessionCacheEntry).state, true
}
return nil, false
}
// TODO(jsing): Make these available to both crypto/x509 and crypto/tls.
type dsaSignature struct {
R, S *big.Int
}
type ecdsaSignature dsaSignature
var emptyConfig Config
func defaultConfig() *Config {
return &emptyConfig
}
var (
once sync.Once
varDefaultCipherSuites []uint16
)
func defaultCipherSuites() []uint16 {
once.Do(initDefaultCipherSuites)
return varDefaultCipherSuites
}
func initDefaultCipherSuites() {
varDefaultCipherSuites = make([]uint16, 0, len(cipherSuites))
for _, suite := range cipherSuites {
if suite.flags&suiteDefaultOff != 0 {
continue
}
varDefaultCipherSuites = append(varDefaultCipherSuites, suite.id)
}
}
func unexpectedMessageError(wanted, got interface{}) error {
return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted)
}
func isSupportedSignatureAndHash(sigHash signatureAndHash, sigHashes []signatureAndHash) bool {
for _, s := range sigHashes {
if s == sigHash {
return true
}
}
return false
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,161 @@
// 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 ignore
// Generate a self-signed X.509 certificate for a TLS server. Outputs to
// 'cert.pem' and 'key.pem' and will overwrite existing files.
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"flag"
"fmt"
"log"
"math/big"
"net"
"os"
"strings"
"time"
)
var (
host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for")
validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011")
validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for")
isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority")
rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set")
ecdsaCurve = flag.String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521")
)
func publicKey(priv interface{}) interface{} {
switch k := priv.(type) {
case *rsa.PrivateKey:
return &k.PublicKey
case *ecdsa.PrivateKey:
return &k.PublicKey
default:
return nil
}
}
func pemBlockForKey(priv interface{}) *pem.Block {
switch k := priv.(type) {
case *rsa.PrivateKey:
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
case *ecdsa.PrivateKey:
b, err := x509.MarshalECPrivateKey(k)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err)
os.Exit(2)
}
return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
default:
return nil
}
}
func main() {
flag.Parse()
if len(*host) == 0 {
log.Fatalf("Missing required --host parameter")
}
var priv interface{}
var err error
switch *ecdsaCurve {
case "":
priv, err = rsa.GenerateKey(rand.Reader, *rsaBits)
case "P224":
priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
case "P256":
priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
case "P384":
priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
case "P521":
priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
default:
fmt.Fprintf(os.Stderr, "Unrecognized elliptic curve: %q", *ecdsaCurve)
os.Exit(1)
}
if err != nil {
log.Fatalf("failed to generate private key: %s", err)
}
var notBefore time.Time
if len(*validFrom) == 0 {
notBefore = time.Now()
} else {
notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err)
os.Exit(1)
}
}
notAfter := notBefore.Add(*validFor)
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
log.Fatalf("failed to generate serial number: %s", err)
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{"Acme Co"},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}
hosts := strings.Split(*host, ",")
for _, h := range hosts {
if ip := net.ParseIP(h); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
} else {
template.DNSNames = append(template.DNSNames, h)
}
}
if *isCA {
template.IsCA = true
template.KeyUsage |= x509.KeyUsageCertSign
}
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
if err != nil {
log.Fatalf("Failed to create certificate: %s", err)
}
certOut, err := os.Create("cert.pem")
if err != nil {
log.Fatalf("failed to open cert.pem for writing: %s", err)
}
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close()
log.Print("written cert.pem\n")
keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
log.Print("failed to open key.pem for writing:", err)
return
}
pem.Encode(keyOut, pemBlockForKey(priv))
keyOut.Close()
log.Print("written key.pem\n")
}

View File

@ -0,0 +1,667 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package tls
import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/rsa"
"crypto/subtle"
"crypto/x509"
"errors"
"fmt"
"io"
"net"
"strconv"
)
type clientHandshakeState struct {
c *Conn
serverHello *serverHelloMsg
hello *clientHelloMsg
suite *cipherSuite
finishedHash finishedHash
masterSecret []byte
session *ClientSessionState
}
func (c *Conn) clientHandshake() error {
if c.config == nil {
c.config = defaultConfig()
}
if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify {
return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config")
}
nextProtosLength := 0
for _, proto := range c.config.NextProtos {
if l := len(proto); l == 0 || l > 255 {
return errors.New("tls: invalid NextProtos value")
} else {
nextProtosLength += 1 + l
}
}
if nextProtosLength > 0xffff {
return errors.New("tls: NextProtos values too large")
}
sni := c.config.ServerName
// IP address literals are not permitted as SNI values. See
// https://tools.ietf.org/html/rfc6066#section-3.
if net.ParseIP(sni) != nil {
sni = ""
}
hello := &clientHelloMsg{
vers: c.config.maxVersion(),
compressionMethods: []uint8{compressionNone},
random: make([]byte, 32),
ocspStapling: true,
scts: true,
serverName: sni,
supportedCurves: c.config.curvePreferences(),
supportedPoints: []uint8{pointFormatUncompressed},
nextProtoNeg: len(c.config.NextProtos) > 0,
secureRenegotiation: true,
alpnProtocols: c.config.NextProtos,
}
possibleCipherSuites := c.config.cipherSuites()
hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
NextCipherSuite:
for _, suiteId := range possibleCipherSuites {
for _, suite := range cipherSuites {
if suite.id != suiteId {
continue
}
// Don't advertise TLS 1.2-only cipher suites unless
// we're attempting TLS 1.2.
if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
continue
}
hello.cipherSuites = append(hello.cipherSuites, suiteId)
continue NextCipherSuite
}
}
_, err := io.ReadFull(c.config.rand(), hello.random)
if err != nil {
c.sendAlert(alertInternalError)
return errors.New("tls: short read from Rand: " + err.Error())
}
if hello.vers >= VersionTLS12 {
hello.signatureAndHashes = supportedSignatureAlgorithms
}
var session *ClientSessionState
var cacheKey string
sessionCache := c.config.ClientSessionCache
if c.config.SessionTicketsDisabled {
sessionCache = nil
}
if sessionCache != nil {
hello.ticketSupported = true
// Try to resume a previously negotiated TLS session, if
// available.
cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
candidateSession, ok := sessionCache.Get(cacheKey)
if ok {
// Check that the ciphersuite/version used for the
// previous session are still valid.
cipherSuiteOk := false
for _, id := range hello.cipherSuites {
if id == candidateSession.cipherSuite {
cipherSuiteOk = true
break
}
}
versOk := candidateSession.vers >= c.config.minVersion() &&
candidateSession.vers <= c.config.maxVersion()
if versOk && cipherSuiteOk {
session = candidateSession
}
}
}
if session != nil {
hello.sessionTicket = session.sessionTicket
// A random session ID is used to detect when the
// server accepted the ticket and is resuming a session
// (see RFC 5077).
hello.sessionId = make([]byte, 16)
if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
c.sendAlert(alertInternalError)
return errors.New("tls: short read from Rand: " + err.Error())
}
}
c.writeRecord(recordTypeHandshake, hello.marshal())
msg, err := c.readHandshake()
if err != nil {
return err
}
serverHello, ok := msg.(*serverHelloMsg)
if !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(serverHello, msg)
}
vers, ok := c.config.mutualVersion(serverHello.vers)
if !ok || vers < VersionTLS10 {
// TLS 1.0 is the minimum version supported as a client.
c.sendAlert(alertProtocolVersion)
return fmt.Errorf("tls: server selected unsupported protocol version %x", serverHello.vers)
}
c.vers = vers
c.haveVers = true
suite := mutualCipherSuite(hello.cipherSuites, serverHello.cipherSuite)
if suite == nil {
c.sendAlert(alertHandshakeFailure)
return errors.New("tls: server chose an unconfigured cipher suite")
}
hs := &clientHandshakeState{
c: c,
serverHello: serverHello,
hello: hello,
suite: suite,
finishedHash: newFinishedHash(c.vers, suite),
session: session,
}
isResume, err := hs.processServerHello()
if err != nil {
return err
}
// No signatures of the handshake are needed in a resumption.
// Otherwise, in a full handshake, if we don't have any certificates
// configured then we will never send a CertificateVerify message and
// thus no signatures are needed in that case either.
if isResume || len(c.config.Certificates) == 0 {
hs.finishedHash.discardHandshakeBuffer()
}
hs.finishedHash.Write(hs.hello.marshal())
hs.finishedHash.Write(hs.serverHello.marshal())
if isResume {
if err := hs.establishKeys(); err != nil {
return err
}
if err := hs.readSessionTicket(); err != nil {
return err
}
if err := hs.readFinished(c.firstFinished[:]); err != nil {
return err
}
if err := hs.sendFinished(nil); err != nil {
return err
}
} else {
if err := hs.doFullHandshake(); err != nil {
return err
}
if err := hs.establishKeys(); err != nil {
return err
}
if err := hs.sendFinished(c.firstFinished[:]); err != nil {
return err
}
if err := hs.readSessionTicket(); err != nil {
return err
}
if err := hs.readFinished(nil); err != nil {
return err
}
}
if sessionCache != nil && hs.session != nil && session != hs.session {
sessionCache.Put(cacheKey, hs.session)
}
c.didResume = isResume
c.handshakeComplete = true
c.cipherSuite = suite.id
return nil
}
func (hs *clientHandshakeState) doFullHandshake() error {
c := hs.c
msg, err := c.readHandshake()
if err != nil {
return err
}
certMsg, ok := msg.(*certificateMsg)
if !ok || len(certMsg.certificates) == 0 {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(certMsg, msg)
}
hs.finishedHash.Write(certMsg.marshal())
certs := make([]*x509.Certificate, len(certMsg.certificates))
for i, asn1Data := range certMsg.certificates {
cert, err := x509.ParseCertificate(asn1Data)
if err != nil {
c.sendAlert(alertBadCertificate)
return errors.New("tls: failed to parse certificate from server: " + err.Error())
}
certs[i] = cert
}
if !c.config.InsecureSkipVerify {
opts := x509.VerifyOptions{
Roots: c.config.RootCAs,
CurrentTime: c.config.time(),
DNSName: c.config.ServerName,
Intermediates: x509.NewCertPool(),
}
for i, cert := range certs {
if i == 0 {
continue
}
opts.Intermediates.AddCert(cert)
}
c.verifiedChains, err = certs[0].Verify(opts)
if err != nil {
c.sendAlert(alertBadCertificate)
return err
}
}
switch certs[0].PublicKey.(type) {
case *rsa.PublicKey, *ecdsa.PublicKey:
break
default:
c.sendAlert(alertUnsupportedCertificate)
return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
}
c.peerCertificates = certs
if hs.serverHello.ocspStapling {
msg, err = c.readHandshake()
if err != nil {
return err
}
cs, ok := msg.(*certificateStatusMsg)
if !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(cs, msg)
}
hs.finishedHash.Write(cs.marshal())
if cs.statusType == statusTypeOCSP {
c.ocspResponse = cs.response
}
}
msg, err = c.readHandshake()
if err != nil {
return err
}
keyAgreement := hs.suite.ka(c.vers)
skx, ok := msg.(*serverKeyExchangeMsg)
if ok {
hs.finishedHash.Write(skx.marshal())
err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, certs[0], skx)
if err != nil {
c.sendAlert(alertUnexpectedMessage)
return err
}
msg, err = c.readHandshake()
if err != nil {
return err
}
}
var chainToSend *Certificate
var certRequested bool
certReq, ok := msg.(*certificateRequestMsg)
if ok {
certRequested = true
// RFC 4346 on the certificateAuthorities field:
// A list of the distinguished names of acceptable certificate
// authorities. These distinguished names may specify a desired
// distinguished name for a root CA or for a subordinate CA;
// thus, this message can be used to describe both known roots
// and a desired authorization space. If the
// certificate_authorities list is empty then the client MAY
// send any certificate of the appropriate
// ClientCertificateType, unless there is some external
// arrangement to the contrary.
hs.finishedHash.Write(certReq.marshal())
var rsaAvail, ecdsaAvail bool
for _, certType := range certReq.certificateTypes {
switch certType {
case certTypeRSASign:
rsaAvail = true
case certTypeECDSASign:
ecdsaAvail = true
}
}
// We need to search our list of client certs for one
// where SignatureAlgorithm is acceptable to the server and the
// Issuer is in certReq.certificateAuthorities
findCert:
for i, chain := range c.config.Certificates {
if !rsaAvail && !ecdsaAvail {
continue
}
for j, cert := range chain.Certificate {
x509Cert := chain.Leaf
// parse the certificate if this isn't the leaf
// node, or if chain.Leaf was nil
if j != 0 || x509Cert == nil {
if x509Cert, err = x509.ParseCertificate(cert); err != nil {
c.sendAlert(alertInternalError)
return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
}
}
switch {
case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
default:
continue findCert
}
if len(certReq.certificateAuthorities) == 0 {
// they gave us an empty list, so just take the
// first cert from c.config.Certificates
chainToSend = &chain
break findCert
}
for _, ca := range certReq.certificateAuthorities {
if bytes.Equal(x509Cert.RawIssuer, ca) {
chainToSend = &chain
break findCert
}
}
}
}
msg, err = c.readHandshake()
if err != nil {
return err
}
}
shd, ok := msg.(*serverHelloDoneMsg)
if !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(shd, msg)
}
hs.finishedHash.Write(shd.marshal())
// If the server requested a certificate then we have to send a
// Certificate message, even if it's empty because we don't have a
// certificate to send.
if certRequested {
certMsg = new(certificateMsg)
if chainToSend != nil {
certMsg.certificates = chainToSend.Certificate
}
hs.finishedHash.Write(certMsg.marshal())
c.writeRecord(recordTypeHandshake, certMsg.marshal())
}
preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, certs[0])
if err != nil {
c.sendAlert(alertInternalError)
return err
}
if ckx != nil {
hs.finishedHash.Write(ckx.marshal())
c.writeRecord(recordTypeHandshake, ckx.marshal())
}
if chainToSend != nil {
certVerify := &certificateVerifyMsg{
hasSignatureAndHash: c.vers >= VersionTLS12,
}
key, ok := chainToSend.PrivateKey.(crypto.Signer)
if !ok {
c.sendAlert(alertInternalError)
return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey)
}
var signatureType uint8
switch key.Public().(type) {
case *ecdsa.PublicKey:
signatureType = signatureECDSA
case *rsa.PublicKey:
signatureType = signatureRSA
default:
c.sendAlert(alertInternalError)
return fmt.Errorf("tls: failed to sign handshake with client certificate: unknown client certificate key type: %T", key)
}
certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, signatureType)
if err != nil {
c.sendAlert(alertInternalError)
return err
}
digest, hashFunc, err := hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret)
if err != nil {
c.sendAlert(alertInternalError)
return err
}
certVerify.signature, err = key.Sign(c.config.rand(), digest, hashFunc)
if err != nil {
c.sendAlert(alertInternalError)
return err
}
hs.finishedHash.Write(certVerify.marshal())
c.writeRecord(recordTypeHandshake, certVerify.marshal())
}
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
hs.finishedHash.discardHandshakeBuffer()
return nil
}
func (hs *clientHandshakeState) establishKeys() error {
c := hs.c
clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
var clientCipher, serverCipher interface{}
var clientHash, serverHash macFunction
if hs.suite.cipher != nil {
clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
clientHash = hs.suite.mac(c.vers, clientMAC)
serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
serverHash = hs.suite.mac(c.vers, serverMAC)
} else {
clientCipher = hs.suite.aead(clientKey, clientIV)
serverCipher = hs.suite.aead(serverKey, serverIV)
}
c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
return nil
}
func (hs *clientHandshakeState) serverResumedSession() bool {
// If the server responded with the same sessionId then it means the
// sessionTicket is being used to resume a TLS session.
return hs.session != nil && hs.hello.sessionId != nil &&
bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
}
func (hs *clientHandshakeState) processServerHello() (bool, error) {
c := hs.c
if hs.serverHello.compressionMethod != compressionNone {
c.sendAlert(alertUnexpectedMessage)
return false, errors.New("tls: server selected unsupported compression format")
}
clientDidNPN := hs.hello.nextProtoNeg
clientDidALPN := len(hs.hello.alpnProtocols) > 0
serverHasNPN := hs.serverHello.nextProtoNeg
serverHasALPN := len(hs.serverHello.alpnProtocol) > 0
if !clientDidNPN && serverHasNPN {
c.sendAlert(alertHandshakeFailure)
return false, errors.New("server advertised unrequested NPN extension")
}
if !clientDidALPN && serverHasALPN {
c.sendAlert(alertHandshakeFailure)
return false, errors.New("server advertised unrequested ALPN extension")
}
if serverHasNPN && serverHasALPN {
c.sendAlert(alertHandshakeFailure)
return false, errors.New("server advertised both NPN and ALPN extensions")
}
if serverHasALPN {
c.clientProtocol = hs.serverHello.alpnProtocol
c.clientProtocolFallback = false
}
c.scts = hs.serverHello.scts
if hs.serverResumedSession() {
// Restore masterSecret and peerCerts from previous state
hs.masterSecret = hs.session.masterSecret
c.peerCertificates = hs.session.serverCertificates
c.verifiedChains = hs.session.verifiedChains
return true, nil
}
return false, nil
}
func (hs *clientHandshakeState) readFinished(out []byte) error {
c := hs.c
c.readRecord(recordTypeChangeCipherSpec)
if err := c.in.error(); err != nil {
return err
}
msg, err := c.readHandshake()
if err != nil {
return err
}
serverFinished, ok := msg.(*finishedMsg)
if !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(serverFinished, msg)
}
verify := hs.finishedHash.serverSum(hs.masterSecret)
if len(verify) != len(serverFinished.verifyData) ||
subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
c.sendAlert(alertHandshakeFailure)
return errors.New("tls: server's Finished message was incorrect")
}
hs.finishedHash.Write(serverFinished.marshal())
copy(out, verify)
return nil
}
func (hs *clientHandshakeState) readSessionTicket() error {
if !hs.serverHello.ticketSupported {
return nil
}
c := hs.c
msg, err := c.readHandshake()
if err != nil {
return err
}
sessionTicketMsg, ok := msg.(*newSessionTicketMsg)
if !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(sessionTicketMsg, msg)
}
hs.finishedHash.Write(sessionTicketMsg.marshal())
hs.session = &ClientSessionState{
sessionTicket: sessionTicketMsg.ticket,
vers: c.vers,
cipherSuite: hs.suite.id,
masterSecret: hs.masterSecret,
serverCertificates: c.peerCertificates,
verifiedChains: c.verifiedChains,
}
return nil
}
func (hs *clientHandshakeState) sendFinished(out []byte) error {
c := hs.c
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
if hs.serverHello.nextProtoNeg {
nextProto := new(nextProtoMsg)
proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos)
nextProto.proto = proto
c.clientProtocol = proto
c.clientProtocolFallback = fallback
hs.finishedHash.Write(nextProto.marshal())
c.writeRecord(recordTypeHandshake, nextProto.marshal())
}
finished := new(finishedMsg)
finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
hs.finishedHash.Write(finished.marshal())
c.writeRecord(recordTypeHandshake, finished.marshal())
copy(out, finished.verifyData)
return nil
}
// clientSessionCacheKey returns a key used to cache sessionTickets that could
// be used to resume previously negotiated TLS sessions with a server.
func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
if len(config.ServerName) > 0 {
return config.ServerName
}
return serverAddr.String()
}
// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
// given list of possible protocols and a list of the preference order. The
// first list must not be empty. It returns the resulting protocol and flag
// indicating if the fallback case was reached.
func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
for _, s := range preferenceProtos {
for _, c := range protos {
if s == c {
return s, false
}
}
}
return protos[0], true
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,750 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package tls
import (
"crypto"
"crypto/ecdsa"
"crypto/rsa"
"crypto/subtle"
"crypto/x509"
"encoding/asn1"
"errors"
"fmt"
"io"
)
// serverHandshakeState contains details of a server handshake in progress.
// It's discarded once the handshake has completed.
type serverHandshakeState struct {
c *Conn
clientHello *clientHelloMsg
hello *serverHelloMsg
suite *cipherSuite
ellipticOk bool
ecdsaOk bool
rsaDecryptOk bool
rsaSignOk bool
sessionState *sessionState
finishedHash finishedHash
masterSecret []byte
certsFromClient [][]byte
cert *Certificate
}
// serverHandshake performs a TLS handshake as a server.
func (c *Conn) serverHandshake() error {
config := c.config
// If this is the first server handshake, we generate a random key to
// encrypt the tickets with.
config.serverInitOnce.Do(config.serverInit)
hs := serverHandshakeState{
c: c,
}
isResume, err := hs.readClientHello()
if err != nil {
return err
}
// For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
if isResume {
// The client has included a session ticket and so we do an abbreviated handshake.
if err := hs.doResumeHandshake(); err != nil {
return err
}
if err := hs.establishKeys(); err != nil {
return err
}
// ticketSupported is set in a resumption handshake if the
// ticket from the client was encrypted with an old session
// ticket key and thus a refreshed ticket should be sent.
if hs.hello.ticketSupported {
if err := hs.sendSessionTicket(); err != nil {
return err
}
}
if err := hs.sendFinished(c.firstFinished[:]); err != nil {
return err
}
if err := hs.readFinished(nil); err != nil {
return err
}
c.didResume = true
} else {
// The client didn't include a session ticket, or it wasn't
// valid so we do a full handshake.
if err := hs.doFullHandshake(); err != nil {
return err
}
if err := hs.establishKeys(); err != nil {
return err
}
if err := hs.readFinished(c.firstFinished[:]); err != nil {
return err
}
if err := hs.sendSessionTicket(); err != nil {
return err
}
if err := hs.sendFinished(nil); err != nil {
return err
}
}
c.handshakeComplete = true
return nil
}
// readClientHello reads a ClientHello message from the client and decides
// whether we will perform session resumption.
func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
config := hs.c.config
c := hs.c
msg, err := c.readHandshake()
if err != nil {
return false, err
}
var ok bool
hs.clientHello, ok = msg.(*clientHelloMsg)
if !ok {
c.sendAlert(alertUnexpectedMessage)
return false, unexpectedMessageError(hs.clientHello, msg)
}
c.vers, ok = config.mutualVersion(hs.clientHello.vers)
if !ok {
c.sendAlert(alertProtocolVersion)
return false, fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers)
}
c.haveVers = true
hs.hello = new(serverHelloMsg)
supportedCurve := false
preferredCurves := config.curvePreferences()
Curves:
for _, curve := range hs.clientHello.supportedCurves {
for _, supported := range preferredCurves {
if supported == curve {
supportedCurve = true
break Curves
}
}
}
supportedPointFormat := false
for _, pointFormat := range hs.clientHello.supportedPoints {
if pointFormat == pointFormatUncompressed {
supportedPointFormat = true
break
}
}
hs.ellipticOk = supportedCurve && supportedPointFormat
foundCompression := false
// We only support null compression, so check that the client offered it.
for _, compression := range hs.clientHello.compressionMethods {
if compression == compressionNone {
foundCompression = true
break
}
}
if !foundCompression {
c.sendAlert(alertHandshakeFailure)
return false, errors.New("tls: client does not support uncompressed connections")
}
hs.hello.vers = c.vers
hs.hello.random = make([]byte, 32)
_, err = io.ReadFull(config.rand(), hs.hello.random)
if err != nil {
c.sendAlert(alertInternalError)
return false, err
}
hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation
hs.hello.compressionMethod = compressionNone
if len(hs.clientHello.serverName) > 0 {
c.serverName = hs.clientHello.serverName
}
if len(hs.clientHello.alpnProtocols) > 0 {
if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
hs.hello.alpnProtocol = selectedProto
c.clientProtocol = selectedProto
}
} else {
// Although sending an empty NPN extension is reasonable, Firefox has
// had a bug around this. Best to send nothing at all if
// config.NextProtos is empty. See
// https://golang.org/issue/5445.
if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
hs.hello.nextProtoNeg = true
hs.hello.nextProtos = config.NextProtos
}
}
if hs.cert, err = config.getCertificate(&ClientHelloInfo{
CipherSuites: hs.clientHello.cipherSuites,
ServerName: hs.clientHello.serverName,
SupportedCurves: hs.clientHello.supportedCurves,
SupportedPoints: hs.clientHello.supportedPoints,
}); err != nil {
c.sendAlert(alertInternalError)
return false, err
}
if hs.clientHello.scts {
hs.hello.scts = hs.cert.SignedCertificateTimestamps
}
if priv, ok := hs.cert.PrivateKey.(crypto.Signer); ok {
switch priv.Public().(type) {
case *ecdsa.PublicKey:
hs.ecdsaOk = true
case *rsa.PublicKey:
hs.rsaSignOk = true
default:
c.sendAlert(alertInternalError)
return false, fmt.Errorf("crypto/tls: unsupported signing key type (%T)", priv.Public())
}
}
if priv, ok := hs.cert.PrivateKey.(crypto.Decrypter); ok {
switch priv.Public().(type) {
case *rsa.PublicKey:
hs.rsaDecryptOk = true
default:
c.sendAlert(alertInternalError)
return false, fmt.Errorf("crypto/tls: unsupported decryption key type (%T)", priv.Public())
}
}
if hs.checkForResumption() {
return true, nil
}
var preferenceList, supportedList []uint16
if c.config.PreferServerCipherSuites {
preferenceList = c.config.cipherSuites()
supportedList = hs.clientHello.cipherSuites
} else {
preferenceList = hs.clientHello.cipherSuites
supportedList = c.config.cipherSuites()
}
for _, id := range preferenceList {
if hs.setCipherSuite(id, supportedList, c.vers) {
break
}
}
if hs.suite == nil {
c.sendAlert(alertHandshakeFailure)
return false, errors.New("tls: no cipher suite supported by both client and server")
}
// See https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00.
for _, id := range hs.clientHello.cipherSuites {
if id == TLS_FALLBACK_SCSV {
// The client is doing a fallback connection.
if hs.clientHello.vers < c.config.maxVersion() {
c.sendAlert(alertInappropriateFallback)
return false, errors.New("tls: client using inappropriate protocol fallback")
}
break
}
}
return false, nil
}
// checkForResumption reports whether we should perform resumption on this connection.
func (hs *serverHandshakeState) checkForResumption() bool {
c := hs.c
if c.config.SessionTicketsDisabled {
return false
}
var ok bool
var sessionTicket = append([]uint8{}, hs.clientHello.sessionTicket...)
if hs.sessionState, ok = c.decryptTicket(sessionTicket); !ok {
return false
}
if hs.sessionState.vers > hs.clientHello.vers {
return false
}
if vers, ok := c.config.mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
return false
}
cipherSuiteOk := false
// Check that the client is still offering the ciphersuite in the session.
for _, id := range hs.clientHello.cipherSuites {
if id == hs.sessionState.cipherSuite {
cipherSuiteOk = true
break
}
}
if !cipherSuiteOk {
return false
}
// Check that we also support the ciphersuite from the session.
if !hs.setCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers) {
return false
}
sessionHasClientCerts := len(hs.sessionState.certificates) != 0
needClientCerts := c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == RequireAndVerifyClientCert
if needClientCerts && !sessionHasClientCerts {
return false
}
if sessionHasClientCerts && c.config.ClientAuth == NoClientCert {
return false
}
return true
}
func (hs *serverHandshakeState) doResumeHandshake() error {
c := hs.c
hs.hello.cipherSuite = hs.suite.id
// We echo the client's session ID in the ServerHello to let it know
// that we're doing a resumption.
hs.hello.sessionId = hs.clientHello.sessionId
hs.hello.ticketSupported = hs.sessionState.usedOldKey
hs.finishedHash = newFinishedHash(c.vers, hs.suite)
hs.finishedHash.discardHandshakeBuffer()
hs.finishedHash.Write(hs.clientHello.marshal())
hs.finishedHash.Write(hs.hello.marshal())
c.writeRecord(recordTypeHandshake, hs.hello.marshal())
if len(hs.sessionState.certificates) > 0 {
if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil {
return err
}
}
hs.masterSecret = hs.sessionState.masterSecret
return nil
}
func (hs *serverHandshakeState) doFullHandshake() error {
config := hs.c.config
c := hs.c
if hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 {
hs.hello.ocspStapling = true
}
hs.hello.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled
hs.hello.cipherSuite = hs.suite.id
hs.finishedHash = newFinishedHash(hs.c.vers, hs.suite)
if config.ClientAuth == NoClientCert {
// No need to keep a full record of the handshake if client
// certificates won't be used.
hs.finishedHash.discardHandshakeBuffer()
}
hs.finishedHash.Write(hs.clientHello.marshal())
hs.finishedHash.Write(hs.hello.marshal())
c.writeRecord(recordTypeHandshake, hs.hello.marshal())
certMsg := new(certificateMsg)
certMsg.certificates = hs.cert.Certificate
hs.finishedHash.Write(certMsg.marshal())
c.writeRecord(recordTypeHandshake, certMsg.marshal())
if hs.hello.ocspStapling {
certStatus := new(certificateStatusMsg)
certStatus.statusType = statusTypeOCSP
certStatus.response = hs.cert.OCSPStaple
hs.finishedHash.Write(certStatus.marshal())
c.writeRecord(recordTypeHandshake, certStatus.marshal())
}
keyAgreement := hs.suite.ka(c.vers)
skx, err := keyAgreement.generateServerKeyExchange(config, hs.cert, hs.clientHello, hs.hello)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
}
if skx != nil {
hs.finishedHash.Write(skx.marshal())
c.writeRecord(recordTypeHandshake, skx.marshal())
}
if config.ClientAuth >= RequestClientCert {
// Request a client certificate
certReq := new(certificateRequestMsg)
certReq.certificateTypes = []byte{
byte(certTypeRSASign),
byte(certTypeECDSASign),
}
if c.vers >= VersionTLS12 {
certReq.hasSignatureAndHash = true
certReq.signatureAndHashes = supportedSignatureAlgorithms
}
// An empty list of certificateAuthorities signals to
// the client that it may send any certificate in response
// to our request. When we know the CAs we trust, then
// we can send them down, so that the client can choose
// an appropriate certificate to give to us.
if config.ClientCAs != nil {
certReq.certificateAuthorities = config.ClientCAs.Subjects()
}
hs.finishedHash.Write(certReq.marshal())
c.writeRecord(recordTypeHandshake, certReq.marshal())
}
helloDone := new(serverHelloDoneMsg)
hs.finishedHash.Write(helloDone.marshal())
c.writeRecord(recordTypeHandshake, helloDone.marshal())
var pub crypto.PublicKey // public key for client auth, if any
msg, err := c.readHandshake()
if err != nil {
return err
}
var ok bool
// If we requested a client certificate, then the client must send a
// certificate message, even if it's empty.
if config.ClientAuth >= RequestClientCert {
if certMsg, ok = msg.(*certificateMsg); !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(certMsg, msg)
}
hs.finishedHash.Write(certMsg.marshal())
if len(certMsg.certificates) == 0 {
// The client didn't actually send a certificate
switch config.ClientAuth {
case RequireAnyClientCert, RequireAndVerifyClientCert:
c.sendAlert(alertBadCertificate)
return errors.New("tls: client didn't provide a certificate")
}
}
pub, err = hs.processCertsFromClient(certMsg.certificates)
if err != nil {
return err
}
msg, err = c.readHandshake()
if err != nil {
return err
}
}
// Get client key exchange
ckx, ok := msg.(*clientKeyExchangeMsg)
if !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(ckx, msg)
}
hs.finishedHash.Write(ckx.marshal())
preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx, c.vers)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
}
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
// If we received a client cert in response to our certificate request message,
// the client will send us a certificateVerifyMsg immediately after the
// clientKeyExchangeMsg. This message is a digest of all preceding
// handshake-layer messages that is signed using the private key corresponding
// to the client's certificate. This allows us to verify that the client is in
// possession of the private key of the certificate.
if len(c.peerCertificates) > 0 {
msg, err = c.readHandshake()
if err != nil {
return err
}
certVerify, ok := msg.(*certificateVerifyMsg)
if !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(certVerify, msg)
}
// Determine the signature type.
var signatureAndHash signatureAndHash
if certVerify.hasSignatureAndHash {
signatureAndHash = certVerify.signatureAndHash
if !isSupportedSignatureAndHash(signatureAndHash, supportedSignatureAlgorithms) {
return errors.New("tls: unsupported hash function for client certificate")
}
} else {
// Before TLS 1.2 the signature algorithm was implicit
// from the key type, and only one hash per signature
// algorithm was possible. Leave the hash as zero.
switch pub.(type) {
case *ecdsa.PublicKey:
signatureAndHash.signature = signatureECDSA
case *rsa.PublicKey:
signatureAndHash.signature = signatureRSA
}
}
switch key := pub.(type) {
case *ecdsa.PublicKey:
if signatureAndHash.signature != signatureECDSA {
err = errors.New("bad signature type for client's ECDSA certificate")
break
}
ecdsaSig := new(ecdsaSignature)
if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil {
break
}
if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
err = errors.New("ECDSA signature contained zero or negative values")
break
}
var digest []byte
if digest, _, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret); err != nil {
break
}
if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) {
err = errors.New("ECDSA verification failure")
}
case *rsa.PublicKey:
if signatureAndHash.signature != signatureRSA {
err = errors.New("bad signature type for client's RSA certificate")
break
}
var digest []byte
var hashFunc crypto.Hash
if digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret); err != nil {
break
}
err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature)
}
if err != nil {
c.sendAlert(alertBadCertificate)
return errors.New("tls: could not validate signature of connection nonces: " + err.Error())
}
hs.finishedHash.Write(certVerify.marshal())
}
hs.finishedHash.discardHandshakeBuffer()
return nil
}
func (hs *serverHandshakeState) establishKeys() error {
c := hs.c
clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
var clientCipher, serverCipher interface{}
var clientHash, serverHash macFunction
if hs.suite.aead == nil {
clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */)
clientHash = hs.suite.mac(c.vers, clientMAC)
serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
serverHash = hs.suite.mac(c.vers, serverMAC)
} else {
clientCipher = hs.suite.aead(clientKey, clientIV)
serverCipher = hs.suite.aead(serverKey, serverIV)
}
c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
return nil
}
func (hs *serverHandshakeState) readFinished(out []byte) error {
c := hs.c
c.readRecord(recordTypeChangeCipherSpec)
if err := c.in.error(); err != nil {
return err
}
if hs.hello.nextProtoNeg {
msg, err := c.readHandshake()
if err != nil {
return err
}
nextProto, ok := msg.(*nextProtoMsg)
if !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(nextProto, msg)
}
hs.finishedHash.Write(nextProto.marshal())
c.clientProtocol = nextProto.proto
}
msg, err := c.readHandshake()
if err != nil {
return err
}
clientFinished, ok := msg.(*finishedMsg)
if !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(clientFinished, msg)
}
verify := hs.finishedHash.clientSum(hs.masterSecret)
if len(verify) != len(clientFinished.verifyData) ||
subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
c.sendAlert(alertHandshakeFailure)
return errors.New("tls: client's Finished message is incorrect")
}
hs.finishedHash.Write(clientFinished.marshal())
copy(out, verify)
return nil
}
func (hs *serverHandshakeState) sendSessionTicket() error {
if !hs.hello.ticketSupported {
return nil
}
c := hs.c
m := new(newSessionTicketMsg)
var err error
state := sessionState{
vers: c.vers,
cipherSuite: hs.suite.id,
masterSecret: hs.masterSecret,
certificates: hs.certsFromClient,
}
m.ticket, err = c.encryptTicket(&state)
if err != nil {
return err
}
hs.finishedHash.Write(m.marshal())
c.writeRecord(recordTypeHandshake, m.marshal())
return nil
}
func (hs *serverHandshakeState) sendFinished(out []byte) error {
c := hs.c
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
finished := new(finishedMsg)
finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
hs.finishedHash.Write(finished.marshal())
c.writeRecord(recordTypeHandshake, finished.marshal())
c.cipherSuite = hs.suite.id
copy(out, finished.verifyData)
return nil
}
// processCertsFromClient takes a chain of client certificates either from a
// Certificates message or from a sessionState and verifies them. It returns
// the public key of the leaf certificate.
func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) {
c := hs.c
hs.certsFromClient = certificates
certs := make([]*x509.Certificate, len(certificates))
var err error
for i, asn1Data := range certificates {
if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
c.sendAlert(alertBadCertificate)
return nil, errors.New("tls: failed to parse client certificate: " + err.Error())
}
}
if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
opts := x509.VerifyOptions{
Roots: c.config.ClientCAs,
CurrentTime: c.config.time(),
Intermediates: x509.NewCertPool(),
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}
for _, cert := range certs[1:] {
opts.Intermediates.AddCert(cert)
}
chains, err := certs[0].Verify(opts)
if err != nil {
c.sendAlert(alertBadCertificate)
return nil, errors.New("tls: failed to verify client's certificate: " + err.Error())
}
c.verifiedChains = chains
}
if len(certs) > 0 {
var pub crypto.PublicKey
switch key := certs[0].PublicKey.(type) {
case *ecdsa.PublicKey, *rsa.PublicKey:
pub = key
default:
c.sendAlert(alertUnsupportedCertificate)
return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey)
}
c.peerCertificates = certs
return pub, nil
}
return nil, nil
}
// setCipherSuite sets a cipherSuite with the given id as the serverHandshakeState
// suite if that cipher suite is acceptable to use.
// It returns a bool indicating if the suite was set.
func (hs *serverHandshakeState) setCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16) bool {
for _, supported := range supportedCipherSuites {
if id == supported {
var candidate *cipherSuite
for _, s := range cipherSuites {
if s.id == id {
candidate = s
break
}
}
if candidate == nil {
continue
}
// Don't select a ciphersuite which we can't
// support for this client.
if candidate.flags&suiteECDHE != 0 {
if !hs.ellipticOk {
continue
}
if candidate.flags&suiteECDSA != 0 {
if !hs.ecdsaOk {
continue
}
} else if !hs.rsaSignOk {
continue
}
} else if !hs.rsaDecryptOk {
continue
}
if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
continue
}
hs.suite = candidate
return true
}
}
return false
}

View File

@ -0,0 +1,405 @@
// Copyright 2010 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"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/md5"
"crypto/rsa"
"crypto/sha1"
"crypto/x509"
"encoding/asn1"
"errors"
"io"
"math/big"
)
var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
// rsaKeyAgreement implements the standard TLS key agreement where the client
// encrypts the pre-master secret to the server's public key.
type rsaKeyAgreement struct{}
func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
return nil, nil
}
func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
if len(ckx.ciphertext) < 2 {
return nil, errClientKeyExchange
}
ciphertext := ckx.ciphertext
if version != VersionSSL30 {
ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
if ciphertextLen != len(ckx.ciphertext)-2 {
return nil, errClientKeyExchange
}
ciphertext = ckx.ciphertext[2:]
}
priv, ok := cert.PrivateKey.(crypto.Decrypter)
if !ok {
return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter")
}
// Perform constant time RSA PKCS#1 v1.5 decryption
preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48})
if err != nil {
return nil, err
}
// We don't check the version number in the premaster secret. For one,
// by checking it, we would leak information about the validity of the
// encrypted pre-master secret. Secondly, it provides only a small
// benefit against a downgrade attack and some implementations send the
// wrong version anyway. See the discussion at the end of section
// 7.4.7.1 of RFC 4346.
return preMasterSecret, nil
}
func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
return errors.New("tls: unexpected ServerKeyExchange")
}
func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
preMasterSecret := make([]byte, 48)
preMasterSecret[0] = byte(clientHello.vers >> 8)
preMasterSecret[1] = byte(clientHello.vers)
_, err := io.ReadFull(config.rand(), preMasterSecret[2:])
if err != nil {
return nil, nil, err
}
encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
if err != nil {
return nil, nil, err
}
ckx := new(clientKeyExchangeMsg)
ckx.ciphertext = make([]byte, len(encrypted)+2)
ckx.ciphertext[0] = byte(len(encrypted) >> 8)
ckx.ciphertext[1] = byte(len(encrypted))
copy(ckx.ciphertext[2:], encrypted)
return preMasterSecret, ckx, nil
}
// sha1Hash calculates a SHA1 hash over the given byte slices.
func sha1Hash(slices [][]byte) []byte {
hsha1 := sha1.New()
for _, slice := range slices {
hsha1.Write(slice)
}
return hsha1.Sum(nil)
}
// md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
// concatenation of an MD5 and SHA1 hash.
func md5SHA1Hash(slices [][]byte) []byte {
md5sha1 := make([]byte, md5.Size+sha1.Size)
hmd5 := md5.New()
for _, slice := range slices {
hmd5.Write(slice)
}
copy(md5sha1, hmd5.Sum(nil))
copy(md5sha1[md5.Size:], sha1Hash(slices))
return md5sha1
}
// hashForServerKeyExchange hashes the given slices and returns their digest
// and the identifier of the hash function used. The sigAndHash argument is
// only used for >= TLS 1.2 and precisely identifies the hash function to use.
func hashForServerKeyExchange(sigAndHash signatureAndHash, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
if version >= VersionTLS12 {
if !isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms) {
return nil, crypto.Hash(0), errors.New("tls: unsupported hash function used by peer")
}
hashFunc, err := lookupTLSHash(sigAndHash.hash)
if err != nil {
return nil, crypto.Hash(0), err
}
h := hashFunc.New()
for _, slice := range slices {
h.Write(slice)
}
digest := h.Sum(nil)
return digest, hashFunc, nil
}
if sigAndHash.signature == signatureECDSA {
return sha1Hash(slices), crypto.SHA1, nil
}
return md5SHA1Hash(slices), crypto.MD5SHA1, nil
}
// pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a
// ServerKeyExchange given the signature type being used and the client's
// advertised list of supported signature and hash combinations.
func pickTLS12HashForSignature(sigType uint8, clientList []signatureAndHash) (uint8, error) {
if len(clientList) == 0 {
// If the client didn't specify any signature_algorithms
// extension then we can assume that it supports SHA1. See
// http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
return hashSHA1, nil
}
for _, sigAndHash := range clientList {
if sigAndHash.signature != sigType {
continue
}
if isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms) {
return sigAndHash.hash, nil
}
}
return 0, errors.New("tls: client doesn't support any common hash functions")
}
func curveForCurveID(id CurveID) (elliptic.Curve, bool) {
switch id {
case CurveP256:
return elliptic.P256(), true
case CurveP384:
return elliptic.P384(), true
case CurveP521:
return elliptic.P521(), true
default:
return nil, false
}
}
// ecdheRSAKeyAgreement implements a TLS key agreement where the server
// generates a ephemeral EC public/private key pair and signs it. The
// pre-master secret is then calculated using ECDH. The signature may
// either be ECDSA or RSA.
type ecdheKeyAgreement struct {
version uint16
sigType uint8
privateKey []byte
curve elliptic.Curve
x, y *big.Int
}
func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
var curveid CurveID
preferredCurves := config.curvePreferences()
NextCandidate:
for _, candidate := range preferredCurves {
for _, c := range clientHello.supportedCurves {
if candidate == c {
curveid = c
break NextCandidate
}
}
}
if curveid == 0 {
return nil, errors.New("tls: no supported elliptic curves offered")
}
var ok bool
if ka.curve, ok = curveForCurveID(curveid); !ok {
return nil, errors.New("tls: preferredCurves includes unsupported curve")
}
var x, y *big.Int
var err error
ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
if err != nil {
return nil, err
}
ecdhePublic := elliptic.Marshal(ka.curve, x, y)
// http://tools.ietf.org/html/rfc4492#section-5.4
serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
serverECDHParams[0] = 3 // named curve
serverECDHParams[1] = byte(curveid >> 8)
serverECDHParams[2] = byte(curveid)
serverECDHParams[3] = byte(len(ecdhePublic))
copy(serverECDHParams[4:], ecdhePublic)
sigAndHash := signatureAndHash{signature: ka.sigType}
if ka.version >= VersionTLS12 {
if sigAndHash.hash, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil {
return nil, err
}
}
digest, hashFunc, err := hashForServerKeyExchange(sigAndHash, ka.version, clientHello.random, hello.random, serverECDHParams)
if err != nil {
return nil, err
}
priv, ok := cert.PrivateKey.(crypto.Signer)
if !ok {
return nil, errors.New("tls: certificate private key does not implement crypto.Signer")
}
var sig []byte
switch ka.sigType {
case signatureECDSA:
_, ok := priv.Public().(*ecdsa.PublicKey)
if !ok {
return nil, errors.New("ECDHE ECDSA requires an ECDSA server key")
}
case signatureRSA:
_, ok := priv.Public().(*rsa.PublicKey)
if !ok {
return nil, errors.New("ECDHE RSA requires a RSA server key")
}
default:
return nil, errors.New("unknown ECDHE signature algorithm")
}
sig, err = priv.Sign(config.rand(), digest, hashFunc)
if err != nil {
return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
}
skx := new(serverKeyExchangeMsg)
sigAndHashLen := 0
if ka.version >= VersionTLS12 {
sigAndHashLen = 2
}
skx.key = make([]byte, len(serverECDHParams)+sigAndHashLen+2+len(sig))
copy(skx.key, serverECDHParams)
k := skx.key[len(serverECDHParams):]
if ka.version >= VersionTLS12 {
k[0] = sigAndHash.hash
k[1] = sigAndHash.signature
k = k[2:]
}
k[0] = byte(len(sig) >> 8)
k[1] = byte(len(sig))
copy(k[2:], sig)
return skx, nil
}
func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
return nil, errClientKeyExchange
}
x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:])
if x == nil {
return nil, errClientKeyExchange
}
if !ka.curve.IsOnCurve(x, y) {
return nil, errClientKeyExchange
}
x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
xBytes := x.Bytes()
copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
return preMasterSecret, nil
}
func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
if len(skx.key) < 4 {
return errServerKeyExchange
}
if skx.key[0] != 3 { // named curve
return errors.New("tls: server selected unsupported curve")
}
curveid := CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
var ok bool
if ka.curve, ok = curveForCurveID(curveid); !ok {
return errors.New("tls: server selected unsupported curve")
}
publicLen := int(skx.key[3])
if publicLen+4 > len(skx.key) {
return errServerKeyExchange
}
ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen])
if ka.x == nil {
return errServerKeyExchange
}
if !ka.curve.IsOnCurve(ka.x, ka.y) {
return errServerKeyExchange
}
serverECDHParams := skx.key[:4+publicLen]
sig := skx.key[4+publicLen:]
if len(sig) < 2 {
return errServerKeyExchange
}
sigAndHash := signatureAndHash{signature: ka.sigType}
if ka.version >= VersionTLS12 {
// handle SignatureAndHashAlgorithm
sigAndHash = signatureAndHash{hash: sig[0], signature: sig[1]}
if sigAndHash.signature != ka.sigType {
return errServerKeyExchange
}
sig = sig[2:]
if len(sig) < 2 {
return errServerKeyExchange
}
}
sigLen := int(sig[0])<<8 | int(sig[1])
if sigLen+2 != len(sig) {
return errServerKeyExchange
}
sig = sig[2:]
digest, hashFunc, err := hashForServerKeyExchange(sigAndHash, ka.version, clientHello.random, serverHello.random, serverECDHParams)
if err != nil {
return err
}
switch ka.sigType {
case signatureECDSA:
pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
if !ok {
return errors.New("ECDHE ECDSA requires a ECDSA server public key")
}
ecdsaSig := new(ecdsaSignature)
if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil {
return err
}
if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
return errors.New("ECDSA signature contained zero or negative values")
}
if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) {
return errors.New("ECDSA verification failure")
}
case signatureRSA:
pubKey, ok := cert.PublicKey.(*rsa.PublicKey)
if !ok {
return errors.New("ECDHE RSA requires a RSA server public key")
}
if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil {
return err
}
default:
return errors.New("unknown ECDHE signature algorithm")
}
return nil
}
func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
if ka.curve == nil {
return nil, nil, errors.New("missing ServerKeyExchange message")
}
priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand())
if err != nil {
return nil, nil, err
}
x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
xBytes := x.Bytes()
copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
serialized := elliptic.Marshal(ka.curve, mx, my)
ckx := new(clientKeyExchangeMsg)
ckx.ciphertext = make([]byte, 1+len(serialized))
ckx.ciphertext[0] = byte(len(serialized))
copy(ckx.ciphertext[1:], serialized)
return preMasterSecret, ckx, nil
}

View File

@ -0,0 +1,368 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package tls
import (
"crypto"
"crypto/hmac"
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"errors"
"hash"
)
// Split a premaster secret in two as specified in RFC 4346, section 5.
func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
s1 = secret[0 : (len(secret)+1)/2]
s2 = secret[len(secret)/2:]
return
}
// pHash implements the P_hash function, as defined in RFC 4346, section 5.
func pHash(result, secret, seed []byte, hash func() hash.Hash) {
h := hmac.New(hash, secret)
h.Write(seed)
a := h.Sum(nil)
j := 0
for j < len(result) {
h.Reset()
h.Write(a)
h.Write(seed)
b := h.Sum(nil)
todo := len(b)
if j+todo > len(result) {
todo = len(result) - j
}
copy(result[j:j+todo], b)
j += todo
h.Reset()
h.Write(a)
a = h.Sum(nil)
}
}
// prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
func prf10(result, secret, label, seed []byte) {
hashSHA1 := sha1.New
hashMD5 := md5.New
labelAndSeed := make([]byte, len(label)+len(seed))
copy(labelAndSeed, label)
copy(labelAndSeed[len(label):], seed)
s1, s2 := splitPreMasterSecret(secret)
pHash(result, s1, labelAndSeed, hashMD5)
result2 := make([]byte, len(result))
pHash(result2, s2, labelAndSeed, hashSHA1)
for i, b := range result2 {
result[i] ^= b
}
}
// prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5.
func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) {
return func(result, secret, label, seed []byte) {
labelAndSeed := make([]byte, len(label)+len(seed))
copy(labelAndSeed, label)
copy(labelAndSeed[len(label):], seed)
pHash(result, secret, labelAndSeed, hashFunc)
}
}
// prf30 implements the SSL 3.0 pseudo-random function, as defined in
// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
func prf30(result, secret, label, seed []byte) {
hashSHA1 := sha1.New()
hashMD5 := md5.New()
done := 0
i := 0
// RFC5246 section 6.3 says that the largest PRF output needed is 128
// bytes. Since no more ciphersuites will be added to SSLv3, this will
// remain true. Each iteration gives us 16 bytes so 10 iterations will
// be sufficient.
var b [11]byte
for done < len(result) {
for j := 0; j <= i; j++ {
b[j] = 'A' + byte(i)
}
hashSHA1.Reset()
hashSHA1.Write(b[:i+1])
hashSHA1.Write(secret)
hashSHA1.Write(seed)
digest := hashSHA1.Sum(nil)
hashMD5.Reset()
hashMD5.Write(secret)
hashMD5.Write(digest)
done += copy(result[done:], hashMD5.Sum(nil))
i++
}
}
const (
tlsRandomLength = 32 // Length of a random nonce in TLS 1.1.
masterSecretLength = 48 // Length of a master secret in TLS 1.1.
finishedVerifyLength = 12 // Length of verify_data in a Finished message.
)
var masterSecretLabel = []byte("master secret")
var keyExpansionLabel = []byte("key expansion")
var clientFinishedLabel = []byte("client finished")
var serverFinishedLabel = []byte("server finished")
func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) {
switch version {
case VersionSSL30:
return prf30, crypto.Hash(0)
case VersionTLS10, VersionTLS11:
return prf10, crypto.Hash(0)
case VersionTLS12:
if suite.flags&suiteSHA384 != 0 {
return prf12(sha512.New384), crypto.SHA384
}
return prf12(sha256.New), crypto.SHA256
default:
panic("unknown version")
}
}
func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) {
prf, _ := prfAndHashForVersion(version, suite)
return prf
}
// masterFromPreMasterSecret generates the master secret from the pre-master
// secret. See http://tools.ietf.org/html/rfc5246#section-8.1
func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
seed := make([]byte, 0, len(clientRandom)+len(serverRandom))
seed = append(seed, clientRandom...)
seed = append(seed, serverRandom...)
masterSecret := make([]byte, masterSecretLength)
prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed)
return masterSecret
}
// keysFromMasterSecret generates the connection keys from the master
// secret, given the lengths of the MAC key, cipher key and IV, as defined in
// RFC 2246, section 6.3.
func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
seed := make([]byte, 0, len(serverRandom)+len(clientRandom))
seed = append(seed, serverRandom...)
seed = append(seed, clientRandom...)
n := 2*macLen + 2*keyLen + 2*ivLen
keyMaterial := make([]byte, n)
prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed)
clientMAC = keyMaterial[:macLen]
keyMaterial = keyMaterial[macLen:]
serverMAC = keyMaterial[:macLen]
keyMaterial = keyMaterial[macLen:]
clientKey = keyMaterial[:keyLen]
keyMaterial = keyMaterial[keyLen:]
serverKey = keyMaterial[:keyLen]
keyMaterial = keyMaterial[keyLen:]
clientIV = keyMaterial[:ivLen]
keyMaterial = keyMaterial[ivLen:]
serverIV = keyMaterial[:ivLen]
return
}
// lookupTLSHash looks up the corresponding crypto.Hash for a given
// TLS hash identifier.
func lookupTLSHash(hash uint8) (crypto.Hash, error) {
switch hash {
case hashSHA1:
return crypto.SHA1, nil
case hashSHA256:
return crypto.SHA256, nil
case hashSHA384:
return crypto.SHA384, nil
default:
return 0, errors.New("tls: unsupported hash algorithm")
}
}
func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash {
var buffer []byte
if version == VersionSSL30 || version >= VersionTLS12 {
buffer = []byte{}
}
prf, hash := prfAndHashForVersion(version, cipherSuite)
if hash != 0 {
return finishedHash{hash.New(), hash.New(), nil, nil, buffer, version, prf}
}
return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf}
}
// A finishedHash calculates the hash of a set of handshake messages suitable
// for including in a Finished message.
type finishedHash struct {
client hash.Hash
server hash.Hash
// Prior to TLS 1.2, an additional MD5 hash is required.
clientMD5 hash.Hash
serverMD5 hash.Hash
// In TLS 1.2, a full buffer is sadly required.
buffer []byte
version uint16
prf func(result, secret, label, seed []byte)
}
func (h *finishedHash) Write(msg []byte) (n int, err error) {
h.client.Write(msg)
h.server.Write(msg)
if h.version < VersionTLS12 {
h.clientMD5.Write(msg)
h.serverMD5.Write(msg)
}
if h.buffer != nil {
h.buffer = append(h.buffer, msg...)
}
return len(msg), nil
}
func (h finishedHash) Sum() []byte {
if h.version >= VersionTLS12 {
return h.client.Sum(nil)
}
out := make([]byte, 0, md5.Size+sha1.Size)
out = h.clientMD5.Sum(out)
return h.client.Sum(out)
}
// finishedSum30 calculates the contents of the verify_data member of a SSLv3
// Finished message given the MD5 and SHA1 hashes of a set of handshake
// messages.
func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic []byte) []byte {
md5.Write(magic)
md5.Write(masterSecret)
md5.Write(ssl30Pad1[:])
md5Digest := md5.Sum(nil)
md5.Reset()
md5.Write(masterSecret)
md5.Write(ssl30Pad2[:])
md5.Write(md5Digest)
md5Digest = md5.Sum(nil)
sha1.Write(magic)
sha1.Write(masterSecret)
sha1.Write(ssl30Pad1[:40])
sha1Digest := sha1.Sum(nil)
sha1.Reset()
sha1.Write(masterSecret)
sha1.Write(ssl30Pad2[:40])
sha1.Write(sha1Digest)
sha1Digest = sha1.Sum(nil)
ret := make([]byte, len(md5Digest)+len(sha1Digest))
copy(ret, md5Digest)
copy(ret[len(md5Digest):], sha1Digest)
return ret
}
var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54}
var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
// clientSum returns the contents of the verify_data member of a client's
// Finished message.
func (h finishedHash) clientSum(masterSecret []byte) []byte {
if h.version == VersionSSL30 {
return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic[:])
}
out := make([]byte, finishedVerifyLength)
h.prf(out, masterSecret, clientFinishedLabel, h.Sum())
return out
}
// serverSum returns the contents of the verify_data member of a server's
// Finished message.
func (h finishedHash) serverSum(masterSecret []byte) []byte {
if h.version == VersionSSL30 {
return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic[:])
}
out := make([]byte, finishedVerifyLength)
h.prf(out, masterSecret, serverFinishedLabel, h.Sum())
return out
}
// selectClientCertSignatureAlgorithm returns a signatureAndHash to sign a
// client's CertificateVerify with, or an error if none can be found.
func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureAndHash, sigType uint8) (signatureAndHash, error) {
if h.version < VersionTLS12 {
// Nothing to negotiate before TLS 1.2.
return signatureAndHash{signature: sigType}, nil
}
for _, v := range serverList {
if v.signature == sigType && isSupportedSignatureAndHash(v, supportedSignatureAlgorithms) {
return v, nil
}
}
return signatureAndHash{}, errors.New("tls: no supported signature algorithm found for signing client certificate")
}
// hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash
// id suitable for signing by a TLS client certificate.
func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash, masterSecret []byte) ([]byte, crypto.Hash, error) {
if (h.version == VersionSSL30 || h.version >= VersionTLS12) && h.buffer == nil {
panic("a handshake hash for a client-certificate was requested after discarding the handshake buffer")
}
if h.version == VersionSSL30 {
if signatureAndHash.signature != signatureRSA {
return nil, 0, errors.New("tls: unsupported signature type for client certificate")
}
md5Hash := md5.New()
md5Hash.Write(h.buffer)
sha1Hash := sha1.New()
sha1Hash.Write(h.buffer)
return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), crypto.MD5SHA1, nil
}
if h.version >= VersionTLS12 {
hashAlg, err := lookupTLSHash(signatureAndHash.hash)
if err != nil {
return nil, 0, err
}
hash := hashAlg.New()
hash.Write(h.buffer)
return hash.Sum(nil), hashAlg, nil
}
if signatureAndHash.signature == signatureECDSA {
return h.server.Sum(nil), crypto.SHA1, nil
}
return h.Sum(), crypto.MD5SHA1, nil
}
// discardHandshakeBuffer is called when there is no more need to
// buffer the entirety of the handshake messages.
func (h *finishedHash) discardHandshakeBuffer() {
h.buffer = nil
}

View File

@ -0,0 +1,204 @@
// Copyright 2012 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 (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/sha256"
"crypto/subtle"
"errors"
"io"
)
// sessionState contains the information that is serialized into a session
// ticket in order to later resume a connection.
type sessionState struct {
vers uint16
cipherSuite uint16
masterSecret []byte
certificates [][]byte
// usedOldKey is true if the ticket from which this session came from
// was encrypted with an older key and thus should be refreshed.
usedOldKey bool
}
func (s *sessionState) equal(i interface{}) bool {
s1, ok := i.(*sessionState)
if !ok {
return false
}
if s.vers != s1.vers ||
s.cipherSuite != s1.cipherSuite ||
!bytes.Equal(s.masterSecret, s1.masterSecret) {
return false
}
if len(s.certificates) != len(s1.certificates) {
return false
}
for i := range s.certificates {
if !bytes.Equal(s.certificates[i], s1.certificates[i]) {
return false
}
}
return true
}
func (s *sessionState) marshal() []byte {
length := 2 + 2 + 2 + len(s.masterSecret) + 2
for _, cert := range s.certificates {
length += 4 + len(cert)
}
ret := make([]byte, length)
x := ret
x[0] = byte(s.vers >> 8)
x[1] = byte(s.vers)
x[2] = byte(s.cipherSuite >> 8)
x[3] = byte(s.cipherSuite)
x[4] = byte(len(s.masterSecret) >> 8)
x[5] = byte(len(s.masterSecret))
x = x[6:]
copy(x, s.masterSecret)
x = x[len(s.masterSecret):]
x[0] = byte(len(s.certificates) >> 8)
x[1] = byte(len(s.certificates))
x = x[2:]
for _, cert := range s.certificates {
x[0] = byte(len(cert) >> 24)
x[1] = byte(len(cert) >> 16)
x[2] = byte(len(cert) >> 8)
x[3] = byte(len(cert))
copy(x[4:], cert)
x = x[4+len(cert):]
}
return ret
}
func (s *sessionState) unmarshal(data []byte) bool {
if len(data) < 8 {
return false
}
s.vers = uint16(data[0])<<8 | uint16(data[1])
s.cipherSuite = uint16(data[2])<<8 | uint16(data[3])
masterSecretLen := int(data[4])<<8 | int(data[5])
data = data[6:]
if len(data) < masterSecretLen {
return false
}
s.masterSecret = data[:masterSecretLen]
data = data[masterSecretLen:]
if len(data) < 2 {
return false
}
numCerts := int(data[0])<<8 | int(data[1])
data = data[2:]
s.certificates = make([][]byte, numCerts)
for i := range s.certificates {
if len(data) < 4 {
return false
}
certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3])
data = data[4:]
if certLen < 0 {
return false
}
if len(data) < certLen {
return false
}
s.certificates[i] = data[:certLen]
data = data[certLen:]
}
if len(data) > 0 {
return false
}
return true
}
func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) {
serialized := state.marshal()
encrypted := make([]byte, ticketKeyNameLen+aes.BlockSize+len(serialized)+sha256.Size)
keyName := encrypted[:ticketKeyNameLen]
iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize]
macBytes := encrypted[len(encrypted)-sha256.Size:]
if _, err := io.ReadFull(c.config.rand(), iv); err != nil {
return nil, err
}
key := c.config.ticketKeys()[0]
copy(keyName, key.keyName[:])
block, err := aes.NewCipher(key.aesKey[:])
if err != nil {
return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error())
}
cipher.NewCTR(block, iv).XORKeyStream(encrypted[ticketKeyNameLen+aes.BlockSize:], serialized)
mac := hmac.New(sha256.New, key.hmacKey[:])
mac.Write(encrypted[:len(encrypted)-sha256.Size])
mac.Sum(macBytes[:0])
return encrypted, nil
}
func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) {
if c.config.SessionTicketsDisabled ||
len(encrypted) < ticketKeyNameLen+aes.BlockSize+sha256.Size {
return nil, false
}
keyName := encrypted[:ticketKeyNameLen]
iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize]
macBytes := encrypted[len(encrypted)-sha256.Size:]
keys := c.config.ticketKeys()
keyIndex := -1
for i, candidateKey := range keys {
if bytes.Equal(keyName, candidateKey.keyName[:]) {
keyIndex = i
break
}
}
if keyIndex == -1 {
return nil, false
}
key := &keys[keyIndex]
mac := hmac.New(sha256.New, key.hmacKey[:])
mac.Write(encrypted[:len(encrypted)-sha256.Size])
expected := mac.Sum(nil)
if subtle.ConstantTimeCompare(macBytes, expected) != 1 {
return nil, false
}
block, err := aes.NewCipher(key.aesKey[:])
if err != nil {
return nil, false
}
ciphertext := encrypted[ticketKeyNameLen+aes.BlockSize : len(encrypted)-sha256.Size]
plaintext := ciphertext
cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext)
state := &sessionState{usedOldKey: keyIndex > 0}
ok := state.unmarshal(plaintext)
return state, ok
}

View File

@ -0,0 +1,298 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package tls partially implements TLS 1.2, as specified in RFC 5246.
package tls
// BUG(agl): The crypto/tls package does not implement countermeasures
// against Lucky13 attacks on CBC-mode encryption. See
// http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and
// https://www.imperialviolet.org/2013/02/04/luckythirteen.html.
import (
"crypto"
"crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"net"
"strings"
"time"
)
// Server returns a new TLS server side connection
// using conn as the underlying transport.
// The configuration config must be non-nil and must include
// at least one certificate or else set GetCertificate.
func Server(conn net.Conn, config *Config) *Conn {
return &Conn{conn: conn, config: config}
}
// Client returns a new TLS client side connection
// using conn as the underlying transport.
// The config cannot be nil: users must set either ServerName or
// InsecureSkipVerify in the config.
func Client(conn net.Conn, config *Config) *Conn {
return &Conn{conn: conn, config: config, isClient: true}
}
// A listener implements a network listener (net.Listener) for TLS connections.
type listener struct {
net.Listener
config *Config
}
// Accept waits for and returns the next incoming TLS connection.
// The returned connection c is a *tls.Conn.
func (l *listener) Accept() (c net.Conn, err error) {
c, err = l.Listener.Accept()
if err != nil {
return
}
c = Server(c, l.config)
return
}
// NewListener creates a Listener which accepts connections from an inner
// Listener and wraps each connection with Server.
// The configuration config must be non-nil and must include
// at least one certificate or else set GetCertificate.
func NewListener(inner net.Listener, config *Config) net.Listener {
l := new(listener)
l.Listener = inner
l.config = config
return l
}
// Listen creates a TLS listener accepting connections on the
// given network address using net.Listen.
// The configuration config must be non-nil and must include
// at least one certificate or else set GetCertificate.
func Listen(network, laddr string, config *Config) (net.Listener, error) {
if config == nil || (len(config.Certificates) == 0 && config.GetCertificate == nil) {
return nil, errors.New("tls: neither Certificates nor GetCertificate set in Config")
}
l, err := net.Listen(network, laddr)
if err != nil {
return nil, err
}
return NewListener(l, config), nil
}
type timeoutError struct{}
func (timeoutError) Error() string { return "tls: DialWithDialer timed out" }
func (timeoutError) Timeout() bool { return true }
func (timeoutError) Temporary() bool { return true }
// DialWithDialer connects to the given network address using dialer.Dial and
// then initiates a TLS handshake, returning the resulting TLS connection. Any
// timeout or deadline given in the dialer apply to connection and TLS
// handshake as a whole.
//
// DialWithDialer interprets a nil configuration as equivalent to the zero
// configuration; see the documentation of Config for the defaults.
func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) {
// We want the Timeout and Deadline values from dialer to cover the
// whole process: TCP connection and TLS handshake. This means that we
// also need to start our own timers now.
timeout := dialer.Timeout
if !dialer.Deadline.IsZero() {
deadlineTimeout := dialer.Deadline.Sub(time.Now())
if timeout == 0 || deadlineTimeout < timeout {
timeout = deadlineTimeout
}
}
var errChannel chan error
if timeout != 0 {
errChannel = make(chan error, 2)
time.AfterFunc(timeout, func() {
errChannel <- timeoutError{}
})
}
rawConn, err := dialer.Dial(network, addr)
if err != nil {
return nil, err
}
colonPos := strings.LastIndex(addr, ":")
if colonPos == -1 {
colonPos = len(addr)
}
hostname := addr[:colonPos]
if config == nil {
config = defaultConfig()
}
// If no ServerName is set, infer the ServerName
// from the hostname we're connecting to.
if config.ServerName == "" {
// Make a copy to avoid polluting argument or default.
c := *config
c.ServerName = hostname
config = &c
}
conn := Client(rawConn, config)
if timeout == 0 {
err = conn.Handshake()
} else {
go func() {
errChannel <- conn.Handshake()
}()
err = <-errChannel
}
if err != nil {
rawConn.Close()
return nil, err
}
return conn, nil
}
// Dial connects to the given network address using net.Dial
// and then initiates a TLS handshake, returning the resulting
// TLS connection.
// Dial interprets a nil configuration as equivalent to
// the zero configuration; see the documentation of Config
// for the defaults.
func Dial(network, addr string, config *Config) (*Conn, error) {
return DialWithDialer(new(net.Dialer), network, addr, config)
}
// LoadX509KeyPair reads and parses a public/private key pair from a pair of
// files. The files must contain PEM encoded data. On successful return,
// Certificate.Leaf will be nil because the parsed form of the certificate is
// not retained.
func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) {
certPEMBlock, err := ioutil.ReadFile(certFile)
if err != nil {
return Certificate{}, err
}
keyPEMBlock, err := ioutil.ReadFile(keyFile)
if err != nil {
return Certificate{}, err
}
return X509KeyPair(certPEMBlock, keyPEMBlock)
}
// X509KeyPair parses a public/private key pair from a pair of
// PEM encoded data. On successful return, Certificate.Leaf will be nil because
// the parsed form of the certificate is not retained.
func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) {
fail := func(err error) (Certificate, error) { return Certificate{}, err }
var cert Certificate
var skippedBlockTypes []string
for {
var certDERBlock *pem.Block
certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
if certDERBlock == nil {
break
}
if certDERBlock.Type == "CERTIFICATE" {
cert.Certificate = append(cert.Certificate, certDERBlock.Bytes)
} else {
skippedBlockTypes = append(skippedBlockTypes, certDERBlock.Type)
}
}
if len(cert.Certificate) == 0 {
if len(skippedBlockTypes) == 0 {
return fail(errors.New("crypto/tls: failed to find any PEM data in certificate input"))
} else if len(skippedBlockTypes) == 1 && strings.HasSuffix(skippedBlockTypes[0], "PRIVATE KEY") {
return fail(errors.New("crypto/tls: failed to find certificate PEM data in certificate input, but did find a private key; PEM inputs may have been switched"))
} else {
return fail(fmt.Errorf("crypto/tls: failed to find \"CERTIFICATE\" PEM block in certificate input after skipping PEM blocks of the following types: %v", skippedBlockTypes))
}
}
skippedBlockTypes = skippedBlockTypes[:0]
var keyDERBlock *pem.Block
for {
keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock)
if keyDERBlock == nil {
if len(skippedBlockTypes) == 0 {
return fail(errors.New("crypto/tls: failed to find any PEM data in key input"))
} else if len(skippedBlockTypes) == 1 && skippedBlockTypes[0] == "CERTIFICATE" {
return fail(errors.New("crypto/tls: found a certificate rather than a key in the PEM for the private key"))
} else {
return fail(fmt.Errorf("crypto/tls: failed to find PEM block with type ending in \"PRIVATE KEY\" in key input after skipping PEM blocks of the following types: %v", skippedBlockTypes))
}
}
if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") {
break
}
skippedBlockTypes = append(skippedBlockTypes, keyDERBlock.Type)
}
var err error
cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes)
if err != nil {
return fail(err)
}
// We don't need to parse the public key for TLS, but we so do anyway
// to check that it looks sane and matches the private key.
x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
if err != nil {
return fail(err)
}
switch pub := x509Cert.PublicKey.(type) {
case *rsa.PublicKey:
priv, ok := cert.PrivateKey.(*rsa.PrivateKey)
if !ok {
return fail(errors.New("crypto/tls: private key type does not match public key type"))
}
if pub.N.Cmp(priv.N) != 0 {
return fail(errors.New("crypto/tls: private key does not match public key"))
}
case *ecdsa.PublicKey:
priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
if !ok {
return fail(errors.New("crypto/tls: private key type does not match public key type"))
}
if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 {
return fail(errors.New("crypto/tls: private key does not match public key"))
}
default:
return fail(errors.New("crypto/tls: unknown public key algorithm"))
}
return cert, nil
}
// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
return key, nil
}
if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
switch key := key.(type) {
case *rsa.PrivateKey, *ecdsa.PrivateKey:
return key, nil
default:
return nil, errors.New("crypto/tls: found unknown private key type in PKCS#8 wrapping")
}
}
if key, err := x509.ParseECPrivateKey(der); err == nil {
return key, nil
}
return nil, errors.New("crypto/tls: failed to parse private key")
}

View File

@ -2,13 +2,13 @@ package scan
import (
"bytes"
"crypto/tls"
"crypto/x509"
"fmt"
"time"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/revoke"
"github.com/cloudflare/cfssl/scan/crypto/tls"
)
// PKI contains scanners for the Public Key Infrastructure.

View File

@ -1,7 +1,6 @@
package scan
import (
"crypto/tls"
"crypto/x509"
"net"
"net/http"
@ -11,6 +10,7 @@ import (
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/scan/crypto/tls"
)
var (

View File

@ -2,13 +2,13 @@ package scan
import (
"bytes"
"crypto/tls"
"errors"
"fmt"
"net"
"strings"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/scan/crypto/tls"
)
// Sentinel for failures in sayHello. Should always be caught.
@ -19,7 +19,7 @@ var TLSHandshake = &Family{
Description: "Scans for host's SSL/TLS version and cipher suite negotiation",
Scanners: map[string]*Scanner{
"CipherSuite": {
"Determines host's cipher suites accepted and prefered order",
"Determines host's cipher suites accepted and preferred order",
cipherSuiteScan,
},
"SigAlgs": {

View File

@ -1,6 +1,6 @@
package scan
import "crypto/tls"
import "github.com/cloudflare/cfssl/scan/crypto/tls"
// TLSSession contains tests of host TLS Session Resumption via
// Session Tickets and Session IDs

View File

@ -337,7 +337,7 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
var certTBS = safeTemplate
if len(profile.CTLogServers) > 0 {
if len(profile.CTLogServers) > 0 || req.ReturnPrecert {
// Add a poison extension which prevents validation
var poisonExtension = pkix.Extension{Id: signer.CTPoisonOID, Critical: true, Value: []byte{0x05, 0x00}}
var poisonedPreCert = certTBS
@ -347,6 +347,10 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
return
}
if req.ReturnPrecert {
return cert, nil
}
derCert, _ := pem.Decode(cert)
prechain := []ct.ASN1Cert{{Data: derCert.Bytes}, {Data: s.ca.Raw}}
var sctList []ct.SignedCertificateTimestamp
@ -414,6 +418,85 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
return signedCert, nil
}
// SignFromPrecert creates and signs a certificate from an existing precertificate
// that was previously signed by Signer.ca and inserts the provided SCTs into the
// new certificate. The resulting certificate will be a exact copy of the precert
// except for the removal of the poison extension and the addition of the SCT list
// extension. SignFromPrecert does not verify that the contents of the certificate
// still match the signing profile of the signer, it only requires that the precert
// was previously signed by the Signers CA.
func (s *Signer) SignFromPrecert(precert *x509.Certificate, scts []ct.SignedCertificateTimestamp) ([]byte, error) {
// Verify certificate was signed by s.ca
if err := precert.CheckSignatureFrom(s.ca); err != nil {
return nil, err
}
// Verify certificate is a precert
isPrecert := false
poisonIndex := 0
for i, ext := range precert.Extensions {
if ext.Id.Equal(signer.CTPoisonOID) {
if !ext.Critical {
return nil, cferr.New(cferr.CTError, cferr.PrecertInvalidPoison)
}
// Check extension contains ASN.1 NULL
if bytes.Compare(ext.Value, []byte{0x05, 0x00}) != 0 {
return nil, cferr.New(cferr.CTError, cferr.PrecertInvalidPoison)
}
isPrecert = true
poisonIndex = i
break
}
}
if !isPrecert {
return nil, cferr.New(cferr.CTError, cferr.PrecertMissingPoison)
}
// Serialize SCTs into list format and create extension
serializedList, err := helpers.SerializeSCTList(scts)
if err != nil {
return nil, err
}
// Serialize again as an octet string before embedding
serializedList, err = asn1.Marshal(serializedList)
if err != nil {
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
}
sctExt := pkix.Extension{Id: signer.SCTListOID, Critical: false, Value: serializedList}
// Create the new tbsCert from precert. Do explicit copies of any slices so that we don't
// use memory that may be altered by us or the caller at a later stage.
tbsCert := x509.Certificate{
SignatureAlgorithm: precert.SignatureAlgorithm,
PublicKeyAlgorithm: precert.PublicKeyAlgorithm,
PublicKey: precert.PublicKey,
Version: precert.Version,
SerialNumber: precert.SerialNumber,
Issuer: precert.Issuer,
Subject: precert.Subject,
NotBefore: precert.NotBefore,
NotAfter: precert.NotAfter,
KeyUsage: precert.KeyUsage,
BasicConstraintsValid: precert.BasicConstraintsValid,
IsCA: precert.IsCA,
MaxPathLen: precert.MaxPathLen,
MaxPathLenZero: precert.MaxPathLenZero,
PermittedDNSDomainsCritical: precert.PermittedDNSDomainsCritical,
}
if len(precert.Extensions) > 0 {
tbsCert.ExtraExtensions = make([]pkix.Extension, len(precert.Extensions))
copy(tbsCert.ExtraExtensions, precert.Extensions)
}
// Remove the poison extension from ExtraExtensions
tbsCert.ExtraExtensions = append(tbsCert.ExtraExtensions[:poisonIndex], tbsCert.ExtraExtensions[poisonIndex+1:]...)
// Insert the SCT list extension
tbsCert.ExtraExtensions = append(tbsCert.ExtraExtensions, sctExt)
// Sign the tbsCert
return s.sign(&tbsCert)
}
// Info return a populated info.Resp struct or an error.
func (s *Signer) Info(req info.Req) (resp *info.Resp, err error) {
cert, err := s.Certificate(req.Label, req.Profile)

View File

@ -64,6 +64,12 @@ type SignRequest struct {
// for canonicalization) as the value of the notAfter field of the
// certificate.
NotAfter time.Time
// If ReturnPrecert is true a certificate with the CT poison extension
// will be returned from the Signer instead of attempting to retrieve
// SCTs and populate the tbsCert with them itself. This precert can then
// be passed to SignFromPrecert with the SCTs in order to create a
// valid certificate.
ReturnPrecert bool
}
// appendIf appends to a if s is not an empty string.

View File

@ -63,13 +63,10 @@ func newLocalSigner(root Root, policy *config.Signing) (s signer.Signer, err err
// signers.
var shouldProvide bool
// localSignerList is defined in the
// universal_signers*.go files. These activate
// and deactivate signers based on build
// flags; for example,
// universal_signers_pkcs11.go contains a list
// of valid signers when PKCS #11 is turned
// on.
// localSignerList is a list of signers defined
// here or in the universal_signers*.go files.
// These activate and deactivate signers based
// on build flags.
for _, possibleSigner := range localSignerList {
s, shouldProvide, err = possibleSigner(&root, policy)
if shouldProvide {

View File

@ -181,7 +181,7 @@ func UntrustedPlatforms(root *x509.Certificate) []string {
return ret
}
// CrossPlatformUbiquity returns a ubiquity score (persumably relecting the market share in percentage)
// CrossPlatformUbiquity returns a ubiquity score (presumably relecting the market share in percentage)
// based on whether the given chain can be verified with the different platforms' root certificate stores.
func CrossPlatformUbiquity(chain []*x509.Certificate) int {
// There is no root store info, every chain is equal weighted as 0.