[dev.boringcrypto] all: merge master into dev.boringcrypto

Conflicts due to simple variable renames (d <-> d0):
    src/crypto/sha1/sha1.go
    src/crypto/sha256/sha256.go
    src/crypto/sha512/sha512.go

Change-Id: I437df180a527fb3ec8b47927ee71960d5d200b76
This commit is contained in:
Filippo Valsorda 2018-05-17 21:04:07 -04:00
commit 562bcf9942
13 changed files with 237 additions and 114 deletions

View file

@ -384,7 +384,7 @@ func mutualCipherSuite(have []uint16, want uint16) *cipherSuite {
// A list of cipher suite IDs that are, or have been, implemented by this
// package.
//
// Taken from http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
// Taken from https://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

View file

@ -91,7 +91,7 @@ const (
)
// 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
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8
type CurveID uint16
const (
@ -102,7 +102,7 @@ const (
)
// TLS Elliptic Curve Point Formats
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9
const (
pointFormatUncompressed uint8 = 0
)
@ -162,6 +162,12 @@ type ConnectionState struct {
SignedCertificateTimestamps [][]byte // SCTs from the server, if any
OCSPResponse []byte // stapled OCSP response from server, if any
// ExportKeyMaterial returns length bytes of exported key material as
// defined in https://tools.ietf.org/html/rfc5705. If context is nil, it is
// not used as part of the seed. If Config.Renegotiation was set to allow
// renegotiation, this function will always return nil, false.
ExportKeyingMaterial func(label string, context []byte, length int) ([]byte, bool)
// 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
@ -406,8 +412,9 @@ type Config struct {
//
// If normal verification fails then the handshake will abort before
// considering this callback. If normal verification is disabled by
// setting InsecureSkipVerify then this callback will be considered but
// the verifiedChains argument will always be nil.
// setting InsecureSkipVerify, or (for a server) when ClientAuth is
// RequestClientCert or RequireAnyClientCert, then this callback will
// be considered but the verifiedChains argument will always be nil.
VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
// RootCAs defines the set of root certificate authorities

90
conn.go
View file

@ -28,15 +28,11 @@ type Conn struct {
isClient bool
// constant after handshake; protected by handshakeMutex
handshakeMutex sync.Mutex // handshakeMutex < in.Mutex, out.Mutex, errMutex
// handshakeCond, if not nil, indicates that a goroutine is committed
// to running the handshake for this Conn. Other goroutines that need
// to wait for the handshake can wait on this, under handshakeMutex.
handshakeCond *sync.Cond
handshakeErr error // error resulting from handshake
vers uint16 // TLS version
haveVers bool // version has been negotiated
config *Config // configuration passed to constructor
handshakeMutex sync.Mutex
handshakeErr error // error resulting from handshake
vers uint16 // TLS version
haveVers bool // version has been negotiated
config *Config // configuration passed to constructor
// handshakeComplete is true if the connection is currently transferring
// application data (i.e. is not currently processing a handshake).
handshakeComplete bool
@ -58,6 +54,8 @@ type Conn struct {
// renegotiation extension. (This is meaningless as a server because
// renegotiation is not supported in that case.)
secureRenegotiation bool
// ekm is a closure for exporting keying material.
ekm func(label string, context []byte, length int) ([]byte, bool)
// clientFinishedIsFirst is true if the client sent the first Finished
// message during the most recent handshake. This is recorded because
@ -82,7 +80,7 @@ type Conn struct {
clientProtocolFallback bool
// input/output
in, out halfConn // in.Mutex < out.Mutex
in, out halfConn
rawInput *block // raw input, right off the wire
input *block // application data waiting to be read
hand bytes.Buffer // handshake data waiting to be read
@ -564,7 +562,6 @@ func (c *Conn) newRecordHeaderError(msg string) (err RecordHeaderError) {
// readRecord reads the next TLS record from the connection
// and updates the record layer state.
// c.in.Mutex <= L; c.input == nil.
func (c *Conn) readRecord(want recordType) error {
// Caller must be in sync with connection:
// handshake data if handshake not yet completed,
@ -736,7 +733,6 @@ Again:
}
// sendAlert sends a TLS alert message.
// c.out.Mutex <= L.
func (c *Conn) sendAlertLocked(err alert) error {
switch err {
case alertNoRenegotiation, alertCloseNotify:
@ -756,7 +752,6 @@ func (c *Conn) sendAlertLocked(err alert) error {
}
// sendAlert sends a TLS alert message.
// L < c.out.Mutex.
func (c *Conn) sendAlert(err alert) error {
c.out.Lock()
defer c.out.Unlock()
@ -793,8 +788,6 @@ const (
//
// In the interests of simplicity and determinism, this code does not attempt
// to reset the record size once the connection is idle, however.
//
// c.out.Mutex <= L.
func (c *Conn) maxPayloadSizeForWrite(typ recordType, explicitIVLen int) int {
if c.config.DynamicRecordSizingDisabled || typ != recordTypeApplicationData {
return maxPlaintext
@ -844,7 +837,6 @@ func (c *Conn) maxPayloadSizeForWrite(typ recordType, explicitIVLen int) int {
return n
}
// c.out.Mutex <= L.
func (c *Conn) write(data []byte) (int, error) {
if c.buffering {
c.sendBuf = append(c.sendBuf, data...)
@ -870,7 +862,6 @@ func (c *Conn) flush() (int, error) {
// writeRecordLocked writes a TLS record with the given type and payload to the
// connection and updates the record layer state.
// c.out.Mutex <= L.
func (c *Conn) writeRecordLocked(typ recordType, data []byte) (int, error) {
b := c.out.newBlock()
defer c.out.freeBlock(b)
@ -946,7 +937,6 @@ func (c *Conn) writeRecordLocked(typ recordType, data []byte) (int, error) {
// writeRecord writes a TLS record with the given type and payload to the
// connection and updates the record layer state.
// L < c.out.Mutex.
func (c *Conn) writeRecord(typ recordType, data []byte) (int, error) {
c.out.Lock()
defer c.out.Unlock()
@ -956,7 +946,6 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (int, error) {
// readHandshake reads the next handshake message from
// the record layer.
// c.in.Mutex < L; c.out.Mutex < L.
func (c *Conn) readHandshake() (interface{}, error) {
for c.hand.Len() < 4 {
if err := c.in.err; err != nil {
@ -1092,7 +1081,6 @@ func (c *Conn) Write(b []byte) (int, error) {
}
// handleRenegotiation processes a HelloRequest handshake message.
// c.in.Mutex <= L
func (c *Conn) handleRenegotiation() error {
msg, err := c.readHandshake()
if err != nil {
@ -1270,61 +1258,19 @@ func (c *Conn) closeNotify() error {
// Most uses of this package need not call Handshake
// explicitly: the first Read or Write will call it automatically.
func (c *Conn) Handshake() error {
// c.handshakeErr and c.handshakeComplete are protected by
// c.handshakeMutex. In order to perform a handshake, we need to lock
// c.in also and c.handshakeMutex must be locked after c.in.
//
// However, if a Read() operation is hanging then it'll be holding the
// lock on c.in and so taking it here would cause all operations that
// need to check whether a handshake is pending (such as Write) to
// block.
//
// Thus we first take c.handshakeMutex to check whether a handshake is
// needed.
//
// If so then, previously, this code would unlock handshakeMutex and
// then lock c.in and handshakeMutex in the correct order to run the
// handshake. The problem was that it was possible for a Read to
// complete the handshake once handshakeMutex was unlocked and then
// keep c.in while waiting for network data. Thus a concurrent
// operation could be blocked on c.in.
//
// Thus handshakeCond is used to signal that a goroutine is committed
// to running the handshake and other goroutines can wait on it if they
// need. handshakeCond is protected by handshakeMutex.
c.handshakeMutex.Lock()
defer c.handshakeMutex.Unlock()
for {
if err := c.handshakeErr; err != nil {
return err
}
if c.handshakeComplete {
return nil
}
if c.handshakeCond == nil {
break
}
c.handshakeCond.Wait()
if err := c.handshakeErr; err != nil {
return err
}
if c.handshakeComplete {
return nil
}
// Set handshakeCond to indicate that this goroutine is committing to
// running the handshake.
c.handshakeCond = sync.NewCond(&c.handshakeMutex)
c.handshakeMutex.Unlock()
c.in.Lock()
defer c.in.Unlock()
c.handshakeMutex.Lock()
// The handshake cannot have completed when handshakeMutex was unlocked
// because this goroutine set handshakeCond.
if c.handshakeErr != nil || c.handshakeComplete {
panic("handshake should not have been able to complete after handshakeCond was set")
}
if c.isClient {
c.handshakeErr = c.clientHandshake()
} else {
@ -1342,11 +1288,6 @@ func (c *Conn) Handshake() error {
panic("handshake should have had a result.")
}
// Wake any other goroutines that are waiting for this handshake to
// complete.
c.handshakeCond.Broadcast()
c.handshakeCond = nil
return c.handshakeErr
}
@ -1376,6 +1317,11 @@ func (c *Conn) ConnectionState() ConnectionState {
state.TLSUnique = c.serverFinished[:]
}
}
if c.config.Renegotiation != RenegotiateNever {
state.ExportKeyingMaterial = noExportedKeyingMaterial
} else {
state.ExportKeyingMaterial = c.ekm
}
}
return state

View file

@ -11,6 +11,7 @@ import (
"net/http"
"net/http/httptest"
"os"
"time"
)
// zeroSource is an io.Reader that returns an unlimited number of zero bytes.
@ -113,3 +114,75 @@ func ExampleConfig_keyLogWriter() {
// Output:
// CLIENT_RANDOM 0000000000000000000000000000000000000000000000000000000000000000 baca0df460a688e44ce018b025183cc2353ae01f89755ef766eedd3ecc302888ee3b3a22962e45f48c20df15a98c0e80
}
func ExampleLoadX509KeyPair() {
cert, err := tls.LoadX509KeyPair("testdata/example-cert.pem", "testdata/example-key.pem")
if err != nil {
log.Fatal(err)
}
cfg := &tls.Config{Certificates: []tls.Certificate{cert}}
listener, err := tls.Listen("tcp", ":2000", cfg)
if err != nil {
log.Fatal(err)
}
_ = listener
}
func ExampleX509KeyPair() {
certPem := []byte(`-----BEGIN CERTIFICATE-----
MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw
DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow
EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d
7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B
5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr
BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1
NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l
Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc
6MF9+Yw1Yy0t
-----END CERTIFICATE-----`)
keyPem := []byte(`-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49
AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q
EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA==
-----END EC PRIVATE KEY-----`)
cert, err := tls.X509KeyPair(certPem, keyPem)
if err != nil {
log.Fatal(err)
}
cfg := &tls.Config{Certificates: []tls.Certificate{cert}}
listener, err := tls.Listen("tcp", ":2000", cfg)
if err != nil {
log.Fatal(err)
}
_ = listener
}
func ExampleX509KeyPair_httpServer() {
certPem := []byte(`-----BEGIN CERTIFICATE-----
MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw
DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow
EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d
7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B
5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr
BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1
NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l
Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc
6MF9+Yw1Yy0t
-----END CERTIFICATE-----`)
keyPem := []byte(`-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49
AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q
EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA==
-----END EC PRIVATE KEY-----`)
cert, err := tls.X509KeyPair(certPem, keyPem)
if err != nil {
log.Fatal(err)
}
cfg := &tls.Config{Certificates: []tls.Certificate{cert}}
srv := &http.Server{
TLSConfig: cfg,
ReadTimeout: time.Minute,
WriteTimeout: time.Minute,
}
log.Fatal(srv.ListenAndServeTLS("", ""))
}

View file

@ -146,16 +146,24 @@ func main() {
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")
if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
log.Fatalf("failed to write data to cert.pem: %s", err)
}
if err := certOut.Close(); err != nil {
log.Fatalf("error closing cert.pem: %s", err)
}
log.Print("wrote 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")
if err := pem.Encode(keyOut, pemBlockForKey(priv)); err != nil {
log.Fatalf("failed to write data to key.pem: %s", err)
}
if err := keyOut.Close(); err != nil {
log.Fatalf("error closing key.pem: %s", err)
}
log.Print("wrote key.pem\n")
}

View file

@ -94,7 +94,6 @@ NextCipherSuite:
return hello, nil
}
// c.out.Mutex <= L; c.handshakeMutex <= L.
func (c *Conn) clientHandshake() error {
if c.config == nil {
c.config = defaultConfig()
@ -268,6 +267,7 @@ func (hs *clientHandshakeState) handshake() error {
}
}
c.ekm = ekmFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random)
c.didResume = isResume
c.handshakeComplete = true
@ -377,26 +377,34 @@ func (hs *clientHandshakeState) doFullHandshake() error {
}
}
if hs.serverHello.ocspStapling {
msg, err = c.readHandshake()
if err != nil {
return err
}
cs, ok := msg.(*certificateStatusMsg)
if !ok {
msg, err = c.readHandshake()
if err != nil {
return err
}
cs, ok := msg.(*certificateStatusMsg)
if ok {
// RFC4366 on Certificate Status Request:
// The server MAY return a "certificate_status" message.
if !hs.serverHello.ocspStapling {
// If a server returns a "CertificateStatus" message, then the
// server MUST have included an extension of type "status_request"
// with empty "extension_data" in the extended server hello.
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(cs, msg)
return errors.New("tls: received unexpected CertificateStatus message")
}
hs.finishedHash.Write(cs.marshal())
if cs.statusType == statusTypeOCSP {
c.ocspResponse = cs.response
}
}
msg, err = c.readHandshake()
if err != nil {
return err
msg, err = c.readHandshake()
if err != nil {
return err
}
}
keyAgreement := hs.suite.ka(c.vers)

View file

@ -36,7 +36,6 @@ type serverHandshakeState struct {
}
// serverHandshake performs a TLS handshake as a server.
// c.out.Mutex <= L; c.handshakeMutex <= L.
func (c *Conn) serverHandshake() error {
// If this is the first server handshake, we generate a random key to
// encrypt the tickets with.
@ -103,6 +102,8 @@ func (c *Conn) serverHandshake() error {
return err
}
}
c.ekm = ekmFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random)
c.handshakeComplete = true
return nil

View file

@ -194,9 +194,9 @@ func TestDontSelectRSAWithECDSAKey(t *testing.T) {
func TestRenegotiationExtension(t *testing.T) {
clientHello := &clientHelloMsg{
vers: VersionTLS12,
compressionMethods: []uint8{compressionNone},
random: make([]byte, 32),
vers: VersionTLS12,
compressionMethods: []uint8{compressionNone},
random: make([]byte, 32),
secureRenegotiationSupported: true,
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
}
@ -992,7 +992,7 @@ func TestFallbackSCSV(t *testing.T) {
name: "FallbackSCSV",
config: &serverConfig,
// OpenSSL 1.0.1j is needed for the -fallback_scsv option.
command: []string{"openssl", "s_client", "-fallback_scsv"},
command: []string{"openssl", "s_client", "-fallback_scsv"},
expectHandshakeErrorIncluding: "inappropriate protocol fallback",
}
runServerTestTLS11(t, test)

40
prf.go
View file

@ -360,3 +360,43 @@ func (h finishedHash) hashForClientCertificate(sigType uint8, signatureAlgorithm
func (h *finishedHash) discardHandshakeBuffer() {
h.buffer = nil
}
// noExportedKeyingMaterial is used as a value of
// ConnectionState.ExportKeyingMaterial when renegotation is enabled and thus
// we wish to fail all key-material export requests.
func noExportedKeyingMaterial(label string, context []byte, length int) ([]byte, bool) {
return nil, false
}
// ekmFromMasterSecret generates exported keying material as defined in
// https://tools.ietf.org/html/rfc5705.
func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte) func(string, []byte, int) ([]byte, bool) {
return func(label string, context []byte, length int) ([]byte, bool) {
switch label {
case "client finished", "server finished", "master secret", "key expansion":
// These values are reserved and may not be used.
return nil, false
}
seedLen := len(serverRandom) + len(clientRandom)
if context != nil {
seedLen += 2 + len(context)
}
seed := make([]byte, 0, seedLen)
seed = append(seed, clientRandom...)
seed = append(seed, serverRandom...)
if context != nil {
if len(context) >= 1<<16 {
return nil, false
}
seed = append(seed, byte(len(context)>>8), byte(len(context)))
seed = append(seed, context...)
}
keyMaterial := make([]byte, length)
prfForVersion(version, suite)(keyMaterial, masterSecret, []byte(label), seed)
return keyMaterial, true
}
}

View file

@ -34,14 +34,15 @@ func TestSplitPreMasterSecret(t *testing.T) {
}
type testKeysFromTest struct {
version uint16
suite *cipherSuite
preMasterSecret string
clientRandom, serverRandom string
masterSecret string
clientMAC, serverMAC string
clientKey, serverKey string
macLen, keyLen int
version uint16
suite *cipherSuite
preMasterSecret string
clientRandom, serverRandom string
masterSecret string
clientMAC, serverMAC string
clientKey, serverKey string
macLen, keyLen int
contextKeyingMaterial, noContextKeyingMaterial string
}
func TestKeysFromPreMasterSecret(t *testing.T) {
@ -67,6 +68,22 @@ func TestKeysFromPreMasterSecret(t *testing.T) {
serverKeyString != test.serverKey {
t.Errorf("#%d: got: (%s, %s, %s, %s) want: (%s, %s, %s, %s)", i, clientMACString, serverMACString, clientKeyString, serverKeyString, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey)
}
ekm := ekmFromMasterSecret(test.version, test.suite, masterSecret, clientRandom, serverRandom)
contextKeyingMaterial, ok := ekm("label", []byte("context"), 32)
if !ok {
t.Fatalf("ekmFromMasterSecret failed")
}
noContextKeyingMaterial, ok := ekm("label", nil, 32)
if !ok {
t.Fatalf("ekmFromMasterSecret failed")
}
if hex.EncodeToString(contextKeyingMaterial) != test.contextKeyingMaterial ||
hex.EncodeToString(noContextKeyingMaterial) != test.noContextKeyingMaterial {
t.Errorf("#%d: got keying material: (%s, %s) want: (%s, %s)", i, contextKeyingMaterial, noContextKeyingMaterial, test.contextKeyingMaterial, test.noContextKeyingMaterial)
}
}
}
@ -94,6 +111,8 @@ var testKeysFromTests = []testKeysFromTest{
"e076e33206b30507a85c32855acd0919",
20,
16,
"4d1bb6fc278c37d27aa6e2a13c2e079095d143272c2aa939da33d88c1c0cec22",
"93fba89599b6321ae538e27c6548ceb8b46821864318f5190d64a375e5d69d41",
},
{
VersionTLS10,
@ -108,6 +127,8 @@ var testKeysFromTests = []testKeysFromTest{
"df3f94f6e1eacc753b815fe16055cd43",
20,
16,
"2c9f8961a72b97cbe76553b5f954caf8294fc6360ef995ac1256fe9516d0ce7f",
"274f19c10291d188857ad8878e2119f5aa437d4da556601cf1337aff23154016",
},
{
VersionTLS10,
@ -122,6 +143,8 @@ var testKeysFromTests = []testKeysFromTest{
"ff07edde49682b45466bd2e39464b306",
20,
16,
"678b0d43f607de35241dc7e9d1a7388a52c35033a1a0336d4d740060a6638fe2",
"f3b4ac743f015ef21d79978297a53da3e579ee047133f38c234d829c0f907dab",
},
{
VersionSSL30,
@ -136,5 +159,7 @@ var testKeysFromTests = []testKeysFromTest{
"2b9d4b4a60cb7f396780ebff50650419",
20,
16,
"d230d8fc4f695be60368635e5268c414ca3ae0995dd93aba9f877272049f35bf",
"6b5e9646e04df8e99482a9b22dbfbe42ddd4725e4b041d02d11e4ef44ad13120",
},
}

11
testdata/example-cert.pem vendored Normal file
View file

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw
DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow
EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d
7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B
5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr
BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1
NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l
Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc
6MF9+Yw1Yy0t
-----END CERTIFICATE-----

5
testdata/example-key.pem vendored Normal file
View file

@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49
AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q
EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA==
-----END EC PRIVATE KEY-----

9
tls.go
View file

@ -237,15 +237,14 @@ func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) {
skippedBlockTypes = append(skippedBlockTypes, keyDERBlock.Type)
}
var err error
cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes)
// 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)
}
// 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])
cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes)
if err != nil {
return fail(err)
}