mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 18:31:15 +00:00
Bump cfssl to 56268a6
This commit is contained in:
parent
952fc9f6f8
commit
ed7304b30c
258
Godeps/Godeps.json
generated
258
Godeps/Godeps.json
generated
@ -26,12 +26,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "cloud.google.com/go/compute/metadata",
|
"ImportPath": "cloud.google.com/go/compute/metadata",
|
||||||
"Comment": "v0.1.0-115-g3b1ae45",
|
"Comment": "v0.1.0-115-g3b1ae453",
|
||||||
"Rev": "3b1ae45394a234c385be014e9a488f2bb6eef821"
|
"Rev": "3b1ae45394a234c385be014e9a488f2bb6eef821"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "cloud.google.com/go/internal",
|
"ImportPath": "cloud.google.com/go/internal",
|
||||||
"Comment": "v0.1.0-115-g3b1ae45",
|
"Comment": "v0.1.0-115-g3b1ae453",
|
||||||
"Rev": "3b1ae45394a234c385be014e9a488f2bb6eef821"
|
"Rev": "3b1ae45394a234c385be014e9a488f2bb6eef821"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -436,308 +436,318 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/api",
|
"ImportPath": "github.com/cloudflare/cfssl/api",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/api/bundle",
|
"ImportPath": "github.com/cloudflare/cfssl/api/bundle",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/api/certinfo",
|
"ImportPath": "github.com/cloudflare/cfssl/api/certinfo",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/api/client",
|
"ImportPath": "github.com/cloudflare/cfssl/api/client",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/api/crl",
|
"ImportPath": "github.com/cloudflare/cfssl/api/crl",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/api/gencrl",
|
"ImportPath": "github.com/cloudflare/cfssl/api/gencrl",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/api/generator",
|
"ImportPath": "github.com/cloudflare/cfssl/api/generator",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/cloudflare/cfssl/api/health",
|
||||||
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/api/info",
|
"ImportPath": "github.com/cloudflare/cfssl/api/info",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/api/initca",
|
"ImportPath": "github.com/cloudflare/cfssl/api/initca",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/api/ocsp",
|
"ImportPath": "github.com/cloudflare/cfssl/api/ocsp",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/api/revoke",
|
"ImportPath": "github.com/cloudflare/cfssl/api/revoke",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/api/scan",
|
"ImportPath": "github.com/cloudflare/cfssl/api/scan",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/api/signhandler",
|
"ImportPath": "github.com/cloudflare/cfssl/api/signhandler",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/auth",
|
"ImportPath": "github.com/cloudflare/cfssl/auth",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/bundler",
|
"ImportPath": "github.com/cloudflare/cfssl/bundler",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/certdb",
|
"ImportPath": "github.com/cloudflare/cfssl/certdb",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/certdb/dbconf",
|
"ImportPath": "github.com/cloudflare/cfssl/certdb/dbconf",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/certdb/sql",
|
"ImportPath": "github.com/cloudflare/cfssl/certdb/sql",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/certinfo",
|
"ImportPath": "github.com/cloudflare/cfssl/certinfo",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli",
|
"ImportPath": "github.com/cloudflare/cfssl/cli",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/bundle",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/bundle",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/certinfo",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/certinfo",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/crl",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/crl",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/gencert",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/gencert",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/gencrl",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/gencrl",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/gencsr",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/gencsr",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/genkey",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/genkey",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/info",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/info",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/ocspdump",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/ocspdump",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/ocsprefresh",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/ocsprefresh",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/ocspserve",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/ocspserve",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/ocspsign",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/ocspsign",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/printdefault",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/printdefault",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/revoke",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/revoke",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/scan",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/scan",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/selfsign",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/selfsign",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/serve",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/serve",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/sign",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/sign",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cli/version",
|
"ImportPath": "github.com/cloudflare/cfssl/cli/version",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cmd/cfssl",
|
"ImportPath": "github.com/cloudflare/cfssl/cmd/cfssl",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/cmd/cfssljson",
|
"ImportPath": "github.com/cloudflare/cfssl/cmd/cfssljson",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/config",
|
"ImportPath": "github.com/cloudflare/cfssl/config",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/crl",
|
"ImportPath": "github.com/cloudflare/cfssl/crl",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs7",
|
"ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs7",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/csr",
|
"ImportPath": "github.com/cloudflare/cfssl/csr",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/errors",
|
"ImportPath": "github.com/cloudflare/cfssl/errors",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/helpers",
|
"ImportPath": "github.com/cloudflare/cfssl/helpers",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/helpers/derhelpers",
|
"ImportPath": "github.com/cloudflare/cfssl/helpers/derhelpers",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/info",
|
"ImportPath": "github.com/cloudflare/cfssl/info",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/initca",
|
"ImportPath": "github.com/cloudflare/cfssl/initca",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/log",
|
"ImportPath": "github.com/cloudflare/cfssl/log",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/ocsp",
|
"ImportPath": "github.com/cloudflare/cfssl/ocsp",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/ocsp/config",
|
"ImportPath": "github.com/cloudflare/cfssl/ocsp/config",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/revoke",
|
"ImportPath": "github.com/cloudflare/cfssl/revoke",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/scan",
|
"ImportPath": "github.com/cloudflare/cfssl/scan",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/cloudflare/cfssl/scan/crypto/tls",
|
||||||
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/selfsign",
|
"ImportPath": "github.com/cloudflare/cfssl/selfsign",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/signer",
|
"ImportPath": "github.com/cloudflare/cfssl/signer",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/signer/local",
|
"ImportPath": "github.com/cloudflare/cfssl/signer/local",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/signer/remote",
|
"ImportPath": "github.com/cloudflare/cfssl/signer/remote",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/signer/universal",
|
"ImportPath": "github.com/cloudflare/cfssl/signer/universal",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/ubiquity",
|
"ImportPath": "github.com/cloudflare/cfssl/ubiquity",
|
||||||
"Comment": "1.3.1",
|
"Comment": "1.3.2-21-g56268a6",
|
||||||
"Rev": "4e2dcbde500472449917533851bf4bae9bdff562"
|
"Rev": "56268a613adfed278936377c18b1152d2c4ad5da"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/clusterhq/flocker-go",
|
"ImportPath": "github.com/clusterhq/flocker-go",
|
||||||
|
64
Godeps/LICENSES
generated
64
Godeps/LICENSES
generated
@ -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: =
|
= 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: =
|
= vendor/github.com/cloudflare/cfssl/selfsign licensed under: =
|
||||||
|
|
||||||
|
1
vendor/github.com/cloudflare/cfssl/api/BUILD
generated
vendored
1
vendor/github.com/cloudflare/cfssl/api/BUILD
generated
vendored
@ -29,6 +29,7 @@ filegroup(
|
|||||||
"//vendor/github.com/cloudflare/cfssl/api/crl:all-srcs",
|
"//vendor/github.com/cloudflare/cfssl/api/crl:all-srcs",
|
||||||
"//vendor/github.com/cloudflare/cfssl/api/gencrl: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/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/info:all-srcs",
|
||||||
"//vendor/github.com/cloudflare/cfssl/api/initca:all-srcs",
|
"//vendor/github.com/cloudflare/cfssl/api/initca:all-srcs",
|
||||||
"//vendor/github.com/cloudflare/cfssl/api/ocsp:all-srcs",
|
"//vendor/github.com/cloudflare/cfssl/api/ocsp:all-srcs",
|
||||||
|
20
vendor/github.com/cloudflare/cfssl/api/client/client.go
generated
vendored
20
vendor/github.com/cloudflare/cfssl/api/client/client.go
generated
vendored
@ -105,14 +105,28 @@ func (srv *server) getURL(endpoint string) string {
|
|||||||
return fmt.Sprintf("%s/api/v1/cfssl/%s", srv.URL, endpoint)
|
return fmt.Sprintf("%s/api/v1/cfssl/%s", srv.URL, endpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *server) createTransport() (transport *http.Transport) {
|
func (srv *server) createTransport() *http.Transport {
|
||||||
transport = new(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
|
// Setup HTTPS client
|
||||||
tlsConfig := srv.TLSConfig
|
tlsConfig := srv.TLSConfig
|
||||||
tlsConfig.BuildNameToCertificate()
|
tlsConfig.BuildNameToCertificate()
|
||||||
transport.TLSClientConfig = tlsConfig
|
transport.TLSClientConfig = tlsConfig
|
||||||
// Setup Proxy
|
// Setup Proxy
|
||||||
transport.Proxy = srv.proxy
|
if srv.proxy != nil {
|
||||||
|
transport.Proxy = srv.proxy
|
||||||
|
}
|
||||||
return transport
|
return transport
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
vendor/github.com/cloudflare/cfssl/api/health/BUILD
generated
vendored
Normal file
24
vendor/github.com/cloudflare/cfssl/api/health/BUILD
generated
vendored
Normal 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"],
|
||||||
|
)
|
26
vendor/github.com/cloudflare/cfssl/api/health/health.go
generated
vendored
Normal file
26
vendor/github.com/cloudflare/cfssl/api/health/health.go
generated
vendored
Normal 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"},
|
||||||
|
}
|
||||||
|
}
|
2
vendor/github.com/cloudflare/cfssl/api/revoke/revoke.go
generated
vendored
2
vendor/github.com/cloudflare/cfssl/api/revoke/revoke.go
generated
vendored
@ -113,7 +113,7 @@ func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
|
|||||||
return err
|
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
|
// update time/expiry time
|
||||||
ocspParsed, err := stdocsp.ParseResponse(ocspResponse, nil)
|
ocspParsed, err := stdocsp.ParseResponse(ocspResponse, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
4
vendor/github.com/cloudflare/cfssl/cli/config.go
generated
vendored
4
vendor/github.com/cloudflare/cfssl/cli/config.go
generated
vendored
@ -30,6 +30,7 @@ type Config struct {
|
|||||||
IntBundleFile string
|
IntBundleFile string
|
||||||
Address string
|
Address string
|
||||||
Port int
|
Port int
|
||||||
|
MinTLSVersion string
|
||||||
Password string
|
Password string
|
||||||
ConfigFile string
|
ConfigFile string
|
||||||
CFG *config.Config
|
CFG *config.Config
|
||||||
@ -68,6 +69,7 @@ type Config struct {
|
|||||||
AKI string
|
AKI string
|
||||||
DBConfigFile string
|
DBConfigFile string
|
||||||
CRLExpiration time.Duration
|
CRLExpiration time.Duration
|
||||||
|
Disable string
|
||||||
}
|
}
|
||||||
|
|
||||||
// registerFlags defines all cfssl command flags and associates their values with variables.
|
// 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.IntBundleFile, "int-bundle", "", "path to intermediate certificate store")
|
||||||
f.StringVar(&c.Address, "address", "127.0.0.1", "Address to bind")
|
f.StringVar(&c.Address, "address", "127.0.0.1", "Address to bind")
|
||||||
f.IntVar(&c.Port, "port", 8888, "Port 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.ConfigFile, "config", "", "path to configuration file")
|
||||||
f.StringVar(&c.Profile, "profile", "", "signing profile to use")
|
f.StringVar(&c.Profile, "profile", "", "signing profile to use")
|
||||||
f.BoolVar(&c.IsCA, "initca", false, "initialise new CA")
|
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.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.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.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
|
// RootFromConfig returns a universal signer Root structure that can
|
||||||
|
1
vendor/github.com/cloudflare/cfssl/cli/serve/BUILD
generated
vendored
1
vendor/github.com/cloudflare/cfssl/cli/serve/BUILD
generated
vendored
@ -14,6 +14,7 @@ go_library(
|
|||||||
"//vendor/github.com/cloudflare/cfssl/api/crl:go_default_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/gencrl:go_default_library",
|
||||||
"//vendor/github.com/cloudflare/cfssl/api/generator: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/info:go_default_library",
|
||||||
"//vendor/github.com/cloudflare/cfssl/api/initca:go_default_library",
|
"//vendor/github.com/cloudflare/cfssl/api/initca:go_default_library",
|
||||||
"//vendor/github.com/cloudflare/cfssl/api/ocsp:go_default_library",
|
"//vendor/github.com/cloudflare/cfssl/api/ocsp:go_default_library",
|
||||||
|
54
vendor/github.com/cloudflare/cfssl/cli/serve/serve.go
generated
vendored
54
vendor/github.com/cloudflare/cfssl/cli/serve/serve.go
generated
vendored
@ -20,6 +20,7 @@ import (
|
|||||||
"github.com/cloudflare/cfssl/api/crl"
|
"github.com/cloudflare/cfssl/api/crl"
|
||||||
"github.com/cloudflare/cfssl/api/gencrl"
|
"github.com/cloudflare/cfssl/api/gencrl"
|
||||||
"github.com/cloudflare/cfssl/api/generator"
|
"github.com/cloudflare/cfssl/api/generator"
|
||||||
|
"github.com/cloudflare/cfssl/api/health"
|
||||||
"github.com/cloudflare/cfssl/api/info"
|
"github.com/cloudflare/cfssl/api/info"
|
||||||
"github.com/cloudflare/cfssl/api/initca"
|
"github.com/cloudflare/cfssl/api/initca"
|
||||||
apiocsp "github.com/cloudflare/cfssl/api/ocsp"
|
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
|
var serverUsageText = `cfssl serve -- set up a HTTP server handles CF SSL requests
|
||||||
|
|
||||||
Usage of serve:
|
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] \
|
[-ca-key key] [-int-bundle bundle] [-int-dir dir] [-port port] \
|
||||||
[-metadata file] [-remote remote_host] [-config config] \
|
[-metadata file] [-remote remote_host] [-config config] \
|
||||||
[-responder cert] [-responder-key key] [-tls-cert cert] [-tls-key key] \
|
[-responder cert] [-responder-key key] \
|
||||||
[-mutual-tls-ca ca] [-mutual-tls-cn regex] \
|
[-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] \
|
[-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:
|
||||||
`
|
`
|
||||||
|
|
||||||
// Flags used by 'cfssl serve'
|
// Flags used by 'cfssl serve'
|
||||||
var serverFlags = []string{"address", "port", "ca", "ca-key", "ca-bundle", "int-bundle", "int-dir", "metadata",
|
var serverFlags = []string{"address", "port", "min-tls-version", "ca", "ca-key", "ca-bundle", "int-bundle", "int-dir",
|
||||||
"remote", "config", "responder", "responder-key", "tls-key", "tls-cert", "mutual-tls-ca", "mutual-tls-cn",
|
"metadata", "remote", "config", "responder", "responder-key", "tls-key", "tls-cert", "mutual-tls-ca",
|
||||||
"tls-remote-ca", "mutual-tls-client-cert", "mutual-tls-client-key", "db-config"}
|
"mutual-tls-cn", "tls-remote-ca", "mutual-tls-client-cert", "mutual-tls-client-key", "db-config", "disable"}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
conf cli.Config
|
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.
|
// 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 {
|
type httpBox struct {
|
||||||
*rice.Box
|
*rice.Box
|
||||||
redirects map[string]string
|
redirects map[string]string
|
||||||
@ -241,13 +242,27 @@ var endpoints = map[string]func() (http.Handler, error){
|
|||||||
|
|
||||||
return http.FileServer(staticBox), nil
|
return http.FileServer(staticBox), nil
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"health": func() (http.Handler, error) {
|
||||||
|
return health.NewHealthCheck(), nil
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// registerHandlers instantiates various handlers and associate them to corresponding endpoints.
|
// registerHandlers instantiates various handlers and associate them to corresponding endpoints.
|
||||||
func registerHandlers() {
|
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 {
|
for path, getHandler := range endpoints {
|
||||||
log.Debugf("getHandler for %s", path)
|
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)
|
log.Warningf("endpoint '%s' is disabled: %v", path, err)
|
||||||
} else {
|
} else {
|
||||||
if path, handler, err = wrapHandler(path, handler, err); err != nil {
|
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))
|
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 == "" {
|
if conf.TLSCertFile == "" || conf.TLSKeyFile == "" {
|
||||||
log.Info("Now listening on ", addr)
|
log.Info("Now listening on ", addr)
|
||||||
return http.ListenAndServe(addr, nil)
|
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)
|
return fmt.Errorf("failed to load mutual TLS CA file: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tlscfg.ClientAuth = tls.RequireAndVerifyClientCert
|
||||||
|
tlscfg.ClientCAs = clientPool
|
||||||
|
|
||||||
server := http.Server{
|
server := http.Server{
|
||||||
Addr: addr,
|
Addr: addr,
|
||||||
TLSConfig: &tls.Config{
|
TLSConfig: &tlscfg,
|
||||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
|
||||||
ClientCAs: clientPool,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if conf.MutualTLSCNRegex != "" {
|
if conf.MutualTLSCNRegex != "" {
|
||||||
@ -338,7 +358,11 @@ func serverMain(args []string, c cli.Config) error {
|
|||||||
return server.ListenAndServeTLS(conf.TLSCertFile, conf.TLSKeyFile)
|
return server.ListenAndServeTLS(conf.TLSCertFile, conf.TLSKeyFile)
|
||||||
}
|
}
|
||||||
log.Info("Now listening on https://", addr)
|
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)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
vendor/github.com/cloudflare/cfssl/cli/version/version.go
generated
vendored
2
vendor/github.com/cloudflare/cfssl/cli/version/version.go
generated
vendored
@ -14,7 +14,7 @@ var version = struct {
|
|||||||
Minor int
|
Minor int
|
||||||
Patch int
|
Patch int
|
||||||
Revision string
|
Revision string
|
||||||
}{1, 3, 0, "release"}
|
}{1, 3, 2, "release"}
|
||||||
|
|
||||||
func versionString() string {
|
func versionString() string {
|
||||||
return fmt.Sprintf("%d.%d.%d", version.Major, version.Minor, version.Patch)
|
return fmt.Sprintf("%d.%d.%d", version.Major, version.Minor, version.Patch)
|
||||||
|
20
vendor/github.com/cloudflare/cfssl/config/config.go
generated
vendored
20
vendor/github.com/cloudflare/cfssl/config/config.go
generated
vendored
@ -551,16 +551,16 @@ func (p *Signing) Valid() bool {
|
|||||||
|
|
||||||
// KeyUsage contains a mapping of string names to key usages.
|
// KeyUsage contains a mapping of string names to key usages.
|
||||||
var KeyUsage = map[string]x509.KeyUsage{
|
var KeyUsage = map[string]x509.KeyUsage{
|
||||||
"signing": x509.KeyUsageDigitalSignature,
|
"signing": x509.KeyUsageDigitalSignature,
|
||||||
"digital signature": x509.KeyUsageDigitalSignature,
|
"digital signature": x509.KeyUsageDigitalSignature,
|
||||||
"content committment": x509.KeyUsageContentCommitment,
|
"content commitment": x509.KeyUsageContentCommitment,
|
||||||
"key encipherment": x509.KeyUsageKeyEncipherment,
|
"key encipherment": x509.KeyUsageKeyEncipherment,
|
||||||
"key agreement": x509.KeyUsageKeyAgreement,
|
"key agreement": x509.KeyUsageKeyAgreement,
|
||||||
"data encipherment": x509.KeyUsageDataEncipherment,
|
"data encipherment": x509.KeyUsageDataEncipherment,
|
||||||
"cert sign": x509.KeyUsageCertSign,
|
"cert sign": x509.KeyUsageCertSign,
|
||||||
"crl sign": x509.KeyUsageCRLSign,
|
"crl sign": x509.KeyUsageCRLSign,
|
||||||
"encipher only": x509.KeyUsageEncipherOnly,
|
"encipher only": x509.KeyUsageEncipherOnly,
|
||||||
"decipher only": x509.KeyUsageDecipherOnly,
|
"decipher only": x509.KeyUsageDecipherOnly,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtKeyUsage contains a mapping of string names to extended key
|
// ExtKeyUsage contains a mapping of string names to extended key
|
||||||
|
13
vendor/github.com/cloudflare/cfssl/errors/error.go
generated
vendored
13
vendor/github.com/cloudflare/cfssl/errors/error.go
generated
vendored
@ -194,6 +194,13 @@ const (
|
|||||||
// CTClientConstructionFailed occurs when the construction of a new
|
// CTClientConstructionFailed occurs when the construction of a new
|
||||||
// github.com/google/certificate-transparency client fails.
|
// github.com/google/certificate-transparency client fails.
|
||||||
CTClientConstructionFailed
|
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
|
// 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"
|
msg = "Certificate transparency parsing failed due to unknown error"
|
||||||
case PrecertSubmissionFailed:
|
case PrecertSubmissionFailed:
|
||||||
msg = "Certificate transparency precertificate submission failed"
|
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:
|
default:
|
||||||
panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category CTError.", reason))
|
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,
|
case PrivateKeyError, IntermediatesError, RootError, PolicyError, DialError,
|
||||||
APIClientError, CSRError, CTError, CertStoreError:
|
APIClientError, CSRError, CTError, CertStoreError, OCSPError:
|
||||||
// no-op, just use the error
|
// no-op, just use the error
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",
|
panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",
|
||||||
|
1
vendor/github.com/cloudflare/cfssl/helpers/BUILD
generated
vendored
1
vendor/github.com/cloudflare/cfssl/helpers/BUILD
generated
vendored
@ -13,6 +13,7 @@ go_library(
|
|||||||
"//vendor/github.com/cloudflare/cfssl/log:go_default_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:go_default_library",
|
||||||
"//vendor/github.com/google/certificate-transparency-go/tls: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/ocsp:go_default_library",
|
||||||
"//vendor/golang.org/x/crypto/pkcs12:go_default_library",
|
"//vendor/golang.org/x/crypto/pkcs12:go_default_library",
|
||||||
],
|
],
|
||||||
|
10
vendor/github.com/cloudflare/cfssl/helpers/derhelpers/BUILD
generated
vendored
10
vendor/github.com/cloudflare/cfssl/helpers/derhelpers/BUILD
generated
vendored
@ -2,11 +2,17 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|||||||
|
|
||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = ["derhelpers.go"],
|
srcs = [
|
||||||
|
"derhelpers.go",
|
||||||
|
"ed25519.go",
|
||||||
|
],
|
||||||
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/helpers/derhelpers",
|
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/helpers/derhelpers",
|
||||||
importpath = "github.com/cloudflare/cfssl/helpers/derhelpers",
|
importpath = "github.com/cloudflare/cfssl/helpers/derhelpers",
|
||||||
visibility = ["//visibility:public"],
|
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(
|
filegroup(
|
||||||
|
22
vendor/github.com/cloudflare/cfssl/helpers/derhelpers/derhelpers.go
generated
vendored
22
vendor/github.com/cloudflare/cfssl/helpers/derhelpers/derhelpers.go
generated
vendored
@ -9,10 +9,11 @@ import (
|
|||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
|
||||||
cferr "github.com/cloudflare/cfssl/errors"
|
cferr "github.com/cloudflare/cfssl/errors"
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParsePrivateKeyDER parses a PKCS #1, PKCS #8, or elliptic curve
|
// ParsePrivateKeyDER parses a PKCS #1, PKCS #8, ECDSA, or Ed25519 DER-encoded
|
||||||
// DER-encoded private key. The key must not be in PEM format.
|
// private key. The key must not be in PEM format.
|
||||||
func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) {
|
func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) {
|
||||||
generalKey, err := x509.ParsePKCS8PrivateKey(keyDER)
|
generalKey, err := x509.ParsePKCS8PrivateKey(keyDER)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -20,12 +21,15 @@ func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
generalKey, err = x509.ParseECPrivateKey(keyDER)
|
generalKey, err = x509.ParseECPrivateKey(keyDER)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// We don't include the actual error into
|
generalKey, err = ParseEd25519PrivateKey(keyDER)
|
||||||
// the final error. The reason might be
|
if err != nil {
|
||||||
// we don't want to leak any info about
|
// We don't include the actual error into
|
||||||
// the private key.
|
// the final error. The reason might be
|
||||||
return nil, cferr.New(cferr.PrivateKeyError,
|
// we don't want to leak any info about
|
||||||
cferr.ParseFailed)
|
// the private key.
|
||||||
|
return nil, cferr.New(cferr.PrivateKeyError,
|
||||||
|
cferr.ParseFailed)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,6 +39,8 @@ func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) {
|
|||||||
return generalKey.(*rsa.PrivateKey), nil
|
return generalKey.(*rsa.PrivateKey), nil
|
||||||
case *ecdsa.PrivateKey:
|
case *ecdsa.PrivateKey:
|
||||||
return generalKey.(*ecdsa.PrivateKey), nil
|
return generalKey.(*ecdsa.PrivateKey), nil
|
||||||
|
case ed25519.PrivateKey:
|
||||||
|
return generalKey.(ed25519.PrivateKey), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// should never reach here
|
// should never reach here
|
||||||
|
133
vendor/github.com/cloudflare/cfssl/helpers/derhelpers/ed25519.go
generated
vendored
Normal file
133
vendor/github.com/cloudflare/cfssl/helpers/derhelpers/ed25519.go
generated
vendored
Normal 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
|
||||||
|
}
|
97
vendor/github.com/cloudflare/cfssl/helpers/helpers.go
generated
vendored
97
vendor/github.com/cloudflare/cfssl/helpers/helpers.go
generated
vendored
@ -12,16 +12,15 @@ import (
|
|||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
"encoding/binary"
|
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/google/certificate-transparency-go"
|
"github.com/google/certificate-transparency-go"
|
||||||
cttls "github.com/google/certificate-transparency-go/tls"
|
cttls "github.com/google/certificate-transparency-go/tls"
|
||||||
|
ctx509 "github.com/google/certificate-transparency-go/x509"
|
||||||
"golang.org/x/crypto/ocsp"
|
"golang.org/x/crypto/ocsp"
|
||||||
|
|
||||||
"strings"
|
"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 {
|
func EncodeCertificatesPEM(certs []*x509.Certificate) []byte {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
for _, cert := range certs {
|
for _, cert := range certs {
|
||||||
@ -198,7 +210,7 @@ func EncodeCertificatesPEM(certs []*x509.Certificate) []byte {
|
|||||||
return buffer.Bytes()
|
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 {
|
func EncodeCertificatePEM(cert *x509.Certificate) []byte {
|
||||||
return EncodeCertificatesPEM([]*x509.Certificate{cert})
|
return EncodeCertificatesPEM([]*x509.Certificate{cert})
|
||||||
}
|
}
|
||||||
@ -408,7 +420,7 @@ func ParseCSR(in []byte) (csr *x509.CertificateRequest, rest []byte, err error)
|
|||||||
return csr, rest, nil
|
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
|
// It does not check the signature. This is useful for dumping data from a CSR
|
||||||
// locally.
|
// locally.
|
||||||
func ParseCSRPEM(csrPEM []byte) (*x509.CertificateRequest, error) {
|
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.
|
// SerializeSCTList serializes a list of SCTs.
|
||||||
func SerializeSCTList(sctList []ct.SignedCertificateTimestamp) ([]byte, error) {
|
func SerializeSCTList(sctList []ct.SignedCertificateTimestamp) ([]byte, error) {
|
||||||
var buf bytes.Buffer
|
list := ctx509.SignedCertificateTimestampList{}
|
||||||
for _, sct := range sctList {
|
for _, sct := range sctList {
|
||||||
sct, err := cttls.Marshal(sct)
|
sctBytes, err := cttls.Marshal(sct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
binary.Write(&buf, binary.BigEndian, uint16(len(sct)))
|
list.SCTList = append(list.SCTList, ctx509.SerializedSCT{Val: sctBytes})
|
||||||
buf.Write(sct)
|
|
||||||
}
|
}
|
||||||
|
return cttls.Marshal(list)
|
||||||
var sctListLengthField = make([]byte, 2)
|
|
||||||
binary.BigEndian.PutUint16(sctListLengthField, uint16(buf.Len()))
|
|
||||||
return bytes.Join([][]byte{sctListLengthField, buf.Bytes()}, nil), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeserializeSCTList deserializes a list of SCTs.
|
// DeserializeSCTList deserializes a list of SCTs.
|
||||||
func DeserializeSCTList(serializedSCTList []byte) (*[]ct.SignedCertificateTimestamp, error) {
|
func DeserializeSCTList(serializedSCTList []byte) ([]ct.SignedCertificateTimestamp, error) {
|
||||||
sctList := new([]ct.SignedCertificateTimestamp)
|
var sctList ctx509.SignedCertificateTimestampList
|
||||||
sctReader := bytes.NewBuffer(serializedSCTList)
|
rest, err := cttls.Unmarshal(serializedSCTList, &sctList)
|
||||||
|
|
||||||
var sctListLen uint16
|
|
||||||
err := binary.Read(sctReader, binary.BigEndian, &sctListLen)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
return nil, err
|
||||||
return sctList, cferr.Wrap(cferr.CTError, cferr.Unknown,
|
|
||||||
errors.New("serialized SCT list could not be read"))
|
|
||||||
}
|
|
||||||
return sctList, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
|
|
||||||
}
|
}
|
||||||
if sctReader.Len() != int(sctListLen) {
|
if len(rest) != 0 {
|
||||||
return sctList, errors.New("SCT length field and SCT length don't match")
|
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, errors.New("serialized SCT list contained trailing garbage"))
|
||||||
}
|
}
|
||||||
|
list := make([]ct.SignedCertificateTimestamp, len(sctList.SCTList))
|
||||||
for err != io.EOF {
|
for i, serializedSCT := range sctList.SCTList {
|
||||||
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))
|
|
||||||
var sct ct.SignedCertificateTimestamp
|
var sct ct.SignedCertificateTimestamp
|
||||||
if _, err := cttls.Unmarshal(serializedSCT, &sct); err != nil {
|
rest, err := cttls.Unmarshal(serializedSCT.Val, &sct)
|
||||||
return sctList, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if len(rest) != 0 {
|
||||||
temp := append(*sctList, sct)
|
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, errors.New("serialized SCT contained trailing garbage"))
|
||||||
sctList = &temp
|
}
|
||||||
|
list[i] = sct
|
||||||
}
|
}
|
||||||
|
return list, nil
|
||||||
return sctList, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SCTListFromOCSPResponse extracts the SCTList from an ocsp.Response,
|
// 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.
|
// This code block extracts the sctList from the SCT extension.
|
||||||
var emptySCTList []ct.SignedCertificateTimestamp
|
var sctList []ct.SignedCertificateTimestamp
|
||||||
sctList := &emptySCTList
|
|
||||||
var err error
|
var err error
|
||||||
if numBytes := len(SCTListExtension.Value); numBytes != 0 {
|
if numBytes := len(SCTListExtension.Value); numBytes != 0 {
|
||||||
serializedSCTList := new([]byte)
|
var serializedSCTList []byte
|
||||||
rest := make([]byte, numBytes)
|
rest := make([]byte, numBytes)
|
||||||
copy(rest, SCTListExtension.Value)
|
copy(rest, SCTListExtension.Value)
|
||||||
for len(rest) != 0 {
|
for len(rest) != 0 {
|
||||||
rest, err = asn1.Unmarshal(rest, serializedSCTList)
|
rest, err = asn1.Unmarshal(rest, &serializedSCTList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
|
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.
|
// ReadBytes reads a []byte either from a file or an environment variable.
|
||||||
|
4
vendor/github.com/cloudflare/cfssl/initca/initca.go
generated
vendored
4
vendor/github.com/cloudflare/cfssl/initca/initca.go
generated
vendored
@ -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
|
// RenewFromPEM re-creates a root certificate from the CA cert and key
|
||||||
// files. The resulting root certificate will have the input CA certificate
|
// 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
|
// 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.
|
// will be valid from now and expire in one year as well.
|
||||||
func RenewFromPEM(caFile, keyFile string) ([]byte, error) {
|
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.
|
// RenewFromSigner re-creates a root certificate from the CA cert and crypto.Signer.
|
||||||
// The resulting root certificate will have ca certificate
|
// 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
|
// 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.
|
// will be valid from now and expire in one year as well.
|
||||||
func RenewFromSigner(ca *x509.Certificate, priv crypto.Signer) ([]byte, error) {
|
func RenewFromSigner(ca *x509.Certificate, priv crypto.Signer) ([]byte, error) {
|
||||||
|
6
vendor/github.com/cloudflare/cfssl/ocsp/ocsp.go
generated
vendored
6
vendor/github.com/cloudflare/cfssl/ocsp/ocsp.go
generated
vendored
@ -164,8 +164,10 @@ func (s StandardSigner) Sign(req SignRequest) ([]byte, error) {
|
|||||||
if bytes.Compare(req.Certificate.RawIssuer, s.issuer.RawSubject) != 0 {
|
if bytes.Compare(req.Certificate.RawIssuer, s.issuer.RawSubject) != 0 {
|
||||||
return nil, cferr.New(cferr.OCSPError, cferr.IssuerMismatch)
|
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
|
var thisUpdate, nextUpdate time.Time
|
||||||
|
6
vendor/github.com/cloudflare/cfssl/scan/BUILD
generated
vendored
6
vendor/github.com/cloudflare/cfssl/scan/BUILD
generated
vendored
@ -18,6 +18,7 @@ go_library(
|
|||||||
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
|
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
|
||||||
"//vendor/github.com/cloudflare/cfssl/log: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/revoke:go_default_library",
|
||||||
|
"//vendor/github.com/cloudflare/cfssl/scan/crypto/tls:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -30,7 +31,10 @@ filegroup(
|
|||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
name = "all-srcs",
|
name = "all-srcs",
|
||||||
srcs = [":package-srcs"],
|
srcs = [
|
||||||
|
":package-srcs",
|
||||||
|
"//vendor/github.com/cloudflare/cfssl/scan/crypto/tls:all-srcs",
|
||||||
|
],
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
5
vendor/github.com/cloudflare/cfssl/scan/connectivity.go
generated
vendored
5
vendor/github.com/cloudflare/cfssl/scan/connectivity.go
generated
vendored
@ -2,11 +2,12 @@ package scan
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/cloudflare/cfssl/scan/crypto/tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Connectivity contains scanners testing basic connectivity to the host
|
// Connectivity contains scanners testing basic connectivity to the host
|
||||||
@ -53,7 +54,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func initOnCloudFlareScan() ([]*net.IPNet, error) {
|
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 {
|
if cfNetsErr != nil {
|
||||||
return nil, cfNetsErr
|
return nil, cfNetsErr
|
||||||
}
|
}
|
||||||
|
37
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/BUILD
generated
vendored
Normal file
37
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/BUILD
generated
vendored
Normal 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"],
|
||||||
|
)
|
79
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/alert.go
generated
vendored
Normal file
79
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/alert.go
generated
vendored
Normal 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()
|
||||||
|
}
|
486
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/cfsslscan_common.go
generated
vendored
Normal file
486
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/cfsslscan_common.go
generated
vendored
Normal 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",
|
||||||
|
}
|
109
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/cfsslscan_handshake.go
generated
vendored
Normal file
109
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/cfsslscan_handshake.go
generated
vendored
Normal 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
|
||||||
|
}
|
289
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/cipher_suites.go
generated
vendored
Normal file
289
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/cipher_suites.go
generated
vendored
Normal 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
|
||||||
|
)
|
714
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/common.go
generated
vendored
Normal file
714
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/common.go
generated
vendored
Normal 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
|
||||||
|
}
|
1091
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/conn.go
generated
vendored
Normal file
1091
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/conn.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
161
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/generate_cert.go
generated
vendored
Normal file
161
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/generate_cert.go
generated
vendored
Normal 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")
|
||||||
|
}
|
667
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/handshake_client.go
generated
vendored
Normal file
667
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/handshake_client.go
generated
vendored
Normal 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
|
||||||
|
}
|
1528
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/handshake_messages.go
generated
vendored
Normal file
1528
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/handshake_messages.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
750
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/handshake_server.go
generated
vendored
Normal file
750
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/handshake_server.go
generated
vendored
Normal 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
|
||||||
|
}
|
405
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/key_agreement.go
generated
vendored
Normal file
405
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/key_agreement.go
generated
vendored
Normal 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
|
||||||
|
}
|
368
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/prf.go
generated
vendored
Normal file
368
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/prf.go
generated
vendored
Normal 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
|
||||||
|
}
|
204
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/ticket.go
generated
vendored
Normal file
204
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/ticket.go
generated
vendored
Normal 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
|
||||||
|
}
|
298
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/tls.go
generated
vendored
Normal file
298
vendor/github.com/cloudflare/cfssl/scan/crypto/tls/tls.go
generated
vendored
Normal 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")
|
||||||
|
}
|
2
vendor/github.com/cloudflare/cfssl/scan/pki.go
generated
vendored
2
vendor/github.com/cloudflare/cfssl/scan/pki.go
generated
vendored
@ -2,13 +2,13 @@ package scan
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cloudflare/cfssl/helpers"
|
"github.com/cloudflare/cfssl/helpers"
|
||||||
"github.com/cloudflare/cfssl/revoke"
|
"github.com/cloudflare/cfssl/revoke"
|
||||||
|
"github.com/cloudflare/cfssl/scan/crypto/tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PKI contains scanners for the Public Key Infrastructure.
|
// PKI contains scanners for the Public Key Infrastructure.
|
||||||
|
2
vendor/github.com/cloudflare/cfssl/scan/scan_common.go
generated
vendored
2
vendor/github.com/cloudflare/cfssl/scan/scan_common.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
package scan
|
package scan
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -11,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/cloudflare/cfssl/helpers"
|
"github.com/cloudflare/cfssl/helpers"
|
||||||
"github.com/cloudflare/cfssl/log"
|
"github.com/cloudflare/cfssl/log"
|
||||||
|
"github.com/cloudflare/cfssl/scan/crypto/tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
4
vendor/github.com/cloudflare/cfssl/scan/tls_handshake.go
generated
vendored
4
vendor/github.com/cloudflare/cfssl/scan/tls_handshake.go
generated
vendored
@ -2,13 +2,13 @@ package scan
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/cloudflare/cfssl/helpers"
|
"github.com/cloudflare/cfssl/helpers"
|
||||||
|
"github.com/cloudflare/cfssl/scan/crypto/tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Sentinel for failures in sayHello. Should always be caught.
|
// 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",
|
Description: "Scans for host's SSL/TLS version and cipher suite negotiation",
|
||||||
Scanners: map[string]*Scanner{
|
Scanners: map[string]*Scanner{
|
||||||
"CipherSuite": {
|
"CipherSuite": {
|
||||||
"Determines host's cipher suites accepted and prefered order",
|
"Determines host's cipher suites accepted and preferred order",
|
||||||
cipherSuiteScan,
|
cipherSuiteScan,
|
||||||
},
|
},
|
||||||
"SigAlgs": {
|
"SigAlgs": {
|
||||||
|
2
vendor/github.com/cloudflare/cfssl/scan/tls_session.go
generated
vendored
2
vendor/github.com/cloudflare/cfssl/scan/tls_session.go
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
package scan
|
package scan
|
||||||
|
|
||||||
import "crypto/tls"
|
import "github.com/cloudflare/cfssl/scan/crypto/tls"
|
||||||
|
|
||||||
// TLSSession contains tests of host TLS Session Resumption via
|
// TLSSession contains tests of host TLS Session Resumption via
|
||||||
// Session Tickets and Session IDs
|
// Session Tickets and Session IDs
|
||||||
|
85
vendor/github.com/cloudflare/cfssl/signer/local/local.go
generated
vendored
85
vendor/github.com/cloudflare/cfssl/signer/local/local.go
generated
vendored
@ -337,7 +337,7 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
|
|||||||
|
|
||||||
var certTBS = safeTemplate
|
var certTBS = safeTemplate
|
||||||
|
|
||||||
if len(profile.CTLogServers) > 0 {
|
if len(profile.CTLogServers) > 0 || req.ReturnPrecert {
|
||||||
// Add a poison extension which prevents validation
|
// Add a poison extension which prevents validation
|
||||||
var poisonExtension = pkix.Extension{Id: signer.CTPoisonOID, Critical: true, Value: []byte{0x05, 0x00}}
|
var poisonExtension = pkix.Extension{Id: signer.CTPoisonOID, Critical: true, Value: []byte{0x05, 0x00}}
|
||||||
var poisonedPreCert = certTBS
|
var poisonedPreCert = certTBS
|
||||||
@ -347,6 +347,10 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if req.ReturnPrecert {
|
||||||
|
return cert, nil
|
||||||
|
}
|
||||||
|
|
||||||
derCert, _ := pem.Decode(cert)
|
derCert, _ := pem.Decode(cert)
|
||||||
prechain := []ct.ASN1Cert{{Data: derCert.Bytes}, {Data: s.ca.Raw}}
|
prechain := []ct.ASN1Cert{{Data: derCert.Bytes}, {Data: s.ca.Raw}}
|
||||||
var sctList []ct.SignedCertificateTimestamp
|
var sctList []ct.SignedCertificateTimestamp
|
||||||
@ -414,6 +418,85 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
|
|||||||
return signedCert, nil
|
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.
|
// Info return a populated info.Resp struct or an error.
|
||||||
func (s *Signer) Info(req info.Req) (resp *info.Resp, err error) {
|
func (s *Signer) Info(req info.Req) (resp *info.Resp, err error) {
|
||||||
cert, err := s.Certificate(req.Label, req.Profile)
|
cert, err := s.Certificate(req.Label, req.Profile)
|
||||||
|
6
vendor/github.com/cloudflare/cfssl/signer/signer.go
generated
vendored
6
vendor/github.com/cloudflare/cfssl/signer/signer.go
generated
vendored
@ -64,6 +64,12 @@ type SignRequest struct {
|
|||||||
// for canonicalization) as the value of the notAfter field of the
|
// for canonicalization) as the value of the notAfter field of the
|
||||||
// certificate.
|
// certificate.
|
||||||
NotAfter time.Time
|
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.
|
// appendIf appends to a if s is not an empty string.
|
||||||
|
11
vendor/github.com/cloudflare/cfssl/signer/universal/universal.go
generated
vendored
11
vendor/github.com/cloudflare/cfssl/signer/universal/universal.go
generated
vendored
@ -63,13 +63,10 @@ func newLocalSigner(root Root, policy *config.Signing) (s signer.Signer, err err
|
|||||||
// signers.
|
// signers.
|
||||||
var shouldProvide bool
|
var shouldProvide bool
|
||||||
|
|
||||||
// localSignerList is defined in the
|
// localSignerList is a list of signers defined
|
||||||
// universal_signers*.go files. These activate
|
// here or in the universal_signers*.go files.
|
||||||
// and deactivate signers based on build
|
// These activate and deactivate signers based
|
||||||
// flags; for example,
|
// on build flags.
|
||||||
// universal_signers_pkcs11.go contains a list
|
|
||||||
// of valid signers when PKCS #11 is turned
|
|
||||||
// on.
|
|
||||||
for _, possibleSigner := range localSignerList {
|
for _, possibleSigner := range localSignerList {
|
||||||
s, shouldProvide, err = possibleSigner(&root, policy)
|
s, shouldProvide, err = possibleSigner(&root, policy)
|
||||||
if shouldProvide {
|
if shouldProvide {
|
||||||
|
2
vendor/github.com/cloudflare/cfssl/ubiquity/ubiquity_platform.go
generated
vendored
2
vendor/github.com/cloudflare/cfssl/ubiquity/ubiquity_platform.go
generated
vendored
@ -181,7 +181,7 @@ func UntrustedPlatforms(root *x509.Certificate) []string {
|
|||||||
return ret
|
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.
|
// based on whether the given chain can be verified with the different platforms' root certificate stores.
|
||||||
func CrossPlatformUbiquity(chain []*x509.Certificate) int {
|
func CrossPlatformUbiquity(chain []*x509.Certificate) int {
|
||||||
// There is no root store info, every chain is equal weighted as 0.
|
// There is no root store info, every chain is equal weighted as 0.
|
||||||
|
Loading…
Reference in New Issue
Block a user